[llvm] 5f1e509 - [llvm-objdump] -p: Dump PE header for PE/COFF

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 9 10:08:45 PST 2021


Author: Fangrui Song
Date: 2021-11-09T10:08:41-08:00
New Revision: 5f1e509579e49e97c4ad7deb0dd3069393ccd461

URL: https://github.com/llvm/llvm-project/commit/5f1e509579e49e97c4ad7deb0dd3069393ccd461
DIFF: https://github.com/llvm/llvm-project/commit/5f1e509579e49e97c4ad7deb0dd3069393ccd461.diff

LOG: [llvm-objdump] -p: Dump PE header for PE/COFF

For a trivial DLL built with `clang --target=x86_64-windows -O2 -c a.c; lld-link -subsystem:console -dll a.o -out:a.dll`,
`objdump -p` vs `llvm-objdump -p`:

```
-a.dll:     file format pei-x86-64
-
+a.dll: file format coff-x86-64
 Characteristics 0x2022
        executable
        large address aware
@@ -57,4 +56,4 @@
 Entry d 0000000000000000 00000000 Delay Import Directory
 Entry e 0000000000000000 00000000 CLR Runtime Header
 Entry f 0000000000000000 00000000 Reserved
-
+Export Table:
```

For a Linux image (`vmlinuz-5.10.76-gentoo-r1`) built with `CONFIG_EFI_STUB=y`

```
-vmlinuz-5.10.76-gentoo-r1:     file format pei-x86-64
-
-Characteristics 0x20e
+vmlinuz-5.10.76-gentoo-r1:     file format coff-x86-64
+Characteristics 0x206
        executable
        line numbers stripped
-       symbols stripped
        debugging information removed

 Time/Date              Wed Dec 31 16:00:00 1969
@@ -55,10 +53,4 @@
 Entry d 0000000000000000 00000000 Delay Import Directory
 Entry e 0000000000000000 00000000 CLR Runtime Header
 Entry f 0000000000000000 00000000 Reserved
-
-
-PE File Base Relocations (interpreted .reloc section contents)
-
-Virtual Address: 000037ca Chunk size 10 (0xa) Number of fixups 1
-       reloc    0 offset    0 [37ca] ABSOLUTE
-
+Export Table:
```

`symbols stripped` looks like a GNU objdump problem.

Reviewed By: jhenderson, alexander-shaposhnikov

Differential Revision: https://reviews.llvm.org/D113356

Added: 
    llvm/test/tools/llvm-objdump/COFF/private-headers-old.test
    llvm/test/tools/llvm-objdump/COFF/private-headers.yaml

Modified: 
    llvm/tools/llvm-objdump/COFFDump.cpp
    llvm/tools/llvm-objdump/COFFDump.h
    llvm/tools/llvm-objdump/llvm-objdump.cpp

Removed: 
    llvm/test/tools/llvm-objdump/COFF/private-headers.test


################################################################################
diff  --git a/llvm/test/tools/llvm-objdump/COFF/private-headers.test b/llvm/test/tools/llvm-objdump/COFF/private-headers-old.test
similarity index 100%
rename from llvm/test/tools/llvm-objdump/COFF/private-headers.test
rename to llvm/test/tools/llvm-objdump/COFF/private-headers-old.test

