[llvm] [llvm-readobj][COFF] Add JSON Output Style (PR #95074)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 10 21:50:21 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-binary-utilities

Author: Miguel A. Arroyo (mayanez)

<details>
<summary>Changes</summary>

## Description

This PR introduces the `--coff-output-style` in the same vein as the `--elf-output-style`. In particular, it implements a `JSONCOFFDumper` which overrides a handful of the `COFFDumper` (aka LLVM style) print methods. 

Most of the changes required for the `JSONCOFFDumper` are minor over the existing dumper with the main exception being the `Resource Directory Table`. The recursive traversal logic the `COFFDumper` implements for the `Resource Directory Table` makes it incompatible with JSON as it doesn't allow for logically segmenting scopes (ie. it uses the `OS` directly adding newlines etc).

I've chosen to leave the existing traversal logic in place and have it be only used for the `COFFDumper`. The `JSONCOFFDumper`'s traversal has been written to be able to keep appropriate scopes. 

Tests were added mirroring those that currently exist but validating JSON output. The tests have a `-json.test` suffix similar to what is done in ELF instead of as additional FileCheck prefixes.

---

Patch is 49.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95074.diff


10 Files Affected:

- (added) llvm/test/tools/llvm-readobj/COFF/file-summary-json.test (+96) 
- (added) llvm/test/tools/llvm-readobj/COFF/imports-json.test (+171) 
- (added) llvm/test/tools/llvm-readobj/COFF/load-config-json.test (+85) 
- (modified) llvm/test/tools/llvm-readobj/COFF/load-config.test (+4-4) 
- (added) llvm/test/tools/llvm-readobj/COFF/output-style.test (+4) 
- (added) llvm/test/tools/llvm-readobj/COFF/pretty-print.test (+43) 
- (added) llvm/test/tools/llvm-readobj/COFF/resources-json.test (+388) 
- (modified) llvm/tools/llvm-readobj/COFFDumper.cpp (+266-10) 
- (modified) llvm/tools/llvm-readobj/Opts.td (+1) 
- (modified) llvm/tools/llvm-readobj/llvm-readobj.cpp (+12) 


``````````diff
diff --git a/llvm/test/tools/llvm-readobj/COFF/file-summary-json.test b/llvm/test/tools/llvm-readobj/COFF/file-summary-json.test
new file mode 100644
index 0000000000000..2e7c080f2bfeb
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/file-summary-json.test
@@ -0,0 +1,96 @@
+## Test how we output JSON file summaries.
+
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir
+# RUN: yaml2obj %s -o %t.dir/obj
+
+## Test outputting file summary for a single file.
+# RUN: llvm-readobj --coff-output-style=JSON --pretty-print %t.dir/obj | \
+# RUN:   FileCheck %s --check-prefix=SINGLE \
+# RUN:     --match-full-lines --strict-whitespace  --implicit-check-not={{.}}
+
+#      SINGLE:[
+# SINGLE-NEXT:  {
+# SINGLE-NEXT:    "FileSummary": {
+# SINGLE-NEXT:      "File": "{{.*}}/obj",
+# SINGLE-NEXT:      "Format": "COFF-x86-64",
+# SINGLE-NEXT:      "Arch": "x86_64",
+# SINGLE-NEXT:      "AddressSize": "64bit"
+# SINGLE-NEXT:    }
+# SINGLE-NEXT:  }
+# SINGLE-NEXT:]
+
+## Test outputting file summary for multiple files.
+# RUN: llvm-readobj --coff-output-style=JSON --pretty-print %t.dir/obj %t.dir/obj | \
+# RUN:   FileCheck %s --check-prefix=MULTI \
+# RUN:     --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+#      MULTI:[
+# MULTI-NEXT:  {
+# MULTI-NEXT:    "FileSummary": {
+# MULTI-NEXT:      "File": "{{.*}}/obj",
+# MULTI-NEXT:      "Format": "COFF-x86-64",
+# MULTI-NEXT:      "Arch": "x86_64",
+# MULTI-NEXT:      "AddressSize": "64bit"
+# MULTI-NEXT:    }
+# MULTI-NEXT:  },
+# MULTI-NEXT:  {
+# MULTI-NEXT:    "FileSummary": {
+# MULTI-NEXT:      "File": "{{.*}}/obj",
+# MULTI-NEXT:      "Format": "COFF-x86-64",
+# MULTI-NEXT:      "Arch": "x86_64",
+# MULTI-NEXT:      "AddressSize": "64bit"
+# MULTI-NEXT:    }
+# MULTI-NEXT:  }
+# MULTI-NEXT:]
+
+## Test outputting file summary for an archive with a single file.
+# RUN: rm -f %t.archive-single
+# RUN: llvm-ar rc %t.archive-single %t.dir/obj
+# RUN: llvm-readobj --coff-output-style=JSON --pretty-print %t.archive-single | \
+# RUN:   FileCheck %s --check-prefix=ARCH-SINGLE \
+# RUN:     --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+#      ARCH-SINGLE:[
+# ARCH-SINGLE-NEXT:  {
+# ARCH-SINGLE-NEXT:    "FileSummary": {
+# ARCH-SINGLE-NEXT:      "File": "{{.*}}.archive-single(obj)",
+# ARCH-SINGLE-NEXT:      "Format": "COFF-x86-64",
+# ARCH-SINGLE-NEXT:      "Arch": "x86_64",
+# ARCH-SINGLE-NEXT:      "AddressSize": "64bit"
+# ARCH-SINGLE-NEXT:    }
+# ARCH-SINGLE-NEXT:  }
+# ARCH-SINGLE-NEXT:]
+
+## Test outputting file summary for an archive with multiple files.
+# RUN: rm -f %t.archive-multiple
+# RUN: llvm-ar rc %t.archive-multiple %t.dir/obj %t.dir/obj
+# RUN: llvm-readobj --coff-output-style=JSON --pretty-print %t.archive-multiple | \
+# RUN:   FileCheck %s --check-prefix=ARCH-MULTI \
+# RUN:     --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+#      ARCH-MULTI:[
+# ARCH-MULTI-NEXT:  {
+# ARCH-MULTI-NEXT:    "FileSummary": {
+# ARCH-MULTI-NEXT:      "File": "{{.*}}.archive-multiple(obj)",
+# ARCH-MULTI-NEXT:      "Format": "COFF-x86-64",
+# ARCH-MULTI-NEXT:      "Arch": "x86_64",
+# ARCH-MULTI-NEXT:      "AddressSize": "64bit"
+# ARCH-MULTI-NEXT:    }
+# ARCH-MULTI-NEXT:  },
+# ARCH-MULTI-NEXT:  {
+# ARCH-MULTI-NEXT:    "FileSummary": {
+# ARCH-MULTI-NEXT:      "File": "{{.*}}.archive-multiple(obj)",
+# ARCH-MULTI-NEXT:      "Format": "COFF-x86-64",
+# ARCH-MULTI-NEXT:      "Arch": "x86_64",
+# ARCH-MULTI-NEXT:      "AddressSize": "64bit"
+# ARCH-MULTI-NEXT:    }
+# ARCH-MULTI-NEXT:  }
+# ARCH-MULTI-NEXT:]
+
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [  ]
+sections:
+symbols:
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-readobj/COFF/imports-json.test b/llvm/test/tools/llvm-readobj/COFF/imports-json.test
new file mode 100644
index 0000000000000..6b5056f6c6337
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/imports-json.test
@@ -0,0 +1,171 @@
+RUN: llvm-readobj --coff-imports --coff-output-style=JSON --pretty-print %p/Inputs/imports.exe.coff-i386 | FileCheck -check-prefix=X86 %s
+RUN: llvm-readobj --coff-imports --coff-output-style=JSON --pretty-print %p/Inputs/imports.exe.coff-x86-64 --coff-output-style=JSON --pretty-print | FileCheck -check-prefixes=X64  %s
+
+X86:    "Import": {
+X86-NEXT:      "Name": "KERNEL32.dll",
+X86-NEXT:      "ImportLookupTableRVA": 8456,
+X86-NEXT:      "ImportAddressTableRVA": 8192,
+X86-NEXT:      "Symbols": [
+X86-NEXT:        {
+X86-NEXT:          "Name": "ExitProcess",
+X86-NEXT:          "Ordinal": 337
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "GetProcAddress",
+X86-NEXT:          "Ordinal": 669
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "FreeLibrary",
+X86-NEXT:          "Ordinal": 414
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "GetLastError",
+X86-NEXT:          "Ordinal": 592
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "RaiseException",
+X86-NEXT:          "Ordinal": 1087
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "LoadLibraryExA",
+X86-NEXT:          "Ordinal": 934
+X86-NEXT:        }
+X86-NEXT:      ]
+X86-NEXT:    },
+X86-NEXT:    "Import": {
+X86-NEXT:      "Name": "USER32.dll",
+X86-NEXT:      "ImportLookupTableRVA": 8484,
+X86-NEXT:      "ImportAddressTableRVA": 8220,
+X86-NEXT:      "Symbols": [
+X86-NEXT:        {
+X86-NEXT:          "Name": "MessageBoxA",
+X86-NEXT:          "Ordinal": 582
+X86-NEXT:        }
+X86-NEXT:      ]
+X86-NEXT:    },
+X86-NEXT:    "Import": {
+X86-NEXT:      "Name": "mydll.dll",
+X86-NEXT:      "ImportLookupTableRVA": 8492,
+X86-NEXT:      "ImportAddressTableRVA": 8228,
+X86-NEXT:      "Symbols": [
+X86-NEXT:        {
+X86-NEXT:          "Name": "Func1",
+X86-NEXT:          "Ordinal": 0
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "Func2",
+X86-NEXT:          "Ordinal": 1
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "",
+X86-NEXT:          "Ordinal": 3
+X86-NEXT:        }
+X86-NEXT:      ]
+X86-NEXT:    },
+X86-NEXT:    "DelayImport": {
+X86-NEXT:      "Name": "lazyload.dll",
+X86-NEXT:      "Attributes": 1,
+X86-NEXT:      "ModuleHandle": 12316,
+X86-NEXT:      "ImportAddressTable": 12304,
+X86-NEXT:      "ImportNameTable": 8336,
+X86-NEXT:      "BoundDelayImportTable": 8364,
+X86-NEXT:      "UnloadDelayImportTable": 0,
+X86-NEXT:      "Symbols": [
+X86-NEXT:        {
+X86-NEXT:          "Name": "Func5",
+X86-NEXT:          "Ordinal": 0,
+X86-NEXT:          "Address": 4198515
+X86-NEXT:        },
+X86-NEXT:        {
+X86-NEXT:          "Name": "Func4",
+X86-NEXT:          "Ordinal": 0,
+X86-NEXT:          "Address": 4198482
+X86-NEXT:        }
+X86-NEXT:      ]
+X86-NEXT:    }
+X86-NEXT:  }
+
+
+X64:    "Import": {
+X64-NEXT:      "Name": "KERNEL32.dll",
+X64-NEXT:      "ImportLookupTableRVA": 8560,
+X64-NEXT:      "ImportAddressTableRVA": 8192,
+X64-NEXT:      "Symbols": [
+X64-NEXT:        {
+X64-NEXT:          "Name": "ExitProcess",
+X64-NEXT:          "Ordinal": 343
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "GetProcAddress",
+X64-NEXT:          "Ordinal": 676
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "FreeLibrary",
+X64-NEXT:          "Ordinal": 420
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "GetLastError",
+X64-NEXT:          "Ordinal": 598
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "RaiseException",
+X64-NEXT:          "Ordinal": 1091
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "LoadLibraryExA",
+X64-NEXT:          "Ordinal": 937
+X64-NEXT:        }
+X64-NEXT:      ]
+X64-NEXT:    },
+X64-NEXT:    "Import": {
+X64-NEXT:      "Name": "USER32.dll",
+X64-NEXT:      "ImportLookupTableRVA": 8616,
+X64-NEXT:      "ImportAddressTableRVA": 8248,
+X64-NEXT:      "Symbols": [
+X64-NEXT:        {
+X64-NEXT:          "Name": "MessageBoxA",
+X64-NEXT:          "Ordinal": 586
+X64-NEXT:        }
+X64-NEXT:      ]
+X64-NEXT:    },
+X64-NEXT:    "Import": {
+X64-NEXT:      "Name": "mydll.dll",
+X64-NEXT:      "ImportLookupTableRVA": 8632,
+X64-NEXT:      "ImportAddressTableRVA": 8264,
+X64-NEXT:      "Symbols": [
+X64-NEXT:        {
+X64-NEXT:          "Name": "Func1",
+X64-NEXT:          "Ordinal": 0
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "Func2",
+X64-NEXT:          "Ordinal": 1
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "",
+X64-NEXT:          "Ordinal": 3
+X64-NEXT:        }
+X64-NEXT:      ]
+X64-NEXT:    },
+X64-NEXT:    "DelayImport": {
+X64-NEXT:      "Name": "lazyload.dll",
+X64-NEXT:      "Attributes": 1,
+X64-NEXT:      "ModuleHandle": 12328,
+X64-NEXT:      "ImportAddressTable": 12304,
+X64-NEXT:      "ImportNameTable": 8416,
+X64-NEXT:      "BoundDelayImportTable": 8456,
+X64-NEXT:      "UnloadDelayImportTable": 0,
+X64-NEXT:      "Symbols": [
+X64-NEXT:        {
+X64-NEXT:          "Name": "Func5",
+X64-NEXT:          "Ordinal": 0,
+X64-NEXT:          "Address": 5368713457
+X64-NEXT:        },
+X64-NEXT:        {
+X64-NEXT:          "Name": "Func4",
+X64-NEXT:          "Ordinal": 0,
+X64-NEXT:          "Address": 5368713318
+X64-NEXT:        }
+X64-NEXT:      ]
+X64-NEXT:    }
+X64-NEXT:  }
diff --git a/llvm/test/tools/llvm-readobj/COFF/load-config-json.test b/llvm/test/tools/llvm-readobj/COFF/load-config-json.test
new file mode 100644
index 0000000000000..93595462918f8
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/load-config-json.test
@@ -0,0 +1,85 @@
+RUN: llvm-readobj --coff-load-config --coff-output-style=JSON --pretty-print %S/Inputs/coff-load-config-x64.dll | FileCheck %s --check-prefix=X64
+
+X64:    "LoadConfig": {
+X64-NEXT:      "Size": 148,
+X64-NEXT:      "TimeDateStamp": {
+X64-NEXT:        "Name": "1970-01-01 00:00:00",
+X64-NEXT:        "Value": 0
+X64-NEXT:      },
+X64-NEXT:      "MajorVersion": 0,
+X64-NEXT:      "MinorVersion": 0,
+X64-NEXT:      "GlobalFlagsClear": 0,
+X64-NEXT:      "GlobalFlagsSet": 0,
+X64-NEXT:      "CriticalSectionDefaultTimeout": 0,
+X64-NEXT:      "DeCommitFreeBlockThreshold": 0,
+X64-NEXT:      "DeCommitTotalFreeThreshold": 0,
+X64-NEXT:      "LockPrefixTable": 0,
+X64-NEXT:      "MaximumAllocationSize": 0,
+X64-NEXT:      "VirtualMemoryThreshold": 0,
+X64-NEXT:      "ProcessHeapFlags": 0,
+X64-NEXT:      "ProcessAffinityMask": 0,
+X64-NEXT:      "CSDVersion": 0,
+X64-NEXT:      "DependentLoadFlags": 0,
+X64-NEXT:      "EditList": 0,
+X64-NEXT:      "SecurityCookie": 6442463256,
+X64-NEXT:      "SEHandlerTable": 0,
+X64-NEXT:      "SEHandlerCount": 0,
+X64-NEXT:      "GuardCFCheckFunction": 6442459392,
+X64-NEXT:      "GuardCFCheckDispatch": 6442459400,
+X64-NEXT:      "GuardCFFunctionTable": 6442459480,
+X64-NEXT:      "GuardCFFunctionCount": 9,
+X64-NEXT:      "GuardFlags": {
+X64-NEXT:        "Value": 79104,
+X64-NEXT:        "Flags": [
+X64-NEXT:          {
+X64-NEXT:            "Name": "CF_FUNCTION_TABLE_PRESENT",
+X64-NEXT:            "Value": 1024
+X64-NEXT:          },
+X64-NEXT:          {
+X64-NEXT:            "Name": "CF_INSTRUMENTED",
+X64-NEXT:            "Value": 256
+X64-NEXT:          },
+X64-NEXT:          {
+X64-NEXT:            "Name": "CF_LONGJUMP_TABLE_PRESENT",
+X64-NEXT:            "Value": 65536
+X64-NEXT:          },
+X64-NEXT:          {
+X64-NEXT:            "Name": "DELAYLOAD_IAT_IN_ITS_OWN_SECTION",
+X64-NEXT:            "Value": 8192
+X64-NEXT:          },
+X64-NEXT:          {
+X64-NEXT:            "Name": "PROTECT_DELAYLOAD_IAT",
+X64-NEXT:            "Value": 4096
+X64-NEXT:          }
+X64-NEXT:        ]
+X64-NEXT:      }
+X64-NEXT:    },
+X64-NEXT:    "GuardFidTable": [
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442455040
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442455120
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442455152
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442455264
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442455312
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442456160
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442457456
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442457936
+X64-NEXT:      },
+X64-NEXT:      {
+X64-NEXT:        "Address": 6442458512
+X64-NEXT:      }
+X64-NEXT:    ]
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-readobj/COFF/load-config.test b/llvm/test/tools/llvm-readobj/COFF/load-config.test
index 63ba11a940ad8..3e1325b651488 100644
--- a/llvm/test/tools/llvm-readobj/COFF/load-config.test
+++ b/llvm/test/tools/llvm-readobj/COFF/load-config.test
@@ -5,7 +5,7 @@ RUN: llvm-readobj --coff-load-config %S/Inputs/coff-load-config-data-end.exe | F
 
 RUN: llvm-readobj --coff-load-config %S/Inputs/coff-no-load-config.exe | FileCheck %s --check-prefix=NOCONFIG
 
