From da2a2372c6ae715befae7f086afe769dd80814f3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 13 Apr 2013 01:45:40 +0000 Subject: Finish templating MachObjectFile over endianness. We are now able to handle big endian macho files in llvm-readobject. Thanks to David Fang for providing the object files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179440 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 432 ++--------------------------------------- 1 file changed, 15 insertions(+), 417 deletions(-) (limited to 'lib/Object') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 627e7485a6..192e7555b4 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -29,30 +29,14 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits, +MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, + bool IsLittleEndian, bool Is64bits, error_code &ec) - : ObjectFile(getMachOType(true, Is64bits), Object) { + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) { } bool MachOObjectFileBase::is64Bit() const { - return isa(this); -} - -const MachOObjectFileBase::LoadCommand * -MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const { - uint64_t Offset; - uint64_t NewOffset = getHeaderSize(); - const LoadCommand *Load; - unsigned I = 0; - do { - Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(LoadCommand)); - Load = reinterpret_cast(Data.data()); - NewOffset = Offset + Load->Size; - ++I; - } while (I != Index + 1); - - return Load; + return isa(this) || isa(this); } void MachOObjectFileBase::ReadULEB128s(uint64_t Index, @@ -67,11 +51,6 @@ void MachOObjectFileBase::ReadULEB128s(uint64_t Index, } } -const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const { - StringRef Data = getData(0, sizeof(Header)); - return reinterpret_cast(Data.data()); -} - unsigned MachOObjectFileBase::getHeaderSize() const { return is64Bit() ? macho::Header64Size : macho::Header32Size; } @@ -80,55 +59,21 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } -const MachOObjectFileBase::RelocationEntry * -MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { - if (const MachOObjectFile32Le *O = dyn_cast(this)) - return O->getRelocation(Rel); - const MachOObjectFile64Le *O = dyn_cast(this); - return O->getRelocation(Rel); -} - -bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { - unsigned Arch = getArch(); - return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); -} - -bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->getPCRel(); - } - return RE->getPCRel(); -} - -unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->getLength(); - } - return RE->getLength(); -} - -unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->getType(); - } - return RE->getType(); -} - ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; - bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE"; ObjectFile *Ret; - if (Is64Bits) - Ret = new MachOObjectFile64Le(Buffer, ec); + if (Magic == "\xFE\xED\xFA\xCE") + Ret = new MachOObjectFileBE32(Buffer, ec); + else if (Magic == "\xCE\xFA\xED\xFE") + Ret = new MachOObjectFileLE32(Buffer, ec); + else if (Magic == "\xFE\xED\xFA\xCF") + Ret = new MachOObjectFileBE64(Buffer, ec); + else if (Magic == "\xCF\xFA\xED\xFE") + Ret = new MachOObjectFileLE64(Buffer, ec); else - Ret = new MachOObjectFile32Le(Buffer, ec); + return NULL; + if (ec) return NULL; return Ret; @@ -136,183 +81,11 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ -void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - if (Command->Type == macho::LCT_Symtab) { - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); - if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -const MachOObjectFileBase::SymbolTableEntryBase * -MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); - return getSymbolTableEntryBase(DRI, SymtabLoadCmd); -} - -const MachOObjectFileBase::SymbolTableEntryBase * -MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, - const SymtabLoadCommand *SymtabLoadCmd) const { - uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; - unsigned Index = DRI.d.b; - - unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOObjectFile64Le::SymbolTableEntry) : - sizeof(MachOObjectFile32Le::SymbolTableEntry); - - uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; - StringRef Data = getData(Offset, SymbolTableEntrySize); - return reinterpret_cast(Data.data()); -} - -error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI, - SymbolRef &Result) const { - DRI.d.b++; - moveToNextSymbol(DRI); - Result = SymbolRef(DRI, this); - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI, - StringRef &Result) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); - - StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, - SymtabLoadCmd->StringTableSize); - - const SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(DRI, SymtabLoadCmd); - uint32_t StringIndex = Entry->StringIndex; - - const char *Start = &StringTable.data()[StringIndex]; - Result = StringRef(Start); - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI, - char &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - uint8_t Type = Entry->Type; - uint16_t Flags = Entry->Flags; - - char Char; - switch (Type & macho::STF_TypeMask) { - case macho::STT_Undefined: - Char = 'u'; - break; - case macho::STT_Absolute: - case macho::STT_Section: - Char = 's'; - break; - default: - Char = '?'; - break; - } - - if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) - Char = toupper(static_cast(Char)); - Result = Char; - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - uint8_t MachOType = Entry->Type; - uint16_t MachOFlags = Entry->Flags; - - // TODO: Correctly set SF_ThreadLocal - Result = SymbolRef::SF_None; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Undefined; - - if (MachOFlags & macho::STF_StabsEntryMask) - Result |= SymbolRef::SF_FormatSpecific; - - if (MachOType & MachO::NlistMaskExternal) { - Result |= SymbolRef::SF_Global; - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Common; - } - - if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) - Result |= SymbolRef::SF_Weak; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) - Result |= SymbolRef::SF_Absolute; - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t index = Entry->SectionIndex; - - if (index == 0) - Res = end_sections(); - else - Res = section_iterator(SectionRef(Sections[index-1], this)); - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t n_type = Entry->Type; - - Res = SymbolRef::ST_Other; - - // If this is a STAB debugging symbol, we can do nothing more. - if (n_type & MachO::NlistMaskStab) { - Res = SymbolRef::ST_Debug; - return object_error::success; - } - - switch (n_type & MachO::NlistMaskType) { - case MachO::NListTypeUndefined : - Res = SymbolRef::ST_Unknown; - break; - case MachO::NListTypeSection : - Res = SymbolRef::ST_Function; - break; - } - return object_error::success; -} - error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb, uint64_t &Val) const { report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFileBase::begin_symbols() const { - // DRI.d.a = segment number; DRI.d.b = symbol index. - DataRefImpl DRI; - moveToNextSymbol(DRI); - return symbol_iterator(SymbolRef(DRI, this)); -} - -symbol_iterator MachOObjectFileBase::end_symbols() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return symbol_iterator(SymbolRef(DRI, this)); -} - symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const { // TODO: implement report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); @@ -347,23 +120,7 @@ std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } -const MachOObjectFileBase::SectionBase* -MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - uintptr_t CommandAddr = reinterpret_cast(Command); - - bool Is64 = is64Bit(); - unsigned SegmentLoadSize = - Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) : - sizeof(MachOObjectFile32Le::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) : - sizeof(MachOObjectFile32Le::Section); - - uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast(SectionAddr); -} - -static StringRef parseSegmentOrSectionName(const char *P) { +StringRef MachOObjectFileBase::parseSegmentOrSectionName(const char *P) const { if (P[15] == 0) // Null terminated. return P; @@ -371,30 +128,6 @@ static StringRef parseSegmentOrSectionName(const char *P) { return StringRef(P, 16); } -ArrayRef MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const { - const SectionBase *Base = getSectionBase(DRI); - return ArrayRef(Base->Name); -} - -error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI, - StringRef &Result) const { - ArrayRef Raw = getSectionRawName(DRI); - Result = parseSegmentOrSectionName(Raw.data()); - return object_error::success; -} - -ArrayRef -MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef(Base->SegmentName); -} - -StringRef -MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const { - ArrayRef Raw = getSectionRawFinalSegmentName(DRI); - return parseSegmentOrSectionName(Raw.data()); -} - error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. @@ -441,11 +174,6 @@ relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) con return relocation_iterator(RelocationRef(ret, this)); } -section_iterator MachOObjectFileBase::end_sections() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return section_iterator(SectionRef(DRI, this)); -} /*===-- Relocations -------------------------------------------------------===*/ @@ -456,88 +184,6 @@ error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel, return object_error::success; } -// Helper to advance a section or symbol iterator multiple increments at a time. -template -error_code advance(T &it, size_t Val) { - error_code ec; - while (Val--) { - it.increment(ec); - } - return ec; -} - -template -void advanceTo(T &it, size_t Val) { - if (error_code ec = advance(it, Val)) - report_fatal_error(ec.message()); -} - -void -MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const { - // Target of a scattered relocation is an address. In the interest of - // generating pretty output, scan through the symbol table looking for a - // symbol that aligns with that address. If we find one, print it. - // Otherwise, we just print the hex address of the target. - if (isScattered(RE)) { - uint32_t Val = RE->SymbolNum; - - error_code ec; - for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - // If we couldn't find a symbol that this relocation refers to, try - // to find a section beginning instead. - for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = RE->getExternal(); - uint32_t Val = RE->Address; - - if (isExtern) { - symbol_iterator SI = begin_symbols(); - advanceTo(SI, Val); - SI->getName(S); - } else { - section_iterator SI = begin_sections(); - advanceTo(SI, Val); - SI->getName(S); - } - - fmt << S; -} - error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); @@ -561,53 +207,5 @@ uint8_t MachOObjectFileBase::getBytesInAddress() const { return is64Bit() ? 8 : 4; } -StringRef MachOObjectFileBase::getFileFormatName() const { - if (!is64Bit()) { - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeI386: - return "Mach-O 32-bit i386"; - case llvm::MachO::CPUTypeARM: - return "Mach-O arm"; - case llvm::MachO::CPUTypePowerPC: - return "Mach-O 32-bit ppc"; - default: - assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 && - "64-bit object file when we're not 64-bit?"); - return "Mach-O 32-bit unknown"; - } - } - - // Make sure the cpu type has the correct mask. - assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) - == llvm::MachO::CPUArchABI64 && - "32-bit object file when we're 64-bit?"); - - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeX86_64: - return "Mach-O 64-bit x86-64"; - case llvm::MachO::CPUTypePowerPC64: - return "Mach-O 64-bit ppc64"; - default: - return "Mach-O 64-bit unknown"; - } -} - -unsigned MachOObjectFileBase::getArch() const { - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeI386: - return Triple::x86; - case llvm::MachO::CPUTypeX86_64: - return Triple::x86_64; - case llvm::MachO::CPUTypeARM: - return Triple::arm; - case llvm::MachO::CPUTypePowerPC: - return Triple::ppc; - case llvm::MachO::CPUTypePowerPC64: - return Triple::ppc64; - default: - return Triple::UnknownArch; - } -} - } // end namespace object } // end namespace llvm -- cgit v1.2.3-18-g5258