diff  --git a/llvm/test/tools/llvm-objdump/COFF/private-headers.yaml b/llvm/test/tools/llvm-objdump/COFF/private-headers.yaml
new file mode 100644
index 0000000000000..990cf681c2639
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/COFF/private-headers.yaml
@@ -0,0 +1,183 @@
+# RUN: yaml2obj --docnum=1 %s -o %t
+# RUN: llvm-objdump -p %t | FileCheck %s --check-prefix=PE32PLUS --strict-whitespace --match-full-lines
+
+#      PE32PLUS:{{.*}}file format coff-arm64
+# PE32PLUS-NEXT:Characteristics 0x22
+# PE32PLUS-NEXT:	executable
+# PE32PLUS-NEXT:	large address aware
+#PE32PLUS-EMPTY:
+# PE32PLUS-NEXT:Time/Date               {{.*}} 19{{69|70}}
+# PE32PLUS-NEXT:Magic                   020b	(PE32+)
+# PE32PLUS-NEXT:MajorLinkerVersion      0
+# PE32PLUS-NEXT:MinorLinkerVersion      0
+# PE32PLUS-NEXT:SizeOfCode              0000000000000200
+# PE32PLUS-NEXT:SizeOfInitializedData   0000000000000400
+# PE32PLUS-NEXT:SizeOfUninitializedData 0000000000000000
+# PE32PLUS-NEXT:AddressOfEntryPoint     0000000000001000
+# PE32PLUS-NEXT:BaseOfCode              0000000000001000
+# PE32PLUS-NEXT:ImageBase               0000000140000000
+# PE32PLUS-NEXT:SectionAlignment        00001000
+# PE32PLUS-NEXT:FileAlignment           00000200
+# PE32PLUS-NEXT:MajorOSystemVersion     6
+# PE32PLUS-NEXT:MinorOSystemVersion     1
+# PE32PLUS-NEXT:MajorImageVersion       7
+# PE32PLUS-NEXT:MinorImageVersion       2
+# PE32PLUS-NEXT:MajorSubsystemVersion   8
+# PE32PLUS-NEXT:MinorSubsystemVersion   3
+# PE32PLUS-NEXT:Win32Version            00000000
+# PE32PLUS-NEXT:SizeOfImage             00004000
+# PE32PLUS-NEXT:SizeOfHeaders           00000200
+# PE32PLUS-NEXT:CheckSum                00000000
+# PE32PLUS-NEXT:Subsystem               00000003	(Windows CUI)
+# PE32PLUS-NEXT:DllCharacteristics      00008160
+# PE32PLUS-NEXT:					HIGH_ENTROPY_VA
+# PE32PLUS-NEXT:					DYNAMIC_BASE
+# PE32PLUS-NEXT:					NX_COMPAT
+# PE32PLUS-NEXT:					TERMINAL_SERVER_AWARE
+# PE32PLUS-NEXT:SizeOfStackReserve      0000000000100000
+# PE32PLUS-NEXT:SizeOfStackCommit       0000000000001000
+# PE32PLUS-NEXT:SizeOfHeapReserve       0000000000100000
+# PE32PLUS-NEXT:SizeOfHeapCommit        0000000000001000
+# PE32PLUS-NEXT:LoaderFlags             00000000
+# PE32PLUS-NEXT:NumberOfRvaAndSizes     00000010
+#PE32PLUS-EMPTY:
+# PE32PLUS-NEXT:The Data Directory
+# PE32PLUS-NEXT:Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
+# PE32PLUS-NEXT:Entry 1 0000000000000000 00000000 Import Directory [parts of .idata]
+# PE32PLUS-NEXT:Entry 2 0000000000000000 00000000 Resource Directory [.rsrc]
+# PE32PLUS-NEXT:Entry 3 0000000000003000 00000008 Exception Directory [.pdata]
+# PE32PLUS-NEXT:Entry 4 0000000000000000 00000000 Security Directory
+# PE32PLUS-NEXT:Entry 5 0000000000000000 00000000 Base Relocation Directory [.reloc]
+# PE32PLUS-NEXT:Entry 6 0000000000000000 00000000 Debug Directory
+# PE32PLUS-NEXT:Entry 7 0000000000000000 00000000 Description Directory
+# PE32PLUS-NEXT:Entry 8 0000000000000000 00000000 Special Directory
+# PE32PLUS-NEXT:Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
+# PE32PLUS-NEXT:Entry a 0000000000000000 00000000 Load Configuration Directory
+# PE32PLUS-NEXT:Entry b 0000000000000000 00000000 Bound Import Directory
+# PE32PLUS-NEXT:Entry c 0000000000000000 00000000 Import Address Table Directory
+# PE32PLUS-NEXT:Entry d 0000000000000000 00000000 Delay Import Directory
+# PE32PLUS-NEXT:Entry e 0000000000000000 00000000 CLR Runtime Header
+# PE32PLUS-NEXT:Entry f 0000000000000000 00000000 Reserved
+
+--- !COFF
+OptionalHeader:
+  AddressOfEntryPoint: 4096
+  ImageBase:           0x140000000
+  SectionAlignment:    4096
+  FileAlignment:       512
+  MajorOperatingSystemVersion: 6
+  MinorOperatingSystemVersion: 1
+  MajorImageVersion:   7
+  MinorImageVersion:   2
+  MajorSubsystemVersion: 8
+  MinorSubsystemVersion: 3
+  Subsystem:       IMAGE_SUBSYSTEM_WINDOWS_CUI
+  DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+  SizeOfStackReserve:  1048576
+  SizeOfStackCommit:   4096
+  SizeOfHeapReserve:   1048576
+  SizeOfHeapCommit:    4096
+  ExceptionTable:
+    RelativeVirtualAddress: 12288
+    Size:            8
+header:
+  Machine:         IMAGE_FILE_MACHINE_ARM64
+  Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  4096
+    VirtualSize:     4
+    SectionData:     C0035FD6
+  - Name:            .rdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  8192
+    VirtualSize:     12
+    SectionData:     0100400800000000E4E3E3E3
+  - Name:            .pdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  12288
+    VirtualSize:     8
+    SectionData:     '0010000000200000'
+symbols:         []
+...
+
+## Test 32-bit object with full Characteristics and DllCharacteristics.
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-objdump -p %t2 | FileCheck %s --check-prefix=PE32 --match-full-lines
+#      PE32:{{.*}}file format coff-i386
+#      PE32:Characteristics 0xffbf
+# PE32-NEXT:        relocations stripped
+# PE32-NEXT:        executable
+# PE32-NEXT:        line numbers stripped
+# PE32-NEXT:        symbols stripped
+# PE32-NEXT:        large address aware
+# PE32-NEXT:        little endian
+# PE32-NEXT:        32 bit words
+# PE32-NEXT:        debugging information removed
+# PE32-NEXT:        copy to swap file if on removable media
+# PE32-NEXT:        copy to swap file if on network media
+# PE32-NEXT:        system file
+# PE32-NEXT:        DLL
+# PE32-NEXT:        run only on uniprocessor machine
+# PE32-NEXT:        big endian
+#PE32-EMPTY:
+#      PE32:Time/Date               {{.*}}
+# PE32-NEXT:Magic                   010b	(PE32)
+# PE32-NEXT:MajorLinkerVersion      0
+# PE32-NEXT:MinorLinkerVersion      0
+# PE32-NEXT:SizeOfCode              00000004
+# PE32-NEXT:SizeOfInitializedData   00000000
+# PE32-NEXT:SizeOfUninitializedData 00000000
+# PE32-NEXT:AddressOfEntryPoint     00000000
+# PE32-NEXT:BaseOfCode              00001000
+# PE32-NEXT:BaseOfData              00000000
+# PE32-NEXT:ImageBase               00000000
+# PE32-NEXT:SectionAlignment        00000001
+# PE32-NEXT:FileAlignment           00000001
+# PE32-NEXT:MajorOSystemVersion     0
+# PE32-NEXT:MinorOSystemVersion     0
+# PE32-NEXT:MajorImageVersion       0
+# PE32-NEXT:MinorImageVersion       0
+# PE32-NEXT:MajorSubsystemVersion   0
+# PE32-NEXT:MinorSubsystemVersion   0
+# PE32-NEXT:Win32Version            00000000
+# PE32-NEXT:SizeOfImage             000001a4
+# PE32-NEXT:SizeOfHeaders           000001a0
+# PE32-NEXT:CheckSum                00000000
+# PE32-NEXT:Subsystem               0000000a	(EFI application)
+# PE32-NEXT:DllCharacteristics      0000ffe0
+# PE32-NEXT:					HIGH_ENTROPY_VA
+# PE32-NEXT:					DYNAMIC_BASE
+# PE32-NEXT:					FORCE_INTEGRITY
+# PE32-NEXT:					NX_COMPAT
+# PE32-NEXT:					NO_ISOLATION
+# PE32-NEXT:					NO_SEH
+# PE32-NEXT:					NO_BIND
+# PE32-NEXT:					APPCONTAINER
+# PE32-NEXT:					WDM_DRIVER
+# PE32-NEXT:					GUARD_CF
+# PE32-NEXT:					TERMINAL_SERVER_AWARE
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LINE_NUMS_STRIPPED,
+                     IMAGE_FILE_LOCAL_SYMS_STRIPPED, IMAGE_FILE_AGGRESSIVE_WS_TRIM, IMAGE_FILE_LARGE_ADDRESS_AWARE,
+                     IMAGE_FILE_BYTES_REVERSED_LO, IMAGE_FILE_32BIT_MACHINE, IMAGE_FILE_DEBUG_STRIPPED,
+                     IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, IMAGE_FILE_NET_RUN_FROM_SWAP, IMAGE_FILE_SYSTEM,
+                     IMAGE_FILE_DLL, IMAGE_FILE_UP_SYSTEM_ONLY, IMAGE_FILE_BYTES_REVERSED_HI ]
+OptionalHeader:
+  Subsystem:          IMAGE_SUBSYSTEM_EFI_APPLICATION
+  DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE,
+                        IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT,
+                        IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION, IMAGE_DLL_CHARACTERISTICS_NO_SEH,
+                        IMAGE_DLL_CHARACTERISTICS_NO_BIND, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER,
+                        IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER, IMAGE_DLL_CHARACTERISTICS_GUARD_CF,
+                        IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  4096
+    VirtualSize:     4
+    SectionData:     C0035FD6
+symbols:

diff  --git a/llvm/tools/llvm-objdump/COFFDump.cpp b/llvm/tools/llvm-objdump/COFFDump.cpp
index 54ae3cfb6c924..750c76cd25289 100644
--- a/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -31,6 +31,159 @@ using namespace llvm::objdump;
 using namespace llvm::object;
 using namespace llvm::Win64EH;
 
+namespace {
+template <typename T> struct EnumEntry {
+  T Value;
+  StringRef Name;
+};
+
+class COFFDumper {
+public:
+  explicit COFFDumper(const llvm::object::COFFObjectFile &Obj) : Obj(Obj) {
+    Is64 = !Obj.getPE32Header();
+  }
+
+  template <class PEHeader> void printPEHeader(const PEHeader &Hdr) const;
+
+private:
+  template <typename T> FormattedNumber formatAddr(T V) const {
+    return format_hex_no_prefix(V, Is64 ? 16 : 8);
+  };
+
+  uint32_t getBaseOfData(const void *Hdr) const {
+    return Is64 ? 0 : static_cast<const pe32_header *>(Hdr)->BaseOfData;
+  }
+
+  const llvm::object::COFFObjectFile &Obj;
+  bool Is64;
+};
+} // namespace
+
+constexpr EnumEntry<uint16_t> PEHeaderMagic[] = {
+    {uint16_t(COFF::PE32Header::PE32), "PE32"},
+    {uint16_t(COFF::PE32Header::PE32_PLUS), "PE32+"},
+};
+
+constexpr EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
+    {COFF::IMAGE_SUBSYSTEM_UNKNOWN, "unspecified"},
+    {COFF::IMAGE_SUBSYSTEM_NATIVE, "NT native"},
+    {COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, "Windows GUI"},
+    {COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, "Windows CUI"},
+    {COFF::IMAGE_SUBSYSTEM_POSIX_CUI, "POSIX CUI"},
+    {COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, "Wince CUI"},
+    {COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application"},
+    {COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver"},
+    {COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver"},
+    {COFF::IMAGE_SUBSYSTEM_EFI_ROM, "SAL runtime driver"},
+    {COFF::IMAGE_SUBSYSTEM_XBOX, "XBOX"},
+};
+
+template <typename T, typename TEnum>
+static void printOptionalEnumName(T Value,
+                                  ArrayRef<EnumEntry<TEnum>> EnumValues) {
+  for (const EnumEntry<TEnum> &I : EnumValues)
+    if (I.Value == Value) {
+      outs() << "\t(" << I.Name << ')';
+      return;
+    }
+}
+
+template <class PEHeader>
+void COFFDumper::printPEHeader(const PEHeader &Hdr) const {
+  auto print = [](const char *K, auto V, const char *Fmt = "%d\n") {
+    outs() << format("%-23s ", K) << format(Fmt, V);
+  };
+  auto printU16 = [&](const char *K, support::ulittle16_t V,
+                      const char *Fmt = "%d\n") { print(K, uint16_t(V), Fmt); };
+  auto printU32 = [&](const char *K, support::ulittle32_t V,
+                      const char *Fmt = "%d\n") { print(K, uint32_t(V), Fmt); };
+  auto printAddr = [=](const char *K, uint64_t V) {
+    outs() << format("%-23s ", K) << formatAddr(V) << '\n';
+  };
+
+  printU16("Magic", Hdr.Magic, "%04x");
+  printOptionalEnumName(Hdr.Magic, makeArrayRef(PEHeaderMagic));
+  outs() << '\n';
+  print("MajorLinkerVersion", Hdr.MajorLinkerVersion);
+  print("MinorLinkerVersion", Hdr.MinorLinkerVersion);
+  printAddr("SizeOfCode", Hdr.SizeOfCode);
+  printAddr("SizeOfInitializedData", Hdr.SizeOfInitializedData);
+  printAddr("SizeOfUninitializedData", Hdr.SizeOfUninitializedData);
+  printAddr("AddressOfEntryPoint", Hdr.AddressOfEntryPoint);
+  printAddr("BaseOfCode", Hdr.BaseOfCode);
+  if (!Is64)
+    printAddr("BaseOfData", getBaseOfData(&Hdr));
+  printAddr("ImageBase", Hdr.ImageBase);
+  printU32("SectionAlignment", Hdr.SectionAlignment, "%08x\n");
+  printU32("FileAlignment", Hdr.FileAlignment, "%08x\n");
+  printU16("MajorOSystemVersion", Hdr.MajorOperatingSystemVersion);
+  printU16("MinorOSystemVersion", Hdr.MinorOperatingSystemVersion);
+  printU16("MajorImageVersion", Hdr.MajorImageVersion);
+  printU16("MinorImageVersion", Hdr.MinorImageVersion);
+  printU16("MajorSubsystemVersion", Hdr.MajorSubsystemVersion);
+  printU16("MinorSubsystemVersion", Hdr.MinorSubsystemVersion);
+  printU32("Win32Version", Hdr.Win32VersionValue, "%08x\n");
+  printU32("SizeOfImage", Hdr.SizeOfImage, "%08x\n");
+  printU32("SizeOfHeaders", Hdr.SizeOfHeaders, "%08x\n");
+  printU32("CheckSum", Hdr.CheckSum, "%08x\n");
+  printU16("Subsystem", Hdr.Subsystem, "%08x");
+  printOptionalEnumName(Hdr.Subsystem, makeArrayRef(PEWindowsSubsystem));
+  outs() << '\n';
+
+  printU16("DllCharacteristics", Hdr.DLLCharacteristics, "%08x\n");
+#define FLAG(Name)                                                             \
+  if (Hdr.DLLCharacteristics & COFF::IMAGE_DLL_CHARACTERISTICS_##Name)         \
+    outs() << "\t\t\t\t\t" << #Name << '\n';
+  FLAG(HIGH_ENTROPY_VA);
+  FLAG(DYNAMIC_BASE);
+  FLAG(FORCE_INTEGRITY);
+  FLAG(NX_COMPAT);
+  FLAG(NO_ISOLATION);
+  FLAG(NO_SEH);
+  FLAG(NO_BIND);
+  FLAG(APPCONTAINER);
+  FLAG(WDM_DRIVER);
+  FLAG(GUARD_CF);
+  FLAG(TERMINAL_SERVER_AWARE);
+#undef FLAG
+
+  printAddr("SizeOfStackReserve", Hdr.SizeOfStackReserve);
+  printAddr("SizeOfStackCommit", Hdr.SizeOfStackCommit);
+  printAddr("SizeOfHeapReserve", Hdr.SizeOfHeapReserve);
+  printAddr("SizeOfHeapCommit", Hdr.SizeOfHeapCommit);
+  printU32("LoaderFlags", Hdr.LoaderFlags, "%08x\n");
+  printU32("NumberOfRvaAndSizes", Hdr.NumberOfRvaAndSize, "%08x\n");
+
+  static const char *DirName[COFF::NUM_DATA_DIRECTORIES + 1] = {
+      "Export Directory [.edata (or where ever we found it)]",
+      "Import Directory [parts of .idata]",
+      "Resource Directory [.rsrc]",
+      "Exception Directory [.pdata]",
+      "Security Directory",
+      "Base Relocation Directory [.reloc]",
+      "Debug Directory",
+      "Description Directory",
+      "Special Directory",
+      "Thread Storage Directory [.tls]",
+      "Load Configuration Directory",
+      "Bound Import Directory",
+      "Import Address Table Directory",
+      "Delay Import Directory",
+      "CLR Runtime Header",
+      "Reserved",
+  };
+  outs() << "\nThe Data Directory\n";
+  for (uint32_t I = 0; I != array_lengthof(DirName); ++I) {
+    uint32_t Addr = 0, Size = 0;
+    if (const data_directory *Data = Obj.getDataDirectory(I)) {
+      Addr = Data->RelativeVirtualAddress;
+      Size = Data->Size;
+    }
+    outs() << format("Entry %x ", I) << formatAddr(Addr)
+           << format(" %08x %s\n", uint32_t(Size), DirName[I]);
+  }
+}
+
 // Returns the name of the unwind code.
 static StringRef getUnwindCodeTypeName(uint8_t Code) {
   switch(Code) {
@@ -622,12 +775,47 @@ void objdump::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
   }
 }
 
-void objdump::printCOFFFileHeader(const object::ObjectFile *Obj) {
-  const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj);
-  printTLSDirectory(file);
-  printLoadConfiguration(file);
-  printImportTables(file);
-  printExportTable(file);
+void objdump::printCOFFFileHeader(const COFFObjectFile &Obj) {
+  COFFDumper CD(Obj);
+  const uint16_t Cha = Obj.getCharacteristics();
+  outs() << "Characteristics 0x" << Twine::utohexstr(Cha) << '\n';
+#define FLAG(F, Name)                                                          \
+  if (Cha & F)                                                                 \
+    outs() << '\t' << Name << '\n';
+  FLAG(COFF::IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped");
+  FLAG(COFF::IMAGE_FILE_EXECUTABLE_IMAGE, "executable");
+  FLAG(COFF::IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped");
+  FLAG(COFF::IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped");
+  FLAG(COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware");
+  FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_LO, "little endian");
+  FLAG(COFF::IMAGE_FILE_32BIT_MACHINE, "32 bit words");
+  FLAG(COFF::IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed");
+  FLAG(COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
+       "copy to swap file if on removable media");
+  FLAG(COFF::IMAGE_FILE_NET_RUN_FROM_SWAP,
+       "copy to swap file if on network media");
+  FLAG(COFF::IMAGE_FILE_SYSTEM, "system file");
+  FLAG(COFF::IMAGE_FILE_DLL, "DLL");
+  FLAG(COFF::IMAGE_FILE_UP_SYSTEM_ONLY, "run only on uniprocessor machine");
+  FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_HI, "big endian");
+#undef FLAG
+
+  // TODO Support PE_IMAGE_DEBUG_TYPE_REPRO.
+  // Since ctime(3) returns a 26 character string of the form:
+  // "Sun Sep 16 01:03:52 1973\n\0"
+  // just print 24 characters.
+  const time_t Timestamp = Obj.getTimeDateStamp();
+  outs() << format("\nTime/Date               %.24s\n", ctime(&Timestamp));
+
+  if (const pe32_header *Hdr = Obj.getPE32Header())
+    CD.printPEHeader<pe32_header>(*Hdr);
+  else if (const pe32plus_header *Hdr = Obj.getPE32PlusHeader())
+    CD.printPEHeader<pe32plus_header>(*Hdr);
+
+  printTLSDirectory(&Obj);
+  printLoadConfiguration(&Obj);
+  printImportTables(&Obj);
+  printExportTable(&Obj);
 }
 
 void objdump::printCOFFSymbolTable(const object::COFFImportFile *i) {

diff  --git a/llvm/tools/llvm-objdump/COFFDump.h b/llvm/tools/llvm-objdump/COFFDump.h
index 21f97bdeb83cd..f933f79523a09 100644
--- a/llvm/tools/llvm-objdump/COFFDump.h
+++ b/llvm/tools/llvm-objdump/COFFDump.h
@@ -28,7 +28,7 @@ Error getCOFFRelocationValueString(const object::COFFObjectFile *Obj,
                                    llvm::SmallVectorImpl<char> &Result);
 
 void printCOFFUnwindInfo(const object::COFFObjectFile *O);
-void printCOFFFileHeader(const object::ObjectFile *O);
+void printCOFFFileHeader(const object::COFFObjectFile &Obj);
 void printCOFFSymbolTable(const object::COFFImportFile *I);
 void printCOFFSymbolTable(const object::COFFObjectFile *O);
 } // namespace objdump

diff  --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index ed605e65bbe83..6f6f543f2f476 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -2245,7 +2245,7 @@ static void printPrivateFileHeaders(const ObjectFile *O, bool OnlyFirst) {
     return;
   }
   if (O->isCOFF())
-    return printCOFFFileHeader(O);
+    return printCOFFFileHeader(cast<object::COFFObjectFile>(*O));
   if (O->isWasm())
     return printWasmFileHeader(O);
   if (O->isMachO()) {


        


More information about the llvm-commits mailing list