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 --- include/llvm/Object/MachO.h | 783 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 677 insertions(+), 106 deletions(-) (limited to 'include/llvm/Object/MachO.h') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 9b7a07372d..33e10ffbbd 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -20,7 +20,9 @@ #include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" @@ -35,6 +37,25 @@ struct MachOType { static const bool Is64Bits = B; }; +template +struct MachOInt24Impl; + +template<> +struct MachOInt24Impl { + uint8_t bytes[3]; + operator uint32_t() const { + return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; + } +}; + +template<> +struct MachOInt24Impl { + uint8_t bytes[3]; + operator uint32_t() const { + return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2]; + } +}; + template struct MachODataTypeTypedefHelperCommon { typedef support::detail::packed_endian_specific_integral @@ -43,12 +64,14 @@ struct MachODataTypeTypedefHelperCommon { MachOInt32; typedef support::detail::packed_endian_specific_integral MachOInt64; + typedef MachOInt24Impl MachOInt24; }; #define LLVM_MACHOB_IMPORT_TYPES(E) \ typedef typename MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \ typedef typename MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \ -typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; +typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; \ +typedef typename MachODataTypeTypedefHelperCommon::MachOInt24 MachOInt24; template struct MachODataTypeTypedefHelper; @@ -120,8 +143,11 @@ namespace MachOFormat { }; template - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + struct RelocationEntry; + + template<> + struct RelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::little) MachOInt32 Address; MachOInt24 SymbolNum; uint8_t Bits; @@ -140,9 +166,33 @@ namespace MachOFormat { } }; + template<> + struct RelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::big) + MachOInt32 Address; + MachOInt24 SymbolNum; + uint8_t Bits; + + unsigned getType() const { + return Bits &0xf; + } + unsigned getExternal() const { + return (Bits >> 4) & 0x1; + } + unsigned getLength() const { + return (Bits >> 5) & 0x3; + } + unsigned getPCRel() const { + return Bits >> 7; + } + }; + template - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + struct ScatteredRelocationEntry; + + template<> + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::little) MachOInt24 Address; uint8_t Bits; MachOInt32 Value; @@ -161,6 +211,26 @@ namespace MachOFormat { } }; + template<> + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::big) + uint8_t Bits; + unsigned getType() const { + return Bits & 0xf; + } + unsigned getLength() const { + return (Bits >> 4) & 0x3; + } + unsigned getPCRel() const { + return (Bits >> 6) & 0x1; + } + unsigned getScattered() const { + return Bits >> 7; + } + MachOInt24 Address; + MachOInt32 Value; + }; + template struct SymbolTableEntryBase { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) @@ -244,69 +314,32 @@ namespace MachOFormat { class MachOObjectFileBase : public ObjectFile { public: - typedef MachOFormat::SymbolTableEntryBase - SymbolTableEntryBase; - typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; - typedef MachOFormat::RelocationEntry RelocationEntry; - typedef MachOFormat::ScatteredRelocationEntry - ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; - typedef MachOFormat::LoadCommand LoadCommand; - typedef MachOFormat::Header Header; - typedef MachOFormat::LinkeditDataLoadCommand - LinkeditDataLoadCommand; - MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); + MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; virtual symbol_iterator begin_dynamic_symbols() const; virtual symbol_iterator end_dynamic_symbols() const; virtual library_iterator begin_libraries_needed() const; virtual library_iterator end_libraries_needed() const; - virtual section_iterator end_sections() const; virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; virtual StringRef getLoadName() const; - // In a MachO file, sections have a segment name. This is used in the .o - // files. They have a single segment, but this field specifies which segment - // a section should be put in in the final object. - StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; - - // Names are stored as 16 bytes. These returns the raw 16 bytes without - // interpreting them as a C string. - ArrayRef getSectionRawName(DataRefImpl Sec) const; - ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; - bool is64Bit() const; - const LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; - bool isScattered(const RelocationEntry *RE) const; - bool isPCRel(const RelocationEntry *RE) const; - unsigned getLength(const RelocationEntry *RE) const; - unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); } protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; + StringRef parseSegmentOrSectionName(const char *P) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, @@ -327,17 +360,75 @@ protected: typedef SmallVector SectionList; SectionList Sections; +}; + +template +class MachOObjectFileMiddle : public MachOObjectFileBase { +public: + + typedef MachOFormat::SymbolTableEntryBase + SymbolTableEntryBase; + typedef MachOFormat::LinkeditDataLoadCommand + LinkeditDataLoadCommand; + typedef MachOFormat::Header Header; + typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; + typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry + ScatteredRelocationEntry; + typedef MachOFormat::LoadCommand LoadCommand; + + MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec); + + const Header *getHeader() const; + const LoadCommand *getLoadCommandInfo(unsigned Index) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + bool isRelocationScattered(const RelocationEntry *RE) const; + bool isRelocationPCRel(const RelocationEntry *RE) const; + unsigned getRelocationLength(const RelocationEntry *RE) const; + unsigned getRelocationTypeImpl(const RelocationEntry *RE) const; void moveToNextSymbol(DataRefImpl &DRI) const; void printRelocationTargetName(const RelocationEntry *RE, raw_string_ostream &fmt) const; const SectionBase *getSectionBase(DataRefImpl DRI) const; const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const; + unsigned getCPUType() const; + + // In a MachO file, sections have a segment name. This is used in the .o + // files. They have a single segment, but this field specifies which segment + // a section should be put in in the final object. + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; + + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef getSectionRawName(DataRefImpl Sec) const; + ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const; + + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual symbol_iterator begin_symbols() const; + virtual unsigned getArch() const; + virtual StringRef getFileFormatName() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator end_sections() const; + + static bool classof(const Binary *v); private: + // Helper to advance a section or symbol iterator multiple increments at a + // time. + template + static error_code advance(T &it, size_t Val); - const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI, - const SymtabLoadCommand *SymtabLoadCmd) const; + template + static void advanceTo(T &it, size_t Val); }; template @@ -369,11 +460,17 @@ struct MachOObjectFileHelper > : }; template -class MachOObjectFile : public MachOObjectFileBase { +class MachOObjectFile : public MachOObjectFileMiddle { public: static const endianness TargetEndianness = MachOT::TargetEndianness; static const bool Is64Bits = MachOT::Is64Bits; + typedef MachOObjectFileMiddle Base; + typedef typename Base::RelocationEntry RelocationEntry; + typedef typename Base::SectionBase SectionBase; + typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase; + typedef typename Base::LoadCommand LoadCommand; + typedef MachOObjectFileHelper Helper; static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType; typedef typename Helper::SegmentLoadCommand SegmentLoadCommand; @@ -413,15 +510,491 @@ public: void moveToNextSection(DataRefImpl &DRI) const; }; +typedef MachOObjectFileMiddle MachOObjectFileLE; +typedef MachOObjectFileMiddle MachOObjectFileBE; + +typedef MachOObjectFile > + MachOObjectFileLE32; +typedef MachOObjectFile > + MachOObjectFileBE32; +typedef MachOObjectFile > + MachOObjectFileLE64; +typedef MachOObjectFile > + MachOObjectFileBE64; + +template +MachOObjectFileMiddle::MachOObjectFileMiddle(MemoryBuffer *O, + bool Is64Bits, + error_code &ec) : + MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) { +} + +template +const typename MachOObjectFileMiddle::SymbolTableEntryBase * +MachOObjectFileMiddle::getSymbolTableEntryBase(DataRefImpl DRI) const { + const LoadCommand *L = getLoadCommandInfo(DRI.d.a); + const SymtabLoadCommand *S = reinterpret_cast(L); + + unsigned Index = DRI.d.b; + + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(MachOObjectFileLE64::SymbolTableEntry) : + sizeof(MachOObjectFileLE32::SymbolTableEntry); + + uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize; + StringRef Data = getData(Offset, SymbolTableEntrySize); + return reinterpret_cast(Data.data()); +} + +template +const typename MachOObjectFileMiddle::Header * +MachOObjectFileMiddle::getHeader() const { + StringRef Data = getData(0, sizeof(Header)); + return reinterpret_cast(Data.data()); +} + +template +const typename MachOObjectFileMiddle::LoadCommand * +MachOObjectFileMiddle::getLoadCommandInfo(unsigned Index) const { + assert(Index < getHeader()->NumLoadCommands); + uint64_t Offset; + uint64_t NewOffset = getHeaderSize(); + const LoadCommand *Load; + unsigned I = 0; + do { + Offset = NewOffset; + StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand)); + Load = reinterpret_cast(Data.data()); + NewOffset = Offset + Load->Size; + ++I; + } while (I != Index + 1); + + return reinterpret_cast(Load); +} + +template +const typename MachOObjectFileMiddle::RelocationEntry * +MachOObjectFileMiddle::getRelocation(DataRefImpl Rel) const { + if (const MachOObjectFile > *O = + dyn_cast > >(this)) + return O->getRelocation(Rel); + + const MachOObjectFile > *O = + cast > >(this); + return O->getRelocation(Rel); +} + +template +bool +MachOObjectFileMiddle::isRelocationScattered(const RelocationEntry *RE) + const { + if (this->getCPUType() == llvm::MachO::CPUTypeX86_64) + return false; + return RE->Address & macho::RF_Scattered; +} + +template +bool +MachOObjectFileMiddle::isRelocationPCRel(const RelocationEntry *RE) const { + typedef MachOObjectFileMiddle ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getPCRel(); + } + return RE->getPCRel(); +} + +template +unsigned +MachOObjectFileMiddle::getRelocationLength(const RelocationEntry *RE) const { + typedef MachOObjectFileMiddle ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getLength(); + } + return RE->getLength(); +} + +template +unsigned +MachOObjectFileMiddle::getRelocationTypeImpl(const RelocationEntry *RE) + const { + typedef MachOObjectFileMiddle ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getType(); + } + return RE->getType(); +} + +// Helper to advance a section or symbol iterator multiple increments at a time. +template +template +error_code MachOObjectFileMiddle::advance(T &it, size_t Val) { + error_code ec; + while (Val--) { + it.increment(ec); + } + return ec; +} + +template +template +void MachOObjectFileMiddle::advanceTo(T &it, size_t Val) { + if (error_code ec = advance(it, Val)) + report_fatal_error(ec.message()); +} + +template +void +MachOObjectFileMiddle::printRelocationTargetName(const RelocationEntry *RE, + raw_string_ostream &fmt) const { + bool IsScattered = isRelocationScattered(RE); + + // 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) { + 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(); + uint64_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; +} + +template +const typename MachOObjectFileMiddle::SectionBase * +MachOObjectFileMiddle::getSectionBase(DataRefImpl DRI) const { + uintptr_t CommandAddr = + reinterpret_cast(getLoadCommandInfo(DRI.d.a)); + + bool Is64 = is64Bit(); + unsigned SegmentLoadSize = + Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) : + sizeof(MachOObjectFileLE32::SegmentLoadCommand); + unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) : + sizeof(MachOObjectFileLE32::Section); + + uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; + return reinterpret_cast(SectionAddr); +} + +template +unsigned MachOObjectFileMiddle::getCPUType() const { + return getHeader()->CPUType; +} + +template +void MachOObjectFileMiddle::moveToNextSymbol(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + const LoadCommand *L = getLoadCommandInfo(DRI.d.a); + if (L->Type == macho::LCT_Symtab) { + const SymtabLoadCommand *S = + reinterpret_cast(L); + if (DRI.d.b < S->NumSymbolTableEntries) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + +template +StringRef +MachOObjectFileMiddle::getSectionFinalSegmentName(DataRefImpl Sec) const { + ArrayRef Raw = getSectionRawFinalSegmentName(Sec); + return parseSegmentOrSectionName(Raw.data()); +} + +template +ArrayRef +MachOObjectFileMiddle::getSectionRawName(DataRefImpl Sec) const { + const SectionBase *Base = getSectionBase(Sec); + return ArrayRef(Base->Name); +} + +template +ArrayRef +MachOObjectFileMiddle::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + const SectionBase *Base = getSectionBase(Sec); + return ArrayRef(Base->SegmentName); +} + +template +error_code MachOObjectFileMiddle::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; +} + +template +error_code MachOObjectFileMiddle::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; +} + +template +error_code MachOObjectFileMiddle::getSymbolName(DataRefImpl Symb, + StringRef &Res) const { + const LoadCommand *L = getLoadCommandInfo(Symb.d.a); + const SymtabLoadCommand *S = reinterpret_cast(L); + StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize); + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + const char *Start = &StringTable.data()[Entry->StringIndex]; + Res = StringRef(Start); + return object_error::success; +} + +template +error_code +MachOObjectFileMiddle::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; +} + + +template +error_code MachOObjectFileMiddle::getSymbolNMTypeChar(DataRefImpl Symb, + char &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + 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)); + Res = Char; + return object_error::success; +} + +template +error_code +MachOObjectFileMiddle::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ArrayRef Raw = getSectionRawName(Sec); + Result = parseSegmentOrSectionName(Raw.data()); + return object_error::success; +} + +template +error_code MachOObjectFileMiddle::getSymbolNext(DataRefImpl Symb, + SymbolRef &Res) const { + Symb.d.b++; + moveToNextSymbol(Symb); + Res = SymbolRef(Symb, this); + return object_error::success; +} + +template +symbol_iterator MachOObjectFileMiddle::begin_symbols() const { + // DRI.d.a = segment number; DRI.d.b = symbol index. + DataRefImpl DRI; + moveToNextSymbol(DRI); + return symbol_iterator(SymbolRef(DRI, this)); +} + +template +unsigned MachOObjectFileMiddle::getArch() const { + switch (getCPUType()) { + 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; + } +} + +template +StringRef MachOObjectFileMiddle::getFileFormatName() const { + unsigned CPUType = getCPUType(); + if (!is64Bit()) { + switch (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((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((CPUType & llvm::MachO::CPUArchABI64) + == llvm::MachO::CPUArchABI64 && + "32-bit object file when we're 64-bit?"); + + switch (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"; + } +} + +template +symbol_iterator MachOObjectFileMiddle::end_symbols() const { + DataRefImpl DRI; + DRI.d.a = getHeader()->NumLoadCommands; + return symbol_iterator(SymbolRef(DRI, this)); +} + +template +section_iterator MachOObjectFileMiddle::end_sections() const { + DataRefImpl DRI; + DRI.d.a = getHeader()->NumLoadCommands; + return section_iterator(SectionRef(DRI, this)); +} + +template +bool MachOObjectFileMiddle::classof(const Binary *v) { + return isa > >(v) || + isa > >(v); +} + template MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) : - MachOObjectFileBase(Object, Is64Bits, ec) { + MachOObjectFileMiddle(Object, Is64Bits, ec) { DataRefImpl DRI; moveToNextSection(DRI); - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - Sections.push_back(DRI); + this->Sections.push_back(DRI); DRI.d.b++; moveToNextSection(DRI); } @@ -429,30 +1002,31 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, template bool MachOObjectFile::classof(const Binary *v) { - return v->getType() == getMachOType(true, Is64Bits); + return v->getType() == + Base::getMachOType(TargetEndianness == support::little, Is64Bits); } template const typename MachOObjectFile::Section * MachOObjectFile::getSection(DataRefImpl DRI) const { - const SectionBase *Addr = getSectionBase(DRI); + const SectionBase *Addr = this->getSectionBase(DRI); return reinterpret_cast(Addr); } template const typename MachOObjectFile::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI); return reinterpret_cast(Base); } template const typename MachOObjectFile::RelocationEntry * MachOObjectFile::getRelocation(DataRefImpl Rel) const { - const Section *Sect = getSection(Sections[Rel.d.b]); + const Section *Sect = getSection(this->Sections[Rel.d.b]); uint32_t RelOffset = Sect->RelocationTableOffset; uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); - StringRef Data = getData(Offset, sizeof(RelocationEntry)); + StringRef Data = this->getData(Offset, sizeof(RelocationEntry)); return reinterpret_cast(Data.data()); } @@ -479,7 +1053,7 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { const Section *Sect = getSection(Sec); - Res = getData(Sect->Offset, Sect->Size); + Res = this->getData(Sect->Offset, Sect->Size); return object_error::success; } @@ -517,7 +1091,7 @@ MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t LastReloc = Sect->NumRelocationTableEntries; DataRefImpl Ret; Ret.d.a = LastReloc; - Ret.d.b = getSectionIndex(Sec); + Ret.d.b = this->getSectionIndex(Sec); return relocation_iterator(RelocationRef(Ret, this)); } @@ -525,12 +1099,12 @@ template error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { - const Section *Sect = getSection(Sections[Rel.d.b]); + const Section *Sect = getSection(this->Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); uint64_t RelAddr; - if (isScattered(RE)) + if (this->isRelocationScattered(RE)) RelAddr = RE->Address & 0xFFFFFF; else RelAddr = RE->Address; @@ -544,7 +1118,7 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - if (isScattered(RE)) + if (this->isRelocationScattered(RE)) Res = RE->Address & 0xFFFFFF; else Res = RE->Address; @@ -560,12 +1134,12 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, bool isExtern = RE->getExternal(); DataRefImpl Sym; - moveToNextSymbol(Sym); + this->moveToNextSymbol(Sym); if (isExtern) { for (unsigned i = 0; i < SymbolIdx; i++) { Sym.d.b++; - moveToNextSymbol(Sym); - assert(Sym.d.a < getHeader()->NumLoadCommands && + this->moveToNextSymbol(Sym); + assert(Sym.d.a < this->getHeader()->NumLoadCommands && "Relocation symbol index out of range!"); } } @@ -577,7 +1151,7 @@ template error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = getType(RE); + Res = this->getRelocationTypeImpl(RE); return object_error::success; } @@ -589,9 +1163,9 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, StringRef res; const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); + unsigned Arch = this->getArch(); - unsigned r_type = getType(RE); + unsigned r_type = this->getRelocationTypeImpl(RE); switch (Arch) { case Triple::x86: { @@ -683,14 +1257,14 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool IsScattered = isScattered(RE); + unsigned Arch = this->getArch(); + bool IsScattered = this->isRelocationScattered(RE); std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - unsigned Type = getType(RE); - bool IsPCRel = isPCRel(RE); + unsigned Type = this->getRelocationTypeImpl(RE); + bool IsPCRel = this->isRelocationPCRel(RE); // Determine any addends that should be displayed with the relocation. // These require decoding the relocation type, which is triple-specific. @@ -702,7 +1276,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@GOT"; if (isPCRel) fmt << "PCREL"; break; @@ -722,30 +1296,30 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // The X86_64_RELOC_UNSIGNED contains the minuend symbol, // X86_64_SUBTRACTOR contains to the subtrahend. - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); fmt << "-"; - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); break; } case macho::RIT_X86_64_TLV: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@TLV"; if (isPCRel) fmt << "P"; break; case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-1"; break; case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-2"; break; case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-4"; break; default: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); break; } // X86 and ARM share some relocation types in common. @@ -772,9 +1346,9 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); break; } } @@ -801,19 +1375,19 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); break; } case macho::RIT_Generic_TLV: { - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@TLV"; if (IsPCRel) fmt << "P"; break; } default: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); } } else { // ARM-specific relocations switch (Type) { @@ -831,7 +1405,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, fmt << ":upper16:("; else fmt << ":lower16:("; - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); DataRefImpl RelNext = Rel; RelNext.d.a++; @@ -860,19 +1434,19 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // symbol/section pointer of the follow-on relocation. if (Type == macho::RIT_ARM_HalfDifference) { fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); } fmt << ")"; break; } default: { - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); } } } } else - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); @@ -884,8 +1458,8 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - unsigned Type = getType(RE); + unsigned Arch = this->getArch(); + unsigned Type = this->getRelocationTypeImpl(RE); Result = false; @@ -899,7 +1473,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { DataRefImpl RelPrev = Rel; RelPrev.d.a--; - const RelocationEntry *REPrev = getRelocation(RelPrev); + const RelocationEntry *REPrev = this->getRelocation(RelPrev); unsigned PrevType = REPrev->getType(); @@ -917,7 +1491,8 @@ MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); Res = Entry->Value; if (Entry->SectionIndex) { - const Section *Sec = getSection(Sections[Entry->SectionIndex-1]); + const Section *Sec = + this->getSection(this->Sections[Entry->SectionIndex-1]); Res += Sec->Offset - Sec->Address; } @@ -930,7 +1505,7 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { SymbolRef::Type ST; - getSymbolType(Symb, ST); + this->getSymbolType(Symb, ST); if (ST == SymbolRef::ST_Unknown) { Result = false; return object_error::success; @@ -959,7 +1534,7 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, template error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; uint64_t BeginOffset; uint64_t EndOffset = 0; uint8_t SectionIndex; @@ -969,7 +1544,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, SectionIndex = Entry->SectionIndex; if (!SectionIndex) { uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); + this->getSymbolFlags(DRI, flags); if (flags & SymbolRef::SF_Common) Result = Entry->Value; else @@ -981,7 +1556,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, DRI.d.b = 0; uint32_t Command = DRI.d.a; while (Command == DRI.d.a) { - moveToNextSymbol(DRI); + this->moveToNextSymbol(DRI); if (DRI.d.a < LoadCommandCount) { Entry = getSymbolTableEntry(DRI); if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) @@ -992,8 +1567,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, } if (!EndOffset) { uint64_t Size; - getSectionSize(Sections[SectionIndex-1], Size); - getSectionAddress(Sections[SectionIndex-1], EndOffset); + this->getSectionSize(this->Sections[SectionIndex-1], Size); + this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset); EndOffset += Size; } Result = EndOffset - BeginOffset; @@ -1018,9 +1593,9 @@ section_iterator MachOObjectFile::begin_sections() const { template void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a); if (Command->Type == SegmentLoadType) { const SegmentLoadCommand *SegmentLoadCmd = reinterpret_cast(Command); @@ -1033,10 +1608,6 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { } } - typedef MachOObjectFile > - MachOObjectFile32Le; - typedef MachOObjectFile > - MachOObjectFile64Le; } } -- cgit v1.2.3