diff options
Diffstat (limited to 'llvm/tools/llvm-objdump/ELFDump.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/ELFDump.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index b17a15a0d8f..3cece3963d2 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/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 @@ Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) { } 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 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 "+ <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(); +} + +std::error_code +llvm::getELFRelocationValueString(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); +} + +template <class ELFT> void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) { auto ProgramHeaderOrError = Elf->program_headers(); if (!ProgramHeaderOrError) |