From 4edf092787cab37d46da96eb1e9df0677ca30b1d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 11 Apr 2013 16:31:37 +0000 Subject: [PATCH] Print more information about relocations. With this patch llvm-readobj now prints if a relocation is pcrel, its length, if it is extern and if it is scattered. It also refactors the code a bit to use bit fields instead of shifts and masks all over the place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179294 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 118 ++++++++++------------ lib/Object/MachOObjectFile.cpp | 52 ++++++++-- test/tools/llvm-readobj/relocations.test | 14 +-- test/tools/llvm-readobj/sections-ext.test | 14 +-- tools/llvm-readobj/MachODumper.cpp | 16 ++- 5 files changed, 124 insertions(+), 90 deletions(-) diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index b02e1ac1007..1fd8b6c92c3 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -115,8 +115,23 @@ namespace MachOFormat { template struct RelocationEntry { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) - MachOInt32 Word0; - MachOInt32 Word1; + MachOInt32 Address; + unsigned SymbolNum : 24; + unsigned PCRel : 1; + unsigned Length : 2; + unsigned External : 1; + unsigned Type : 4; + }; + + template + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + unsigned Address : 24; + unsigned Type : 4; + unsigned Length : 2; + unsigned PCRel : 1; + unsigned Scattered : 1; + MachOInt32 Value; }; template @@ -206,6 +221,8 @@ public: SymbolTableEntryBase; typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry + ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; typedef MachOFormat::LoadCommand LoadCommand; typedef MachOFormat::Header Header; @@ -243,6 +260,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 +501,12 @@ MachOObjectFile::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 +517,10 @@ error_code MachOObjectFile::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 +529,8 @@ error_code MachOObjectFile::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->External; DataRefImpl Sym; moveToNextSymbol(Sym); @@ -535,9 +550,7 @@ template error_code MachOObjectFile::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 +563,8 @@ MachOObjectFile::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 +657,20 @@ MachOObjectFile::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->PCRel; switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD @@ -691,7 +688,7 @@ MachOObjectFile::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->Type; if (RType != 0) report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " "X86_64_RELOC_SUBTRACTOR."); @@ -738,12 +735,12 @@ MachOObjectFile::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->Type; if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); @@ -767,12 +764,12 @@ MachOObjectFile::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->Type; if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); @@ -785,7 +782,7 @@ MachOObjectFile::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 +795,10 @@ MachOObjectFile::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->Length >> 1) & 1; if (isUpper) fmt << ":upper16:("; @@ -816,12 +813,12 @@ MachOObjectFile::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->Type; if (RType != 1) report_fatal_error("Expected ARM_RELOC_PAIR after " @@ -860,15 +857,8 @@ error_code MachOObjectFile::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 +874,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, RelPrev.d.a--; const RelocationEntry *REPrev = getRelocation(RelPrev); - unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + unsigned PrevType = REPrev->Type; if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index c846206e6e4..98e28db88dc 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(this)) + return O->getRelocation(Rel); + const MachOObjectFile64Le *O = dyn_cast(this); + return O->getRelocation(Rel); +} + +bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { + unsigned Arch = getArch(); + return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); +} + +bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->PCRel; + } + return RE->PCRel; +} + +unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->Length; + } + return RE->Length; +} + +unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->Type; + } + return RE->Type; +} + 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->External; + 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 b4b876a70b0..96aac231dba 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 a16bca2b19d..a12d9e46466 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 2073ddf4639..b027d40beac 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->External; + OS << " " << RelocName + << " " << IsScattered << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) << "\n"; }