Ejemplo n.º 1
0
void MachOObject::postConstruct()
{
	detectAbsolutePath();
	m_header = m_file->header();

	for (std::string rpath : m_file->rpaths())
	{
		if (rpath.compare(0, 16, "@executable_path") == 0)
		{
			if (isMainModule())
				rpath.replace(0, 16, directory());
			else
			{
				MachOObject* mainModule = MachOMgr::instance()->mainModule();
			
				if (!mainModule)
					throw std::runtime_error("Cannot resolve @executable_path without a main module");
			
				rpath.replace(0, 16, mainModule->directory());
			}
		}
		else if (rpath.compare(0, 12, "@loader_path") == 0)
		{
			rpath = expandLoaderPath(rpath, this);
		}

		m_rpaths.push_back(rpath);
	}

	m_bindAllAtLoad = MachOMgr::instance()->bindAtLaunch();
}
Ejemplo n.º 2
0
StringRef MachOObjectFile::getFileFormatName() const {
  if (!MachOObj->is64Bit()) {
    switch (MachOObj->getHeader().CPUType) {
    case 0x00000007:
      return "MACHO32-i386";
    case 0x01000007:
      return "MACHO32-x86-64";
    case 0x0000000c:
      return "MACHO32-arm";
    case 0x00000012:
      return "MACHO32-ppc";
    case 0x01000012:
      return "MACHO32-ppc64";
    }
  }

  switch (MachOObj->getHeader().CPUType) {
  case 0x00000007:
    return "MACHO64-i386";
  case 0x01000007:
    return "MACHO64-x86-64";
  case 0x0000000c:
    return "MACHO64-arm";
  case 0x00000012:
    return "MACHO64-ppc";
  case 0x01000012:
    return "MACHO64-ppc64";
  default:
    return "MACHO64-unknown";
  }
}
Ejemplo n.º 3
0
int main(int argc, char** argv, char** envp)
{
	if (argc != 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
		showHelp(argv[0]);
	
	try
	{
		MachOObject* obj;
		std::set<std::string> deps;
		MachOMgr* mgr = MachOMgr::instance();
		
		mgr->detectSysRootFromPath(argv[1]);
		mgr->setLoadAnyArchitecture(true);
		
		obj = new MachOObject(argv[1]);
		
		mgr->add(obj, true);
		
		std::cout << c(ANSI_COLOR_GRAY) << "Resolving dependencies of " << obj->path() << "\n\n" << c(ANSI_COLOR_RESET);
		
		resolve(obj, deps);
		
		mgr->remove(obj);
	}
	catch (const std::exception& e)
	{
		std::cerr << c(ANSI_COLOR_RED) << e.what() << c(ANSI_COLOR_RESET) << std::endl;
		return 1;
	}
}
Ejemplo n.º 4
0
void
MachOObjectFile::getSection(DataRefImpl DRI,
                            InMemoryStruct<macho::Section> &Res) const {
  InMemoryStruct<macho::SegmentLoadCommand> SLC;
  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  MachOObj->ReadSegmentLoadCommand(LCI, SLC);
  MachOObj->ReadSection(LCI, DRI.d.b, Res);
}
Ejemplo n.º 5
0
const char* dyld_image_path_containing_address(const void* addr)
{
	MachOObject* module = MachOMgr::instance()->objectForAddress((void*) addr);
	if (!module)
		return nullptr;
	else
		return module->path().c_str();
}
Ejemplo n.º 6
0
int __darwin_dladdr(void *addr, Dl_info *info)
{
	MachOObject* obj;

	obj = MachOMgr::instance()->objectForAddress(addr);

	if (obj)
		return obj->findSymbolInfo(addr, info);
	else
		return dladdr(addr, info);
}
Ejemplo n.º 7
0
int NSIsSymbolNameDefinedInImage(const struct mach_header *image, const char *symbolName)
{
	MachOObject* obj;
	
	obj = MachOMgr::instance()->objectByHeader((struct mach_header*) image);

	if (!obj)
		return false;

	return obj->getExportedSymbol(symbolName, false) != nullptr;
}
Ejemplo n.º 8
0
StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const {
  InMemoryStruct<macho::SegmentLoadCommand> SLC;
  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  MachOObj->ReadSegmentLoadCommand(LCI, SLC);
  InMemoryStruct<macho::Section> Sect;
  MachOObj->ReadSection(LCI, DRI.d.b, Sect);

  static char Result[34];
  strcpy(Result, SLC->Name);
  strcat(Result, ",");
  strcat(Result, Sect->Name);
  return StringRef(Result);
}
Ejemplo n.º 9
0
void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
    InMemoryStruct<macho::SymbolTableEntry> &Res) const {
  InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);

  if (RegisteredStringTable != DRI.d.a) {
    MachOObj->RegisterStringTable(*SymtabLoadCmd);
    RegisteredStringTable = DRI.d.a;
  }

  MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
                                 Res);
}
Ejemplo n.º 10
0
char* getsectdata(const struct mach_header* header, const char* segname, const char* sectname, unsigned long* size)
{
	MachOObject* obj = MachOMgr::instance()->objectByHeader((mach_header*) header);

	if (!obj || !sectname)
	{
		if (size)
			*size = 0;
		return nullptr;
	}
	if (!segname)
		segname = "";

	return (char*) obj->getSection(segname, sectname, (uintptr_t*) size);
}
Ejemplo n.º 11
0
void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
  while (DRI.d.a < LoadCommandCount) {
    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    if (LCI.Command.Type == macho::LCT_Symtab) {
      InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
      MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
      if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
        return;
    }

    DRI.d.a++;
    DRI.d.b = 0;
  }
}
Ejemplo n.º 12
0
int _NSGetExecutablePath(char* buf, unsigned int* size)
{
	std::string path;

	MachOObject* mainModule = MachOMgr::instance()->mainModule();

	if (mainModule)
		path = mainModule->path();

	if (*size > path.length()+1)
		*size = path.length()+1;

	strncpy(buf, path.c_str(), *size);
	buf[(*size)-1] = 0;

	return 0;
}
Ejemplo n.º 13
0
void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
  while (DRI.d.a < LoadCommandCount) {
    LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    if (LCI.Command.Type == macho::LCT_Segment) {
      InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
      MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
      if (DRI.d.b < SegmentLoadCmd->NumSections)
        return;
    } else if (LCI.Command.Type == macho::LCT_Segment64) {
      InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
      MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
      if (DRI.d.b < Segment64LoadCmd->NumSections)
        return;
    }

    DRI.d.a++;
    DRI.d.b = 0;
  }
}
Ejemplo n.º 14
0
unsigned MachOObjectFile::getArch() const {
  switch (MachOObj->getHeader().CPUType) {
  case 0x00000007:
    return Triple::x86;
  case 0x01000007:
    return Triple::x86_64;
  case 0x0000000c:
    return Triple::arm;
  case 0x00000012:
    return Triple::ppc;
  case 0x01000012:
    return Triple::ppc64;
  default:
    return Triple::UnknownArch;
  }
}
Ejemplo n.º 15
0
static void ReadInMemoryStruct(const MachOObject &MOO,
                               StringRef Buffer, uint64_t Base,
                               InMemoryStruct<T> &Res) {
  typedef T struct_type;
  uint64_t Size = sizeof(struct_type);

  // Check that the buffer contains the expected data.
  if (Base + Size >  Buffer.size()) {
    Res = 0;
    return;
  }

  // Check whether we can return a direct pointer.
  struct_type *Ptr = (struct_type *) (Buffer.data() + Base);
  if (!MOO.isSwappedEndian()) {
    Res = Ptr;
    return;
  }

  // Otherwise, copy the struct and translate the values.
  Res = *Ptr;
  SwapStruct(*Res);
}
Ejemplo n.º 16
0
StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const {
  InMemoryStruct<macho::Section> Sect;
  getSection(DRI, Sect);
  return MachOObj->getData(Sect->Offset, Sect->Size);
}
Ejemplo n.º 17
0
bool MachOObjectFile::isSectionText(DataRefImpl DRI) const {
  InMemoryStruct<macho::SegmentLoadCommand> SLC;
  LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  MachOObj->ReadSegmentLoadCommand(LCI, SLC);
  return !strcmp(SLC->Name, "__TEXT");
}
Ejemplo n.º 18
0
std::string DylibSearch::resolve(std::string dylib, MachOObject* requester)
{
	if (dylib.empty())
		return std::string();

	// expand @rpath, @executable_path and @loader_path
	if (requester != nullptr && dylib[0] == '@')
	{
		if (dylib.compare(0, 16, "@executable_path") == 0)
		{
			MachOObject* mainModule = MachOMgr::instance()->mainModule();
			
			if (!mainModule)
				throw std::runtime_error("Cannot resolve @executable_path without a main module");
			
			dylib.replace(0, 16, mainModule->directory());
		}
		else if (dylib.compare(0, 12, "@loader_path") == 0)
		{
			dylib.replace(0, 12, requester->directory());
		}
		else if (dylib.compare(0, 6, "@rpath") == 0)
		{
			return resolveViaRpath(dylib, requester);
		}
	}
	
	// Search in configuration
	if (const char* aliasTarget = resolveAlias(dylib))
		return aliasTarget;
	
	// Search in extra paths
	std::string epath;
	epath = resolveInPathList(dylib, m_extraPaths);
	if (!epath.empty())
		return epath;
	
	// Search in DYLD_LIBRARY_PATH
	epath = resolveInLdPath(dylib);
	if (!epath.empty())
		return epath;
	
	// Try the path as is
	epath = checkPresence(dylib);
	if (!epath.empty())
		return epath;

	// If absolute, search in sysroot
	if (dylib[0] == '/' && !MachOMgr::instance()->sysRoot().empty())
	{
		std::string path = MachOMgr::instance()->sysRoot();
		path += '/';
		path += dylib;
		
		epath = checkPresence(path);
		if (!epath.empty())
			return epath;
	}

	return std::string();
}
Ejemplo n.º 19
0
void* __darwin_dlopen(const char* filename, int flag)
{
	std::string resolved;

	if (!filename)
		return MachOMgr::instance()->mainModule();
	
	resolved = DylibSearch::instance()->resolve(filename, nullptr);

	LOG << "dlopen(): " << filename << " resolved to " << resolved << std::endl;
	if (resolved.empty())
		resolved = filename;

	LoadableObject* obj;

	obj = MachOMgr::instance()->lookup(resolved);

	// Alternative search for native objects
	if (!obj && !MachO::isMachO(resolved.c_str()))
	{
		void* native = ::dlopen(resolved.c_str(), RTLD_NOLOAD);
		if (native)
		{
			obj = MachOMgr::instance()->objectByNativeRef(native);
			::dlclose(native);
		}
	}

	if (!obj)
	{
		if (!(flag & DARWIN_RTLD_NOLOAD))
		{
			try
			{
				if (MachO::isMachO(resolved.c_str()))
				{
					MachOObject* mach;

					obj = mach = new MachOObject(resolved);
					mach->setNoRecursion(flag & DARWIN_RTLD_FIRST);
				}
				else
				{
					obj = new NativeObject(resolved);
				}

				if (flag & DARWIN_RTLD_NOW)
					obj->setBindAllAtLoad(true);

				obj->load();
			}
			catch (const std::exception& e)
			{
				dl_setLastError(e.what());
				return nullptr;
			}
		}
	}
	else
		obj->addRef();

	if (obj)
	{
		obj->setGlobalExports(flag & DARWIN_RTLD_GLOBAL);
		obj->setNoDelete(flag & DARWIN_RTLD_NODELETE);
	}

	return obj;
}
Ejemplo n.º 20
0
ObjectFile::section_iterator MachOObjectFile::end_sections() const {
  DataRefImpl DRI;
  DRI.d.a = MachOObj->getHeader().NumLoadCommands;
  DRI.d.b = 0;
  return section_iterator(SectionRef(DRI, this));
}
Ejemplo n.º 21
0
uint8_t MachOObjectFile::getBytesInAddress() const {
  return MachOObj->is64Bit() ? 8 : 4;
}
Ejemplo n.º 22
0
void llvm::DisassembleInputMachO(StringRef Filename) {
  OwningPtr<MemoryBuffer> Buff;

  if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
    errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n";
    return;
  }

  OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>(
        ObjectFile::createMachOObjectFile(Buff.take())));
  MachOObject *MachOObj = MachOOF->getObject();

  const Target *TheTarget = GetTarget(MachOObj);
  if (!TheTarget) {
    // GetTarget prints out stuff.
    return;
  }
  OwningPtr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
  OwningPtr<MCInstrAnalysis>
    InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get()));

  // Set up disassembler.
  OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName));
  OwningPtr<const MCSubtargetInfo>
    STI(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
  OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
  OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
  OwningPtr<MCInstPrinter>
    IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo,
                                      *MRI, *STI));

  if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) {
    errs() << "error: couldn't initialize disassembler for target "
           << TripleName << '\n';
    return;
  }

  outs() << '\n' << Filename << ":\n\n";

  const macho::Header &Header = MachOObj->getHeader();

  const MachOObject::LoadCommandInfo *SymtabLCI = 0;
  // First, find the symbol table segment.
  for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
    const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i);
    if (LCI.Command.Type == macho::LCT_Symtab) {
      SymtabLCI = &LCI;
      break;
    }
  }

  // Read and register the symbol table data.
  InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
  if (SymtabLCI) {
    MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
    MachOObj->RegisterStringTable(*SymtabLC);
  }

  std::vector<SectionRef> Sections;
  std::vector<SymbolRef> Symbols;
  SmallVector<uint64_t, 8> FoundFns;

  getSectionsAndSymbols(Header, MachOOF.get(), &SymtabLC, Sections, Symbols,
                        FoundFns);

  // Make a copy of the unsorted symbol list. FIXME: duplication
  std::vector<SymbolRef> UnsortedSymbols(Symbols);
  // Sort the symbols by address, just in case they didn't come in that way.
  std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());

