diff options
Diffstat (limited to 'llvm/tools/llvm-objdump')
-rw-r--r-- | llvm/tools/llvm-objdump/ELFDump.cpp | 89 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.cpp | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.h | 1 |
3 files changed, 94 insertions, 2 deletions
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 9475ab35f11..f4d36656a6c 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -21,6 +21,77 @@ using namespace llvm; using namespace llvm::object; +template <class ELFT> +Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) { + typedef ELFFile<ELFT> ELFO; + + auto DynamicEntriesOrError = Elf->dynamicEntries(); + if (!DynamicEntriesOrError) + return DynamicEntriesOrError.takeError(); + + for (const typename ELFO::Elf_Dyn &Dyn : *DynamicEntriesOrError) { + if (Dyn.d_tag == ELF::DT_STRTAB) { + auto MappedAddrOrError = Elf->toMappedAddr(Dyn.getPtr()); + if (!MappedAddrOrError) + consumeError(MappedAddrOrError.takeError()); + return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError)); + } + } + + // If the dynamic segment is not present, we fall back on the sections. + auto SectionsOrError = Elf->sections(); + if (!SectionsOrError) + return SectionsOrError.takeError(); + + for (const typename ELFO::Elf_Shdr &Sec : *SectionsOrError) { + if (Sec.sh_type == ELF::SHT_DYNSYM) + return Elf->getStringTableForSymtab(Sec); + } + + return createError("dynamic string table not found"); +} + +template <class ELFT> +void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) { + auto ProgramHeaderOrError = Elf->program_headers(); + if (!ProgramHeaderOrError) + report_error(Filename, ProgramHeaderOrError.takeError()); + + auto DynamicEntriesOrError = Elf->dynamicEntries(); + if (!DynamicEntriesOrError) + report_error(Filename, DynamicEntriesOrError.takeError()); + + outs() << "Dynamic Section:\n"; + for (const auto &Dyn : *DynamicEntriesOrError) { + if (Dyn.d_tag == ELF::DT_NULL) + continue; + + StringRef Str = StringRef(Elf->getDynamicTagAsString(Dyn.d_tag)); + + if (Str.empty()) { + std::string HexStr = utohexstr(static_cast<uint64_t>(Dyn.d_tag), true); + outs() << format(" 0x%-19s", HexStr.c_str()); + } else { + // We use "-21" in order to match GNU objdump's output. + outs() << format(" %-21s", Str.data()); + } + + const char *Fmt = + ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; + if (Dyn.d_tag == ELF::DT_NEEDED) { + Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf); + if (StrTabOrErr) { + const char *Data = StrTabOrErr.get().data(); + outs() << (Data + Dyn.d_un.d_val) << "\n"; + continue; + } + warn(errorToErrorCode(StrTabOrErr.takeError()).message()); + consumeError(StrTabOrErr.takeError()); + } + outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); + } +} + template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) { typedef ELFFile<ELFT> ELFO; outs() << "Program Header:\n"; @@ -103,3 +174,21 @@ void llvm::printELFFileHeader(const object::ObjectFile *Obj) { if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) printProgramHeaders(ELFObj->getELFFile()); } + +void llvm::printELFDynamicSection(const object::ObjectFile *Obj) { + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) + printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) + printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); +} diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index bbac90e74ed..610cd11365c 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2153,8 +2153,10 @@ static void printFaultMaps(const ObjectFile *Obj) { } static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) { - if (o->isELF()) - return printELFFileHeader(o); + if (o->isELF()) { + printELFFileHeader(o); + return printELFDynamicSection(o); + } if (o->isCOFF()) return printCOFFFileHeader(o); if (o->isWasm()) diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index c5a1ac8df9e..b2eb6e9d777 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -79,6 +79,7 @@ void printMachOBindTable(object::MachOObjectFile* o); void printMachOLazyBindTable(object::MachOObjectFile* o); void printMachOWeakBindTable(object::MachOObjectFile* o); void printELFFileHeader(const object::ObjectFile *o); +void printELFDynamicSection(const object::ObjectFile *Obj); void printCOFFFileHeader(const object::ObjectFile *o); void printCOFFSymbolTable(const object::COFFImportFile *i); void printCOFFSymbolTable(const object::COFFObjectFile *o); |