summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objdump/llvm-objdump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp')
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.cpp431
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");
}
OpenPOWER on IntegriCloud