#ifndef NDEBUG
  raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
#else
  raw_ostream &DebugOut = nulls();
#endif

  StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection,
            DebugLineSection, DebugStrSection;
  OwningPtr<DIContext> diContext;
  OwningPtr<MachOObjectFile> DSYMObj;
  MachOObject *DbgInfoObj = MachOObj;
  // Try to find debug info and set up the DIContext for it.
  if (UseDbg) {
    ArrayRef<SectionRef> DebugSections = Sections;
    std::vector<SectionRef> DSYMSections;

    // A separate DSym file path was specified, parse it as a macho file,
    // get the sections and supply it to the section name parsing machinery.
    if (!DSYMFile.empty()) {
      OwningPtr<MemoryBuffer> Buf;
      if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) {
        errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n';
        return;
      }
      DSYMObj.reset(static_cast<MachOObjectFile*>(
            ObjectFile::createMachOObjectFile(Buf.take())));
      const macho::Header &Header = DSYMObj->getObject()->getHeader();

      std::vector<SymbolRef> Symbols;
      SmallVector<uint64_t, 8> FoundFns;
      getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols,
                            FoundFns);
      DebugSections = DSYMSections;
      DbgInfoObj = DSYMObj.get()->getObject();
    }

    // Find the named debug info sections.
    for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) {
      StringRef SectName;
      if (!DebugSections[SectIdx].getName(SectName)) {
        if (SectName.equals("__DWARF,__debug_abbrev"))
          DebugSections[SectIdx].getContents(DebugAbbrevSection);
        else if (SectName.equals("__DWARF,__debug_info"))
          DebugSections[SectIdx].getContents(DebugInfoSection);
        else if (SectName.equals("__DWARF,__debug_aranges"))
          DebugSections[SectIdx].getContents(DebugArangesSection);
        else if (SectName.equals("__DWARF,__debug_line"))
          DebugSections[SectIdx].getContents(DebugLineSection);
        else if (SectName.equals("__DWARF,__debug_str"))
          DebugSections[SectIdx].getContents(DebugStrSection);
      }
    }

    // Setup the DIContext.
    diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(),
                                               DebugInfoSection,
                                               DebugAbbrevSection,
                                               DebugArangesSection,
                                               DebugLineSection,
                                               DebugStrSection));
  }

  FunctionMapTy FunctionMap;
  FunctionListTy Functions;

  for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
    StringRef SectName;
    if (Sections[SectIdx].getName(SectName) ||
        SectName.compare("__TEXT,__text"))
      continue; // Skip non-text sections

    // Insert the functions from the function starts segment into our map.
    uint64_t VMAddr;
    Sections[SectIdx].getAddress(VMAddr);
    for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) {
      StringRef SectBegin;
      Sections[SectIdx].getContents(SectBegin);
      uint64_t Offset = (uint64_t)SectBegin.data();
      FunctionMap.insert(std::make_pair(VMAddr + FoundFns[i]-Offset,
                                        (MCFunction*)0));
    }

    StringRef Bytes;
    Sections[SectIdx].getContents(Bytes);
    StringRefMemoryObject memoryObject(Bytes);
    bool symbolTableWorked = false;

    // Parse relocations.
    std::vector<std::pair<uint64_t, SymbolRef> > Relocs;
    error_code ec;
    for (relocation_iterator RI = Sections[SectIdx].begin_relocations(),
         RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) {
      uint64_t RelocOffset, SectionAddress;
      RI->getAddress(RelocOffset);
      Sections[SectIdx].getAddress(SectionAddress);
      RelocOffset -= SectionAddress;

      SymbolRef RelocSym;
      RI->getSymbol(RelocSym);

      Relocs.push_back(std::make_pair(RelocOffset, RelocSym));
    }
    array_pod_sort(Relocs.begin(), Relocs.end());

    // Disassemble symbol by symbol.
    for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
      StringRef SymName;
      Symbols[SymIdx].getName(SymName);

      SymbolRef::Type ST;
      Symbols[SymIdx].getType(ST);
      if (ST != SymbolRef::ST_Function)
        continue;

      // Make sure the symbol is defined in this section.
      bool containsSym = false;
      Sections[SectIdx].containsSymbol(Symbols[SymIdx], containsSym);
      if (!containsSym)
        continue;

      // Start at the address of the symbol relative to the section's address.
      uint64_t SectionAddress = 0;
      uint64_t Start = 0;
      Sections[SectIdx].getAddress(SectionAddress);
      Symbols[SymIdx].getAddress(Start);
      Start -= SectionAddress;

      // Stop disassembling either at the beginning of the next symbol or at
      // the end of the section.
      bool containsNextSym = false;
      uint64_t NextSym = 0;
      uint64_t NextSymIdx = SymIdx+1;
      while (Symbols.size() > NextSymIdx) {
        SymbolRef::Type NextSymType;
        Symbols[NextSymIdx].getType(NextSymType);
        if (NextSymType == SymbolRef::ST_Function) {
          Sections[SectIdx].containsSymbol(Symbols[NextSymIdx],
                                           containsNextSym);
          Symbols[NextSymIdx].getAddress(NextSym);
          NextSym -= SectionAddress;
          break;
        }
        ++NextSymIdx;
      }

      uint64_t SectSize;
      Sections[SectIdx].getSize(SectSize);
      uint64_t End = containsNextSym ?  NextSym : SectSize;
      uint64_t Size;

      symbolTableWorked = true;

      if (!CFG) {
        // Normal disassembly, print addresses, bytes and mnemonic form.
        StringRef SymName;
        Symbols[SymIdx].getName(SymName);

        outs() << SymName << ":\n";
        DILineInfo lastLine;
        for (uint64_t Index = Start; Index < End; Index += Size) {
          MCInst Inst;

          if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
                                     DebugOut, nulls())) {
            uint64_t SectAddress = 0;
            Sections[SectIdx].getAddress(SectAddress);
            outs() << format("%8" PRIx64 ":\t", SectAddress + Index);

            DumpBytes(StringRef(Bytes.data() + Index, Size));
            IP->printInst(&Inst, outs(), "");

            // Print debug info.
            if (diContext) {
              DILineInfo dli =
                diContext->getLineInfoForAddress(SectAddress + Index);
              // Print valid line info if it changed.
              if (dli != lastLine && dli.getLine() != 0)
                outs() << "\t## " << dli.getFileName() << ':'
                       << dli.getLine() << ':' << dli.getColumn();
              lastLine = dli;
            }
            outs() << "\n";
          } else {
            errs() << "llvm-objdump: warning: invalid instruction encoding\n";
            if (Size == 0)
              Size = 1; // skip illegible bytes
          }
        }
      } else {
        // Create CFG and use it for disassembly.
        StringRef SymName;
        Symbols[SymIdx].getName(SymName);
        createMCFunctionAndSaveCalls(
            SymName, DisAsm.get(), memoryObject, Start, End,
            InstrAnalysis.get(), Start, DebugOut, FunctionMap, Functions);
      }
    }
    if (!CFG && !symbolTableWorked) {
      // Reading the symbol table didn't work, disassemble the whole section. 
      uint64_t SectAddress;
      Sections[SectIdx].getAddress(SectAddress);
      uint64_t SectSize;
      Sections[SectIdx].getSize(SectSize);
      uint64_t InstSize;
      for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
        MCInst Inst;

        if (DisAsm->getInstruction(Inst, InstSize, memoryObject, Index,
                                   DebugOut, nulls())) {
          outs() << format("%8" PRIx64 ":\t", SectAddress + Index);
          DumpBytes(StringRef(Bytes.data() + Index, InstSize));
          IP->printInst(&Inst, outs(), "");
          outs() << "\n";
        } else {
          errs() << "llvm-objdump: warning: invalid instruction encoding\n";
          if (InstSize == 0)
            InstSize = 1; // skip illegible bytes
        }
      }
    }

    if (CFG) {
      if (!symbolTableWorked) {
        // Reading the symbol table didn't work, create a big __TEXT symbol.
        uint64_t SectSize = 0, SectAddress = 0;
        Sections[SectIdx].getSize(SectSize);
        Sections[SectIdx].getAddress(SectAddress);
        createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject,
                                     0, SectSize,
                                     InstrAnalysis.get(),
                                     SectAddress, DebugOut,
                                     FunctionMap, Functions);
      }
      for (std::map<uint64_t, MCFunction*>::iterator mi = FunctionMap.begin(),
           me = FunctionMap.end(); mi != me; ++mi)
        if (mi->second == 0) {
          // Create functions for the remaining callees we have gathered,
          // but we didn't find a name for them.
          uint64_t SectSize = 0;
          Sections[SectIdx].getSize(SectSize);

          SmallVector<uint64_t, 16> Calls;
          MCFunction f =
            MCFunction::createFunctionFromMC("unknown", DisAsm.get(),
                                             memoryObject, mi->first,
                                             SectSize,
                                             InstrAnalysis.get(), DebugOut,
                                             Calls);
          Functions.push_back(f);
          mi->second = &Functions.back();
          for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
            std::pair<uint64_t, MCFunction*> p(Calls[i], (MCFunction*)0);
            if (FunctionMap.insert(p).second)
              mi = FunctionMap.begin();
          }
        }

      DenseSet<uint64_t> PrintedBlocks;
      for (unsigned ffi = 0, ffe = Functions.size(); ffi != ffe; ++ffi) {
        MCFunction &f = Functions[ffi];
        for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){
          if (!PrintedBlocks.insert(fi->first).second)
            continue; // We already printed this block.

          // We assume a block has predecessors when it's the first block after
          // a symbol.
          bool hasPreds = FunctionMap.find(fi->first) != FunctionMap.end();

          // See if this block has predecessors.
          // FIXME: Slow.
          for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe;
              ++pi)
            if (pi->second.contains(fi->first)) {
              hasPreds = true;
              break;
            }

          uint64_t SectSize = 0, SectAddress;
          Sections[SectIdx].getSize(SectSize);
          Sections[SectIdx].getAddress(SectAddress);

          // No predecessors, this is a data block. Print as .byte directives.
          if (!hasPreds) {
            uint64_t End = llvm::next(fi) == fe ? SectSize :
                                                  llvm::next(fi)->first;
            outs() << "# " << End-fi->first << " bytes of data:\n";
            for (unsigned pos = fi->first; pos != End; ++pos) {
              outs() << format("%8x:\t", SectAddress + pos);
              DumpBytes(StringRef(Bytes.data() + pos, 1));
              outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]);
            }
            continue;
          }

          if (fi->second.contains(fi->first)) // Print a header for simple loops
            outs() << "# Loop begin:\n";

          DILineInfo lastLine;
          // Walk over the instructions and print them.
          for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie;
               ++ii) {
            const MCDecodedInst &Inst = fi->second.getInsts()[ii];

            // If there's a symbol at this address, print its name.
            if (FunctionMap.find(SectAddress + Inst.Address) !=
                FunctionMap.end())
              outs() << FunctionMap[SectAddress + Inst.Address]-> getName()
                     << ":\n";

            outs() << format("%8" PRIx64 ":\t", SectAddress + Inst.Address);
            DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size));

            if (fi->second.contains(fi->first)) // Indent simple loops.
              outs() << '\t';

            IP->printInst(&Inst.Inst, outs(), "");

            // Look for relocations inside this instructions, if there is one
            // print its target and additional information if available.
            for (unsigned j = 0; j != Relocs.size(); ++j)
              if (Relocs[j].first >= SectAddress + Inst.Address &&
                  Relocs[j].first < SectAddress + Inst.Address + Inst.Size) {
                StringRef SymName;
                uint64_t Addr;
                Relocs[j].second.getAddress(Addr);
                Relocs[j].second.getName(SymName);

                outs() << "\t# " << SymName << ' ';
                DumpAddress(Addr, Sections, MachOObj, outs());
              }

            // If this instructions contains an address, see if we can evaluate
            // it and print additional information.
            uint64_t targ = InstrAnalysis->evaluateBranch(Inst.Inst,
                                                          Inst.Address,
                                                          Inst.Size);
            if (targ != -1ULL)
              DumpAddress(targ, Sections, MachOObj, outs());

            // Print debug info.
            if (diContext) {
              DILineInfo dli =
                diContext->getLineInfoForAddress(SectAddress + Inst.Address);
              // Print valid line info if it changed.
              if (dli != lastLine && dli.getLine() != 0)
                outs() << "\t## " << dli.getFileName() << ':'
                       << dli.getLine() << ':' << dli.getColumn();
              lastLine = dli;
            }

            outs() << '\n';
          }
        }

        emitDOTFile((f.getName().str() + ".dot").c_str(), f, IP.get());
      }
    }
  }
}
Ejemplo n.º 23
0
int main(int argc, char** argv, char** envp)
{
	if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
	{
		printHelp(argv[0]);
		return 1;
	}
	
	if (!HasUserDirectoryStructure())
		SetupUserDirectoryStructure();

	std::set_terminate(terminateHandler);

	sigset_t set;
	sigemptyset(&set);
	sigaddset(&set, SIGHUP);
	sigprocmask(SIG_BLOCK, &set, NULL);

	try
	{
		MachOObject* obj;
		MachOMgr* mgr = MachOMgr::instance();
		std::string executable;

		executable = locateBundleExecutable(argv[1]);
		argv[1] = const_cast<char*>(executable.c_str());

		mgr->detectSysRootFromPath(argv[1]);

		mgr->setPrintInitializers(getenv("DYLD_PRINT_INITIALIZERS") != nullptr);
		mgr->setPrintLibraries(getenv("DYLD_PRINT_LIBRARIES") != nullptr);
#ifdef __arm__ // dyld_stub_binder hasn't been ported to ARM yet
		mgr->setBindAtLaunch(true);
#else
		mgr->setBindAtLaunch(getenv("DYLD_BIND_AT_LAUNCH") != nullptr);
#endif
		mgr->setIgnoreMissingSymbols(getenv("DYLD_IGN_MISSING_SYMS") != nullptr);
		mgr->setPrintSegments(getenv("DYLD_PRINT_SEGMENTS") != nullptr);
		mgr->setPrintBindings(getenv("DYLD_PRINT_BINDINGS") != nullptr);
		mgr->setPrintRpathExpansion(getenv("DYLD_PRINT_RPATHS") != nullptr);

		if (const char* path = getenv("DYLD_LIBRARY_PATH"))
			mgr->setLibraryPath(path);
		if (const char* path = getenv("DYLD_ROOT_PATH"))
			mgr->setSysRoot(path);
		if (const char* path = getenv("DYLD_TRAMPOLINE"))
			mgr->setUseTrampolines(true, path);
		
		obj = new MachOObject(argv[1]);
		if (!obj->isMainModule())
			throw std::runtime_error("Not an MH_EXECUTE file");
		
		obj->setCommandLine(argc-1, &argv[1], envp);

		obj->load();
		obj->run();
	}
	catch (const std::exception& e)
	{
		std::cerr << "dyld: Cannot execute binary file: " << e.what() << std::endl;
		return ENOSYS;
	}
}
Ejemplo n.º 24
0
int main(int argc, char** argv, char** envp)
{
	if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
	{
		printHelp(argv[0]);
		return 1;
	}
	
	if (!HasUserDirectoryStructure())
		SetupUserDirectoryStructure();

	try
	{
		MachOMgr* mgr = MachOMgr::instance();
		std::string executable, unprefixed_argv0;
		const char* pretendArgv0;
		
		pretendArgv0 = findFakeArgv0(argv[1]);

		executable = locateBundleExecutable(argv[1]);
		argv[1] = const_cast<char*>(executable.c_str());

		mgr->detectSysRootFromPath(argv[1]);

		mgr->setPrintInitializers(getenv("DYLD_PRINT_INITIALIZERS") != nullptr);
		mgr->setPrintLibraries(getenv("DYLD_PRINT_LIBRARIES") != nullptr);
#ifdef __arm__ // dyld_stub_binder hasn't been ported to ARM yet
		mgr->setBindAtLaunch(true);
#else
		mgr->setBindAtLaunch(getenv("DYLD_BIND_AT_LAUNCH") != nullptr);
#endif
		mgr->setIgnoreMissingSymbols(getenv("DYLD_IGN_MISSING_SYMS") != nullptr);
		// mgr->setIgnoreMissingDependencies(getenv("DYLD_IGN_MISSING_DEPS") != nullptr);
		mgr->setPrintSegments(getenv("DYLD_PRINT_SEGMENTS") != nullptr);
		mgr->setPrintBindings(getenv("DYLD_PRINT_BINDINGS") != nullptr);
		mgr->setPrintRpathExpansion(getenv("DYLD_PRINT_RPATHS") != nullptr);
		mgr->setForceFlatNamespace(getenv("DYLD_FORCE_FLAT_NAMESPACE") != nullptr);

		if (const char* path = getenv("DYLD_LIBRARY_PATH"))
			mgr->setLibraryPath(path);
		if (const char* path = getenv("DYLD_ROOT_PATH"))
			mgr->setSysRoot(path);
		if (const char* path = getenv("DYLD_TRAMPOLINE"))
			mgr->setUseTrampolines(true, path);
		if (const char* path = getenv("DPREFIX"))
		{
			__prefix_set(path);
			unprefixed_argv0 = __prefix_untranslate_path(argv[1], strlen(argv[1]));
		}
		
		if (getenv("DYLD_GDBJIT") != nullptr)
			Darling::SetupGDBJIT();

		if (isELF(argv[1]))
		{
			NativeObject* obj;
			typedef int (mainPtr)(int argc, char** argv, char** envp);
			mainPtr* main;

			obj = new NativeObject(argv[1]);
			obj->load();
			NativeObject::setMainObject(obj);

			main = (mainPtr*) obj->getExportedSymbol("main", false);

			if (!main)
				throw std::runtime_error("No entry point found in Darling-native executable");

			if (pretendArgv0 != nullptr)
				argv[1] = (char*) pretendArgv0;
			else if (!unprefixed_argv0.empty())
				argv[1] = (char*) unprefixed_argv0.c_str();
			exit(main(argc-1, &argv[1], envp));
		}
		else
		{
			MachOObject* obj;
			
			if (::mmap(0, 4096, PROT_READ|PROT_EXEC, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) != 0)
			{
				if (errno == EPERM)
				{
					std::cerr << "Cannot map page zero, some macOS apps may require this.\n";
					std::cerr << "This problem can be fixed by running 'setcap cap_sys_rawio=ep " << pathToSelf() << "' as root.\n";
				}
			}

			obj = new MachOObject(argv[1]);
			if (!obj->isMainModule())
			{
				throw std::runtime_error("This is not a Mach-O executable; dynamic libraries, "
				"kernel extensions and other Mach-O files cannot be executed with dyld");
			}
		
			if (pretendArgv0 != nullptr)
				argv[1] = (char*) pretendArgv0;
			else if (!unprefixed_argv0.empty())
				argv[1] = (char*) unprefixed_argv0.c_str();
			
			obj->setCommandLine(argc-1, &argv[1], envp);

			obj->load();
			obj->run();
		}
	}
	catch (const std::exception& e)
	{
		std::cerr << "dyld: Cannot execute binary file: " << e.what() << std::endl;
		return ENOSYS;
	}
}
Ejemplo n.º 25
0
std::string DylibSearch::resolve(std::string dylib, MachOObject* requester)
{
	if (dylib.empty())
		return std::string();

	// expand @rpath, @executable_path and @loader_path
	if (requester != nullptr && dylib[0] == '@')
	{
		if (dylib.compare(0, 16, "@executable_path") == 0)
		{
			MachOObject* mainModule = MachOMgr::instance()->mainModule();
			
			if (!mainModule)
				throw std::runtime_error("Cannot resolve @executable_path without a main module");
			
			dylib.replace(0, 16, mainModule->directory());
		}
		else if (dylib.compare(0, 12, "@loader_path") == 0)
		{
			dylib.replace(0, 12, requester->directory());
		}
		else if (dylib.compare(0, 6, "@rpath") == 0)
		{
			return resolveViaRpath(dylib, requester);
		}
	}
	
	// Search in configuration
	if (const char* aliasTarget = resolveAlias(dylib))
	{
		std::string p;
		
		if (!strchr(aliasTarget, '/'))
		{
			p = LIB_PATH;
			p += '/';
			p += aliasTarget;
			// std::cout << p << std::endl;
		}
		
		return p;
	}
	
	// Search in extra paths
	std::string epath;
	epath = resolveInPathList(dylib, m_extraPaths);
	if (!epath.empty())
		return epath;
	
	// Search in DYLD_LIBRARY_PATH
	epath = resolveInLdPath(dylib);
	if (!epath.empty())
		return epath;
	
	// Try the path as is
	epath = checkPresence(dylib);
	if (!epath.empty())
		return epath;

	// If absolute, search in sysroot
	if (dylib[0] == '/')
	{
		const char* prefix = __prefix_get();
		
		if (!MachOMgr::instance()->sysRoot().empty())
		{
			std::vector<std::string> roots = string_explode(MachOMgr::instance()->sysRoot(), ':');

			for (const std::string& in_path : roots)
			{
				std::string path;
				
				if (prefix != nullptr)
					path = prefix;
				
				path += in_path;
				path += '/';
				path += dylib;

				epath = checkPresence(path);
				if (!epath.empty())
					return epath;
			}
		}
		if (prefix != nullptr)
		{
			std::string path = prefix;
			path += dylib;
			
			epath = checkPresence(path);
			if (!epath.empty())
				return epath;
		}
	}
	
	/*if (MachOMgr::instance()->ignoreMissingDependencies())
	{
		
	}*/

	return std::string();
}
Ejemplo n.º 26
0
StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const {
  InMemoryStruct<macho::SymbolTableEntry> Entry;
  getSymbolTableEntry(DRI, Entry);
  return MachOObj->getStringAtIndex(Entry->StringIndex);
}