[llvm] r264415 - [llvm-readobj] Impl GNU style program headers print

Hemant Kulkarni via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 25 09:04:49 PDT 2016


Author: khemant
Date: Fri Mar 25 11:04:48 2016
New Revision: 264415

URL: http://llvm.org/viewvc/llvm-project?rev=264415&view=rev
Log:
[llvm-readobj] Impl GNU style program headers print

readelf -lW

Differential Revision: http://reviews.llvm.org/D18372

Added:
    llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-i386   (with props)
    llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-x86_64   (with props)
    llvm/trunk/test/tools/llvm-readobj/gnu-phdrs.test
Modified:
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-i386
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-i386?rev=264415&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-i386 (added) and llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-i386 Fri Mar 25 11:04:48 2016 differ

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-i386
------------------------------------------------------------------------------
    svn:executable = *

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-x86_64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-x86_64?rev=264415&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-x86_64 (added) and llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-x86_64 Fri Mar 25 11:04:48 2016 differ

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/phdrs-elf.exe-x86_64
------------------------------------------------------------------------------
    svn:executable = *

Added: llvm/trunk/test/tools/llvm-readobj/gnu-phdrs.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/gnu-phdrs.test?rev=264415&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/gnu-phdrs.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/gnu-phdrs.test Fri Mar 25 11:04:48 2016
@@ -0,0 +1,78 @@
+#Source :
+#__thread int a = 1;
+#__thread int b;
+#
+#int main () {
+#  b = 2;
+#  throw (a + b) ;
+#  return 0;
+#}
+# compiled as clang++ source.cpp
+# and  clang++ -m32 source.cpp
+
+RUN: llvm-readobj -program-headers %p/Inputs/phdrs-elf.exe-i386 --elf-output-style=GNU \
+RUN:   | FileCheck %s -check-prefix ELF32
+RUN: llvm-readobj -program-headers %p/Inputs/phdrs-elf.exe-x86_64 \
+RUN:  --elf-output-style=GNU | FileCheck %s -check-prefix ELF64
+
+ELF32: Elf file type is EXEC (Executable file)
+ELF32-NEXT: Entry point 0x8048460
+ELF32-NEXT: There are 10 program headers, starting at offset 52
+
+ELF32: Program Headers:
+ELF32-NEXT:   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
+ELF32-NEXT:   PHDR           0x000034 0x08048034 0x08048034 0x00140 0x00140 R E 0x4
+ELF32-NEXT:   INTERP         0x000174 0x08048174 0x08048174 0x00013 0x00013 R   0x1
+ELF32-NEXT:       [Requesting program interpreter: /lib/ld-linux.so.2]
+ELF32-NEXT:   LOAD           0x000000 0x08048000 0x08048000 0x006d0 0x006d0 R E 0x1000
+ELF32-NEXT:   LOAD           0x000ef0 0x08049ef0 0x08049ef0 0x00128 0x00140 RW  0x1000
+ELF32-NEXT:   DYNAMIC        0x000f08 0x08049f08 0x08049f08 0x000e8 0x000e8 RW  0x4
+ELF32-NEXT:   NOTE           0x000188 0x08048188 0x08048188 0x00044 0x00044 R   0x4
+ELF32-NEXT:   TLS            0x000ef0 0x08049ef0 0x08049ef0 0x00004 0x00008 R   0x4
+ELF32-NEXT:   GNU_EH_FRAME   0x000640 0x08048640 0x08048640 0x0001c 0x0001c R   0x4
+ELF32-NEXT:   GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
+ELF32-NEXT:   GNU_RELRO      0x000ef0 0x08049ef0 0x08049ef0 0x00110 0x00110 R   0x1
+
+ELF32:  Section to Segment mapping:
+ELF32-NEXT:   Segment Sections...
+ELF32-NEXT:    00
+ELF32-NEXT:    01     .interp
+ELF32-NEXT:    02     .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
+ELF32-NEXT:    03     .tdata .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
+ELF32-NEXT:    04     .dynamic
+ELF32-NEXT:    05     .note.ABI-tag .note.gnu.build-id
+ELF32-NEXT:    06     .tdata .tbss
+ELF32-NEXT:    07     .eh_frame_hdr
+ELF32-NEXT:    08
+ELF32-NEXT:    09     .tdata .ctors .dtors .jcr .dynamic .got
+
+ELF64: Elf file type is EXEC (Executable file)
+ELF64-NEXT: Entry point 0x400610
+ELF64-NEXT: There are 10 program headers, starting at offset 64
+
+ELF64: Program Headers:
+ELF64-NEXT:   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+ELF64-NEXT:   PHDR           0x000040 0x0000000000400040 0x0000000000400040 0x000230 0x000230 R E 0x8
+ELF64-NEXT:   INTERP         0x000270 0x0000000000400270 0x0000000000400270 0x00001c 0x00001c R   0x1
+ELF64-NEXT:       [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
+ELF64-NEXT:   LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x000924 0x000924 R E 0x200000
+ELF64-NEXT:   LOAD           0x000db4 0x0000000000600db4 0x0000000000600db4 0x000274 0x0002a4 RW  0x200000
+ELF64-NEXT:   DYNAMIC        0x000dd0 0x0000000000600dd0 0x0000000000600dd0 0x000210 0x000210 RW  0x8
+ELF64-NEXT:   NOTE           0x00028c 0x000000000040028c 0x000000000040028c 0x000044 0x000044 R   0x4
+ELF64-NEXT:   TLS            0x000db4 0x0000000000600db4 0x0000000000600db4 0x000004 0x000008 R   0x4
+ELF64-NEXT:   GNU_EH_FRAME   0x00083c 0x000000000040083c 0x000000000040083c 0x00002c 0x00002c R   0x4
+ELF64-NEXT:   GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x8
+ELF64-NEXT:   GNU_RELRO      0x000db4 0x0000000000600db4 0x0000000000600db4 0x00024c 0x00024c R   0x1
+
+ELF64:  Section to Segment mapping:
+ELF64-NEXT:   Segment Sections...
+ELF64-NEXT:    00
+ELF64-NEXT:    01     .interp
+ELF64-NEXT:    02     .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
+ELF64-NEXT:    03     .tdata .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
+ELF64-NEXT:    04     .dynamic
+ELF64-NEXT:    05     .note.ABI-tag .note.gnu.build-id
+ELF64-NEXT:    06     .tdata .tbss
+ELF64-NEXT:    07     .eh_frame_hdr
+ELF64-NEXT:    08
+ELF64-NEXT:    09     .tdata .init_array .fini_array .jcr .dynamic .got

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=264415&r1=264414&r2=264415&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Fri Mar 25 11:04:48 2016
@@ -279,6 +279,7 @@ public:
   virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol,
                            const Elf_Sym *FirstSym, StringRef StrTable,
                            bool IsDynamic) = 0;