-X86: LoadConfig [
+X86: LoadConfig {
 X86:   Size: 0x5C
 X86:   TimeDateStamp: 1970-01-01 00:00:00 (0x0)
 X86:   MajorVersion: 0x0
@@ -37,7 +37,7 @@ X86:     CF_LONGJUMP_TABLE_PRESENT (0x10000)
 X86:     DELAYLOAD_IAT_IN_ITS_OWN_SECTION (0x2000)
 X86:     PROTECT_DELAYLOAD_IAT (0x1000)
 X86:   ]
-X86: ]
+X86: }
 X86: SEHTable [
 X86:   0x10001BE0
 X86:   0x10001E30
@@ -56,7 +56,7 @@ X86:   0x10001BE0
 X86:   0x10001DC0
 X86: ]
 
-X64: LoadConfig [
+X64: LoadConfig {
 X64:   Size: 0x94
 X64:   TimeDateStamp: 1970-01-01 00:00:00 (0x0)
 X64:   MajorVersion: 0x0
@@ -88,7 +88,7 @@ X64:    CF_LONGJUMP_TABLE_PRESENT (0x10000)
 X64:    DELAYLOAD_IAT_IN_ITS_OWN_SECTION (0x2000)
 X64:    PROTECT_DELAYLOAD_IAT (0x1000)
 X64:  ]
-X64: ]
+X64: }
 X64-NOT: SEHTable
 X64: GuardFidTable [
 X64:   0x180001000
diff --git a/llvm/test/tools/llvm-readobj/COFF/output-style.test b/llvm/test/tools/llvm-readobj/COFF/output-style.test
new file mode 100644
index 0000000000000..70a1d5112b05d
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/output-style.test
@@ -0,0 +1,4 @@
+## Error for an unknown output style.
+RUN: not llvm-readobj --coff-output-style=unknown 2>&1 | FileCheck %s
+
+CHECK: error: --coff-output-style value should be either 'LLVM' or 'JSON', but was 'unknown'
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-readobj/COFF/pretty-print.test b/llvm/test/tools/llvm-readobj/COFF/pretty-print.test
new file mode 100644
index 0000000000000..0ae42a7e09b73
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/pretty-print.test
@@ -0,0 +1,43 @@
+## Test the JSON pretty-print flag.
+#
+# RUN: yaml2obj %s -o %t.pretty
+
+## Test JSON with pretty-print off.
+# RUN: llvm-readobj --coff-output-style=JSON %t.pretty | \
+# RUN:   FileCheck %s --check-prefix=NO-PRETTY \
+# RUN:     --strict-whitespace
+
+#      NO-PRETTY:[
+# NO-PRETTY-SAME:{
+# NO-PRETTY-SAME:"FileSummary":{
+# NO-PRETTY-SAME:"File":"{{.*}}.pretty",
+# NO-PRETTY-SAME:"Format":"COFF-x86-64",
+# NO-PRETTY-SAME:"Arch":"x86_64",
+# NO-PRETTY-SAME:"AddressSize":"64bit"
+# NO-PRETTY-SAME:}
+# NO-PRETTY-SAME:}
+# NO-PRETTY-SAME:]
+
+## Test JSON with pretty-print on.
+# RUN: llvm-readobj --coff-output-style=JSON --pretty-print %t.pretty | \
+# RUN:   FileCheck %s --check-prefix=PRETTY \
+# RUN:     --match-full-lines --strict-whitespace
+
+#      PRETTY:[
+# PRETTY-NEXT:  {
+# PRETTY-NEXT:    "FileSummary": {
+# PRETTY-NEXT:      "File": "{{.*}}.pretty",
+# PRETTY-NEXT:      "Format": "COFF-x86-64",
+# PRETTY-NEXT:      "Arch": "x86_64",
+# PRETTY-NEXT:      "AddressSize": "64bit"
+# PRETTY-NEXT:    }
+# PRETTY-NEXT:  }
+# PRETTY-NEXT:]
+
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [  ]
+sections:
+symbols:
+
diff --git a/llvm/test/tools/llvm-readobj/COFF/resources-json.test b/llvm/test/tools/llvm-readobj/COFF/resources-json.test
new file mode 100644
index 0000000000000..7e752c971c6a1
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/resources-json.test
@@ -0,0 +1,388 @@
+RUN: llvm-readobj --coff-resources --coff-output-style=JSON --pretty-print %p/Inputs/zero-string-table.obj.coff-i386 \
+RUN:   | FileCheck %s -check-prefix ZERO
+RUN: llvm-readobj --coff-resources --coff-output-style=JSON --pretty-print %p/Inputs/resources/test_resource.obj.coff \
+RUN:   | FileCheck %s -check-prefix TEST_RES
+
+
+ZERO:         "Resource Sections": [
+ZERO-NEXT:      {
+ZERO-NEXT:        "Name": ".rsrc$01",
+ZERO-NEXT:        "Total Number of Resources": 1,
+ZERO-NEXT:        "Base Table Address": 392,
+ZERO-NEXT:        "Resource Type Table": {
+ZERO-NEXT:          "Number of String Entries": 0,
+ZERO-NEXT:          "Number of ID Entries": 1,
+ZERO-NEXT:          "Entries": [
+ZERO-NEXT:            {
+ZERO-NEXT:              "Table Offset": 24,
+ZERO-NEXT:              "Type": 6,
+ZERO-NEXT:              "Resource Name Table": {
+ZERO-NEXT:                "Number of String Entries": 0,
+ZERO-NEXT:                "Number of ID Entries": 1,
+ZERO-NEXT:                "Entries": [
+ZERO-NEXT:                  {
+ZERO-NEXT:                    "Table Offset": 48,
+ZERO-NEXT:                    "Name": "",
+ZERO-NEXT:                    "ID": 1,
+ZERO-NEXT:                    "Resource Language Table": {
+ZERO-NEXT:                      "Number of String Entries": 0,
+ZERO-NEXT:                      "Number of ID Entries": 1,
+ZERO-NEXT:                      "Entries": [
+ZERO-NEXT:                        {
+ZERO-NEXT:                          "Entry Offset": 72,
+ZERO-NEXT:                          "Time/Date Stamp": {
+ZERO-NEXT:                            "Name": "1970-01-01 00:00:00",
+ZERO-NEXT:                            "Value": 0
+ZERO-NEXT:                          },
+ZERO-NEXT:                          "Major Version": 0,
+ZERO-NEXT:                          "Minor Version": 0,
+ZERO-NEXT:                          "Characteristics": 0,
+ZERO-NEXT:                          "Data": {
+ZERO-NEXT:                            "DataRVA": 0,
+ZERO-NEXT:                            "DataSize": 42,
+ZERO-NEXT:                            "Codepage": 0,
+ZERO-NEXT:                            "Reserved": 0,
+ZERO-NEXT:                            "Data": {
+ZERO-NEXT:                              "Offset": 0,
+ZERO-NEXT:                              "Bytes": [
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                5,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                72,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                101,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                108,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                108,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                111,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                                0,
+ZERO-NEXT:                              ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/95074


More information about the llvm-commits mailing list