From 8c7a0fd91a1a0a64bba5545bc45c634f4315a2e3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 3 Jun 2015 04:48:06 +0000 Subject: [PATCH] Move to llvm-objdump a large amount of code to that is only used there. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238898 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 4 - include/llvm/Object/ELFObjectFile.h | 84 ------ include/llvm/Object/MachO.h | 3 - include/llvm/Object/ObjectFile.h | 13 - lib/Object/COFFObjectFile.cpp | 16 -- lib/Object/MachOObjectFile.cpp | 240 ----------------- lib/Object/Object.cpp | 8 +- tools/llvm-objdump/llvm-objdump.cpp | 385 +++++++++++++++++++++++++++- 8 files changed, 383 insertions(+), 370 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index faf3249f307..762f46b45bd 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -647,10 +647,6 @@ protected: std::error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - public: COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); basic_symbol_iterator symbol_begin_impl() const override; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 1a9e2dadd67..6addf499b4a 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -118,9 +118,6 @@ protected: std::error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -707,87 +704,6 @@ ELFObjectFile::getRelocationAddend(DataRefImpl Rel, } } -template -std::error_code ELFObjectFile::getRelocationValueString( - DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - uint8_t type; - StringRef res; - int64_t addend = 0; - uint16_t symbol_index = 0; - switch (sec->sh_type) { - default: - return object_error::parse_failed; - case ELF::SHT_REL: { - type = getRel(Rel)->getType(EF.isMips64EL()); - symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); - // TODO: Read implicit addend from section data. - break; - } - case ELF::SHT_RELA: { - type = getRela(Rel)->getType(EF.isMips64EL()); - symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); - addend = getRela(Rel)->r_addend; - break; - } - } - const Elf_Sym *symb = - EF.template getEntry(sec->sh_link, symbol_index); - ErrorOr SymName = - EF.getSymbolName(EF.getSection(sec->sh_link), symb); - if (!SymName) - return SymName.getError(); - switch (EF.getHeader()->e_machine) { - case ELF::EM_X86_64: - switch (type) { - case ELF::R_X86_64_PC8: - case ELF::R_X86_64_PC16: - case ELF::R_X86_64_PC32: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } break; - case ELF::R_X86_64_8: - case ELF::R_X86_64_16: - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - case ELF::R_X86_64_64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << *SymName << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } break; - default: - res = "Unknown"; - } - break; - case ELF::EM_AARCH64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << *SymName; - if (addend != 0) - fmt << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - break; - } - case ELF::EM_386: - case ELF::EM_ARM: - case ELF::EM_HEXAGON: - case ELF::EM_MIPS: - res = *SymName; - break; - default: - res = "Unknown"; - } - if (Result.empty()) - Result.append(res.begin(), res.end()); - return object_error::success; -} - template const typename ELFFile::Elf_Sym * ELFObjectFile::getSymbol(DataRefImpl Symb) const { diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index d5e6929d99f..d8bb85d6f78 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -240,9 +240,6 @@ public: std::error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; std::error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; uint8_t getRelocationLength(DataRefImpl Rel) const; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index d94d4870726..b938737437a 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -66,11 +66,6 @@ public: /// This is for display purposes only. std::error_code getTypeName(SmallVectorImpl &Result) const; - /// @brief Get a string that represents the calculation of the value of this - /// relocation. - /// - /// This is for display purposes only. - std::error_code getValueString(SmallVectorImpl &Result) const; DataRefImpl getRawDataRefImpl() const; const ObjectFile *getObjectFile() const; @@ -252,9 +247,6 @@ protected: virtual std::error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const = 0; - virtual std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const = 0; virtual std::error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const { Result = false; @@ -480,11 +472,6 @@ RelocationRef::getTypeName(SmallVectorImpl &Result) const { return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline std::error_code -RelocationRef::getValueString(SmallVectorImpl &Result) const { - return OwningObject->getRelocationValueString(RelocationPimpl, Result); -} - inline std::error_code RelocationRef::getHidden(bool &Result) const { return OwningObject->getRelocationHidden(RelocationPimpl, Result); } diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 96c7fae79eb..f98ca4c90e3 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -1114,22 +1114,6 @@ COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME -std::error_code -COFFObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const { - const coff_relocation *Reloc = toRel(Rel); - DataRefImpl Sym; - ErrorOr Symb = getSymbol(Reloc->SymbolTableIndex); - if (std::error_code EC = Symb.getError()) - return EC; - Sym.p = reinterpret_cast(Symb->getRawPtr()); - StringRef SymName; - if (std::error_code EC = getSymbolName(Sym, SymName)) - return EC; - Result.append(SymName.begin(), SymName.end()); - return object_error::success; -} - bool COFFObjectFile::isRelocatableObject() const { return !DataDirectory; } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index e1ace497ca2..01f2fc5d488 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -128,70 +128,6 @@ static unsigned getCPUType(const MachOObjectFile *O) { return O->getHeader().cputype; } -static void printRelocationTargetName(const MachOObjectFile *O, - const MachO::any_relocation_info &RE, - raw_string_ostream &fmt) { - bool IsScattered = O->isRelocationScattered(RE); - - // 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 = O->getPlainRelocationSymbolNum(RE); - - for (const SymbolRef &Symbol : O->symbols()) { - std::error_code ec; - uint64_t Addr; - StringRef Name; - - if ((ec = Symbol.getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) - continue; - if ((ec = Symbol.getName(Name))) - report_fatal_error(ec.message()); - 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 : O->sections()) { - std::error_code ec; - - StringRef Name; - uint64_t Addr = Section.getAddress(); - if (Addr != Val) - continue; - if ((ec = Section.getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = O->getPlainRelocationExternal(RE); - uint64_t Val = O->getPlainRelocationSymbolNum(RE); - - if (isExtern) { - symbol_iterator SI = O->symbol_begin(); - advance(SI, Val); - SI->getName(S); - } else { - section_iterator SI = O->section_begin(); - // Adjust for the fact that sections are 1-indexed. - advance(SI, Val - 1); - SI->getName(S); - } - - fmt << S; -} - static uint32_t getPlainRelocationAddress(const MachO::any_relocation_info &RE) { return RE.r_word0; @@ -794,182 +730,6 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, return object_error::success; } -std::error_code -MachOObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const { - MachO::any_relocation_info RE = getRelocation(Rel); - - unsigned Arch = this->getArch(); - - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - unsigned Type = this->getAnyRelocationType(RE); - bool IsPCRel = this->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) { - bool isPCRel = getAnyRelocationPCRel(RE); - - switch (Type) { - case MachO::X86_64_RELOC_GOT_LOAD: - case MachO::X86_64_RELOC_GOT: { - printRelocationTargetName(this, RE, fmt); - fmt << "@GOT"; - if (isPCRel) fmt << "PCREL"; - break; - } - case MachO::X86_64_RELOC_SUBTRACTOR: { - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = 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 = getAnyRelocationType(RENext); - if (RType != MachO::X86_64_RELOC_UNSIGNED) - report_fatal_error("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(this, RENext, fmt); - fmt << "-"; - printRelocationTargetName(this, RE, fmt); - break; - } - case MachO::X86_64_RELOC_TLV: - printRelocationTargetName(this, RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - case MachO::X86_64_RELOC_SIGNED_1: - printRelocationTargetName(this, RE, fmt); - fmt << "-1"; - break; - case MachO::X86_64_RELOC_SIGNED_2: - printRelocationTargetName(this, RE, fmt); - fmt << "-2"; - break; - case MachO::X86_64_RELOC_SIGNED_4: - printRelocationTargetName(this, RE, fmt); - fmt << "-4"; - break; - default: - printRelocationTargetName(this, 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 object_error::success; - case MachO::GENERIC_RELOC_SECTDIFF: { - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - unsigned RType = getAnyRelocationType(RENext); - - if (RType != MachO::GENERIC_RELOC_PAIR) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); - - printRelocationTargetName(this, RE, fmt); - fmt << "-"; - printRelocationTargetName(this, RENext, fmt); - break; - } - } - - if (Arch == Triple::x86 || Arch == Triple::ppc) { - switch (Type) { - case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - unsigned RType = getAnyRelocationType(RENext); - if (RType != MachO::GENERIC_RELOC_PAIR) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); - - printRelocationTargetName(this, RE, fmt); - fmt << "-"; - printRelocationTargetName(this, RENext, fmt); - break; - } - case MachO::GENERIC_RELOC_TLV: { - printRelocationTargetName(this, RE, fmt); - fmt << "@TLV"; - if (IsPCRel) fmt << "P"; - break; - } - default: - printRelocationTargetName(this, 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 = getAnyRelocationLength(RE) >> 1; - - if (isUpper) - fmt << ":upper16:("; - else - fmt << ":lower16:("; - printRelocationTargetName(this, RE, fmt); - - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // ARM half relocs must be followed by a relocation of type - // ARM_RELOC_PAIR. - unsigned RType = getAnyRelocationType(RENext); - if (RType != MachO::ARM_RELOC_PAIR) - report_fatal_error("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(this, RENext, fmt); - } - - fmt << ")"; - break; - } - default: { - printRelocationTargetName(this, RE, fmt); - } - } - } - } else - printRelocationTargetName(this, RE, fmt); - - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - return object_error::success; -} - std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { unsigned Arch = getArch(); diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index 67e50243a49..85f243675ef 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -230,12 +230,6 @@ const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { // NOTE: Caller takes ownership of returned string. const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { - SmallVector ret; - if (std::error_code ec = (*unwrap(RI))->getValueString(ret)) - report_fatal_error(ec.message()); - - char *str = static_cast(malloc(ret.size())); - std::copy(ret.begin(), ret.end(), str); - return str; + return strdup(""); } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index d4127b56fc6..75099314037 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -32,6 +32,7 @@ #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/COFF.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" @@ -281,6 +282,384 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { } } +template +static const typename ELFObjectFile::Elf_Rel * +getRel(const ELFFile &EF, DataRefImpl Rel) { + typedef typename ELFObjectFile::Elf_Rel Elf_Rel; + return EF.template getEntry(Rel.d.a, Rel.d.b); +} + +template +static const typename ELFObjectFile::Elf_Rela * +getRela(const ELFFile &EF, DataRefImpl Rela) { + typedef typename ELFObjectFile::Elf_Rela Elf_Rela; + return EF.template getEntry(Rela.d.a, Rela.d.b); +} + +template +static std::error_code getRelocationValueString(const ELFObjectFile *Obj, + DataRefImpl Rel, + SmallVectorImpl &Result) { + typedef typename ELFObjectFile::Elf_Sym Elf_Sym; + typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; + const ELFFile &EF = *Obj->getELFFile(); + + const Elf_Shdr *sec = EF.getSection(Rel.d.a); + uint8_t type; + StringRef res; + int64_t addend = 0; + uint16_t symbol_index = 0; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(EF, Rel)->getType(EF.isMips64EL()); + symbol_index = getRel(EF, Rel)->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + type = getRela(EF, Rel)->getType(EF.isMips64EL()); + symbol_index = getRela(EF, Rel)->getSymbol(EF.isMips64EL()); + addend = getRela(EF, Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry(sec->sh_link, symbol_index); + ErrorOr SymName = + EF.getSymbolName(EF.getSection(sec->sh_link), symb); + if (!SymName) + return SymName.getError(); + switch (EF.getHeader()->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_PC8: + case ELF::R_X86_64_PC16: + case ELF::R_X86_64_PC32: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + case ELF::R_X86_64_8: + case ELF::R_X86_64_16: + case ELF::R_X86_64_32: + case ELF::R_X86_64_32S: + case ELF::R_X86_64_64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + default: + res = "Unknown"; + } + break; + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } + case ELF::EM_386: + case ELF::EM_ARM: + case ELF::EM_HEXAGON: + case ELF::EM_MIPS: + res = *SymName; + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return object_error::success; +} + +static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj, + const RelocationRef &RelRef, + SmallVectorImpl &Result) { + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + 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(); + StringRef SymName; + if (std::error_code EC = SymI->getName(SymName)) + return EC; + Result.append(SymName.begin(), SymName.end()); + return object_error::success; +} + +static void printRelocationTargetName(const MachOObjectFile *O, + const MachO::any_relocation_info &RE, + raw_string_ostream &fmt) { + bool IsScattered = O->isRelocationScattered(RE); + + // 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 = O->getPlainRelocationSymbolNum(RE); + + for (const SymbolRef &Symbol : O->symbols()) { + std::error_code ec; + uint64_t Addr; + StringRef Name; + + if ((ec = Symbol.getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) + continue; + if ((ec = Symbol.getName(Name))) + report_fatal_error(ec.message()); + 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 : O->sections()) { + std::error_code ec; + + StringRef Name; + uint64_t Addr = Section.getAddress(); + if (Addr != Val) + continue; + if ((ec = Section.getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + fmt << format("0x%x", Val); + return; + } + + StringRef S; + bool isExtern = O->getPlainRelocationExternal(RE); + uint64_t Val = O->getPlainRelocationSymbolNum(RE); + + if (isExtern) { + symbol_iterator SI = O->symbol_begin(); + advance(SI, Val); + SI->getName(S); + } else { + section_iterator SI = O->section_begin(); + // Adjust for the fact that sections are 1-indexed. + advance(SI, Val - 1); + SI->getName(S); + } + + fmt << S; +} + +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) { + bool isPCRel = Obj->getAnyRelocationPCRel(RE); + + 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_fatal_error("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 object_error::success; + 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_fatal_error("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_fatal_error("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) >> 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_fatal_error("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 object_error::success; +} + +static std::error_code getRelocationValueString(const RelocationRef &Rel, + SmallVectorImpl &Result) { + const ObjectFile *Obj = Rel.getObjectFile(); + if (auto *ELF = dyn_cast(Obj)) + return getRelocationValueString(ELF, Rel, Result); + if (auto *COFF = dyn_cast(Obj)) + return getRelocationValueString(COFF, Rel, Result); + auto *MachO = cast(Obj); + return getRelocationValueString(MachO, Rel, Result); +} + static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = getTarget(Obj); // getTarget() will have already issued a diagnostic if necessary, so @@ -491,8 +870,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; if (error(rel_cur->getTypeName(name))) goto skip_print_rel; - if (error(rel_cur->getValueString(val))) goto skip_print_rel; - + if (error(getRelocationValueString(*rel_cur, val))) + goto skip_print_rel; outs() << format(Fmt.data(), SectionAddr + addr) << name << "\t" << val << "\n"; @@ -532,7 +911,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { continue; if (error(Reloc.getOffset(address))) continue; - if (error(Reloc.getValueString(valuestr))) + if (error(getRelocationValueString(Reloc, valuestr))) continue; outs() << format(Fmt.data(), address) << " " << relocname << " " << valuestr << "\n"; -- 2.34.1