Index: llvm/trunk/tools/llvm-objdump/COFFDump.cpp =================================================================== --- llvm/trunk/tools/llvm-objdump/COFFDump.cpp +++ llvm/trunk/tools/llvm-objdump/COFFDump.cpp @@ -469,6 +469,19 @@ return false; } +std::error_code +llvm::getCOFFRelocationValueString(const COFFObjectFile *Obj, + const RelocationRef &Rel, + SmallVectorImpl &Result) { + symbol_iterator SymI = Rel.getSymbol(); + Expected SymNameOrErr = SymI->getName(); + if (!SymNameOrErr) + return errorToErrorCode(SymNameOrErr.takeError()); + StringRef SymName = *SymNameOrErr; + Result.append(SymName.begin(), SymName.end()); + return std::error_code(); +} + static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) { // The casts to int are required in order to output the value as number. // Without the casts the value would be interpreted as char data (which Index: llvm/trunk/tools/llvm-objdump/ELFDump.cpp =================================================================== --- llvm/trunk/tools/llvm-objdump/ELFDump.cpp +++ llvm/trunk/tools/llvm-objdump/ELFDump.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" @@ -52,6 +53,87 @@ } template +static std::error_code getRelocationValueString(const ELFObjectFile *Obj, + const RelocationRef &RelRef, + SmallVectorImpl &Result) { + typedef typename ELFObjectFile::Elf_Sym Elf_Sym; + typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; + typedef typename ELFObjectFile::Elf_Rela Elf_Rela; + + const ELFFile &EF = *Obj->getELFFile(); + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + auto SecOrErr = EF.getSection(Rel.d.a); + if (!SecOrErr) + return errorToErrorCode(SecOrErr.takeError()); + + int64_t Addend = 0; + // If there is no Symbol associated with the relocation, we set the undef + // boolean value to 'true'. This will prevent us from calling functions that + // requires the relocation to be associated with a symbol. + // + // In SHT_REL case we would need to read the addend from section data. + // GNU objdump does not do that and we just follow for simplicity atm. + bool Undef = false; + if ((*SecOrErr)->sh_type == ELF::SHT_RELA) { + const Elf_Rela *ERela = Obj->getRela(Rel); + Addend = ERela->r_addend; + Undef = ERela->getSymbol(false) == 0; + } else if ((*SecOrErr)->sh_type != ELF::SHT_REL) { + return object_error::parse_failed; + } + + // Default scheme is to print Target, as well as "+ " for nonzero + // addend. Should be acceptable for all normal purposes. + std::string FmtBuf; + raw_string_ostream Fmt(FmtBuf); + + if (!Undef) { + symbol_iterator SI = RelRef.getSymbol(); + const Elf_Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl()); + if (Sym->getType() == ELF::STT_SECTION) { + Expected SymSI = SI->getSection(); + if (!SymSI) + return errorToErrorCode(SymSI.takeError()); + const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); + auto SecName = EF.getSectionName(SymSec); + if (!SecName) + return errorToErrorCode(SecName.takeError()); + Fmt << *SecName; + } else { + Expected SymName = SI->getName(); + if (!SymName) + return errorToErrorCode(SymName.takeError()); + if (Demangle) + Fmt << demangle(*SymName); + else + Fmt << *SymName; + } + } else { + Fmt << "*ABS*"; + } + + if (Addend != 0) + Fmt << (Addend < 0 ? "" : "+") << Addend; + Fmt.flush(); + Result.append(FmtBuf.begin(), FmtBuf.end()); + return std::error_code(); +} + +std::error_code +llvm::getELFRelocationValueString(const ELFObjectFileBase *Obj, + const RelocationRef &Rel, + SmallVectorImpl &Result) { + if (auto *ELF32LE = dyn_cast(Obj)) + return getRelocationValueString(ELF32LE, Rel, Result); + if (auto *ELF64LE = dyn_cast(Obj)) + return getRelocationValueString(ELF64LE, Rel, Result); + if (auto *ELF32BE = dyn_cast(Obj)) + return getRelocationValueString(ELF32BE, Rel, Result); + auto *ELF64BE = cast(Obj); + return getRelocationValueString(ELF64BE, Rel, Result); +} + +template void printDynamicSection(const ELFFile *Elf, StringRef Filename) { auto ProgramHeaderOrError = Elf->program_headers(); if (!ProgramHeaderOrError) Index: llvm/trunk/tools/llvm-objdump/MachODump.cpp =================================================================== --- llvm/trunk/tools/llvm-objdump/MachODump.cpp +++ llvm/trunk/tools/llvm-objdump/MachODump.cpp @@ -342,6 +342,264 @@ } } +static void printRelocationTargetName(const MachOObjectFile *O, + const MachO::any_relocation_info &RE, + raw_string_ostream &Fmt) { + // 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 (O->isRelocationScattered(RE)) { + uint32_t Val = O->getPlainRelocationSymbolNum(RE); + + for (const SymbolRef &Symbol : O->symbols()) { + Expected Addr = Symbol.getAddress(); + if (!Addr) + report_error(O->getFileName(), Addr.takeError()); + if (*Addr != Val) + continue; + Expected Name = Symbol.getName(); + if (!Name) + report_error(O->getFileName(), Name.takeError()); + Fmt << *Name; + return; + } + + // If we couldn't find a symbol that this relocation refers to, try + // to find a section beginning instead. + for (const SectionRef &Section : ToolSectionFilter(*O)) { + std::error_code ec; + + StringRef Name; + uint64_t Addr = Section.getAddress(); + if (Addr != Val) + continue; + if ((ec = Section.getName(Name))) + report_error(O->getFileName(), ec); + Fmt << Name; + return; + } + + Fmt << format("0x%x", Val); + return; + } + + StringRef S; + bool isExtern = O->getPlainRelocationExternal(RE); + uint64_t Val = O->getPlainRelocationSymbolNum(RE); + + if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND) { + Fmt << format("0x%0" PRIx64, Val); + return; + } + + if (isExtern) { + symbol_iterator SI = O->symbol_begin(); + advance(SI, Val); + Expected SOrErr = SI->getName(); + if (!SOrErr) + report_error(O->getFileName(), SOrErr.takeError()); + S = *SOrErr; + } else { + section_iterator SI = O->section_begin(); + // Adjust for the fact that sections are 1-indexed. + if (Val == 0) { + Fmt << "0 (?,?)"; + return; + } + uint32_t I = Val - 1; + while (I != 0 && SI != O->section_end()) { + --I; + advance(SI, 1); + } + if (SI == O->section_end()) + Fmt << Val << " (?,?)"; + else + SI->getName(S); + } + + Fmt << S; +} + +std::error_code +llvm::getMachORelocationValueString(const MachOObjectFile *Obj, + const RelocationRef &RelRef, + SmallVectorImpl &Result) { + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + MachO::any_relocation_info RE = Obj->getRelocation(Rel); + + unsigned Arch = Obj->getArch(); + + std::string FmtBuf; + raw_string_ostream Fmt(FmtBuf); + unsigned Type = Obj->getAnyRelocationType(RE); + bool IsPCRel = Obj->getAnyRelocationPCRel(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) { + switch (Type) { + case MachO::X86_64_RELOC_GOT_LOAD: + case MachO::X86_64_RELOC_GOT: { + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "@GOT"; + if (IsPCRel) + Fmt << "PCREL"; + break; + } + case MachO::X86_64_RELOC_SUBTRACTOR: { + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type + // X86_64_RELOC_UNSIGNED. + // NOTE: Scattered relocations don't exist on x86_64. + unsigned RType = Obj->getAnyRelocationType(RENext); + if (RType != MachO::X86_64_RELOC_UNSIGNED) + report_error(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); + + // The X86_64_RELOC_UNSIGNED contains the minuend symbol; + // X86_64_RELOC_SUBTRACTOR contains the subtrahend. + printRelocationTargetName(Obj, RENext, Fmt); + Fmt << "-"; + printRelocationTargetName(Obj, RE, Fmt); + break; + } + case MachO::X86_64_RELOC_TLV: + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "@TLV"; + if (IsPCRel) + Fmt << "P"; + break; + case MachO::X86_64_RELOC_SIGNED_1: + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "-1"; + break; + case MachO::X86_64_RELOC_SIGNED_2: + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "-2"; + break; + case MachO::X86_64_RELOC_SIGNED_4: + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "-4"; + break; + default: + printRelocationTargetName(Obj, RE, Fmt); + break; + } + // X86 and ARM share some relocation types in common. + } else if (Arch == Triple::x86 || Arch == Triple::arm || + Arch == Triple::ppc) { + // Generic relocation types... + switch (Type) { + case MachO::GENERIC_RELOC_PAIR: // prints no info + return std::error_code(); + case MachO::GENERIC_RELOC_SECTDIFF: { + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = Obj->getAnyRelocationType(RENext); + + if (RType != MachO::GENERIC_RELOC_PAIR) + report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); + + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "-"; + printRelocationTargetName(Obj, RENext, Fmt); + break; + } + } + + if (Arch == Triple::x86 || Arch == Triple::ppc) { + switch (Type) { + case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = Obj->getAnyRelocationType(RENext); + if (RType != MachO::GENERIC_RELOC_PAIR) + report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); + + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "-"; + printRelocationTargetName(Obj, RENext, Fmt); + break; + } + case MachO::GENERIC_RELOC_TLV: { + printRelocationTargetName(Obj, RE, Fmt); + Fmt << "@TLV"; + if (IsPCRel) + Fmt << "P"; + break; + } + default: + printRelocationTargetName(Obj, RE, Fmt); + } + } else { // ARM-specific relocations + switch (Type) { + case MachO::ARM_RELOC_HALF: + case MachO::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 = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; + + if (isUpper) + Fmt << ":upper16:("; + else + Fmt << ":lower16:("; + printRelocationTargetName(Obj, RE, Fmt); + + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // ARM half relocs must be followed by a relocation of type + // ARM_RELOC_PAIR. + unsigned RType = Obj->getAnyRelocationType(RENext); + if (RType != MachO::ARM_RELOC_PAIR) + report_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " + "ARM_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::ARM_RELOC_HALF_SECTDIFF) { + Fmt << "-"; + printRelocationTargetName(Obj, RENext, Fmt); + } + + Fmt << ")"; + break; + } + default: { + printRelocationTargetName(Obj, RE, Fmt); + } + } + } + } else + printRelocationTargetName(Obj, RE, Fmt); + + Fmt.flush(); + Result.append(FmtBuf.begin(), FmtBuf.end()); + return std::error_code(); +} + static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, uint32_t n, uint32_t count, uint32_t stride, uint64_t addr) { Index: llvm/trunk/tools/llvm-objdump/WasmDump.cpp =================================================================== --- llvm/trunk/tools/llvm-objdump/WasmDump.cpp +++ llvm/trunk/tools/llvm-objdump/WasmDump.cpp @@ -26,3 +26,28 @@ outs().write_hex(File->getHeader().Version); outs() << "\n"; } + +std::error_code +llvm::getWasmRelocationValueString(const WasmObjectFile *Obj, + const RelocationRef &RelRef, + SmallVectorImpl &Result) { + const wasm::WasmRelocation &Rel = Obj->getWasmRelocation(RelRef); + symbol_iterator SI = RelRef.getSymbol(); + std::string FmtBuf; + raw_string_ostream Fmt(FmtBuf); + if (SI == Obj->symbol_end()) { + // Not all wasm relocations have symbols associated with them. + // In particular R_WEBASSEMBLY_TYPE_INDEX_LEB. + Fmt << Rel.Index; + } else { + Expected SymNameOrErr = SI->getName(); + if (!SymNameOrErr) + return errorToErrorCode(SymNameOrErr.takeError()); + StringRef SymName = *SymNameOrErr; + Result.append(SymName.begin(), SymName.end()); + } + Fmt << (Rel.Addend < 0 ? "" : "+") << Rel.Addend; + Fmt.flush(); + Result.append(FmtBuf.begin(), FmtBuf.end()); + return std::error_code(); +} Index: llvm/trunk/tools/llvm-objdump/llvm-objdump.h =================================================================== --- llvm/trunk/tools/llvm-objdump/llvm-objdump.h +++ llvm/trunk/tools/llvm-objdump/llvm-objdump.h @@ -19,13 +19,14 @@ class StringRef; namespace object { - class COFFObjectFile; - class COFFImportFile; - class MachOObjectFile; - class MachOUniversalBinary; - class ObjectFile; - class Archive; - class RelocationRef; +class COFFObjectFile; +class COFFImportFile; +class ELFObjectFileBase; +class MachOObjectFile; +class MachOUniversalBinary; +class ObjectFile; +class Archive; +class RelocationRef; } extern cl::opt TripleName; @@ -68,7 +69,75 @@ extern cl::opt PrintImmHex; extern cl::opt DwarfDumpType; +typedef std::function FilterPredicate; + +class SectionFilterIterator { +public: + SectionFilterIterator(FilterPredicate P, + llvm::object::section_iterator const &I, + llvm::object::section_iterator const &E) + : Predicate(std::move(P)), Iterator(I), End(E) { + ScanPredicate(); + } + const llvm::object::SectionRef &operator*() const { return *Iterator; } + SectionFilterIterator &operator++() { + ++Iterator; + ScanPredicate(); + return *this; + } + bool operator!=(SectionFilterIterator const &Other) const { + return Iterator != Other.Iterator; + } + +private: + void ScanPredicate() { + while (Iterator != End && !Predicate(*Iterator)) { + ++Iterator; + } + } + FilterPredicate Predicate; + llvm::object::section_iterator Iterator; + llvm::object::section_iterator End; +}; + +class SectionFilter { +public: + SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O) + : Predicate(std::move(P)), Object(O) {} + SectionFilterIterator begin() { + return SectionFilterIterator(Predicate, Object.section_begin(), + Object.section_end()); + } + SectionFilterIterator end() { + return SectionFilterIterator(Predicate, Object.section_end(), + Object.section_end()); + } + +private: + FilterPredicate Predicate; + llvm::object::ObjectFile const &Object; +}; + // Various helper functions. +SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O); + +std::error_code +getELFRelocationValueString(const object::ELFObjectFileBase *Obj, + const object::RelocationRef &Rel, + llvm::SmallVectorImpl &Result); +std::error_code +getCOFFRelocationValueString(const object::COFFObjectFile *Obj, + const object::RelocationRef &Rel, + llvm::SmallVectorImpl &Result); +std::error_code +getWasmRelocationValueString(const object::WasmObjectFile *Obj, + const object::RelocationRef &RelRef, + llvm::SmallVectorImpl &Result); +std::error_code +getMachORelocationValueString(const object::MachOObjectFile *Obj, + const object::RelocationRef &RelRef, + llvm::SmallVectorImpl &Result); + void error(std::error_code ec); bool isRelocAddressLess(object::RelocationRef A, object::RelocationRef B); void parseInputMachO(StringRef Filename); Index: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp @@ -281,56 +281,7 @@ typedef std::vector> SectionSymbolsTy; -namespace { -typedef std::function FilterPredicate; - -class SectionFilterIterator { -public: - SectionFilterIterator(FilterPredicate P, - llvm::object::section_iterator const &I, - llvm::object::section_iterator const &E) - : Predicate(std::move(P)), Iterator(I), End(E) { - ScanPredicate(); - } - const llvm::object::SectionRef &operator*() const { return *Iterator; } - SectionFilterIterator &operator++() { - ++Iterator; - ScanPredicate(); - return *this; - } - bool operator!=(SectionFilterIterator const &Other) const { - return Iterator != Other.Iterator; - } - -private: - void ScanPredicate() { - while (Iterator != End && !Predicate(*Iterator)) { - ++Iterator; - } - } - FilterPredicate Predicate; - llvm::object::section_iterator Iterator; - llvm::object::section_iterator End; -}; - -class SectionFilter { -public: - SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O) - : Predicate(std::move(P)), Object(O) {} - SectionFilterIterator begin() { - return SectionFilterIterator(Predicate, Object.section_begin(), - Object.section_end()); - } - SectionFilterIterator end() { - return SectionFilterIterator(Predicate, Object.section_end(), - Object.section_end()); - } - -private: - FilterPredicate Predicate; - llvm::object::ObjectFile const &Object; -}; -SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) { +SectionFilter llvm::ToolSectionFilter(llvm::object::ObjectFile const &O) { return SectionFilter( [](llvm::object::SectionRef const &S) { if (FilterSections.empty()) @@ -343,7 +294,6 @@ }, O); } -} void llvm::error(std::error_code EC) { if (!EC) @@ -464,388 +414,17 @@ return A.getOffset() < B.getOffset(); } -template -static std::error_code getRelocationValueString(const ELFObjectFile *Obj, - const RelocationRef &RelRef, - SmallVectorImpl &Result) { - typedef typename ELFObjectFile::Elf_Sym Elf_Sym; - typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; - typedef typename ELFObjectFile::Elf_Rela Elf_Rela; - - const ELFFile &EF = *Obj->getELFFile(); - DataRefImpl Rel = RelRef.getRawDataRefImpl(); - auto SecOrErr = EF.getSection(Rel.d.a); - if (!SecOrErr) - return errorToErrorCode(SecOrErr.takeError()); - - int64_t Addend = 0; - // If there is no Symbol associated with the relocation, we set the undef - // boolean value to 'true'. This will prevent us from calling functions that - // requires the relocation to be associated with a symbol. - // - // In SHT_REL case we would need to read the addend from section data. - // GNU objdump does not do that and we just follow for simplicity. - bool Undef = false; - if ((*SecOrErr)->sh_type == ELF::SHT_RELA) { - const Elf_Rela *ERela = Obj->getRela(Rel); - Addend = ERela->r_addend; - Undef = ERela->getSymbol(false) == 0; - } else if ((*SecOrErr)->sh_type != ELF::SHT_REL) { - return object_error::parse_failed; - } - - // Default scheme is to print Target, as well as "+ " for nonzero - // addend. Should be acceptable for all normal purposes. - std::string FmtBuf; - raw_string_ostream Fmt(FmtBuf); - - if (!Undef) { - symbol_iterator SI = RelRef.getSymbol(); - const Elf_Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl()); - if (Sym->getType() == ELF::STT_SECTION) { - Expected SymSI = SI->getSection(); - if (!SymSI) - return errorToErrorCode(SymSI.takeError()); - const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); - auto SecName = EF.getSectionName(SymSec); - if (!SecName) - return errorToErrorCode(SecName.takeError()); - Fmt << *SecName; - } else { - Expected SymName = SI->getName(); - if (!SymName) - return errorToErrorCode(SymName.takeError()); - if (Demangle) - Fmt << demangle(*SymName); - else - Fmt << *SymName; - } - } else { - Fmt << "*ABS*"; - } - - if (Addend != 0) - Fmt << (Addend < 0 ? "" : "+") << Addend; - Fmt.flush(); - Result.append(FmtBuf.begin(), FmtBuf.end()); - return std::error_code(); -} - -static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj, - const RelocationRef &Rel, - SmallVectorImpl &Result) { - if (auto *ELF32LE = dyn_cast(Obj)) - return getRelocationValueString(ELF32LE, Rel, Result); - if (auto *ELF64LE = dyn_cast(Obj)) - return getRelocationValueString(ELF64LE, Rel, Result); - if (auto *ELF32BE = dyn_cast(Obj)) - return getRelocationValueString(ELF32BE, Rel, Result); - auto *ELF64BE = cast(Obj); - return getRelocationValueString(ELF64BE, Rel, Result); -} - -static std::error_code getRelocationValueString(const COFFObjectFile *Obj, - const RelocationRef &Rel, - SmallVectorImpl &Result) { - symbol_iterator SymI = Rel.getSymbol(); - Expected SymNameOrErr = SymI->getName(); - if (!SymNameOrErr) - return errorToErrorCode(SymNameOrErr.takeError()); - StringRef SymName = *SymNameOrErr; - Result.append(SymName.begin(), SymName.end()); - return std::error_code(); -} - -static void printRelocationTargetName(const MachOObjectFile *O, - const MachO::any_relocation_info &RE, - raw_string_ostream &Fmt) { - // 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 (O->isRelocationScattered(RE)) { - uint32_t Val = O->getPlainRelocationSymbolNum(RE); - - for (const SymbolRef &Symbol : O->symbols()) { - Expected Addr = Symbol.getAddress(); - if (!Addr) - report_error(O->getFileName(), Addr.takeError()); - if (*Addr != Val) - continue; - Expected Name = Symbol.getName(); - if (!Name) - report_error(O->getFileName(), Name.takeError()); - Fmt << *Name; - return; - } - - // If we couldn't find a symbol that this relocation refers to, try - // to find a section beginning instead. - for (const SectionRef &Section : ToolSectionFilter(*O)) { - std::error_code ec; - - StringRef Name; - uint64_t Addr = Section.getAddress(); - if (Addr != Val) - continue; - if ((ec = Section.getName(Name))) - report_error(O->getFileName(), ec); - Fmt << Name; - return; - } - - Fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = O->getPlainRelocationExternal(RE); - uint64_t Val = O->getPlainRelocationSymbolNum(RE); - - if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND) { - Fmt << format("0x%0" PRIx64, Val); - return; - } - - if (isExtern) { - symbol_iterator SI = O->symbol_begin(); - advance(SI, Val); - Expected SOrErr = SI->getName(); - if (!SOrErr) - report_error(O->getFileName(), SOrErr.takeError()); - S = *SOrErr; - } else { - section_iterator SI = O->section_begin(); - // Adjust for the fact that sections are 1-indexed. - if (Val == 0) { - Fmt << "0 (?,?)"; - return; - } - uint32_t I = Val - 1; - while (I != 0 && SI != O->section_end()) { - --I; - advance(SI, 1); - } - if (SI == O->section_end()) - Fmt << Val << " (?,?)"; - else - SI->getName(S); - } - - Fmt << S; -} - -static std::error_code getRelocationValueString(const WasmObjectFile *Obj, - const RelocationRef &RelRef, - SmallVectorImpl &Result) { - const wasm::WasmRelocation& Rel = Obj->getWasmRelocation(RelRef); - symbol_iterator SI = RelRef.getSymbol(); - std::string FmtBuf; - raw_string_ostream Fmt(FmtBuf); - if (SI == Obj->symbol_end()) { - // Not all wasm relocations have symbols associated with them. - // In particular R_WEBASSEMBLY_TYPE_INDEX_LEB. - Fmt << Rel.Index; - } else { - Expected SymNameOrErr = SI->getName(); - if (!SymNameOrErr) - return errorToErrorCode(SymNameOrErr.takeError()); - StringRef SymName = *SymNameOrErr; - Result.append(SymName.begin(), SymName.end()); - } - Fmt << (Rel.Addend < 0 ? "" : "+") << Rel.Addend; - Fmt.flush(); - Result.append(FmtBuf.begin(), FmtBuf.end()); - return std::error_code(); -} - -static std::error_code getRelocationValueString(const MachOObjectFile *Obj, - const RelocationRef &RelRef, - SmallVectorImpl &Result) { - DataRefImpl Rel = RelRef.getRawDataRefImpl(); - MachO::any_relocation_info RE = Obj->getRelocation(Rel); - - unsigned Arch = Obj->getArch(); - - std::string FmtBuf; - raw_string_ostream Fmt(FmtBuf); - unsigned Type = Obj->getAnyRelocationType(RE); - bool IsPCRel = Obj->getAnyRelocationPCRel(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) { - switch (Type) { - case MachO::X86_64_RELOC_GOT_LOAD: - case MachO::X86_64_RELOC_GOT: { - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "@GOT"; - if (IsPCRel) - Fmt << "PCREL"; - break; - } - case MachO::X86_64_RELOC_SUBTRACTOR: { - DataRefImpl RelNext = Rel; - Obj->moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); - - // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type - // X86_64_RELOC_UNSIGNED. - // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = Obj->getAnyRelocationType(RENext); - if (RType != MachO::X86_64_RELOC_UNSIGNED) - report_error(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); - - // The X86_64_RELOC_UNSIGNED contains the minuend symbol; - // X86_64_RELOC_SUBTRACTOR contains the subtrahend. - printRelocationTargetName(Obj, RENext, Fmt); - Fmt << "-"; - printRelocationTargetName(Obj, RE, Fmt); - break; - } - case MachO::X86_64_RELOC_TLV: - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "@TLV"; - if (IsPCRel) - Fmt << "P"; - break; - case MachO::X86_64_RELOC_SIGNED_1: - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "-1"; - break; - case MachO::X86_64_RELOC_SIGNED_2: - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "-2"; - break; - case MachO::X86_64_RELOC_SIGNED_4: - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "-4"; - break; - default: - printRelocationTargetName(Obj, RE, Fmt); - break; - } - // X86 and ARM share some relocation types in common. - } else if (Arch == Triple::x86 || Arch == Triple::arm || - Arch == Triple::ppc) { - // Generic relocation types... - switch (Type) { - case MachO::GENERIC_RELOC_PAIR: // prints no info - return std::error_code(); - case MachO::GENERIC_RELOC_SECTDIFF: { - DataRefImpl RelNext = Rel; - Obj->moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - unsigned RType = Obj->getAnyRelocationType(RENext); - - if (RType != MachO::GENERIC_RELOC_PAIR) - report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); - - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "-"; - printRelocationTargetName(Obj, RENext, Fmt); - break; - } - } - - if (Arch == Triple::x86 || Arch == Triple::ppc) { - switch (Type) { - case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { - DataRefImpl RelNext = Rel; - Obj->moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - unsigned RType = Obj->getAnyRelocationType(RENext); - if (RType != MachO::GENERIC_RELOC_PAIR) - report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); - - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "-"; - printRelocationTargetName(Obj, RENext, Fmt); - break; - } - case MachO::GENERIC_RELOC_TLV: { - printRelocationTargetName(Obj, RE, Fmt); - Fmt << "@TLV"; - if (IsPCRel) - Fmt << "P"; - break; - } - default: - printRelocationTargetName(Obj, RE, Fmt); - } - } else { // ARM-specific relocations - switch (Type) { - case MachO::ARM_RELOC_HALF: - case MachO::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 = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; - - if (isUpper) - Fmt << ":upper16:("; - else - Fmt << ":lower16:("; - printRelocationTargetName(Obj, RE, Fmt); - - DataRefImpl RelNext = Rel; - Obj->moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); - - // ARM half relocs must be followed by a relocation of type - // ARM_RELOC_PAIR. - unsigned RType = Obj->getAnyRelocationType(RENext); - if (RType != MachO::ARM_RELOC_PAIR) - report_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " - "ARM_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::ARM_RELOC_HALF_SECTDIFF) { - Fmt << "-"; - printRelocationTargetName(Obj, RENext, Fmt); - } - - Fmt << ")"; - break; - } - default: { printRelocationTargetName(Obj, RE, Fmt); } - } - } - } else - printRelocationTargetName(Obj, RE, Fmt); - - Fmt.flush(); - Result.append(FmtBuf.begin(), FmtBuf.end()); - return std::error_code(); -} - static std::error_code getRelocationValueString(const RelocationRef &Rel, SmallVectorImpl &Result) { const ObjectFile *Obj = Rel.getObject(); if (auto *ELF = dyn_cast(Obj)) - return getRelocationValueString(ELF, Rel, Result); + return getELFRelocationValueString(ELF, Rel, Result); if (auto *COFF = dyn_cast(Obj)) - return getRelocationValueString(COFF, Rel, Result); + return getCOFFRelocationValueString(COFF, Rel, Result); if (auto *Wasm = dyn_cast(Obj)) - return getRelocationValueString(Wasm, Rel, Result); + return getWasmRelocationValueString(Wasm, Rel, Result); if (auto *MachO = dyn_cast(Obj)) - return getRelocationValueString(MachO, Rel, Result); + return getMachORelocationValueString(MachO, Rel, Result); llvm_unreachable("unknown object file format"); }