+  virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0;
   const ELFDumper<ELFT> *dumper() const { return Dumper; }
 private:
   const ELFDumper<ELFT> *Dumper;
@@ -299,6 +300,7 @@ public:
   void printDynamicRelocations(const ELFO *Obj) override;
   virtual void printSymtabMessage(const ELFO *Obj, StringRef Name,
                                   size_t Offset) override;
+  void printProgramHeaders(const ELFO *Obj) override;
 
 private:
   struct Field {
@@ -329,6 +331,10 @@ private:
                    StringRef StrTable, bool IsDynamic) override;
   std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol,
                                   const Elf_Sym *FirstSym);
+  bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
+  bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
+  bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
+  bool checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec);
 };
 
 template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> {
@@ -345,6 +351,7 @@ public:
   void printSymbols(const ELFO *Obj) override;
   void printDynamicSymbols(const ELFO *Obj) override;
   void printDynamicRelocations(const ELFO *Obj) override;
+  void printProgramHeaders(const ELFO *Obj) override;
 
 private:
   void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
@@ -1076,6 +1083,65 @@ static const char *getElfSegmentType(uns
   }
 }
 
+static std::string getElfPtType(unsigned Arch, unsigned Type) {
+  switch (Type) {
+  case ELF::PT_NULL:
+    return "NULL";
+  case ELF::PT_LOAD:
+    return "LOAD";
+  case ELF::PT_DYNAMIC:
+    return "DYNAMIC";
+  case ELF::PT_INTERP:
+    return "INTERP";
+  case ELF::PT_NOTE:
+    return "NOTE";
+  case ELF::PT_SHLIB:
+    return "SHLIB";
+  case ELF::PT_PHDR:
+    return "PHDR";
+  case ELF::PT_TLS:
+    return "TLS";
+  case ELF::PT_GNU_EH_FRAME:
+    return "GNU_EH_FRAME";
+  case ELF::PT_SUNW_UNWIND:
+    return "SUNW_UNWIND";
+  case ELF::PT_GNU_STACK:
+    return "GNU_STACK";
+  case ELF::PT_GNU_RELRO:
+    return "GNU_RELRO";
+  default:
+    // All machine specific PT_* types
+    switch (Arch) {
+    case ELF::EM_AMDGPU:
+      switch (Type) {
+        LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM);
+        LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT);
+        LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT);
+        LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT);
+      }
+      return "";
+    case ELF::EM_ARM:
+      if (Type == ELF::PT_ARM_EXIDX)
+        return "EXIDX";
+      return "";
+    case ELF::EM_MIPS:
+    case ELF::EM_MIPS_RS3_LE:
+      switch (Type) {
+      case PT_MIPS_REGINFO:
+        return "REGINFO";
+      case PT_MIPS_RTPROC:
+        return "RTPROC";
+      case PT_MIPS_OPTIONS:
+        return "OPTIONS";
+      case PT_MIPS_ABIFLAGS:
+        return "ABIFLAGS";
+      }
+      return "";
+    }
+  }
+  return std::string("<unknown>: ") + to_string(format_hex(Type, 1));
+}
+
 static const EnumEntry<unsigned> ElfSegmentFlags[] = {
   LLVM_READOBJ_ENUM_ENT(ELF, PF_X),
   LLVM_READOBJ_ENUM_ENT(ELF, PF_W),
@@ -1313,11 +1379,14 @@ void ELFDumper<ELFT>::printRelocations()
   ELFDumperStyle->printRelocations(Obj);
 }
 
