From: Nico Rieck Date: Fri, 12 Apr 2013 04:07:39 +0000 (+0000) Subject: Teach llvm-readobj to print ELF program headers X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cf3b55ab18b6d0f5b658e746b57ec3cf193d5688;p=oota-llvm.git 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 --- diff --git a/docs/CommandGuide/llvm-readobj.rst b/docs/CommandGuide/llvm-readobj.rst index 1ca0b19a425..b1918b548f8 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 00000000000..2a574bb2e64 --- /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 b0e2734ac93..3757b09c394 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::Elf_Shdr Elf_Shdr; - typedef typename ELFObjectFile::Elf_Sym Elf_Sym; + typedef ELFObjectFile 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 *Obj; + const ELFO *Obj; }; } // namespace @@ -399,11 +401,37 @@ static const EnumEntry ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ) }; +static const EnumEntry 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 ElfSegmentFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, PF_X), + LLVM_READOBJ_ENUM_ENT(ELF, PF_W), + LLVM_READOBJ_ENUM_ENT(ELF, PF_R) +}; + template void ELFDumper::printFileHeaders() { error_code EC; - typedef ELFObjectFile ELFO; const typename ELFO::Elf_Ehdr *Header = Obj->getElfHeader(); @@ -745,7 +773,6 @@ void ELFDumper::printUnwindInfo() { template void ELFDumper::printDynamicTable() { - typedef ELFObjectFile 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::printNeededLibraries() { outs() << " " << Path << "\n"; } } + +template +void ELFDumper::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 8d191cbe07d..6918e28cb93 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 9d5cfcbd6a2..7a4b4e4431c 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -121,6 +121,10 @@ namespace opts { cl::opt NeededLibraries("needed-libs", cl::desc("Display the needed libraries")); + // -program-headers + cl::opt ProgramHeaders("program-headers", + cl::desc("Display ELF program headers")); + // -expand-relocs cl::opt 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(); }