Index: tools/llvm-objdump/ELFDump.cpp =================================================================== --- tools/llvm-objdump/ELFDump.cpp +++ tools/llvm-objdump/ELFDump.cpp @@ -21,10 +21,168 @@ using namespace llvm; using namespace llvm::object; +template +Expected getDynamicStrTab(const ELFFile *o, + const typename ELFFile::Elf_Dyn *Dyn, + uint64_t VirtBase) { + for (; Dyn->d_tag != ELF::DT_NULL; Dyn++) { + if (Dyn->d_tag == ELF::DT_STRTAB) + return StringRef(reinterpret_cast( + o->base() + (Dyn->d_un.d_val - VirtBase))); + } + return createError("string table entry not present"); +} + +template +void printDynamicSection(const ELFFile *o, + const typename ELFFile::Elf_Dyn *Dyn, + uint64_t VirtBase) { + outs() << "Dynamic Section:\n"; + for (; Dyn->d_tag != ELF::DT_NULL; Dyn++) { + const char *Str = nullptr; + switch (Dyn->d_tag) { + case ELF::DT_NEEDED: + Str = "NEEDED"; + break; + case ELF::DT_PLTRELSZ: + Str = "PLTRELSZ"; + break; + case ELF::DT_PLTGOT: + Str = "PLTGOT"; + break; + case ELF::DT_HASH: + Str = "HASH"; + break; + case ELF::DT_STRTAB: + Str = "STRTAB"; + break; + case ELF::DT_SYMTAB: + Str = "SYMTAB"; + break; + case ELF::DT_RELA: + Str = "RELA"; + break; + case ELF::DT_RELASZ: + Str = "RELASZ"; + break; + case ELF::DT_RELAENT: + Str = "RELAENT"; + break; + case ELF::DT_STRSZ: + Str = "STRSZ"; + break; + case ELF::DT_SYMENT: + Str = "SYMENT"; + break; + case ELF::DT_INIT: + Str = "INIT"; + break; + case ELF::DT_FINI: + Str = "FINI"; + break; + case ELF::DT_SONAME: + Str = "SONAME"; + break; + case ELF::DT_RPATH: + Str = "RPATH"; + break; + case ELF::DT_SYMBOLIC: + Str = "SYMBOLIC"; + break; + case ELF::DT_REL: + Str = "REL"; + break; + case ELF::DT_RELSZ: + Str = "RELSZ"; + break; + case ELF::DT_RELENT: + Str = "RELENT"; + break; + case ELF::DT_PLTREL: + Str = "PLTREL"; + break; + case ELF::DT_DEBUG: + Str = "DEBUG"; + break; + case ELF::DT_TEXTREL: + Str = "TEXTREL"; + break; + case ELF::DT_JMPREL: + Str = "JMPREL"; + break; + case ELF::DT_BIND_NOW: + Str = "BIND_NOW"; + break; + case ELF::DT_INIT_ARRAY: + Str = "INIT_ARRAY"; + break; + case ELF::DT_FINI_ARRAY: + Str = "FINI_ARRAY"; + break; + case ELF::DT_INIT_ARRAYSZ: + Str = "INIT_ARRAYSZ"; + break; + case ELF::DT_FINI_ARRAYSZ: + Str = "FINI_ARRAYSZ"; + break; + case ELF::DT_RUNPATH: + Str = "RUNPATH"; + break; + case ELF::DT_FLAGS: + Str = "FLAGS"; + break; + case ELF::DT_PREINIT_ARRAY: + Str = "PREINIT_ARRAY"; + break; + case ELF::DT_PREINIT_ARRAYSZ: + Str = "PREINIT_ARRAYSZ"; + break; + case ELF::DT_LOOS: + Str = "LOOS"; + break; + case ELF::DT_GNU_HASH: + Str = "GNU_HASH"; + break; + case ELF::DT_TLSDESC_PLT: + Str = "TLSDESC_PLT"; + break; + case ELF::DT_TLSDESC_GOT: + Str = "TLSDESC_GOT"; + break; + case ELF::DT_VERNEEDNUM: + Str = "VERNEEDNUM"; + break; + case ELF::DT_VERSYM: + Str = "VERSYM"; + break; + case ELF::DT_VERNEED: + Str = "VERNEED"; + break; + default: + Str = "Unknown"; + break; + } + outs() << format(" %-18s", Str); + const char *Fmt = + ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; + if (Dyn->d_tag == ELF::DT_NEEDED) { + Expected StrTabOrErr = getDynamicStrTab(o, Dyn, VirtBase); + if (StrTabOrErr) { + const char *Data = StrTabOrErr.get().data(); + outs() << (Data + Dyn->d_un.d_val) << "\n"; + continue; + } + } + outs() << format(Fmt, (uint64_t)Dyn->d_un.d_val); + } +} + template void printProgramHeaders(const ELFFile *o) { typedef ELFFile ELFO; outs() << "Program Header:\n"; auto ProgramHeaderOrError = o->program_headers(); + const typename ELFO::Elf_Dyn *Dyn = nullptr; + uint64_t VirtBase = 0; if (!ProgramHeaderOrError) report_fatal_error( errorToErrorCode(ProgramHeaderOrError.takeError()).message()); @@ -32,6 +190,8 @@ switch (Phdr.p_type) { case ELF::PT_DYNAMIC: outs() << " DYNAMIC "; + Dyn = reinterpret_cast(o->base() + + Phdr.p_offset); break; case ELF::PT_GNU_EH_FRAME: outs() << "EH_FRAME "; @@ -62,6 +222,7 @@ break; case ELF::PT_PHDR: outs() << " PHDR "; + VirtBase = Phdr.p_vaddr - Phdr.p_offset; break; case ELF::PT_TLS: outs() << " TLS "; @@ -84,6 +245,9 @@ << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n"; } outs() << "\n"; + + if (Dyn) + printDynamicSection(o, Dyn, VirtBase); } void llvm::printELFFileHeader(const object::ObjectFile *Obj) {