+template <class ELFT> void ELFDumper<ELFT>::printProgramHeaders() {
+  ELFDumperStyle->printProgramHeaders(Obj);
+}
+
 template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() {
   ELFDumperStyle->printDynamicRelocations(Obj);
 }
 
-
 template<class ELFT>
 void ELFDumper<ELFT>::printSymbols() {
   ELFDumperStyle->printSymbols(Obj);
@@ -1328,7 +1397,6 @@ void ELFDumper<ELFT>::printDynamicSymbol
   ELFDumperStyle->printDynamicSymbols(Obj);
 }
 
-
 #define LLVM_READOBJ_TYPE_CASE(name) \
   case DT_##name: return #name
 
@@ -1642,24 +1710,6 @@ void ELFDumper<ELFT>::printNeededLibrari
   }
 }
 
-template<class ELFT>
-void ELFDumper<ELFT>::printProgramHeaders() {
-  ListScope L(W, "ProgramHeaders");
-
-  for (const Elf_Phdr &Phdr : Obj->program_headers()) {
-    DictScope P(W, "ProgramHeader");
-    W.printHex("Type",
-               getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
-               Phdr.p_type);
-    W.printHex("Offset", Phdr.p_offset);
-    W.printHex("VirtualAddress", Phdr.p_vaddr);
-    W.printHex("PhysicalAddress", Phdr.p_paddr);
-    W.printNumber("FileSize", Phdr.p_filesz);
-    W.printNumber("MemSize", Phdr.p_memsz);
-    W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
-    W.printNumber("Alignment", Phdr.p_align);
-  }
-}
 
 template <typename ELFT>
 void ELFDumper<ELFT>::printHashTable() {
@@ -2648,6 +2698,143 @@ void GNUStyle<ELFT>::printDynamicSymbols
   this->dumper()->printSymbolsHelper(true);
 }
 
