diff options
-rw-r--r-- | include/llvm/Object/MachO.h | 802 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 962 | ||||
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 8 | ||||
-rw-r--r-- | tools/llvm-objdump/llvm-objdump.cpp | 4 | ||||
-rw-r--r-- | tools/llvm-readobj/MachODumper.cpp | 28 | ||||
-rw-r--r-- | tools/llvm-symbolizer/LLVMSymbolize.cpp | 2 |
6 files changed, 881 insertions, 925 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8c2e268..384e9ad 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/MachOObject.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Endian.h" @@ -164,9 +165,16 @@ namespace MachOFormat { }; } -class MachOObjectFile : public ObjectFile { +class MachOObjectFileBase : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, bool Is64bits, error_code &ec); + typedef MachOFormat::SymbolTableEntryBase SymbolTableEntryBase; + typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; + typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::SectionBase SectionBase; + typedef MachOFormat::LoadCommand LoadCommand; + typedef MachOFormat::Header Header; + + MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; @@ -174,7 +182,6 @@ public: virtual symbol_iterator end_dynamic_symbols() const; virtual library_iterator begin_libraries_needed() const; virtual library_iterator end_libraries_needed() const; - virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; virtual uint8_t getBytesInAddress() const; @@ -192,16 +199,10 @@ public: ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; ArrayRef<char>getSectionRawFinalSegmentName(DataRefImpl Sec) const; - const MachOFormat::Section<true> *getSection64(DataRefImpl DRI) const; - const MachOFormat::Section<false> *getSection(DataRefImpl DRI) const; - const MachOFormat::SymbolTableEntry<true> * - getSymbol64TableEntry(DataRefImpl DRI) const; - const MachOFormat::SymbolTableEntry<false> * - getSymbolTableEntry(DataRefImpl DRI) const; bool is64Bit() const; - const MachOFormat::LoadCommand *getLoadCommandInfo(unsigned Index) const; + const LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; - const MachOFormat::Header *getHeader() const; + const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; @@ -212,79 +213,774 @@ public: protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &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; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &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, bool &Res) const; virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, - bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; -private: + std::size_t getSectionIndex(DataRefImpl Sec) const; + typedef SmallVector<DataRefImpl, 1> SectionList; SectionList Sections; - const MachOFormat::SectionBase *getSectionBase(DataRefImpl DRI) 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; - void moveToNextSection(DataRefImpl &DRI) const; +private: - const MachOFormat::SymbolTableEntryBase * - getSymbolTableEntryBase(DataRefImpl DRI) const; + const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI, + const SymtabLoadCommand *SymtabLoadCmd) const; +}; - const MachOFormat::SymbolTableEntryBase * - getSymbolTableEntryBase(DataRefImpl DRI, - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; +template<bool is64Bits> +struct MachOObjectFileHelperCommon { + typedef MachOFormat::SegmentLoadCommand<is64Bits> SegmentLoadCommand; + typedef MachOFormat::SymbolTableEntry<is64Bits> SymbolTableEntry; + typedef MachOFormat::Section<is64Bits> Section; +}; - void moveToNextSymbol(DataRefImpl &DRI) const; - const MachOFormat::RelocationEntry *getRelocation(DataRefImpl Rel) const; - std::size_t getSectionIndex(DataRefImpl Sec) const; +template<bool is64Bits> +struct MachOObjectFileHelper; - void printRelocationTargetName(const MachOFormat::RelocationEntry *RE, - raw_string_ostream &fmt) const; +template<> +struct MachOObjectFileHelper<false> : + public MachOObjectFileHelperCommon<false> { + static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment; +}; + +template<> +struct MachOObjectFileHelper<true> : + public MachOObjectFileHelperCommon<true> { + static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64; +}; + +template<bool is64Bits> +class MachOObjectFile : public MachOObjectFileBase { +public: + static const macho::LoadCommandType SegmentLoadType = + MachOObjectFileHelper<is64Bits>::SegmentLoadType; + typedef typename MachOObjectFileHelper<is64Bits>::SegmentLoadCommand + SegmentLoadCommand; + typedef typename MachOObjectFileHelper<is64Bits>::SymbolTableEntry + SymbolTableEntry; + typedef typename MachOObjectFileHelper<is64Bits>::Section Section; + + MachOObjectFile(MemoryBuffer *Object, error_code &ec) : + MachOObjectFileBase(Object, is64Bits, ec) { + DataRefImpl DRI; + moveToNextSection(DRI); + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + Sections.push_back(DRI); + DRI.d.b++; + moveToNextSection(DRI); + } + } + + static inline bool classof(const Binary *v) { + return v->getType() == getMachOType(true, is64Bits); + } + + const Section *getSection(DataRefImpl DRI) const; + const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const; + virtual error_code getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const; + virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual section_iterator begin_sections() const; + void moveToNextSection(DataRefImpl &DRI) const; }; +template<bool is64Bits> +const typename MachOObjectFile<is64Bits>::Section * +MachOObjectFile<is64Bits>::getSection(DataRefImpl DRI) const { + const SectionBase *Addr = getSectionBase(DRI); + return reinterpret_cast<const Section*>(Addr); +} + +template<bool is64Bits> +const typename MachOObjectFile<is64Bits>::SymbolTableEntry * +MachOObjectFile<is64Bits>::getSymbolTableEntry(DataRefImpl DRI) const { + const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + return reinterpret_cast<const SymbolTableEntry*>(Base); +} + +template<bool is64Bits> +const typename MachOObjectFile<is64Bits>::RelocationEntry * +MachOObjectFile<is64Bits>::getRelocation(DataRefImpl Rel) const { + const Section *Sect = getSection(Sections[Rel.d.b]); + uint32_t RelOffset = Sect->RelocationTableOffset; + uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); + StringRef Data = getData(Offset, sizeof(RelocationEntry)); + return reinterpret_cast<const RelocationEntry*>(Data.data()); +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const { + const Section *Sect = getSection(Sec); + Res = Sect->Address; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getSectionSize(DataRefImpl Sec, + uint64_t &Res) const { + const Section *Sect = getSection(Sec); + Res = Sect->Size; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { + const Section *Sect = getSection(Sec); + Res = getData(Sect->Offset, Sect->Size); + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const { + const Section *Sect = getSection(Sec); + Res = uint64_t(1) << Sect->Align; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::isSectionText(DataRefImpl Sec, bool &Res) const { + const Section *Sect = getSection(Sec); + Res = Sect->Flags & macho::SF_PureInstructions; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { + const Section *Sect = getSection(Sec); + unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; + Res = SectionType == MachO::SectionTypeZeroFill || + SectionType == MachO::SectionTypeZeroFillLarge; + return object_error::success; +} + +template<bool is64Bits> +relocation_iterator +MachOObjectFile<is64Bits>::getSectionRelEnd(DataRefImpl Sec) const { + const Section *Sect = getSection(Sec); + uint32_t LastReloc = Sect->NumRelocationTableEntries; + DataRefImpl Ret; + Ret.d.a = LastReloc; + Ret.d.b = getSectionIndex(Sec); + return relocation_iterator(RelocationRef(Ret, this)); +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + const Section *Sect = getSection(Sections[Rel.d.b]); + uint64_t SectAddress = Sect->Address; + const RelocationEntry *RE = getRelocation(Rel); + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + + uint64_t RelAddr; + if (isScattered) + RelAddr = RE->Word0 & 0xFFFFFF; + else + RelAddr = RE->Word0; + + Res = SectAddress + RelAddr; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + if (isScattered) + Res = RE->Word0 & 0xFFFFFF; + else + Res = RE->Word0; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + uint32_t SymbolIdx = RE->Word1 & 0xffffff; + bool isExtern = (RE->Word1 >> 27) & 1; + + DataRefImpl Sym; + moveToNextSymbol(Sym); + if (isExtern) { + for (unsigned i = 0; i < SymbolIdx; i++) { + Sym.d.b++; + moveToNextSymbol(Sym); + assert(Sym.d.a < getHeader()->NumLoadCommands && + "Relocation symbol index out of range!"); + } + } + Res = SymbolRef(Sym, this); + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + bool isExtern = (RE->Word1 >> 27) & 1; + Res = 0; + if (!isExtern) { + const uint8_t* sectAddress = base(); + const Section *Sect = getSection(Sections[Rel.d.b]); + sectAddress += Sect->Offset; + Res = reinterpret_cast<uintptr_t>(sectAddress); + } + return object_error::success; +} + +template<bool is64Bits> +error_code MachOObjectFile<is64Bits>::getRelocationType(DataRefImpl Rel, + uint64_t &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + Res = RE->Word0; + Res <<= 32; + Res |= RE->Word1; + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const { + // TODO: Support scattered relocations. + StringRef res; + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + + unsigned r_type; + if (isScattered) + r_type = (RE->Word0 >> 24) & 0xF; + else + r_type = (RE->Word1 >> 28) & 0xF; + + switch (Arch) { + case Triple::x86: { + static const char *const Table[] = { + "GENERIC_RELOC_VANILLA", + "GENERIC_RELOC_PAIR", + "GENERIC_RELOC_SECTDIFF", + "GENERIC_RELOC_PB_LA_PTR", + "GENERIC_RELOC_LOCAL_SECTDIFF", + "GENERIC_RELOC_TLV" }; + + if (r_type > 6) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::x86_64: { + static const char *const Table[] = { + "X86_64_RELOC_UNSIGNED", + "X86_64_RELOC_SIGNED", + "X86_64_RELOC_BRANCH", + "X86_64_RELOC_GOT_LOAD", + "X86_64_RELOC_GOT", + "X86_64_RELOC_SUBTRACTOR", + "X86_64_RELOC_SIGNED_1", + "X86_64_RELOC_SIGNED_2", + "X86_64_RELOC_SIGNED_4", + "X86_64_RELOC_TLV" }; + + if (r_type > 9) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::arm: { + static const char *const Table[] = { + "ARM_RELOC_VANILLA", + "ARM_RELOC_PAIR", + "ARM_RELOC_SECTDIFF", + "ARM_RELOC_LOCAL_SECTDIFF", + "ARM_RELOC_PB_LA_PTR", + "ARM_RELOC_BR24", + "ARM_THUMB_RELOC_BR22", + "ARM_THUMB_32BIT_BRANCH", + "ARM_RELOC_HALF", + "ARM_RELOC_HALF_SECTDIFF" }; + + if (r_type > 9) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::ppc: { + static const char *const Table[] = { + "PPC_RELOC_VANILLA", + "PPC_RELOC_PAIR", + "PPC_RELOC_BR14", + "PPC_RELOC_BR24", + "PPC_RELOC_HI16", + "PPC_RELOC_LO16", + "PPC_RELOC_HA16", + "PPC_RELOC_LO14", + "PPC_RELOC_SECTDIFF", + "PPC_RELOC_PB_LA_PTR", + "PPC_RELOC_HI16_SECTDIFF", + "PPC_RELOC_LO16_SECTDIFF", + "PPC_RELOC_HA16_SECTDIFF", + "PPC_RELOC_JBSR", + "PPC_RELOC_LO14_SECTDIFF", + "PPC_RELOC_LOCAL_SECTDIFF" }; + + res = Table[r_type]; + break; + } + case Triple::UnknownArch: + res = "Unknown"; + break; + } + Result.append(res.begin(), res.end()); + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const { + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + + unsigned Type; + if (isScattered) + Type = (RE->Word0 >> 24) & 0xF; + else + Type = (RE->Word1 >> 28) & 0xF; + + bool isPCRel; + if (isScattered) + isPCRel = ((RE->Word0 >> 30) & 1); + else + isPCRel = ((RE->Word1 >> 24) & 1); + + // Determine any addends that should be displayed with the relocation. + // These require decoding the relocation type, which is triple-specific. + + // X86_64 has entirely custom relocation types. + if (Arch == Triple::x86_64) { + bool isPCRel = ((RE->Word1 >> 24) & 1); + + 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); + fmt << "@GOT"; + if (isPCRel) fmt << "PCREL"; + break; + } + case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // X86_64_SUBTRACTOR must be followed by a relocation of type + // X86_64_RELOC_UNSIGNED. + // NOTE: Scattered relocations don't exist on x86_64. + unsigned RType = (RENext->Word1 >> 28) & 0xF; + if (RType != 0) + report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); + + // The X86_64_RELOC_UNSIGNED contains the minuend symbol, + // X86_64_SUBTRACTOR contains to the subtrahend. + printRelocationTargetName(RENext, fmt); + fmt << "-"; + printRelocationTargetName(RE, fmt); + break; + } + case macho::RIT_X86_64_TLV: + printRelocationTargetName(RE, fmt); + fmt << "@TLV"; + if (isPCRel) fmt << "P"; + break; + case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 + printRelocationTargetName(RE, fmt); + fmt << "-1"; + break; + case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 + printRelocationTargetName(RE, fmt); + fmt << "-2"; + break; + case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 + printRelocationTargetName(RE, fmt); + fmt << "-4"; + break; + default: + printRelocationTargetName(RE, fmt); + break; + } + // X86 and ARM share some relocation types in common. + } else if (Arch == Triple::x86 || Arch == Triple::arm) { + // Generic relocation types... + switch (Type) { + case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info + return object_error::success; + case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + bool isNextScattered = (Arch != Triple::x86_64) && + (RENext->Word0 & macho::RF_Scattered); + unsigned RType; + if (isNextScattered) + RType = (RENext->Word0 >> 24) & 0xF; + else + RType = (RENext->Word1 >> 28) & 0xF; + if (RType != 1) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); + + printRelocationTargetName(RE, fmt); + fmt << "-"; + printRelocationTargetName(RENext, fmt); + break; + } + } + + if (Arch == Triple::x86) { + // All X86 relocations that need special printing were already + // handled in the generic code. + switch (Type) { + case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + bool isNextScattered = (Arch != Triple::x86_64) && + (RENext->Word0 & macho::RF_Scattered); + unsigned RType; + if (isNextScattered) + RType = (RENext->Word0 >> 24) & 0xF; + else + RType = (RENext->Word1 >> 28) & 0xF; + if (RType != 1) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); + + printRelocationTargetName(RE, fmt); + fmt << "-"; + printRelocationTargetName(RENext, fmt); + break; + } + case macho::RIT_Generic_TLV: { + printRelocationTargetName(RE, fmt); + fmt << "@TLV"; + if (isPCRel) fmt << "P"; + break; + } + default: + printRelocationTargetName(RE, fmt); + } + } else { // ARM-specific relocations + switch (Type) { + case macho::RIT_ARM_Half: // ARM_RELOC_HALF + case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF + // Half relocations steal a bit from the length field to encode + // whether this is an upper16 or a lower16 relocation. + bool isUpper; + if (isScattered) + isUpper = (RE->Word0 >> 28) & 1; + else + isUpper = (RE->Word1 >> 25) & 1; + + if (isUpper) + fmt << ":upper16:("; + else + fmt << ":lower16:("; + printRelocationTargetName(RE, fmt); + + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // ARM half relocs must be followed by a relocation of type + // ARM_RELOC_PAIR. + bool isNextScattered = (Arch != Triple::x86_64) && + (RENext->Word0 & macho::RF_Scattered); + unsigned RType; + if (isNextScattered) + RType = (RENext->Word0 >> 24) & 0xF; + else + RType = (RENext->Word1 >> 28) & 0xF; + + if (RType != 1) + report_fatal_error("Expected ARM_RELOC_PAIR after " + "GENERIC_RELOC_HALF"); + + // NOTE: The half of the target virtual address is stashed in the + // address field of the secondary relocation, but we can't reverse + // engineer the constant offset from it without decoding the movw/movt + // instruction to find the other half in its immediate field. + + // ARM_RELOC_HALF_SECTDIFF encodes the second section in the + // symbol/section pointer of the follow-on relocation. + if (Type == macho::RIT_ARM_HalfDifference) { + fmt << "-"; + printRelocationTargetName(RENext, fmt); + } + + fmt << ")"; + break; + } + default: { + printRelocationTargetName(RE, fmt); + } + } + } + } else + printRelocationTargetName(RE, fmt); + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getRelocationHidden(DataRefImpl Rel, + bool &Result) const { + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + unsigned Type; + if (isScattered) + Type = (RE->Word0 >> 24) & 0xF; + else + Type = (RE->Word1 >> 28) & 0xF; + + Result = false; + + // On arches that use the generic relocations, GENERIC_RELOC_PAIR + // is always hidden. + if (Arch == Triple::x86 || Arch == Triple::arm) { + if (Type == macho::RIT_Pair) Result = true; + } else if (Arch == Triple::x86_64) { + // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows + // an X864_64_RELOC_SUBTRACTOR. + if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { + DataRefImpl RelPrev = Rel; + RelPrev.d.a--; + const RelocationEntry *REPrev = getRelocation(RelPrev); + + unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + + if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; + } + } + + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Res) const { + const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + Res = Entry->Value; + if (Entry->SectionIndex) { + const Section *Sec = getSection(Sections[Entry->SectionIndex-1]); + Res += Sec->Offset - Sec->Address; + } + + return object_error::success; +} + +template<bool is64Bits> +error_code +MachOObjectFile<is64Bits>::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + SymbolRef::Type ST; + getSymbolType(Symb, ST); + if (ST == SymbolRef::ST_Unknown) { + Result = false; + return object_error::success; + } + + uint64_t SectBegin, SectEnd; + getSectionAddress(Sec, SectBegin); + getSectionSize(Sec, SectEnd); + SectEnd += SectBegin; + + const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + uint64_t SymAddr= Entry->Value; + Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); + + return object_error::success; +} + +template<bool is64Bits> +error_code MachOObjectFile<is64Bits>::getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const { + const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + Res = Entry->Value; + return object_error::success; +} + +template<bool is64Bits> +error_code MachOObjectFile<is64Bits>::getSymbolSize(DataRefImpl DRI, + uint64_t &Result) const { + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint64_t BeginOffset; + uint64_t EndOffset = 0; + uint8_t SectionIndex; + + const SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + BeginOffset = Entry->Value; + SectionIndex = Entry->SectionIndex; + if (!SectionIndex) { + uint32_t flags = SymbolRef::SF_None; + getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) + Result = Entry->Value; + else + Result = UnknownAddressOrSize; + return object_error::success; + } + // Unfortunately symbols are unsorted so we need to touch all + // symbols from load command + DRI.d.b = 0; + uint32_t Command = DRI.d.a; + while (Command == DRI.d.a) { + moveToNextSymbol(DRI); + if (DRI.d.a < LoadCommandCount) { + Entry = getSymbolTableEntry(DRI); + if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) + if (!EndOffset || Entry->Value < EndOffset) + EndOffset = Entry->Value; + } + DRI.d.b++; + } + if (!EndOffset) { + uint64_t Size; + getSectionSize(Sections[SectionIndex-1], Size); + getSectionAddress(Sections[SectionIndex-1], EndOffset); + EndOffset += Size; + } + Result = EndOffset - BeginOffset; + return object_error::success; +} + +template<bool is64Bits> +error_code MachOObjectFile<is64Bits>::getSectionNext(DataRefImpl Sec, + SectionRef &Res) const { + Sec.d.b++; + moveToNextSection(Sec); + Res = SectionRef(Sec, this); + return object_error::success; +} + +template<bool is64Bits> +section_iterator MachOObjectFile<is64Bits>::begin_sections() const { + DataRefImpl DRI; + moveToNextSection(DRI); + return section_iterator(SectionRef(DRI, this)); +} + +template<bool is64Bits> +void MachOObjectFile<is64Bits>::moveToNextSection(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + if (Command->Type == SegmentLoadType) { + const SegmentLoadCommand *SegmentLoadCmd = + reinterpret_cast<const SegmentLoadCommand*>(Command); + if (DRI.d.b < SegmentLoadCmd->NumSections) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + } } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index e1eec36..20b66d9 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -15,6 +15,7 @@ #include "llvm/Object/MachO.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" @@ -28,34 +29,25 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool Is64bits, - error_code &ec) +MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits, + error_code &ec) : ObjectFile(getMachOType(true, Is64bits), Object) { - DataRefImpl DRI; - moveToNextSection(DRI); - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - Sections.push_back(DRI); - DRI.d.b++; - moveToNextSection(DRI); - } } -bool MachOObjectFile::is64Bit() const { - unsigned int Type = getType(); - return Type == ID_MachO64L || Type == ID_MachO64B; +bool MachOObjectFileBase::is64Bit() const { + return isa<MachOObjectFile<true> >(this); } -const MachOFormat::LoadCommand * -MachOObjectFile::getLoadCommandInfo(unsigned Index) const { +const MachOObjectFileBase::LoadCommand * +MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const { uint64_t Offset; uint64_t NewOffset = getHeaderSize(); - const MachOFormat::LoadCommand *Load; + const LoadCommand *Load; unsigned I = 0; do { Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand)); - Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data()); + StringRef Data = getData(Offset, sizeof(LoadCommand)); + Load = reinterpret_cast<const LoadCommand*>(Data.data()); NewOffset = Offset + Load->Size; ++I; } while (I != Index + 1); @@ -63,8 +55,8 @@ MachOObjectFile::getLoadCommandInfo(unsigned Index) const { return Load; } -void MachOObjectFile::ReadULEB128s(uint64_t Index, - SmallVectorImpl<uint64_t> &Out) const { +void MachOObjectFileBase::ReadULEB128s(uint64_t Index, + SmallVectorImpl<uint64_t> &Out) const { DataExtractor extractor(ObjectFile::getData(), true, 0); uint32_t offset = Index; @@ -75,16 +67,16 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, } } -const MachOFormat::Header *MachOObjectFile::getHeader() const { - StringRef Data = getData(0, sizeof(MachOFormat::Header)); - return reinterpret_cast<const MachOFormat::Header*>(Data.data()); +const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const { + StringRef Data = getData(0, sizeof(Header)); + return reinterpret_cast<const Header*>(Data.data()); } -unsigned MachOObjectFile::getHeaderSize() const { +unsigned MachOObjectFileBase::getHeaderSize() const { return is64Bit() ? macho::Header64Size : macho::Header32Size; } -StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const { +StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } @@ -92,7 +84,11 @@ 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 = new MachOObjectFile(Buffer, Is64Bits, ec); + ObjectFile *Ret; + if (Is64Bits) + Ret = new MachOObjectFile<true>(Buffer, ec); + else + Ret = new MachOObjectFile<false>(Buffer, ec); if (ec) return NULL; return Ret; @@ -100,13 +96,13 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ -void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { +void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Symtab) { - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command); + const SymtabLoadCommand *SymtabLoadCmd = + reinterpret_cast<const SymtabLoadCommand*>(Command); if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) return; } @@ -116,23 +112,17 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { } } -const MachOFormat::SymbolTableEntryBase * -MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command); +const MachOObjectFileBase::SymbolTableEntryBase * +MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const SymtabLoadCommand *SymtabLoadCmd = + reinterpret_cast<const SymtabLoadCommand*>(Command); return getSymbolTableEntryBase(DRI, SymtabLoadCmd); } -const MachOFormat::SymbolTableEntry<false> * -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); - return reinterpret_cast<const MachOFormat::SymbolTableEntry<false>*>(Base); -} - -const MachOFormat::SymbolTableEntryBase * -MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI, - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { +const MachOObjectFileBase::SymbolTableEntryBase * +MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, + const SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; @@ -142,34 +132,27 @@ MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI, uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; StringRef Data = getData(Offset, SymbolTableEntrySize); - return - reinterpret_cast<const MachOFormat::SymbolTableEntryBase*>(Data.data()); + return reinterpret_cast<const SymbolTableEntryBase*>(Data.data()); } -const MachOFormat::SymbolTableEntry<true>* -MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); - return reinterpret_cast<const MachOFormat::SymbolTableEntry<true>*>(Base); -} - -error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, - SymbolRef &Result) const { +error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI, + SymbolRef &Result) const { DRI.d.b++; moveToNextSymbol(DRI); Result = SymbolRef(DRI, this); return object_error::success; } -error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, - StringRef &Result) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command); +error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI, + StringRef &Result) const { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const SymtabLoadCommand *SymtabLoadCmd = + reinterpret_cast<const SymtabLoadCommand*>(Command); StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, SymtabLoadCmd->StringTableSize); - const MachOFormat::SymbolTableEntryBase *Entry = + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI, SymtabLoadCmd); uint32_t StringIndex = Entry->StringIndex; @@ -179,121 +162,9 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::SymbolTableEntry<true> *Entry = - getSymbol64TableEntry(DRI); - Result = Entry->Value; - if (Entry->SectionIndex) { - const MachOFormat::Section<true> *Section = - getSection64(Sections[Entry->SectionIndex-1]); - Result += Section->Offset - Section->Address; - } - } else { - const MachOFormat::SymbolTableEntry<false> *Entry = - getSymbolTableEntry(DRI); - Result = Entry->Value; - if (Entry->SectionIndex) { - const MachOFormat::Section<false> *Section = - getSection(Sections[Entry->SectionIndex-1]); - Result += Section->Offset - Section->Address; - } - } - - return object_error::success; -} - -error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::SymbolTableEntry<true> *Entry = - getSymbol64TableEntry(DRI); - Result = Entry->Value; - } else { - const MachOFormat::SymbolTableEntry<false> *Entry = - getSymbolTableEntry(DRI); - Result = Entry->Value; - } - return object_error::success; -} - -error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, - uint64_t &Result) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - uint64_t BeginOffset; - uint64_t EndOffset = 0; - uint8_t SectionIndex; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry<true> *Entry = - getSymbol64TableEntry(DRI); - BeginOffset = Entry->Value; - SectionIndex = Entry->SectionIndex; - if (!SectionIndex) { - uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); - if (flags & SymbolRef::SF_Common) - Result = Entry->Value; - else - Result = UnknownAddressOrSize; - return object_error::success; - } - // Unfortunately symbols are unsorted so we need to touch all - // symbols from load command - DRI.d.b = 0; - uint32_t Command = DRI.d.a; - while (Command == DRI.d.a) { - moveToNextSymbol(DRI); - if (DRI.d.a < LoadCommandCount) { - Entry = getSymbol64TableEntry(DRI); - if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) - if (!EndOffset || Entry->Value < EndOffset) - EndOffset = Entry->Value; - } - DRI.d.b++; - } - } else { - const MachOFormat::SymbolTableEntry<false> *Entry = - getSymbolTableEntry(DRI); - BeginOffset = Entry->Value; - SectionIndex = Entry->SectionIndex; - if (!SectionIndex) { - uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); - if (flags & SymbolRef::SF_Common) - Result = Entry->Value; - else - Result = UnknownAddressOrSize; - return object_error::success; - } - // Unfortunately symbols are unsorted so we need to touch all - // symbols from load command - DRI.d.b = 0; - uint32_t Command = DRI.d.a; - while (Command == DRI.d.a) { - moveToNextSymbol(DRI); - if (DRI.d.a < LoadCommandCount) { - Entry = getSymbolTableEntry(DRI); - if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) - if (!EndOffset || Entry->Value < EndOffset) - EndOffset = Entry->Value; - } - DRI.d.b++; - } - } - if (!EndOffset) { - uint64_t Size; - getSectionSize(Sections[SectionIndex-1], Size); - getSectionAddress(Sections[SectionIndex-1], EndOffset); - EndOffset += Size; - } - Result = EndOffset - BeginOffset; - return object_error::success; -} - -error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, - char &Result) const { - const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); +error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI, + char &Result) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); uint8_t Type = Entry->Type; uint16_t Flags = Entry->Flags; @@ -317,9 +188,9 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { - const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); +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; @@ -347,10 +218,9 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const MachOFormat::SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(Symb); +error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); uint8_t index = Entry->SectionIndex; if (index == 0) @@ -361,10 +231,9 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { - const MachOFormat::SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(Symb); +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; @@ -386,97 +255,61 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); +error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFile::begin_symbols() const { +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 MachOObjectFile::end_symbols() const { +symbol_iterator MachOObjectFileBase::end_symbols() const { DataRefImpl DRI; DRI.d.a = getHeader()->NumLoadCommands; return symbol_iterator(SymbolRef(DRI, this)); } -symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { +symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const { // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFile::end_dynamic_symbols() const { +symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const { // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); } -library_iterator MachOObjectFile::begin_libraries_needed() const { +library_iterator MachOObjectFileBase::begin_libraries_needed() const { // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } -library_iterator MachOObjectFile::end_libraries_needed() const { +library_iterator MachOObjectFileBase::end_libraries_needed() const { // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } -StringRef MachOObjectFile::getLoadName() const { +StringRef MachOObjectFileBase::getLoadName() const { // TODO: Implement - report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); + report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase"); } /*===-- Sections ----------------------------------------------------------===*/ -void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - if (Command->Type == macho::LCT_Segment) { - const MachOFormat::SegmentLoadCommand<false> *SegmentLoadCmd = - reinterpret_cast<const MachOFormat::SegmentLoadCommand<false>*>(Command); - if (DRI.d.b < SegmentLoadCmd->NumSections) - return; - } else if (Command->Type == macho::LCT_Segment64) { - const MachOFormat::SegmentLoadCommand<true> *SegmentLoadCmd = - reinterpret_cast<const MachOFormat::SegmentLoadCommand<true>*>(Command); - if (DRI.d.b < SegmentLoadCmd->NumSections) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, - SectionRef &Result) const { - DRI.d.b++; - moveToNextSection(DRI); - Result = SectionRef(DRI, this); - return object_error::success; -} - -const MachOFormat::Section<false> * -MachOObjectFile::getSection(DataRefImpl DRI) const { - assert(!is64Bit()); - const MachOFormat::SectionBase *Addr = getSectionBase(DRI); - return reinterpret_cast<const MachOFormat::Section<false>*>(Addr); -} - -std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { +std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const { SectionList::const_iterator loc = std::find(Sections.begin(), Sections.end(), Sec); assert(loc != Sections.end() && "Sec is not a valid section!"); return std::distance(Sections.begin(), loc); } -const MachOFormat::SectionBase* -MachOObjectFile::getSectionBase(DataRefImpl DRI) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); +const MachOObjectFileBase::SectionBase* +MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command); bool Is64 = is64Bit(); @@ -487,14 +320,7 @@ MachOObjectFile::getSectionBase(DataRefImpl DRI) const { sizeof(MachOFormat::Section<false>); uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast<const MachOFormat::SectionBase*>(SectionAddr); -} - -const MachOFormat::Section<true> * -MachOObjectFile::getSection64(DataRefImpl DRI) const { - assert(is64Bit()); - const MachOFormat::SectionBase *Addr = getSectionBase(DRI); - return reinterpret_cast<const MachOFormat::Section<true>*>(Addr); + return reinterpret_cast<const SectionBase*>(SectionAddr); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -505,136 +331,61 @@ static StringRef parseSegmentOrSectionName(const char *P) { return StringRef(P, 16); } -ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { - const MachOFormat::SectionBase *Base = getSectionBase(DRI); +ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const { + const SectionBase *Base = getSectionBase(DRI); return ArrayRef<char>(Base->Name); } -error_code MachOObjectFile::getSectionName(DataRefImpl DRI, - StringRef &Result) const { +error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI, + StringRef &Result) const { ArrayRef<char> Raw = getSectionRawName(DRI); Result = parseSegmentOrSectionName(Raw.data()); return object_error::success; } ArrayRef<char> -MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const MachOFormat::SectionBase *Base = getSectionBase(Sec); +MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + const SectionBase *Base = getSectionBase(Sec); return ArrayRef<char>(Base->SegmentName); } -StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { +StringRef +MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const { ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI); return parseSegmentOrSectionName(Raw.data()); } -error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(DRI); - Result = Sect->Address; - } else { - const MachOFormat::Section<false> *Sect = getSection(DRI); - Result = Sect->Address; - } - return object_error::success; -} - -error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(DRI); - Result = Sect->Size; - } else { - const MachOFormat::Section<false> *Sect = getSection(DRI); - Result = Sect->Size; - } - return object_error::success; -} - -error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, - StringRef &Result) const { - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(DRI); - Result = getData(Sect->Offset, Sect->Size); - } else { - const MachOFormat::Section<false> *Sect = getSection(DRI); - Result = getData(Sect->Offset, Sect->Size); - } - return object_error::success; -} - -error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(DRI); - Result = uint64_t(1) << Sect->Align; - } else { - const MachOFormat::Section<false> *Sect = getSection(DRI); - Result = uint64_t(1) << Sect->Align; - } - return object_error::success; -} - -error_code MachOObjectFile::isSectionText(DataRefImpl DRI, - bool &Result) const { - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(DRI); - Result = Sect->Flags & macho::SF_PureInstructions; - } else { - const MachOFormat::Section<false> *Sect = getSection(DRI); - Result = Sect->Flags & macho::SF_PureInstructions; - } - return object_error::success; -} - -error_code MachOObjectFile::isSectionData(DataRefImpl DRI, - bool &Result) const { +error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, - bool &Result) const { +error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { +error_code +MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { // FIXME: Unimplemented. Result = true; return object_error::success; } -error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, - bool &Result) const { - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(DRI); - unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; - Result = (SectionType == MachO::SectionTypeZeroFill || - SectionType == MachO::SectionTypeZeroFillLarge); - } else { - const MachOFormat::Section<false> *Sect = getSection(DRI); - unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; - Result = (SectionType == MachO::SectionTypeZeroFill || - SectionType == MachO::SectionTypeZeroFillLarge); - } - - return object_error::success; -} - -error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { // Consider using the code from isSectionText to look for __const sections. // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS // to use section attributes to distinguish code from data. @@ -644,64 +395,13 @@ error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, return object_error::success; } -error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - SymbolRef::Type ST; - getSymbolType(Symb, ST); - if (ST == SymbolRef::ST_Unknown) { - Result = false; - return object_error::success; - } - - uint64_t SectBegin, SectEnd; - getSectionAddress(Sec, SectBegin); - getSectionSize(Sec, SectEnd); - SectEnd += SectBegin; - - if (is64Bit()) { - const MachOFormat::SymbolTableEntry<true> *Entry = - getSymbol64TableEntry(Symb); - uint64_t SymAddr= Entry->Value; - Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); - } else { - const MachOFormat::SymbolTableEntry<false> *Entry = - getSymbolTableEntry(Symb); - uint64_t SymAddr= Entry->Value; - Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); - } - - return object_error::success; -} - -relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { +relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl ret; ret.d.b = getSectionIndex(Sec); return relocation_iterator(RelocationRef(ret, this)); } -relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - uint32_t last_reloc; - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(Sec); - last_reloc = Sect->NumRelocationTableEntries; - } else { - const MachOFormat::Section<false> *Sect = getSection(Sec); - last_reloc = Sect->NumRelocationTableEntries; - } - DataRefImpl ret; - ret.d.a = last_reloc; - ret.d.b = getSectionIndex(Sec); - return relocation_iterator(RelocationRef(ret, this)); -} - -section_iterator MachOObjectFile::begin_sections() const { - DataRefImpl DRI; - moveToNextSection(DRI); - return section_iterator(SectionRef(DRI, this)); -} - -section_iterator MachOObjectFile::end_sections() const { +section_iterator MachOObjectFileBase::end_sections() const { DataRefImpl DRI; DRI.d.a = getHeader()->NumLoadCommands; return section_iterator(SectionRef(DRI, this)); @@ -709,208 +409,12 @@ section_iterator MachOObjectFile::end_sections() const { /*===-- Relocations -------------------------------------------------------===*/ -const MachOFormat::RelocationEntry * -MachOObjectFile::getRelocation(DataRefImpl Rel) const { - uint32_t relOffset; - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]); - relOffset = Sect->RelocationTableOffset; - } else { - const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]); - relOffset = Sect->RelocationTableOffset; - } - uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry); - StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry)); - return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data()); -} - -error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { +error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { ++Rel.d.a; Res = RelocationRef(Rel, this); return object_error::success; } -error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const { - const uint8_t* sectAddress = 0; - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]); - sectAddress += Sect->Address; - } else { - const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]); - sectAddress += Sect->Address; - } - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - uint64_t RelAddr = 0; - if (isScattered) - RelAddr = RE->Word0 & 0xFFFFFF; - else - RelAddr = RE->Word0; - - Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr); - return object_error::success; -} -error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - if (isScattered) - Res = RE->Word0 & 0xFFFFFF; - else - Res = RE->Word0; - return object_error::success; -} -error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->Word1 & 0xffffff; - bool isExtern = (RE->Word1 >> 27) & 1; - - DataRefImpl Sym; - moveToNextSymbol(Sym); - if (isExtern) { - for (unsigned i = 0; i < SymbolIdx; i++) { - Sym.d.b++; - moveToNextSymbol(Sym); - assert(Sym.d.a < getHeader()->NumLoadCommands && - "Relocation symbol index out of range!"); - } - } - Res = SymbolRef(Sym, this); - return object_error::success; -} -error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - Res = RE->Word0; - Res <<= 32; - Res |= RE->Word1; - return object_error::success; -} -error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { - // TODO: Support scattered relocations. - StringRef res; - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - - unsigned r_type; - if (isScattered) - r_type = (RE->Word0 >> 24) & 0xF; - else - r_type = (RE->Word1 >> 28) & 0xF; - - switch (Arch) { - case Triple::x86: { - static const char *const Table[] = { - "GENERIC_RELOC_VANILLA", - "GENERIC_RELOC_PAIR", - "GENERIC_RELOC_SECTDIFF", - "GENERIC_RELOC_PB_LA_PTR", - "GENERIC_RELOC_LOCAL_SECTDIFF", - "GENERIC_RELOC_TLV" }; - - if (r_type > 6) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::x86_64: { - static const char *const Table[] = { - "X86_64_RELOC_UNSIGNED", - "X86_64_RELOC_SIGNED", - "X86_64_RELOC_BRANCH", - "X86_64_RELOC_GOT_LOAD", - "X86_64_RELOC_GOT", - "X86_64_RELOC_SUBTRACTOR", - "X86_64_RELOC_SIGNED_1", - "X86_64_RELOC_SIGNED_2", - "X86_64_RELOC_SIGNED_4", - "X86_64_RELOC_TLV" }; - - if (r_type > 9) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::arm: { - static const char *const Table[] = { - "ARM_RELOC_VANILLA", - "ARM_RELOC_PAIR", - "ARM_RELOC_SECTDIFF", - "ARM_RELOC_LOCAL_SECTDIFF", - "ARM_RELOC_PB_LA_PTR", - "ARM_RELOC_BR24", - "ARM_THUMB_RELOC_BR22", - "ARM_THUMB_32BIT_BRANCH", - "ARM_RELOC_HALF", - "ARM_RELOC_HALF_SECTDIFF" }; - - if (r_type > 9) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::ppc: { - static const char *const Table[] = { - "PPC_RELOC_VANILLA", - "PPC_RELOC_PAIR", - "PPC_RELOC_BR14", - "PPC_RELOC_BR24", - "PPC_RELOC_HI16", - "PPC_RELOC_LO16", - "PPC_RELOC_HA16", - "PPC_RELOC_LO14", - "PPC_RELOC_SECTDIFF", - "PPC_RELOC_PB_LA_PTR", - "PPC_RELOC_HI16_SECTDIFF", - "PPC_RELOC_LO16_SECTDIFF", - "PPC_RELOC_HA16_SECTDIFF", - "PPC_RELOC_JBSR", - "PPC_RELOC_LO14_SECTDIFF", - "PPC_RELOC_LOCAL_SECTDIFF" }; - - res = Table[r_type]; - break; - } - case Triple::UnknownArch: - res = "Unknown"; - break; - } - Result.append(res.begin(), res.end()); - return object_error::success; -} -error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - bool isExtern = (RE->Word1 >> 27) & 1; - Res = 0; - if (!isExtern) { - const uint8_t* sectAddress = base(); - if (is64Bit()) { - const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]); - sectAddress += Sect->Offset; - } else { - const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]); - sectAddress += Sect->Offset; - } - Res = reinterpret_cast<uintptr_t>(sectAddress); - } - return object_error::success; -} // Helper to advance a section or symbol iterator multiple increments at a time. template<class T> @@ -928,9 +432,9 @@ void advanceTo(T &it, size_t Val) { report_fatal_error(ec.message()); } -void MachOObjectFile::printRelocationTargetName( - const MachOFormat::RelocationEntry *RE, - raw_string_ostream &fmt) const { +void +MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, + raw_string_ostream &fmt) const { unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && (RE->Word0 & macho::RF_Scattered); @@ -998,270 +502,24 @@ void MachOObjectFile::printRelocationTargetName( fmt << S; } -error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; - - bool isPCRel; - if (isScattered) - isPCRel = ((RE->Word0 >> 30) & 1); - else - isPCRel = ((RE->Word1 >> 24) & 1); - - // Determine any addends that should be displayed with the relocation. - // These require decoding the relocation type, which is triple-specific. - - // X86_64 has entirely custom relocation types. - if (Arch == Triple::x86_64) { - bool isPCRel = ((RE->Word1 >> 24) & 1); - - 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); - fmt << "@GOT"; - if (isPCRel) fmt << "PCREL"; - break; - } - case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // X86_64_SUBTRACTOR must be followed by a relocation of type - // X86_64_RELOC_UNSIGNED. - // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = (RENext->Word1 >> 28) & 0xF; - if (RType != 0) - report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); - - // The X86_64_RELOC_UNSIGNED contains the minuend symbol, - // X86_64_SUBTRACTOR contains to the subtrahend. - printRelocationTargetName(RENext, fmt); - fmt << "-"; - printRelocationTargetName(RE, fmt); - break; - } - case macho::RIT_X86_64_TLV: - printRelocationTargetName(RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 - printRelocationTargetName(RE, fmt); - fmt << "-1"; - break; - case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 - printRelocationTargetName(RE, fmt); - fmt << "-2"; - break; - case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 - printRelocationTargetName(RE, fmt); - fmt << "-4"; - break; - default: - printRelocationTargetName(RE, fmt); - break; - } - // X86 and ARM share some relocation types in common. - } else if (Arch == Triple::x86 || Arch == Triple::arm) { - // Generic relocation types... - switch (Type) { - case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info - return object_error::success; - case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; - else - RType = (RENext->Word1 >> 28) & 0xF; - if (RType != 1) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); - - printRelocationTargetName(RE, fmt); - fmt << "-"; - printRelocationTargetName(RENext, fmt); - break; - } - } - - if (Arch == Triple::x86) { - // All X86 relocations that need special printing were already - // handled in the generic code. - switch (Type) { - case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; - else - RType = (RENext->Word1 >> 28) & 0xF; - if (RType != 1) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); - - printRelocationTargetName(RE, fmt); - fmt << "-"; - printRelocationTargetName(RENext, fmt); - break; - } - case macho::RIT_Generic_TLV: { - printRelocationTargetName(RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - } - default: - printRelocationTargetName(RE, fmt); - } - } else { // ARM-specific relocations - switch (Type) { - case macho::RIT_ARM_Half: // ARM_RELOC_HALF - case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF - // Half relocations steal a bit from the length field to encode - // whether this is an upper16 or a lower16 relocation. - bool isUpper; - if (isScattered) - isUpper = (RE->Word0 >> 28) & 1; - else - isUpper = (RE->Word1 >> 25) & 1; - - if (isUpper) - fmt << ":upper16:("; - else - fmt << ":lower16:("; - printRelocationTargetName(RE, fmt); - - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // ARM half relocs must be followed by a relocation of type - // ARM_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; - else - RType = (RENext->Word1 >> 28) & 0xF; - - if (RType != 1) - report_fatal_error("Expected ARM_RELOC_PAIR after " - "GENERIC_RELOC_HALF"); - - // NOTE: The half of the target virtual address is stashed in the - // address field of the secondary relocation, but we can't reverse - // engineer the constant offset from it without decoding the movw/movt - // instruction to find the other half in its immediate field. - - // ARM_RELOC_HALF_SECTDIFF encodes the second section in the - // symbol/section pointer of the follow-on relocation. - if (Type == macho::RIT_ARM_HalfDifference) { - fmt << "-"; - printRelocationTargetName(RENext, fmt); - } - - fmt << ")"; - break; - } - default: { - printRelocationTargetName(RE, fmt); - } - } - } - } else - printRelocationTargetName(RE, fmt); - - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - return object_error::success; -} - -error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, - bool &Result) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; - - Result = false; - - // On arches that use the generic relocations, GENERIC_RELOC_PAIR - // is always hidden. - if (Arch == Triple::x86 || Arch == Triple::arm) { - if (Type == macho::RIT_Pair) Result = true; - } else if (Arch == Triple::x86_64) { - // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows - // an X864_64_RELOC_SUBTRACTOR. - if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { - DataRefImpl RelPrev = Rel; - RelPrev.d.a--; - const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev); - - unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; - - if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; - } - } - - return object_error::success; -} - -error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const { + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } -error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData, + StringRef &Res) const { + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } /*===-- Miscellaneous -----------------------------------------------------===*/ -uint8_t MachOObjectFile::getBytesInAddress() const { +uint8_t MachOObjectFileBase::getBytesInAddress() const { return is64Bit() ? 8 : 4; } -StringRef MachOObjectFile::getFileFormatName() const { +StringRef MachOObjectFileBase::getFileFormatName() const { if (!is64Bit()) { switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: @@ -1292,7 +550,7 @@ StringRef MachOObjectFile::getFileFormatName() const { } } -unsigned MachOObjectFile::getArch() const { +unsigned MachOObjectFileBase::getArch() const { switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: return Triple::x86; diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 7c65658..b0a1aca 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -52,7 +52,7 @@ static cl::opt<bool> static cl::opt<std::string> DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); -static const Target *GetTarget(const MachOObjectFile *MachOObj) { +static const Target *GetTarget(const MachOObjectFileBase *MachOObj) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); @@ -108,7 +108,7 @@ struct SymbolSorter { // Print additional information about an address, if available. static void DumpAddress(uint64_t Address, ArrayRef<SectionRef> Sections, - const MachOObjectFile *MachOObj, raw_ostream &OS) { + const MachOObjectFileBase *MachOObj, raw_ostream &OS) { for (unsigned i = 0; i != Sections.size(); ++i) { uint64_t SectAddr = 0, SectSize = 0; Sections[i].getAddress(SectAddr); @@ -200,7 +200,7 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, } static void getSectionsAndSymbols(const MachOFormat::Header *Header, - MachOObjectFile *MachOObj, + MachOObjectFileBase *MachOObj, std::vector<SectionRef> &Sections, std::vector<SymbolRef> &Symbols, SmallVectorImpl<uint64_t> &FoundFns) { @@ -238,7 +238,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { return; } - OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>( + OwningPtr<MachOObjectFileBase> MachOOF(static_cast<MachOObjectFileBase*>( ObjectFile::createMachOObjectFile(Buff.take()))); const Target *TheTarget = GetTarget(MachOOF.get()); diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 9a36e82..4790d7a 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -255,7 +255,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); StringRef SegmentName = ""; - if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) { + if (const MachOObjectFileBase *MachO = dyn_cast<const MachOObjectFileBase>(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); SegmentName = MachO->getSectionFinalSegmentName(DR); } @@ -591,7 +591,7 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { - if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(o)) { + if (const MachOObjectFileBase *MachO = dyn_cast<const MachOObjectFileBase>(o)) { DataRefImpl DR = Section->getRawDataRefImpl(); StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); outs() << SegmentName << ","; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 8940280..3dad4d6 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -27,7 +27,7 @@ namespace { class MachODumper : public ObjDumper { public: - MachODumper(const llvm::object::MachOObjectFile *Obj, StreamWriter& Writer) + MachODumper(const llvm::object::MachOObjectFileBase *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { } @@ -43,7 +43,7 @@ private: void printRelocation(section_iterator SecI, relocation_iterator RelI); - const llvm::object::MachOObjectFile *Obj; + const llvm::object::MachOObjectFileBase *Obj; }; } // namespace @@ -54,7 +54,7 @@ namespace llvm { error_code createMachODumper(const object::ObjectFile *Obj, StreamWriter& Writer, OwningPtr<ObjDumper> &Result) { - const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(Obj); + const MachOObjectFileBase *MachOObj = dyn_cast<MachOObjectFileBase>(Obj); if (!MachOObj) return readobj_error::unsupported_obj_file_format; @@ -157,11 +157,11 @@ namespace { }; } -static void getSection(const MachOObjectFile *Obj, +static void getSection(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSection &Section) { - if (Obj->is64Bit()) { - const MachOFormat::Section<true> *Sect = Obj->getSection64(DRI); + if (const MachOObjectFile<true> *O = dyn_cast<MachOObjectFile<true> >(Obj)) { + const MachOObjectFile<true>::Section *Sect = O->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -173,7 +173,8 @@ static void getSection(const MachOObjectFile *Obj, Section.Reserved1 = Sect->Reserved1; Section.Reserved2 = Sect->Reserved2; } else { - const MachOFormat::Section<false> *Sect = Obj->getSection(DRI); + const MachOObjectFile<false> *O2 = cast<MachOObjectFile<false> >(Obj); + const MachOObjectFile<false>::Section *Sect = O2->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -187,20 +188,21 @@ static void getSection(const MachOObjectFile *Obj, } } -static void getSymbol(const MachOObjectFile *Obj, +static void getSymbol(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (Obj->is64Bit()) { - const MachOFormat::SymbolTableEntry<true> *Entry = - Obj->getSymbol64TableEntry(DRI); + if (const MachOObjectFile<true> *O = dyn_cast<MachOObjectFile<true> >(Obj)) { + const MachOObjectFile<true>::SymbolTableEntry *Entry = + O->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; Symbol.SectionIndex = Entry->SectionIndex; Symbol.Flags = Entry->Flags; Symbol.Value = Entry->Value; } else { - const MachOFormat::SymbolTableEntry<false> *Entry = - Obj->getSymbolTableEntry(DRI); + const MachOObjectFile<false> *O2 = cast<MachOObjectFile<false> >(Obj); + const MachOObjectFile<false>::SymbolTableEntry *Entry = + O2->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; Symbol.SectionIndex = Entry->SectionIndex; diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index 29d91a0..ffe8712 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -233,7 +233,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { // On Darwin we may find DWARF in separate object file in // resource directory. ObjectFile *DbgObj = Obj; - if (isa<MachOObjectFile>(Obj)) { + if (isa<MachOObjectFileBase>(Obj)) { const std::string &ResourceName = getDarwinDWARFResourceForModule(ModuleName); ObjectFile *ResourceObj = getObjectFile(ResourceName); |