diff options
author | Nico Rieck <nico.rieck@gmail.com> | 2013-04-12 04:07:39 +0000 |
---|---|---|
committer | Nico Rieck <nico.rieck@gmail.com> | 2013-04-12 04:07:39 +0000 |
commit | cf3b55ab18b6d0f5b658e746b57ec3cf193d5688 (patch) | |
tree | 26eb0b2d937072d5b091fe111ecde2ddb3d1a468 | |
parent | 7e87373e91afe6a9ed1ead63d9d02448f02213d3 (diff) |
Teach llvm-readobj to print ELF program headers
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179363 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/CommandGuide/llvm-readobj.rst | 4 | ||||
-rw-r--r-- | test/tools/llvm-readobj/program-headers.test | 74 | ||||
-rw-r--r-- | tools/llvm-readobj/ELFDumper.cpp | 56 | ||||
-rw-r--r-- | tools/llvm-readobj/ObjDumper.h | 1 | ||||
-rw-r--r-- | tools/llvm-readobj/llvm-readobj.cpp | 6 |
5 files changed, 136 insertions, 5 deletions
diff --git a/docs/CommandGuide/llvm-readobj.rst b/docs/CommandGuide/llvm-readobj.rst index 1ca0b19a42..b1918b548f 100644 --- a/docs/CommandGuide/llvm-readobj.rst +++ b/docs/CommandGuide/llvm-readobj.rst @@ -76,6 +76,10 @@ input. Otherwise, it will read from the specified ``filenames``. Display the needed libraries (only for ELF object files). +.. option:: -program-headers + + Display the ELF program headers (only for ELF object files). + EXIT STATUS ----------- diff --git a/test/tools/llvm-readobj/program-headers.test b/test/tools/llvm-readobj/program-headers.test new file mode 100644 index 0000000000..2a574bb2e6 --- /dev/null +++ b/test/tools/llvm-readobj/program-headers.test @@ -0,0 +1,74 @@ +RUN: llvm-readobj -program-headers %p/../../Object/Inputs/program-headers.elf-i386 \ +RUN: | FileCheck %s -check-prefix ELF-I386 +RUN: llvm-readobj -program-headers %p/../../Object/Inputs/program-headers.elf-x86-64 \ +RUN: | FileCheck %s -check-prefix ELF-X86-64 + +ELF-I386: ProgramHeaders [ +ELF-I386-NEXT: ProgramHeader { +ELF-I386-NEXT: Type: PT_LOAD (0x1) +ELF-I386-NEXT: Offset: 0x0 +ELF-I386-NEXT: VirtualAddress: 0x8048000 +ELF-I386-NEXT: PhysicalAddress: 0x8048000 +ELF-I386-NEXT: FileSize: 308 +ELF-I386-NEXT: MemSize: 308 +ELF-I386-NEXT: Flags [ (0x5) +ELF-I386-NEXT: PF_R (0x4) +ELF-I386-NEXT: PF_X (0x1) +ELF-I386-NEXT: ] +ELF-I386-NEXT: Alignment: 4096 +ELF-I386-NEXT: } +ELF-I386-NEXT: ProgramHeader { +ELF-I386-NEXT: Type: PT_GNU_STACK (0x6474E551) +ELF-I386-NEXT: Offset: 0x0 +ELF-I386-NEXT: VirtualAddress: 0x0 +ELF-I386-NEXT: PhysicalAddress: 0x0 +ELF-I386-NEXT: FileSize: 0 +ELF-I386-NEXT: MemSize: 0 +ELF-I386-NEXT: Flags [ (0x6) +ELF-I386-NEXT: PF_R (0x4) +ELF-I386-NEXT: PF_W (0x2) +ELF-I386-NEXT: ] +ELF-I386-NEXT: Alignment: 4 +ELF-I386-NEXT: } +ELF-I386-NEXT: ] + +ELF-X86-64: ProgramHeaders [ +ELF-X86-64-NEXT: ProgramHeader { +ELF-X86-64-NEXT: Type: PT_LOAD (0x1) +ELF-X86-64-NEXT: Offset: 0x0 +ELF-X86-64-NEXT: VirtualAddress: 0x400000 +ELF-X86-64-NEXT: PhysicalAddress: 0x400000 +ELF-X86-64-NEXT: FileSize: 312 +ELF-X86-64-NEXT: MemSize: 312 +ELF-X86-64-NEXT: Flags [ (0x5) +ELF-X86-64-NEXT: PF_R (0x4) +ELF-X86-64-NEXT: PF_X (0x1) +ELF-X86-64-NEXT: ] +ELF-X86-64-NEXT: Alignment: 2097152 +ELF-X86-64-NEXT: } +ELF-X86-64-NEXT: ProgramHeader { +ELF-X86-64-NEXT: Type: PT_GNU_EH_FRAME (0x6474E550) +ELF-X86-64-NEXT: Offset: 0xF4 +ELF-X86-64-NEXT: VirtualAddress: 0x4000F4 +ELF-X86-64-NEXT: PhysicalAddress: 0x4000F4 +ELF-X86-64-NEXT: FileSize: 20 +ELF-X86-64-NEXT: MemSize: 20 +ELF-X86-64-NEXT: Flags [ (0x4) +ELF-X86-64-NEXT: PF_R (0x4) +ELF-X86-64-NEXT: ] +ELF-X86-64-NEXT: Alignment: 4 +ELF-X86-64-NEXT: } +ELF-X86-64-NEXT: ProgramHeader { +ELF-X86-64-NEXT: Type: PT_GNU_STACK (0x6474E551) +ELF-X86-64-NEXT: Offset: 0x0 +ELF-X86-64-NEXT: VirtualAddress: 0x0 +ELF-X86-64-NEXT: PhysicalAddress: 0x0 +ELF-X86-64-NEXT: FileSize: 0 +ELF-X86-64-NEXT: MemSize: 0 +ELF-X86-64-NEXT: Flags [ (0x6) +ELF-X86-64-NEXT: PF_R (0x4) +ELF-X86-64-NEXT: PF_W (0x2) +ELF-X86-64-NEXT: ] +ELF-X86-64-NEXT: Alignment: 8 +ELF-X86-64-NEXT: } +ELF-X86-64-NEXT: ] diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index b0e2734ac9..3757b09c39 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -50,16 +50,18 @@ public: virtual void printDynamicTable() LLVM_OVERRIDE; virtual void printNeededLibraries() LLVM_OVERRIDE; + virtual void printProgramHeaders() LLVM_OVERRIDE; private: - typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; - typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; + typedef ELFObjectFile<ELFT> ELFO; + typedef typename ELFO::Elf_Shdr Elf_Shdr; + typedef typename ELFO::Elf_Sym Elf_Sym; void printSymbol(symbol_iterator SymI, bool IsDynamic = false); void printRelocation(section_iterator SecI, relocation_iterator RelI); - const ELFObjectFile<ELFT> *Obj; + const ELFO *Obj; }; } // namespace @@ -399,11 +401,37 @@ static const EnumEntry<unsigned> ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ) }; +static const EnumEntry<unsigned> ElfSegmentTypes[] = { + LLVM_READOBJ_ENUM_ENT(ELF, PT_NULL ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_LOAD ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_DYNAMIC), + LLVM_READOBJ_ENUM_ENT(ELF, PT_INTERP ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_NOTE ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_SHLIB ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_PHDR ), + LLVM_READOBJ_ENUM_ENT(ELF, PT_TLS ), + + LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_EH_FRAME), + LLVM_READOBJ_ENUM_ENT(ELF, PT_SUNW_EH_FRAME), + LLVM_READOBJ_ENUM_ENT(ELF, PT_SUNW_UNWIND), + + LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_STACK), + LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_RELRO), + + LLVM_READOBJ_ENUM_ENT(ELF, PT_ARM_EXIDX), + LLVM_READOBJ_ENUM_ENT(ELF, PT_ARM_UNWIND) +}; + +static const EnumEntry<unsigned> ElfSegmentFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, PF_X), + LLVM_READOBJ_ENUM_ENT(ELF, PF_W), + LLVM_READOBJ_ENUM_ENT(ELF, PF_R) +}; + template<class ELFT> void ELFDumper<ELFT>::printFileHeaders() { error_code EC; - typedef ELFObjectFile<ELFT> ELFO; const typename ELFO::Elf_Ehdr *Header = Obj->getElfHeader(); @@ -745,7 +773,6 @@ void ELFDumper<ELFT>::printUnwindInfo() { template<class ELFT> void ELFDumper<ELFT>::printDynamicTable() { - typedef ELFObjectFile<ELFT> ELFO; typedef typename ELFO::Elf_Dyn_iterator EDI; EDI Start = Obj->begin_dynamic_table(), End = Obj->end_dynamic_table(true); @@ -808,3 +835,22 @@ void ELFDumper<ELFT>::printNeededLibraries() { outs() << " " << Path << "\n"; } } + +template<class ELFT> +void ELFDumper<ELFT>::printProgramHeaders() { + ListScope L(W, "ProgramHeaders"); + + for (typename ELFO::Elf_Phdr_Iter PI = Obj->begin_program_headers(), + PE = Obj->end_program_headers(); + PI != PE; ++PI) { + DictScope P(W, "ProgramHeader"); + W.printEnum ("Type", PI->p_type, makeArrayRef(ElfSegmentTypes)); + W.printHex ("Offset", PI->p_offset); + W.printHex ("VirtualAddress", PI->p_vaddr); + W.printHex ("PhysicalAddress", PI->p_paddr); + W.printNumber("FileSize", PI->p_filesz); + W.printNumber("MemSize", PI->p_memsz); + W.printFlags ("Flags", PI->p_flags, makeArrayRef(ElfSegmentFlags)); + W.printNumber("Alignment", PI->p_align); + } +} diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 8d191cbe07..6918e28cb9 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -38,6 +38,7 @@ public: // Only implemented for ELF at this time. virtual void printDynamicTable() { } virtual void printNeededLibraries() { } + virtual void printProgramHeaders() { } protected: StreamWriter& W; diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 9d5cfcbd6a..7a4b4e4431 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -121,6 +121,10 @@ namespace opts { cl::opt<bool> NeededLibraries("needed-libs", cl::desc("Display the needed libraries")); + // -program-headers + cl::opt<bool> ProgramHeaders("program-headers", + cl::desc("Display ELF program headers")); + // -expand-relocs cl::opt<bool> ExpandRelocs("expand-relocs", cl::desc("Expand each shown relocation to multiple lines")); @@ -215,6 +219,8 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printDynamicTable(); if (opts::NeededLibraries) Dumper->printNeededLibraries(); + if (opts::ProgramHeaders) + Dumper->printProgramHeaders(); } |