Index: test/tools/llvm-objdump/stripped-shared.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/stripped-shared.test @@ -0,0 +1,10 @@ +// This test checks that dynamic symbols are used when disassembling elf files. +// RUN: llvm-objdump -d %p/Inputs/stripped-elf.so | FileCheck %s + +# CHECK: .init +# CHECK: .plt +# CHECK: .text +# CHECK: func0 +# CHECK: func1 +# CHECK: func2 +# CHECK: .fini Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -213,6 +213,8 @@ cl::value_desc("address"), cl::init(UINT64_MAX)); static StringRef ToolName; +typedef std::vector> SectionSymbolsTy; + namespace { typedef std::function FilterPredicate; @@ -1108,6 +1110,52 @@ llvm_unreachable("Unsupported binary format"); } +template static void +addDynamicElfSymbols(const ELFObjectFile *Obj, + std::map &AllSymbols) { + for (auto Symbol : Obj->getDynamicSymbolIterators()) { + uint8_t SymbolType = Symbol.getELFType(); + if (SymbolType != ELF::STT_FUNC || Symbol.getSize() == 0) + continue; + + Expected AddressOrErr = Symbol.getAddress(); + if (!AddressOrErr) + report_error(Obj->getFileName(), AddressOrErr.takeError()); + uint64_t Address = *AddressOrErr; + + Expected Name = Symbol.getName(); + if (!Name) + report_error(Obj->getFileName(), Name.takeError()); + if (Name->empty()) + continue; + + Expected SectionOrErr = Symbol.getSection(); + if (!SectionOrErr) + report_error(Obj->getFileName(), SectionOrErr.takeError()); + section_iterator SecI = *SectionOrErr; + if (SecI == Obj->section_end()) + continue; + + AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); + } +} + +static void +addDynamicElfSymbols(const ObjectFile *Obj, + std::map &AllSymbols) { + assert(Obj->isELF()); + if (auto *Elf32LEObj = dyn_cast(Obj)) + addDynamicElfSymbols(Elf32LEObj, AllSymbols); + else if (auto *Elf64LEObj = dyn_cast(Obj)) + addDynamicElfSymbols(Elf64LEObj, AllSymbols); + else if (auto *Elf32BEObj = dyn_cast(Obj)) + addDynamicElfSymbols(Elf32BEObj, AllSymbols); + else if (auto *Elf64BEObj = cast(Obj)) + addDynamicElfSymbols(Elf64BEObj, AllSymbols); + else + llvm_unreachable("Unsupported binary format"); +} + static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (StartAddress > StopAddress) error("Start address should be less than stop address"); @@ -1182,7 +1230,6 @@ // Create a mapping from virtual address to symbol name. This is used to // pretty print the symbols while disassembling. - typedef std::vector> SectionSymbolsTy; std::map AllSymbols; for (const SymbolRef &Symbol : Obj->symbols()) { Expected AddressOrErr = Symbol.getAddress(); @@ -1210,6 +1257,8 @@ AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); } + if (AllSymbols.empty() && Obj->isELF()) + addDynamicElfSymbols(Obj, AllSymbols); // Create a mapping from virtual address to section. std::vector> SectionAddresses;