diff options
-rw-r--r-- | include/llvm/Object/MachO.h | 145 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 52 | ||||
-rw-r--r-- | test/tools/llvm-readobj/relocations.test | 14 | ||||
-rw-r--r-- | test/tools/llvm-readobj/sections-ext.test | 14 | ||||
-rw-r--r-- | tools/llvm-readobj/MachODumper.cpp | 16 |
5 files changed, 151 insertions, 90 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index b02e1ac..9b7a073 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -112,11 +112,53 @@ namespace MachOFormat { MachOInt32 Reserved3; }; + struct MachOInt24 { + uint8_t bytes[3]; + operator uint32_t() const { + return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; + } + }; + template<endianness TargetEndianness> struct RelocationEntry { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) - MachOInt32 Word0; - MachOInt32 Word1; + MachOInt32 Address; + MachOInt24 SymbolNum; + uint8_t Bits; + + unsigned getPCRel() const { + return Bits & 0x1; + } + unsigned getLength() const { + return (Bits >> 1) & 0x3; + } + unsigned getExternal() const { + return (Bits >> 3) & 0x1; + } + unsigned getType() const { + return Bits >> 4; + } + }; + + template<endianness TargetEndianness> + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt24 Address; + uint8_t Bits; + MachOInt32 Value; + + unsigned getType() const { + return Bits & 0xf; + } + unsigned getLength() const { + return (Bits >> 4) & 0x3; + } + unsigned getPCRel() const { + return (Bits >> 6) & 0x1; + } + unsigned getScattered() const { + return Bits >> 7; + } }; template<endianness TargetEndianness> @@ -206,6 +248,8 @@ public: SymbolTableEntryBase; typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand; typedef MachOFormat::RelocationEntry<support::little> RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry<support::little> + ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; typedef MachOFormat::LoadCommand<support::little> LoadCommand; typedef MachOFormat::Header<support::little> Header; @@ -243,6 +287,11 @@ public: const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + bool isScattered(const RelocationEntry *RE) const; + bool isPCRel(const RelocationEntry *RE) const; + unsigned getLength(const RelocationEntry *RE) const; + unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); @@ -479,15 +528,12 @@ MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel, 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; + if (isScattered(RE)) + RelAddr = RE->Address & 0xFFFFFF; else - RelAddr = RE->Word0; + RelAddr = RE->Address; Res = SectAddress + RelAddr; return object_error::success; @@ -498,14 +544,10 @@ error_code MachOObjectFile<MachOT>::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; + if (isScattered(RE)) + Res = RE->Address & 0xFFFFFF; else - Res = RE->Word0; + Res = RE->Address; return object_error::success; } @@ -514,8 +556,8 @@ error_code MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { const RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->Word1 & 0xffffff; - bool isExtern = (RE->Word1 >> 27) & 1; + uint32_t SymbolIdx = RE->SymbolNum; + bool isExtern = RE->getExternal(); DataRefImpl Sym; moveToNextSymbol(Sym); @@ -535,9 +577,7 @@ template<class MachOT> error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = RE->Word0; - Res <<= 32; - Res |= RE->Word1; + Res = getType(RE); return object_error::success; } @@ -550,14 +590,8 @@ MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel, 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; + unsigned r_type = getType(RE); switch (Arch) { case Triple::x86: { @@ -650,30 +684,20 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); + bool IsScattered = isScattered(RE); 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); + unsigned Type = getType(RE); + bool IsPCRel = isPCRel(RE); // 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); + bool isPCRel = RE->getPCRel(); switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD @@ -691,7 +715,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // 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; + unsigned RType = RENext->getType(); if (RType != 0) report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " "X86_64_RELOC_SUBTRACTOR."); @@ -738,12 +762,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // 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); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->getType(); if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); @@ -767,12 +791,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // 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); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->getType(); if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); @@ -785,7 +809,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, case macho::RIT_Generic_TLV: { printRelocationTargetName(RE, fmt); fmt << "@TLV"; - if (isPCRel) fmt << "P"; + if (IsPCRel) fmt << "P"; break; } default: @@ -798,10 +822,10 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // 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; + if (IsScattered) + isUpper = (RE->Address >> 28) & 1; else - isUpper = (RE->Word1 >> 25) & 1; + isUpper = (RE->getLength() >> 1) & 1; if (isUpper) fmt << ":upper16:("; @@ -816,12 +840,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // 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); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->getType(); if (RType != 1) report_fatal_error("Expected ARM_RELOC_PAIR after " @@ -860,15 +884,8 @@ error_code MachOObjectFile<MachOT>::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; + unsigned Type = getType(RE); Result = false; @@ -884,7 +901,7 @@ MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel, RelPrev.d.a--; const RelocationEntry *REPrev = getRelocation(RelPrev); - unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + unsigned PrevType = REPrev->getType(); if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index c846206..627e748 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -80,6 +80,46 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } +const MachOObjectFileBase::RelocationEntry * +MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { + if (const MachOObjectFile32Le *O = dyn_cast<MachOObjectFile32Le>(this)) + return O->getRelocation(Rel); + const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(this); + return O->getRelocation(Rel); +} + +bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { + unsigned Arch = getArch(); + return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); +} + +bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast<const ScatteredRelocationEntry *>(RE); + return SRE->getPCRel(); + } + return RE->getPCRel(); +} + +unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast<const ScatteredRelocationEntry *>(RE); + return SRE->getLength(); + } + return RE->getLength(); +} + +unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast<const ScatteredRelocationEntry *>(RE); + return SRE->getType(); + } + return RE->getType(); +} + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; @@ -435,16 +475,12 @@ void advanceTo(T &it, size_t Val) { 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); - // Target of a scattered relocation is an address. In the interest of // generating pretty output, scan through the symbol table looking for a // symbol that aligns with that address. If we find one, print it. // Otherwise, we just print the hex address of the target. - if (isScattered) { - uint32_t Val = RE->Word1; + if (isScattered(RE)) { + uint32_t Val = RE->SymbolNum; error_code ec; for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; @@ -486,8 +522,8 @@ MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, } StringRef S; - bool isExtern = (RE->Word1 >> 27) & 1; - uint32_t Val = RE->Word1 & 0xFFFFFF; + bool isExtern = RE->getExternal(); + uint32_t Val = RE->Address; if (isExtern) { symbol_iterator SI = begin_symbols(); diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index b4b876a..96aac23 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -26,17 +26,17 @@ ELF-NEXT: ] MACHO-I386: Relocations [ MACHO-I386-NEXT: Section __text { -MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 -MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 -MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} -MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction +MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main MACHO-I386-NEXT: } MACHO-I386-NEXT: ] MACHO-X86-64: Relocations [ MACHO-X86-64-NEXT: Section __text { -MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 -MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 -MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 +MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction +MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts +MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index a16bca2..a12d9e4 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -153,10 +153,10 @@ MACHO-I386-NEXT: ] MACHO-I386-NEXT: Reserved1: 0x0 MACHO-I386-NEXT: Reserved2: 0x0 MACHO-I386-NEXT: Relocations [ -MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 -MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 -MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} -MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction +MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main MACHO-I386-NEXT: ] MACHO-I386-NEXT: Symbols [ MACHO-I386-NEXT: Symbol { @@ -196,9 +196,9 @@ MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Reserved1: 0x0 MACHO-X86-64-NEXT: Reserved2: 0x0 MACHO-X86-64-NEXT: Relocations [ -MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 -MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 -MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 +MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction +MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts +MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Symbols [ MACHO-X86-64-NEXT: Symbol { diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 2073ddf..a13593b 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -330,20 +330,28 @@ void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; - int64_t Info; StringRef SymbolName; SymbolRef Symbol; if (error(RelI->getOffset(Offset))) return; if (error(RelI->getTypeName(RelocName))) return; - if (error(RelI->getAdditionalInfo(Info))) return; if (error(RelI->getSymbol(Symbol))) return; if (error(Symbol.getName(SymbolName))) return; + DataRefImpl DR = RelI->getRawDataRefImpl(); + const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR); + bool IsScattered = Obj->isScattered(RE); + raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << RelocName + << " " << Obj->isPCRel(RE) + << " " << Obj->getLength(RE); + if (IsScattered) + OS << " n/a"; + else + OS << " " << RE->getExternal(); + OS << " " << RelocName + << " " << IsScattered << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) << "\n"; } |