diff options
Diffstat (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.cpp | 431 |
1 files changed, 5 insertions, 426 deletions
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 356a4cc21f5..088a120d31e 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -281,56 +281,7 @@ static StringRef ToolName; typedef std::vector<std::tuple<uint64_t, StringRef, uint8_t>> SectionSymbolsTy; -namespace { -typedef std::function<bool(llvm::object::SectionRef const &)> 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 @@ SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) { }, O); } -} void llvm::error(std::error_code EC) { if (!EC) @@ -464,388 +414,17 @@ bool llvm::isRelocAddressLess(RelocationRef A, RelocationRef B) { return A.getOffset() < B.getOffset(); } -template <class ELFT> -static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, - const RelocationRef &RelRef, - SmallVectorImpl<char> &Result) { - typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; - typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; - typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela; - - const ELFFile<ELFT> &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 "+ <addend>" 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<section_iterator> 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<StringRef> 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<char> &Result) { - if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj)) - return getRelocationValueString(ELF32LE, Rel, Result); - if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj)) - return getRelocationValueString(ELF64LE, Rel, Result); - if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj)) - return getRelocationValueString(ELF32BE, Rel, Result); - auto *ELF64BE = cast<ELF64BEObjectFile>(Obj); - return getRelocationValueString(ELF64BE, Rel, Result); -} - -static std::error_code getRelocationValueString(const COFFObjectFile *Obj, - const RelocationRef &Rel, - SmallVectorImpl<char> &Result) { - symbol_iterator SymI = Rel.getSymbol(); - Expected<StringRef> 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<uint64_t> Addr = Symbol.getAddress(); - if (!Addr) - report_error(O->getFileName(), Addr.takeError()); - if (*Addr != Val) - continue; - Expected<StringRef> 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<StringRef> 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<char> &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<StringRef> 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<char> &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<char> &Result) { const ObjectFile *Obj = Rel.getObject(); if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj)) - return getRelocationValueString(ELF, Rel, Result); + return getELFRelocationValueString(ELF, Rel, Result); if (auto *COFF = dyn_cast<COFFObjectFile>(Obj)) - return getRelocationValueString(COFF, Rel, Result); + return getCOFFRelocationValueString(COFF, Rel, Result); if (auto *Wasm = dyn_cast<WasmObjectFile>(Obj)) - return getRelocationValueString(Wasm, Rel, Result); + return getWasmRelocationValueString(Wasm, Rel, Result); if (auto *MachO = dyn_cast<MachOObjectFile>(Obj)) - return getRelocationValueString(MachO, Rel, Result); + return getMachORelocationValueString(MachO, Rel, Result); llvm_unreachable("unknown object file format"); } |