diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2011-09-08 20:52:17 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2011-09-08 20:52:17 +0000 |
commit | 0fcab076f0358890e2f1b213f4303c780e05d99d (patch) | |
tree | 612998d2d795023495c4932e67684eba986294cd /lib/Object | |
parent | cbf479df8abe5e208f1438092a9632a145551cbc (diff) |
Add support for relocations to ObjectFile.
Patch by Danil Malyshev!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139314 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 75 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 292 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 167 |
3 files changed, 516 insertions, 18 deletions
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 07de6bc999..594fcd1698 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -327,7 +327,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart); if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) return; - + SectionTable = reinterpret_cast<const coff_section *>( base() + HeaderStart @@ -360,7 +360,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) ec = object_error::parse_failed; return; } - + ec = object_error::success; } @@ -445,6 +445,77 @@ error_code COFFObjectFile::getString(uint32_t offset, return object_error::success; } +const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { + assert(Rel.d.b < Header->NumberOfSections && "Section index out of range!"); + const coff_section *Sect; + getSection(Rel.d.b, Sect); + assert(Rel.d.a < Sect->NumberOfRelocations && "Relocation index out of range!"); + return + reinterpret_cast<const coff_relocation*>(base() + + Sect->PointerToRelocations) + + Rel.d.a; +} +error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { + const coff_section *Sect = NULL; + if (error_code ec = getSection(Rel.d.b, Sect)) + return ec; + if (++Rel.d.a >= Sect->NumberOfRelocations) { + Rel.d.a = 0; + while (++Rel.d.b < Header->NumberOfSections) { + const coff_section *Sect; + getSection(Rel.d.b, Sect); + if (Sect->NumberOfRelocations > 0) + break; + } + } + Res = RelocationRef(Rel, this); + return object_error::success; +} +error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + const coff_section *Sect; + if (error_code ec = getSection(Rel.d.b, Sect)) + return ec; + const coff_relocation* R = toRel(Rel); + Res = reinterpret_cast<uintptr_t>(base() + + Sect->PointerToRawData + + R->VirtualAddress); + return object_error::success; +} +error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + const coff_relocation* R = toRel(Rel); + DataRefImpl Symb; + Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); + Res = SymbolRef(Symb, this); + return object_error::success; +} +error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, + uint32_t &Res) const { + const coff_relocation* R = toRel(Rel); + Res = R->Type; + return object_error::success; +} +error_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + Res = 0; + return object_error::success; +} +ObjectFile::relocation_iterator COFFObjectFile::begin_relocations() const { + DataRefImpl ret; + ret.d.a = 0; + ret.d.b = 1; + return relocation_iterator(RelocationRef(ret, this)); +} +ObjectFile::relocation_iterator COFFObjectFile::end_relocations() const { + DataRefImpl ret; + ret.d.a = 0; + ret.d.b = Header->NumberOfSections; + return relocation_iterator(RelocationRef(ret, this)); +} + + namespace llvm { ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index e2ff4dfc03..15e7652774 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" @@ -176,12 +177,89 @@ struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { } namespace { +template<support::endianness target_endianness, bool is64Bits, bool isRela> +struct Elf_Rel_Base; + +template<support::endianness target_endianness> +struct Elf_Rel_Base<target_endianness, false, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply +}; + +template<support::endianness target_endianness> +struct Elf_Rel_Base<target_endianness, true, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply +}; + +template<support::endianness target_endianness> +struct Elf_Rel_Base<target_endianness, false, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Sword r_addend; // Compute value for relocatable field by adding this +}; + +template<support::endianness target_endianness> +struct Elf_Rel_Base<target_endianness, true, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. +}; + +template<support::endianness target_endianness, bool is64Bits, bool isRela> +struct Elf_Rel_Impl; + +template<support::endianness target_endianness, bool isRela> +struct Elf_Rel_Impl<target_endianness, true, isRela> + : Elf_Rel_Base<target_endianness, true, isRela> { + using Elf_Rel_Base<target_endianness, true, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + uint64_t getSymbol() const { return (r_info >> 32); } + unsigned char getType() const { + return (unsigned char) (r_info & 0xffffffffL); + } + void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint64_t s, unsigned char t) { + r_info = (s << 32) + (t&0xffffffffL); + } +}; + +template<support::endianness target_endianness, bool isRela> +struct Elf_Rel_Impl<target_endianness, false, isRela> + : Elf_Rel_Base<target_endianness, false, isRela> { + using Elf_Rel_Base<target_endianness, false, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(target_endianness, false) + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + uint32_t getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint32_t s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +} + +namespace { template<support::endianness target_endianness, bool is64Bits> class ELFObjectFile : public ObjectFile { LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; + typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; + typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; struct Elf_Ehdr { unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes @@ -206,18 +284,26 @@ class ELFObjectFile : public ObjectFile { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; - typedef SmallVector<const Elf_Shdr*, 1> SymbolTableSections_t; + typedef SmallVector<const Elf_Shdr*, 1> Sections_t; + typedef DenseMap<unsigned, unsigned> IndexMap_t; const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable; const Elf_Shdr *dot_shstrtab_sec; // Section header string table. const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - SymbolTableSections_t SymbolTableSections; + Sections_t SymbolTableSections; + IndexMap_t SymbolTableSectionsIndexMap; + Sections_t RelocationTableSections; void validateSymbol(DataRefImpl Symb) const; + bool isRelocationHasAddend(DataRefImpl Rel) const; + template<typename T> + const T *getEntry(DataRefImpl Entry, Sections_t Sections) const; const Elf_Sym *getSymbol(DataRefImpl Symb) const; const Elf_Shdr *getSection(DataRefImpl index) const; const Elf_Shdr *getSection(uint16_t index) const; + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; const char *getString(uint16_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; @@ -238,12 +324,25 @@ protected: virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const; + virtual error_code getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, + uint32_t &Res) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; + public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; + virtual relocation_iterator begin_relocations() const; + virtual relocation_iterator end_relocations() const; virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; @@ -416,7 +515,8 @@ error_code ELFObjectFile<target_endianness, is64Bits> return ec; Result = StringSwitch<char>(name) .StartsWith(".debug", 'N') - .StartsWith(".note", 'n'); + .StartsWith(".note", 'n') + .Default('?'); return object_error::success; } @@ -507,6 +607,121 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } +// Relocations +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { + const Elf_Shdr *RelocationTableSection = RelocationTableSections[Rel.d.b]; + + // Check to see if we are at the end of this relocation table. + if (++Rel.d.a >= RelocationTableSection->getEntityCount()) { + // We are at the end. If there are other relocation tables, jump to them. + Rel.d.a = 0; + // Otherwise return the terminator. + if (++Rel.d.b >= SymbolTableSections.size()) { + Rel.d.a = std::numeric_limits<uint32_t>::max(); + Rel.d.b = std::numeric_limits<uint32_t>::max(); + } + } + + Result = RelocationRef(Rel, this); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Result) const { + uint32_t symbolIdx; + const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; + switch (sec->sh_type) { + default : + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL : { + symbolIdx = getRel(Rel)->getSymbol(); + break; + } + case ELF::SHT_RELA : { + symbolIdx = getRela(Rel)->getSymbol(); + break; + } + } + DataRefImpl SymbolData; + IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); + if (it == SymbolTableSectionsIndexMap.end()) + report_fatal_error("Relocation symbol table not found!"); + SymbolData.d.a = symbolIdx; + SymbolData.d.b = it->second; + Result = SymbolRef(SymbolData, this); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + uint64_t offset; + const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; + switch (sec->sh_type) { + default : + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL : { + offset = getRel(Rel)->r_offset; + break; + } + case ELF::SHT_RELA : { + offset = getRela(Rel)->r_offset; + break; + } + } + + const Elf_Shdr *secAddr = getSection(sec->sh_info); + Result = offset + reinterpret_cast<uintptr_t>(base() + secAddr->sh_offset); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getRelocationType(DataRefImpl Rel, + uint32_t &Result) const { + const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; + switch (sec->sh_type) { + default : + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL : { + Result = getRel(Rel)->getType(); + break; + } + case ELF::SHT_RELA : { + Result = getRela(Rel)->getType(); + break; + } + } + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Result) const { + const Elf_Shdr *sec = RelocationTableSections[Rel.d.b]; + switch (sec->sh_type) { + default : + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL : { + Result = 0; + return object_error::success; + } + case ELF::SHT_RELA : { + Result = getRela(Rel)->r_addend; + return object_error::success; + } + } +} + + + template<support::endianness target_endianness, bool is64Bits> ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object , error_code &ec) @@ -529,13 +744,17 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object // To find the symbol tables we walk the section table to find SHT_STMTAB. - for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable), - *e = i + Header->e_shnum * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i); + const Elf_Shdr* sh = + reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable); + for (unsigned i = 0; i < Header->e_shnum; ++i) { if (sh->sh_type == ELF::SHT_SYMTAB) { + SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); SymbolTableSections.push_back(sh); } + if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { + RelocationTableSections.push_back(sh); + } + ++sh; } // Get string table sections. @@ -615,6 +834,31 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> } template<support::endianness target_endianness, bool is64Bits> +ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits> + ::begin_relocations() const { + DataRefImpl RelData; + memset(&RelData, 0, sizeof(RelData)); + if (RelocationTableSections.size() == 0) { + RelData.d.a = std::numeric_limits<uint32_t>::max(); + RelData.d.b = std::numeric_limits<uint32_t>::max(); + } else { + RelData.d.a = 0; + RelData.d.b = 0; + } + return relocation_iterator(RelocationRef(RelData, this)); +} + +template<support::endianness target_endianness, bool is64Bits> +ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits> + ::end_relocations() const { + DataRefImpl RelData; + memset(&RelData, 0, sizeof(RelData)); + RelData.d.a = std::numeric_limits<uint32_t>::max(); + RelData.d.b = std::numeric_limits<uint32_t>::max(); + return relocation_iterator(RelocationRef(RelData, this)); +} + +template<support::endianness target_endianness, bool is64Bits> uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { return is64Bits ? 8 : 4; } @@ -629,6 +873,8 @@ StringRef ELFObjectFile<target_endianness, is64Bits> return "ELF32-i386"; case ELF::EM_X86_64: return "ELF32-x86-64"; + case ELF::EM_ARM: + return "ELF32-arm"; default: return "ELF32-unknown"; } @@ -654,19 +900,41 @@ unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { return Triple::x86; case ELF::EM_X86_64: return Triple::x86_64; + case ELF::EM_ARM: + return Triple::arm; default: return Triple::UnknownArch; } } template<support::endianness target_endianness, bool is64Bits> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * -ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { - const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; - return reinterpret_cast<const Elf_Sym *>( +template<typename T> +inline const T * +ELFObjectFile<target_endianness, is64Bits>::getEntry(DataRefImpl Entry, + Sections_t Sections) const { + const Elf_Shdr *sec = Sections[Entry.d.b]; + return reinterpret_cast<const T *>( base() + sec->sh_offset - + (Symb.d.a * sec->sh_entsize)); + + (Entry.d.a * sec->sh_entsize)); +} + +template<support::endianness target_endianness, bool is64Bits> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * +ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { + return getEntry<Elf_Sym>(Symb, SymbolTableSections); +} + +template<support::endianness target_endianness, bool is64Bits> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel * +ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const { + return getEntry<Elf_Rel>(Rel, RelocationTableSections); +} + +template<support::endianness target_endianness, bool is64Bits> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela * +ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const { + return getEntry<Elf_Rela>(Rela, RelocationTableSections); } template<support::endianness target_endianness, bool is64Bits> diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 26a6e136d7..ce202cfe32 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -18,6 +18,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MachO.h" +#include "llvm/ADT/SmallVector.h" #include <cctype> #include <cstring> @@ -32,15 +33,14 @@ typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) - : ObjectFile(Binary::isMachO, Object, ec), - MachOObj(MOO), - RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {} + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; + virtual relocation_iterator begin_relocations() const; + virtual relocation_iterator end_relocations() const; virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; @@ -63,9 +63,22 @@ protected: virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, bool &Result) const; + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const; + virtual error_code getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, + uint32_t &Res) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; private: MachOObject *MachOObj; mutable uint32_t RegisteredStringTable; + typedef SmallVector<DataRefImpl, 1> SectionList; + SectionList Sections; + void moveToNextSection(DataRefImpl &DRI) const; void getSymbolTableEntry(DataRefImpl DRI, @@ -76,8 +89,35 @@ private: void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const; void getSection64(DataRefImpl DRI, InMemoryStruct<macho::Section64> &Res) const; + void getRelocation(DataRefImpl Rel, + InMemoryStruct<macho::RelocationEntry> &Res) const; }; +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, + error_code &ec) + : ObjectFile(Binary::isMachO, Object, ec), + MachOObj(MOO), + RegisteredStringTable(std::numeric_limits<uint32_t>::max()) { + DataRefImpl DRI; + DRI.d.a = DRI.d.b = 0; + moveToNextSection(DRI); + uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + Sections.push_back(DRI); + uint64_t Addr; + uint64_t Size; + StringRef Name; + getSectionAddress(DRI, Addr); + getSectionSize(DRI, Size); + getSectionName(DRI, Name); + InMemoryStruct<macho::Section> Sect; + getSection(DRI, Sect); + DRI.d.b++; + moveToNextSection(DRI); + } +} + + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { error_code ec; std::string Err; @@ -414,6 +454,125 @@ ObjectFile::section_iterator MachOObjectFile::end_sections() const { return section_iterator(SectionRef(DRI, this)); } +/*===-- Relocations -------------------------------------------------------===*/ + +void MachOObjectFile:: +getRelocation(DataRefImpl Rel, + InMemoryStruct<macho::RelocationEntry> &Res) const { + uint32_t relOffset; + if (MachOObj->is64Bit()) { + InMemoryStruct<macho::Section64> Sect; + getSection64(Sections[Rel.d.b], Sect); + relOffset = Sect->RelocationTableOffset; + } else { + InMemoryStruct<macho::Section> Sect; + getSection(Sections[Rel.d.b], Sect); + relOffset = Sect->RelocationTableOffset; + } + MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); +} +error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { + ++Rel.d.a; + while (Rel.d.b < Sections.size()) { + unsigned relocationCount; + if (MachOObj->is64Bit()) { + InMemoryStruct<macho::Section64> Sect; + getSection64(Sections[Rel.d.b], Sect); + relocationCount = Sect->NumRelocationTableEntries; + } else { + InMemoryStruct<macho::Section> Sect; + getSection(Sections[Rel.d.b], Sect); + relocationCount = Sect->NumRelocationTableEntries; + } + if (Rel.d.a < relocationCount) + break; + + Rel.d.a = 0; + ++Rel.d.b; + } + Res = RelocationRef(Rel, this); + return object_error::success; +} +error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + const uint8_t* sectAddress = base(); + if (MachOObj->is64Bit()) { + InMemoryStruct<macho::Section64> Sect; + getSection64(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } else { + InMemoryStruct<macho::Section> Sect; + getSection(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } + InMemoryStruct<macho::RelocationEntry> RE; + getRelocation(Rel, RE); + Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0); + return object_error::success; +} +error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + InMemoryStruct<macho::RelocationEntry> RE; + getRelocation(Rel, RE); + uint32_t SymbolIdx = RE->Word1 & 0xffffff; + bool isExtern = (RE->Word1 >> 27) & 1; + + DataRefImpl Sym; + Sym.d.a = Sym.d.b = 0; + moveToNextSymbol(Sym); + uint32_t NumLoadCommands = MachOObj->getHeader().NumLoadCommands; + if (isExtern) { + for (unsigned i = 0; i < SymbolIdx; i++) { + Sym.d.b++; + moveToNextSymbol(Sym); + assert(Sym.d.a < NumLoadCommands && + "Relocation symbol index out of range!"); + } + } + Res = SymbolRef(Sym, this); + return object_error::success; +} +error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, + uint32_t &Res) const { + InMemoryStruct<macho::RelocationEntry> RE; + getRelocation(Rel, RE); + Res = RE->Word1; + return object_error::success; +} +error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + InMemoryStruct<macho::RelocationEntry> RE; + getRelocation(Rel, RE); + bool isExtern = (RE->Word1 >> 27) & 1; + Res = 0; + if (!isExtern) { + const uint8_t* sectAddress = base(); + if (MachOObj->is64Bit()) { + InMemoryStruct<macho::Section64> Sect; + getSection64(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } else { + InMemoryStruct<macho::Section> Sect; + getSection(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } + Res = reinterpret_cast<uintptr_t>(sectAddress); + } + return object_error::success; +} +ObjectFile::relocation_iterator MachOObjectFile::begin_relocations() const { + DataRefImpl ret; + ret.d.a = ret.d.b = 0; + return relocation_iterator(RelocationRef(ret, this)); +} +ObjectFile::relocation_iterator MachOObjectFile::end_relocations() const { + DataRefImpl ret; + ret.d.a = 0; + ret.d.b = Sections.size(); + return relocation_iterator(RelocationRef(ret, this)); +} + /*===-- Miscellaneous -----------------------------------------------------===*/ uint8_t MachOObjectFile::getBytesInAddress() const { |