+static inline std::string printPhdrFlags(unsigned Flag) {
+  std::string Str;
+  Str = (Flag & PF_R) ? "R" : " ";
+  Str += (Flag & PF_W) ? "W" : " ";
+  Str += (Flag & PF_X) ? "E" : " ";
+  return Str;
+}
+
+// SHF_TLS sections are only in PT_TLS, PT_LOAD or PT_GNU_RELRO
+// PT_TLS must only have SHF_TLS sections
+template <class ELFT>
+bool GNUStyle<ELFT>::checkTLSSections(const Elf_Phdr &Phdr,
+                                      const Elf_Shdr &Sec) {
+  return (((Sec.sh_flags & ELF::SHF_TLS) &&
+           ((Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) ||
+            (Phdr.p_type == ELF::PT_GNU_RELRO))) ||
+          (!(Sec.sh_flags & ELF::SHF_TLS) && Phdr.p_type != ELF::PT_TLS));
+}
+
+// Non-SHT_NOBITS must have its offset inside the segment
+// Only non-zero section can be at end of segment
+template <class ELFT>
+bool GNUStyle<ELFT>::checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
+  if (Sec.sh_type == ELF::SHT_NOBITS)
+    return true;
+  bool IsSpecial =
+      (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
+  // .tbss is special, it only has memory in PT_TLS and has NOBITS properties
+  auto SectionSize =
+      (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size;
+  if (Sec.sh_offset >= Phdr.p_offset)
+    return ((Sec.sh_offset + SectionSize <= Phdr.p_filesz + Phdr.p_offset)
+            /*only non-zero sized sections at end*/ &&
+            (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz));
+  return false;
+}
+
+// SHF_ALLOC must have VMA inside segment
+// Only non-zero section can be at end of segment
+template <class ELFT>
+bool GNUStyle<ELFT>::checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
+  if (!(Sec.sh_flags & ELF::SHF_ALLOC))
+    return true;
+  bool IsSpecial =
+      (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
+  // .tbss is special, it only has memory in PT_TLS and has NOBITS properties
+  auto SectionSize =
+      (IsSpecial && Phdr.p_type != ELF::PT_TLS) ? 0 : Sec.sh_size;
+  if (Sec.sh_addr >= Phdr.p_vaddr)
+    return ((Sec.sh_addr + SectionSize <= Phdr.p_vaddr + Phdr.p_memsz) &&
+            (Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz));
+  return false;
+}
+
+// No section with zero size must be at start or end of PT_DYNAMIC
+template <class ELFT>
+bool GNUStyle<ELFT>::checkPTDynamic(const Elf_Phdr &Phdr, const Elf_Shdr &Sec) {
+  if (Phdr.p_type != ELF::PT_DYNAMIC || Sec.sh_size != 0 || Phdr.p_memsz == 0)
+    return true;
+  // Is section within the phdr both based on offset and VMA ?
+  return ((Sec.sh_type == ELF::SHT_NOBITS) ||
+          (Sec.sh_offset > Phdr.p_offset &&
+           Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz)) &&
+         (!(Sec.sh_flags & ELF::SHF_ALLOC) ||
+          (Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz));
+}
+
+template <class ELFT>
+void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
+  int Bias = (ELFT::Is64Bits) ? 8 : 0;
+  unsigned Width = (ELFT::Is64Bits) ? 18 : 10;
+  unsigned SizeWidth = (ELFT::Is64Bits) ? 8 : 7;
+  std::string Type, Offset, VMA, LMA, FileSz, MemSz, Flag, Align;
+
+  const Elf_Ehdr *Header = Obj->getHeader();
+  Field Fields[8] = {2,         17,        26,        37 + Bias,
+                     48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};
+  OS << "\nElf file type is "
+     << printEnum(Header->e_type, makeArrayRef(ElfObjectFileType)) << "\n"
+     << "Entry point " << format_hex(Header->e_entry, 1) << "\n"
+     << "There are " << Header->e_phnum << " program headers,"
+     << " starting at offset " << Header->e_phoff << "\n\n"
+     << "Program Headers:\n";
+  if (ELFT::Is64Bits)
+    OS << "  Type           Offset   VirtAddr           PhysAddr         "
+       << "  FileSiz  MemSiz   Flg Align\n";
+  else
+    OS << "  Type           Offset   VirtAddr   PhysAddr   FileSiz "
+       << "MemSiz  Flg Align\n";
+  for (const auto &Phdr : Obj->program_headers()) {
+    Type = getElfPtType(Header->e_machine, Phdr.p_type);
+    Offset = to_string(format_hex(Phdr.p_offset, 8));
+    VMA = to_string(format_hex(Phdr.p_vaddr, Width));
+    LMA = to_string(format_hex(Phdr.p_paddr, Width));
+    FileSz = to_string(format_hex(Phdr.p_filesz, SizeWidth));
+    MemSz = to_string(format_hex(Phdr.p_memsz, SizeWidth));
+    Flag = printPhdrFlags(Phdr.p_flags);
+    Align = to_string(format_hex(Phdr.p_align, 1));
+    Fields[0].Str = Type;
+    Fields[1].Str = Offset;
+    Fields[2].Str = VMA;
+    Fields[3].Str = LMA;
+    Fields[4].Str = FileSz;
+    Fields[5].Str = MemSz;
+    Fields[6].Str = Flag;
+    Fields[7].Str = Align;
+    for (auto Field : Fields)
+      printField(Field);
+    if (Phdr.p_type == ELF::PT_INTERP) {
+      OS << "\n      [Requesting program interpreter: ";
+      OS << reinterpret_cast<const char *>(Obj->base()) + Phdr.p_offset << "]";
+    }
+    OS << "\n";
+  }
+  OS << "\n Section to Segment mapping:\n  Segment Sections...\n";
+  int Phnum = 0;
+  for (const Elf_Phdr &Phdr : Obj->program_headers()) {
+    std::string Sections;
+    OS << format("   %2.2d     ", Phnum++);
+    for (const Elf_Shdr &Sec : Obj->sections()) {
+      // Check if each section is in a segment and then print mapping.
+      // readelf additionally makes sure it does not print zero sized sections
+      // at end of segments and for PT_DYNAMIC both start and end of section
+      // .tbss must only be shown in PT_TLS section.
+      bool TbssInNonTLS = (Sec.sh_type == ELF::SHT_NOBITS) &&
+                          ((Sec.sh_flags & ELF::SHF_TLS) != 0) &&
+                          Phdr.p_type != ELF::PT_TLS;
+      if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) &&
+          checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) &&
+          checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL))
+        Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " ";
+    }
+    OS << Sections << "\n";
+    OS.flush();
+  }
+}
+
 template <class ELFT>
 void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
   OS << "GNU style dynamic relocations not implemented!\n";
@@ -2995,3 +3182,22 @@ void LLVMStyle<ELFT>::printDynamicReloca
        << W.hex(Rel.r_addend) << "\n";
   }
 }
+
+template <class ELFT>
+void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
+  ListScope L(W, "ProgramHeaders");
+
+  for (const Elf_Phdr &Phdr : Obj->program_headers()) {
+    DictScope P(W, "ProgramHeader");
+    W.printHex("Type",
+               getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
+               Phdr.p_type);
+    W.printHex("Offset", Phdr.p_offset);
+    W.printHex("VirtualAddress", Phdr.p_vaddr);
+    W.printHex("PhysicalAddress", Phdr.p_paddr);
+    W.printNumber("FileSize", Phdr.p_filesz);
+    W.printNumber("MemSize", Phdr.p_memsz);
+    W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
+    W.printNumber("Alignment", Phdr.p_align);
+  }
+}




More information about the llvm-commits mailing list