[llvm] faf6ba4 - [llvm-readobj][COFF] Implement --coff-pseudoreloc in llvm-readobj to dump runtime pseudo-relocation records (#151816)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 27 13:16:46 PDT 2025
Author: Tomohiro Kashiwada
Date: 2025-08-27T23:16:42+03:00
New Revision: faf6ba47bf90be1a2c3dbcf02927f1e262c69c32
URL: https://github.com/llvm/llvm-project/commit/faf6ba47bf90be1a2c3dbcf02927f1e262c69c32
DIFF: https://github.com/llvm/llvm-project/commit/faf6ba47bf90be1a2c3dbcf02927f1e262c69c32.diff
LOG: [llvm-readobj][COFF] Implement --coff-pseudoreloc in llvm-readobj to dump runtime pseudo-relocation records (#151816)
MinGW toolchain uses "runtime pseudo-relocation" mechanism to support
auto-importing symbols from DLLs.
There is no commonly used tools for dump the pseudo-relocation records,
so we implement that functionality in llvm-readobj.
Added:
llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
Modified:
llvm/tools/llvm-readobj/COFFDumper.cpp
llvm/tools/llvm-readobj/ObjDumper.h
llvm/tools/llvm-readobj/Opts.td
llvm/tools/llvm-readobj/llvm-readobj.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
new file mode 100644
index 0000000000000..9eb56dd7f9794
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
@@ -0,0 +1,123 @@
+--- !COFF
+OptionalHeader:
+ AddressOfEntryPoint: 4096
+ ImageBase: 4194304
+ SectionAlignment: 4096
+ FileAlignment: 512
+ MajorOperatingSystemVersion: 6
+ MinorOperatingSystemVersion: 0
+ MajorImageVersion: 0
+ MinorImageVersion: 0
+ MajorSubsystemVersion: 6
+ MinorSubsystemVersion: 0
+ Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
+ DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+ SizeOfStackReserve: 1048576
+ SizeOfStackCommit: 4096
+ SizeOfHeapReserve: 1048576
+ SizeOfHeapCommit: 4096
+ ExportTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ImportTable:
+ RelativeVirtualAddress: 8288
+ Size: 60
+ ResourceTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ExceptionTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ CertificateTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ BaseRelocationTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ Debug:
+ RelativeVirtualAddress: 0
+ Size: 0
+ Architecture:
+ RelativeVirtualAddress: 0
+ Size: 0
+ GlobalPtr:
+ RelativeVirtualAddress: 0
+ Size: 0
+ TlsTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ LoadConfigTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ BoundImport:
+ RelativeVirtualAddress: 0
+ Size: 0
+ IAT:
+ RelativeVirtualAddress: 8368
+ Size: 20
+ DelayImportDescriptor:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ClrRuntimeHeader:
+ RelativeVirtualAddress: 0
+ Size: 0
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_32BIT_MACHINE ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 4096
+ VirtualSize: 60
+ SectionData: A1003040000FBE008B0D043040000FBE0901C1A1083040000FBE10A1103040000FBE0001D001C8C39090909090909090A1502040002B0508204000C3
+ SizeOfRawData: 512
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 8192
+ VirtualSize: 254
+ SectionData: 3377115566228844000000000000000001000000[[SYMBOL0=B0200000]]0030000020000000[[SYMBOL1=B4200000]]0430000020000000[[SYMBOL2=BC200000]]0830000020000000BC2000000C30000020000000B02000001030000020000000FFFFFFFF00000000FFFFFFFF000000009C2000000000000000000000DC200000B0200000A82000000000000000000000ED200000BC2000000000000000000000000000000000000000000000C4200000CC20000000000000D420000000000000C4200000CC20000000000000D420000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
+ SizeOfRawData: 512
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ VirtualAddress: 12288
+ VirtualSize: 20
+ SectionData: B1204000B6204000BD204000BD204000B2204000
+ SizeOfRawData: 512
+symbols:
+ - Name: _start
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _local2a
+ Value: 4
+ SectionNumber: [[SECTION_OF_LOCAL2A=3]]
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _local3a
+ Value: 8
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __pei386_runtime_relocator
+ Value: 48
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: ___RUNTIME_PSEUDO_RELOC_LIST_END__
+ Value: [[END=80]]
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: ___RUNTIME_PSEUDO_RELOC_LIST__
+ Value: [[BEGIN=8]]
+ SectionNumber: [[SECTION_OF_BEGIN=2]]
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
new file mode 100644
index 0000000000000..e31f61c17fd3d
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
@@ -0,0 +1,123 @@
+--- !COFF
+OptionalHeader:
+ AddressOfEntryPoint: 4096
+ ImageBase: 5368709120
+ SectionAlignment: 4096
+ FileAlignment: 512
+ MajorOperatingSystemVersion: 6
+ MinorOperatingSystemVersion: 0
+ MajorImageVersion: 0
+ MinorImageVersion: 0
+ MajorSubsystemVersion: 6
+ MinorSubsystemVersion: 0
+ Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
+ DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+ SizeOfStackReserve: 1048576
+ SizeOfStackCommit: 4096
+ SizeOfHeapReserve: 1048576
+ SizeOfHeapCommit: 4096
+ ExportTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ImportTable:
+ RelativeVirtualAddress: 8304
+ Size: 60
+ ResourceTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ExceptionTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ CertificateTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ BaseRelocationTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ Debug:
+ RelativeVirtualAddress: 0
+ Size: 0
+ Architecture:
+ RelativeVirtualAddress: 0
+ Size: 0
+ GlobalPtr:
+ RelativeVirtualAddress: 0
+ Size: 0
+ TlsTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ LoadConfigTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ BoundImport:
+ RelativeVirtualAddress: 0
+ Size: 0
+ IAT:
+ RelativeVirtualAddress: 8408
+ Size: 40
+ DelayImportDescriptor:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ClrRuntimeHeader:
+ RelativeVirtualAddress: 0
+ Size: 0
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, 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: 61
+ SectionData: 488B05F91F00000FBE00488B0DF71F00000FBE0901C1488B05F31F00000FBE10488B05F91F00000FBE0001D001C8C3908B051A1000002B05CC0F0000C3
+ SizeOfRawData: 512
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 8192
+ VirtualSize: 318
+ SectionData: 3377115566228844000000000000000001000000[[SYMBOL0=E8200000]]0030000040000000[[SYMBOL1=F0200000]]0830000040000000[[SYMBOL2=D8200000]]1030000040000000D82000001830000040000000E82000002030000040000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000B0200000000000000000000018210000D8200000C020000000000000000000002B210000E82000000000000000000000000000000000000000000000000000000021000000000000000000000000000008210000000000001021000000000000000000000000000000210000000000000000000000000000082100000000000010210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
+ SizeOfRawData: 512
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ VirtualAddress: 12288
+ VirtualSize: 40
+ SectionData: E920004001000000F220004001000000D920004001000000D920004001000000EA20004001000000
+ SizeOfRawData: 512
+symbols:
+ - Name: start
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: local2a
+ Value: 8
+ SectionNumber: [[SECTION_OF_LOCAL2A=3]]
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: local3a
+ Value: 16
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _pei386_runtime_relocator
+ Value: 48
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __RUNTIME_PSEUDO_RELOC_LIST_END__
+ Value: [[END=80]]
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __RUNTIME_PSEUDO_RELOC_LIST__
+ Value: [[BEGIN=8]]
+ SectionNumber: [[SECTION_OF_BEGIN=2]]
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
new file mode 100644
index 0000000000000..1c5c3cce21cdc
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -0,0 +1,274 @@
+DEFINE: %{local1a_386} = 0x3000
+DEFINE: %{sym1_386} = 0x20B0
+DEFINE: %{sym3_386} = 0x20BC
+DEFINE: %{local1a_x64} = 0x3000
+DEFINE: %{sym1_x64} = 0x20E8
+DEFINE: %{sym3_x64} = 0x20D8
+DEFINE: %{relocbegin} = 8
+DEFINE: %{relocend} = 80
+DEFINE: %{rdatasize} = 254
+
+RUN: yaml2obj -o %t.exe-x86_64 %p/Inputs/pseudoreloc.x86_64.yaml
+RUN: llvm-readobj %t.exe-x86_64 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=CHECK,CHECK-X64 --match-full-lines --implicit-check-not=warning \
+RUN: -D#WORD=8 -D#SYM1=%{sym1_x64} -D#SYM3=%{sym3_x64} -D#LOCAL1A=%{local1a_x64} -DPREFIX=
+
+RUN: yaml2obj -o %t.exe-i386 %p/Inputs/pseudoreloc.i386.yaml
+RUN: llvm-readobj %t.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=CHECK,CHECK-386 --match-full-lines --implicit-check-not=warning \
+RUN: -D#WORD=4 -D#SYM1=%{sym1_386} -D#SYM3=%{sym3_386} -D#LOCAL1A=%{local1a_386} -DPREFIX=_
+
+CHECK-X64: Format: COFF-x86-64
+CHECK-X64-NEXT: Arch: x86_64
+CHECK-386: Format: COFF-i386
+CHECK-386-NEXT: Arch: i386
+CHECK-NEXT: AddressSize: [[#%u,BW:mul(WORD,8)]]bit
+CHECK-NEXT: PseudoReloc [
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x[[#%X,SYM1]]
+CHECK-NEXT: SymbolName: sym1
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A]]
+CHECK-NEXT: TargetSymbol: .data+0x0
+CHECK-NEXT: BitWidth: [[#BW]]
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x[[#%X,SYM1+mul(1,WORD)]]
+CHECK-NEXT: SymbolName: sym2
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(1,WORD)]]
+CHECK-NEXT: TargetSymbol: [[PREFIX]]local2a
+CHECK-NEXT: BitWidth: [[#BW]]
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x[[#%X,SYM3]]
+CHECK-NEXT: SymbolName: sym3
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(2,WORD)]]
+CHECK-NEXT: TargetSymbol: [[PREFIX]]local3a
+CHECK-NEXT: BitWidth: [[#BW]]
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x[[#%X,SYM3]]
+CHECK-NEXT: SymbolName: sym3
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(3,WORD)]]
+CHECK-NEXT: TargetSymbol: [[PREFIX]]local3a+0x[[#%X,mul(1,WORD)]]
+CHECK-NEXT: BitWidth: [[#BW]]
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x[[#%X,SYM1]]
+CHECK-NEXT: SymbolName: sym1
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(4,WORD)]]
+CHECK-NEXT: TargetSymbol: [[PREFIX]]local3a+0x[[#%X,mul(2,WORD)]]
+CHECK-NEXT: BitWidth: [[#BW]]
+CHECK-NEXT: }
+CHECK-NEXT: ]
+
+; Test that llvm-readobj warns about missing imported symbol names.
+RUN: yaml2obj -o %t.corrupted-iat.exe-i386 %p/Inputs/pseudoreloc.i386.yaml \
+RUN: -DSYMBOL0=30000000 -DSYMBOL1=B2200000 -DSYMBOL2=00FFFF00
+RUN: llvm-readobj %t.corrupted-iat.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefix=INVALIDSYMBOL --match-full-lines -D#LOCAL1A=%{local1a_386} --implicit-check-not=warning
+
+INVALIDSYMBOL: Symbol: 0x[[#%X,ADDR:0x0030]]
+INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the address referenced by pseudo-relocation is not a valid import entry: 0x[[#%x,ADDR]]
+INVALIDSYMBOL-NEXT: SymbolName: (missing)
+INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A]]
+INVALIDSYMBOL: Symbol: 0x[[#%X,ADDR:0x20B2]]
+INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the address referenced by pseudo-relocation is not a valid import entry: 0x[[#%x,ADDR]]
+INVALIDSYMBOL-NEXT: SymbolName: (missing)
+INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+4]]
+INVALIDSYMBOL: Symbol: 0x[[#%X,ADDR:0xFFFF00]]
+INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the address referenced by pseudo-relocation is not a valid import entry: 0x[[#%x,ADDR]]
+INVALIDSYMBOL-NEXT: SymbolName: (missing)
+INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+8]]
+
+; Assume the position of the section and the relocation list for further tests.
+RUN: FileCheck --input-file=%p/Inputs/pseudoreloc.i386.yaml %s --check-prefix=RELOCPOS --match-full-lines \
+RUN: -D#RDATASIZE=%{rdatasize} -DTHEBEGIN=%{relocbegin} -DTHEEND=%{relocend}
+
+RELOCPOS: sections:
+RELOCPOS-NOT: - Name:
+RELOCPOS: - Name: .text
+RELOCPOS-NOT: - Name:
+RELOCPOS: - Name: .rdata
+RELOCPOS-NEXT: Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+RELOCPOS-NEXT: VirtualAddress: 8192
+RELOCPOS-NEXT: VirtualSize: [[#%d,RDATASIZE]]
+RELOCPOS: - Name: .data
+RELOCPOS-NEXT: Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+RELOCPOS-NEXT: VirtualAddress: 12288
+RELOCPOS: - Name: ___RUNTIME_PSEUDO_RELOC_LIST_END__
+RELOCPOS-NEXT: Value: [{{\[}}END=[[THEEND]]{{]}}]
+RELOCPOS: - Name: ___RUNTIME_PSEUDO_RELOC_LIST__
+RELOCPOS-NEXT: Value: [{{\[}}BEGIN=[[THEBEGIN]]{{]}}]
+RELOCPOS-NEXT: SectionNumber: {{\[\[SECTION_OF_BEGIN=2\]\]}}
+
+; Test that llvm-readobj warns if a symbol belongs to a nonexistent section.
+RUN: yaml2obj -o %t.nosection.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSECTION_OF_LOCAL2A=999
+RUN: llvm-readobj %t.nosection.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=WARN-NOSECTION --match-full-lines
+
+WARN-NOSECTION: {{.*}} warning:{{.*}}: section index out of bounds
+
+; Test that llvm-readobj shows an empty list if the relocation list has no contents.
+RUN: yaml2obj -o %t.empty-list.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=20
+RUN: llvm-readobj %t.empty-list.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning
+
+; Test that llvm-readobj shows an empty list if the relocation list has no header.
+RUN: yaml2obj -o %t.no-header.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=%{relocbegin}
+RUN: llvm-readobj %t.no-header.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning
+
+; Test that llvm-readobj shows an empty list if the image is stripped.
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/imports.exe.coff-i386 2>&1 | \
+RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning
+
+; Test that llvm-readobj warns if the marker symbol of the relocation list is absent from the symbol table.
+RUN: sed -e 's/__RUNTIME//' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN: yaml2obj -o %t.nosymbol.exe-i386
+RUN: llvm-readobj %t.nosymbol.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=EMPTY,WARN-MISSINGMARKER --match-full-lines
+
+; Test that llvm-readobj shows an empty list if a .obj is specified.
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | \
+RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning
+
+; Test that llvm-readobj warns if the header of the relocation list is broken.
+RUN: yaml2obj -o %t.broken-header.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=1%{relocbegin}
+RUN: llvm-readobj %t.broken-header.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=EMPTY,WARN-INVALIDHEADER --match-full-lines
+
+; Test that llvm-readobj warns if end < start.
+RUN: yaml2obj -o %t.negative-size.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=%{relocend} -DEND=%{relocbegin}
+RUN: llvm-readobj %t.negative-size.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=EMPTY,WARN-LOWEREND -D#BEGIN=%{relocend} -D#END=%{relocbegin} --match-full-lines
+
+; Test that llvm-readobj warns if the marker symbol points out of the section space.
+RUN: yaml2obj -o %t.outofrange-both.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=8888 -DEND=9999
+RUN: llvm-readobj %t.outofrange-both.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE --match-full-lines -D#RDATASIZE=%{rdatasize}
+
+RUN: yaml2obj -o %t.outofrange-end.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=8888
+RUN: llvm-readobj %t.outofrange-end.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE --match-full-lines -D#RDATASIZE=%{rdatasize}
+
+; Test that llvm-readobj warns if the marker symbols point
diff erent sections.
+RUN: yaml2obj -o %t.section-
diff ers.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSECTION_OF_BEGIN=1
+RUN: llvm-readobj %t.section-
diff ers.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: FileCheck %s --check-prefixes=EMPTY,WARN-SECTIONDIFFERS --match-full-lines
+
+EMPTY: Format: COFF-i386
+EMPTY-NEXT: Arch: i386
+EMPTY-NEXT: AddressSize: 32bit
+EMPTY-NEXT: PseudoReloc [
+WARN-MISSINGMARKER-NEXT: {{.*}}warning: {{.*}}: the marker symbols for runtime pseudo-relocation were not found
+WARN-INVALIDHEADER-NEXT: {{.*}}warning: {{.*}}: invalid runtime pseudo-relocation records
+WARN-LOWEREND-NEXT: {{.*}}warning: {{.*}}: the end marker symbol for runtime pseudo-relocation must point to a higher address than where the begin marker points to: expected >=0x[[#%x,BEGIN]], but got 0x[[#%x,END]]
+WARN-OUTOFRANGE-NEXT: {{.*}}warning: {{.*}}: the marker symbol of runtime pseudo-relocation points past the end of the section 0x[[#%x,RDATASIZE]]: got 0x[[#%x,8888]]
+WARN-SECTIONDIFFERS-NEXT: {{.*}}warning: {{.*}}: the end marker symbol for runtime pseudo-relocation must point to the same section where the begin marker points to: expected 1, but got {{[2-9]}}
+EMPTY-NEXT: ]
+
+;;
+;; To regenerate Inputs/pseudoreloc.*.yaml, run following one-liner and review actual address map:
+;;
+;; $ split-file pseudoreloc.test /tmp/pseudoreloc && bash /tmp/pseudoreloc/generate.sh && cp /tmp/pseudoreloc/*.yaml Inputs/
+;;
+
+#--- generate.sh
+cd "$(dirname $0)"
+set -e
+
+generate() {
+ LANG=C
+ local arch=$1
+ local emul=$2
+
+ llc -mtriple $arch-mingw32 -filetype obj export1.ll -o export1.$arch.o
+ ld.lld -m $emul --dll export1.$arch.o -o export1.$arch.dll -entry=
+ llc -mtriple $arch-mingw32 -filetype obj export2.ll -o export2.$arch.o
+ ld.lld -m $emul --dll export2.$arch.o -o export2.$arch.dll -entry=
+ llc -mtriple $arch-mingw32 -filetype obj import.ll -o import.$arch.o
+ ld.lld -m $emul -S import.$arch.o export1.$arch.dll export2.$arch.dll -o pseudoreloc.$arch.exe -entry=start \
+ --disable-dynamicbase --disable-reloc-section
+
+ obj2yaml pseudoreloc.$arch.exe -o pseudoreloc.$arch.yaml.orig
+
+ llvm-readobj --coff-imports --syms --section-headers pseudoreloc.$arch.exe > dump.$arch.txt
+ local begin=$(sed -n -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Value:/{/Value:/{s/ *Value: *//p;q}}' dump.$arch.txt)
+
+ # Make these parameterizable:
+ # - the referenced symbol in 1st, 2nd, and 3rd relocation entry
+ # - the marker symbols' value
+ # - a section which the marker symbol belongs to
+ # - a section which the symbol of the relocation target belongs to
+ sed -E -f - pseudoreloc.$arch.yaml.orig <<EOT > pseudoreloc.$arch.yaml
+/- Name: *\\.rdata/,/SectionData:/{
+ s/( *SectionData: *[0-9A-F]{$(($begin * 2 + 24))})(.{8})(.{16})(.{8})(.{16})(.{8})/\\1[[SYMBOL0=\\2]]\\3[[SYMBOL1=\\4]]\\5[[SYMBOL2=\\6]]/
+}
+/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Value:/{
+ /Value:/s/([0-9]+)/[[END=\1]]/
+}
+/__RUNTIME_PSEUDO_RELOC_LIST__/,/Value:/{
+ /Value:/s/([0-9]+)/[[BEGIN=\1]]/
+}
+/__RUNTIME_PSEUDO_RELOC_LIST__/,/SectionNumber:/{
+ /SectionNumber:/s/([0-9]+)/[[SECTION_OF_BEGIN=\1]]/
+}
+/local2a/,/SectionNumber:/{
+ /SectionNumber:/s/([0-9]+)/[[SECTION_OF_LOCAL2A=\1]]/
+}
+EOT
+
+ # Ensure the binaries generated from the parameterized yaml and original one are exactly the same.
+
diff <(yaml2obj pseudoreloc.$arch.yaml.orig -o -) <(yaml2obj pseudoreloc.$arch.yaml -o -)
+}
+
+generate i386 i386pe
+generate x86_64 i386pep
+
+#--- export1.ll
+ at sym1 = dso_local dllexport global [4 x i8] c"\11\22\33\44"
+ at sym2 = dso_local dllexport global [4 x i8] c"\55\66\77\88"
+
+#--- export2.ll
+ at sym3 = dso_local dllexport global [4 x i8] c"\AA\BB\CC\DD"
+
+#--- import.ll
+ at __RUNTIME_PSEUDO_RELOC_LIST__ = external dso_local constant ptr
+ at __RUNTIME_PSEUDO_RELOC_LIST_END__ = external dso_local constant ptr
+ at sym1 = external dso_local global [4 x i8]
+ at sym2 = external dso_local global [4 x i8]
+ at sym3 = external dso_local global [4 x i8]
+ at dummy_to_bump_address = private constant i64 u0x4488226655117733
+ at local1a = private global ptr getelementptr (i8, ptr @sym1, i32 1)
+ at local2a = dso_local global ptr getelementptr (i8, ptr @sym2, i32 2)
+ at local3a = dso_local global [2 x ptr] [ptr getelementptr (i8, ptr @sym3, i32 1), ptr getelementptr (i8, ptr @sym3, i32 1)]
+ at local1b = private global ptr getelementptr (i8, ptr @sym1, i32 2)
+
+define dso_local i32 @start() noinline nounwind {
+ %p1a = load ptr, ptr @local1a
+ %v1a = load i8, ptr %p1a
+ %x1a = sext i8 %v1a to i32
+ %p2a = load ptr, ptr @local2a
+ %v2a = load i8, ptr %p2a
+ %x2a = sext i8 %v2a to i32
+ %p3a = load ptr, ptr @local3a
+ %v3a = load i8, ptr %p3a
+ %x3a = sext i8 %v3a to i32
+ %p1b = load ptr, ptr @local1b
+ %v1b = load i8, ptr %p1b
+ %x1b = sext i8 %v1b to i32
+ %1 = add nsw i32 %x1a, %x2a
+ %2 = add nsw i32 %x3a, %x1b
+ %3 = add nsw i32 %1, %2
+ ret i32 %3
+}
+
+define dso_local i32 @_pei386_runtime_relocator() noinline nounwind {
+ %1 = load ptr, ptr @__RUNTIME_PSEUDO_RELOC_LIST_END__
+ %2 = load ptr, ptr @__RUNTIME_PSEUDO_RELOC_LIST__
+ %3 = ptrtoint ptr %1 to i64
+ %4 = ptrtoint ptr %2 to i64
+ %5 = sub i64 %3, %4
+ %6 = trunc i64 %5 to i32
+ ret i32 %6
+}
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 96e0a634648e4..73115fbb7e55e 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -95,6 +95,7 @@ class COFFDumper : public ObjDumper {
void printCOFFExports() override;
void printCOFFDirectives() override;
void printCOFFBaseReloc() override;
+ void printCOFFPseudoReloc() override;
void printCOFFDebugDirectory() override;
void printCOFFTLSDirectory() override;
void printCOFFResources() override;
@@ -2000,6 +2001,264 @@ void COFFDumper::printCOFFBaseReloc() {
}
}
+void COFFDumper::printCOFFPseudoReloc() {
+ ListScope D(W, "PseudoReloc");
+
+ // Pseudo-relocations are only meaningful with PE image files.
+ if (!Obj->getDOSHeader())
+ return;
+
+ const StringRef RelocBeginName = Obj->getArch() == Triple::x86
+ ? "___RUNTIME_PSEUDO_RELOC_LIST__"
+ : "__RUNTIME_PSEUDO_RELOC_LIST__";
+ const StringRef RelocEndName = Obj->getArch() == Triple::x86
+ ? "___RUNTIME_PSEUDO_RELOC_LIST_END__"
+ : "__RUNTIME_PSEUDO_RELOC_LIST_END__";
+
+ const uint32_t Count = Obj->getNumberOfSymbols();
+ // Skip if no symbol was found (maybe stripped).
+ if (Count == 0)
+ return;
+
+ struct SymbolEntry {
+ uint32_t RVA;
+ COFFSymbolRef Symbol;
+ const coff_section *Section;
+ StringRef SymbolName;
+ };
+ SmallVector<SymbolEntry> RVASymbolMap;
+ COFFSymbolRef RelocBegin, RelocEnd;
+ for (uint32_t i = 0; i < Count; ++i) {
+ COFFSymbolRef Sym;
+ if (Expected<COFFSymbolRef> SymOrErr = Obj->getSymbol(i)) {
+ Sym = *SymOrErr;
+ } else {
+ reportUniqueWarning(SymOrErr.takeError());
+ continue;
+ }
+
+ i += Sym.getNumberOfAuxSymbols();
+
+ if (Sym.getSectionNumber() <= 0)
+ continue;
+
+ StringRef Name;
+ if (Expected<StringRef> NameOrErr = Obj->getSymbolName(Sym)) {
+ Name = *NameOrErr;
+ } else {
+ reportUniqueWarning(NameOrErr.takeError());
+ continue;
+ }
+
+ if (Name == RelocBeginName)
+ RelocBegin = Sym;
+ else if (Name == RelocEndName)
+ RelocEnd = Sym;
+
+ const coff_section *Sec = nullptr;
+ if (Expected<const coff_section *> SecOrErr =
+ Obj->getSection(Sym.getSectionNumber())) {
+ Sec = *SecOrErr;
+ } else {
+ reportUniqueWarning(SecOrErr.takeError());
+ continue;
+ }
+
+ RVASymbolMap.push_back(
+ {Sec->VirtualAddress + Sym.getValue(), Sym, Sec, Name});
+ }
+
+ if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
+ reportUniqueWarning(createStringError(
+ "the marker symbols for runtime pseudo-relocation were not found"));
+ return;
+ }
+
+ const coff_section *Section = nullptr;
+ if (Expected<const coff_section *> SecOrErr =
+ Obj->getSection(RelocBegin.getSectionNumber())) {
+ Section = *SecOrErr;
+ } else {
+ reportUniqueWarning(SecOrErr.takeError());
+ return;
+ }
+
+ if (RelocBegin.getSectionNumber() != RelocEnd.getSectionNumber()) {
+ reportUniqueWarning(createStringError(
+ "the end marker symbol for runtime pseudo-relocation must "
+ "point to the same section where the begin marker points to: "
+ "expected %d, but got %d",
+ RelocBegin.getSectionNumber(), RelocEnd.getSectionNumber()));
+ return;
+ }
+
+ // Skip if the relocation list is empty.
+ if (RelocBegin.getValue() == RelocEnd.getValue())
+ return;
+
+ if (RelocEnd.getValue() < RelocBegin.getValue()) {
+ reportUniqueWarning(createStringError(
+ "the end marker symbol for runtime pseudo-relocation must point "
+ "to a higher address than where the begin marker points to: "
+ "expected >=0x%x, but got 0x%x",
+ RelocBegin.getValue(), RelocEnd.getValue()));
+ return;
+ }
+
+ ArrayRef<uint8_t> Data;
+ if (auto E = Obj->getSectionContents(Section, Data)) {
+ reportUniqueWarning(std::move(E));
+ return;
+ }
+
+ if (const uint32_t Begin = RelocBegin.getValue(), End = RelocEnd.getValue();
+ Begin >= Data.size() || End > Data.size()) {
+ reportUniqueWarning(
+ createStringError("the marker symbol of runtime pseudo-relocation "
+ "points past the end of the section 0x%x: got 0x%x",
+ Data.size(), Begin >= Data.size() ? Begin : End));
+ return;
+ }
+
+ const ArrayRef<uint8_t> RawRelocs =
+ Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());
+ struct alignas(4) PseudoRelocationHeader {
+ PseudoRelocationHeader(uint32_t Signature)
+ : Zero1(0), Zero2(0), Signature(Signature) {}
+ support::ulittle32_t Zero1;
+ support::ulittle32_t Zero2;
+ support::ulittle32_t Signature;
+ };
+ const PseudoRelocationHeader HeaderV2(1);
+ if (RawRelocs.size() < sizeof(HeaderV2) ||
+ (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {
+ reportUniqueWarning(
+ createStringError("invalid runtime pseudo-relocation records"));
+ return;
+ }
+
+ struct alignas(4) PseudoRelocationRecord {
+ support::ulittle32_t Symbol;
+ support::ulittle32_t Target;
+ support::ulittle32_t BitSize;
+ };
+ ArrayRef<PseudoRelocationRecord> RelocRecords(
+ reinterpret_cast<const PseudoRelocationRecord *>(
+ RawRelocs.data() + sizeof(PseudoRelocationHeader)),
+ (RawRelocs.size() - sizeof(PseudoRelocationHeader)) /
+ sizeof(PseudoRelocationRecord));
+
+ struct CachingImportedSymbolLookup {
+ struct SizedImportDirectoryEntry {
+ uint32_t StartRVA;
+ uint32_t EndRVA;
+ ImportDirectoryEntryRef EntryRef;
+ };
+
+ CachingImportedSymbolLookup(const COFFObjectFile *Obj) : Obj(Obj) {
+ for (auto D : Obj->import_directories()) {
+ auto &Entry = ImportDirectories.emplace_back();
+ Entry.EntryRef = D;
+ Entry.EndRVA = 0;
+ if (auto E = D.getImportAddressTableRVA(Entry.StartRVA))
+ reportError(std::move(E), Obj->getFileName());
+ }
+ if (ImportDirectories.empty())
+ return;
+ llvm::sort(ImportDirectories, [](const auto &x, const auto &y) {
+ return x.StartRVA < y.StartRVA;
+ });
+ }
+
+ Expected<StringRef> find(COFFDumper *Self, uint32_t EntryRVA) {
+ static constexpr char Msg[] =
+ "the address referenced by pseudo-relocation is not a valid import "
+ "entry: 0x%x";
+ if (auto Ite = ImportedSymbols.find(EntryRVA);
+ Ite != ImportedSymbols.end())
+ return Ite->second;
+
+ auto Ite = llvm::upper_bound(
+ ImportDirectories, EntryRVA,
+ [](uint32_t RVA, const auto &D) { return RVA < D.StartRVA; });
+ if (Ite == ImportDirectories.begin())
+ return createStringError(Msg, EntryRVA);
+
+ --Ite;
+ uint32_t RVA = Ite->StartRVA;
+ if (Ite->EndRVA != 0 && Ite->EndRVA <= RVA)
+ return createStringError(Msg, EntryRVA);
+ // Search with linear iteration to care if padding or garbage exist
+ // between ImportDirectoryEntry.
+ for (auto S : Ite->EntryRef.imported_symbols()) {
+ if (RVA == EntryRVA) {
+ StringRef &NameDst = ImportedSymbols[RVA];
+ if (auto E = S.getSymbolName(NameDst)) {
+ Self->reportUniqueWarning(std::move(E));
+ NameDst = "(no symbol)";
+ }
+ return NameDst;
+ }
+ RVA += Obj->is64() ? 8 : 4;
+ if (EntryRVA < RVA)
+ return createStringError(Msg, EntryRVA);
+ }
+ Ite->EndRVA = RVA;
+
+ return createStringError(Msg, EntryRVA);
+ }
+
+ private:
+ const COFFObjectFile *Obj;
+ SmallVector<SizedImportDirectoryEntry> ImportDirectories;
+ DenseMap<uint32_t, StringRef> ImportedSymbols;
+ };
+ CachingImportedSymbolLookup ImportedSymbols(Obj);
+ llvm::stable_sort(RVASymbolMap,
+ [](const auto &x, const auto &y) { return x.RVA < y.RVA; });
+ RVASymbolMap.erase(
+ llvm::unique(RVASymbolMap,
+ [](const auto &x, const auto &y) { return x.RVA == y.RVA; }),
+ RVASymbolMap.end());
+
+ for (const auto &Reloc : RelocRecords) {
+ DictScope Entry(W, "Entry");
+
+ W.printHex("Symbol", Reloc.Symbol);
+ if (Expected<StringRef> SymOrErr =
+ ImportedSymbols.find(this, Reloc.Symbol)) {
+ W.printString("SymbolName", *SymOrErr);
+ } else {
+ reportUniqueWarning(SymOrErr.takeError());
+ W.printString("SymbolName", "(missing)");
+ }
+
+ W.printHex("Target", Reloc.Target);
+ if (auto Ite = llvm::upper_bound(
+ RVASymbolMap, Reloc.Target.value(),
+ [](uint32_t RVA, const auto &Sym) { return RVA < Sym.RVA; });
+ Ite == RVASymbolMap.begin()) {
+ W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
+ } else if (const uint32_t Offset = Reloc.Target.value() - (--Ite)->RVA;
+ Offset == 0) {
+ W.printString("TargetSymbol", Ite->SymbolName);
+ } else if (Offset < Ite->Section->VirtualSize) {
+ W.printSymbolOffset("TargetSymbol", Ite->SymbolName, Offset);
+ } else if (++Ite == RVASymbolMap.end()) {
+ W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
+ } else if (Expected<StringRef> NameOrErr =
+ Obj->getSectionName(Ite->Section)) {
+ W.printSymbolOffset("TargetSymbol", *NameOrErr,
+ Reloc.Target - Ite->Section->VirtualAddress);
+ } else {
+ reportUniqueWarning(NameOrErr.takeError());
+ W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
+ }
+
+ W.printNumber("BitWidth", Reloc.BitSize);
+ }
+}
+
void COFFDumper::printCOFFResources() {
ListScope ResourcesD(W, "Resources");
for (const SectionRef &S : Obj->sections()) {
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 1dc29661f7178..a654078a770ff 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -146,6 +146,7 @@ class ObjDumper {
virtual void printCOFFExports() { }
virtual void printCOFFDirectives() { }
virtual void printCOFFBaseReloc() { }
+ virtual void printCOFFPseudoReloc() {}
virtual void printCOFFDebugDirectory() { }
virtual void printCOFFTLSDirectory() {}
virtual void printCOFFResources() {}
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 48d43cc635a4f..711522c4acb14 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -87,6 +87,10 @@ def coff_directives : FF<"coff-directives", "Display .drectve section">, Group<g
def coff_exports : FF<"coff-exports", "Display export table">, Group<grp_coff>;
def coff_imports : FF<"coff-imports", "Display import table">, Group<grp_coff>;
def coff_load_config : FF<"coff-load-config", "Display load config">, Group<grp_coff>;
+def coff_pseudoreloc
+ : FF<"coff-pseudoreloc",
+ "Display runtime pseudo-relocations (Cygwin/MinGW specific)">,
+ Group<grp_coff>;
def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group<grp_coff>;
def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group<grp_coff>;
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 4c84ed701bb9a..2b34761b2cc6c 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -154,6 +154,7 @@ static bool CodeViewEnableGHash;
static bool CodeViewMergedTypes;
bool CodeViewSubsectionBytes;
static bool COFFBaseRelocs;
+static bool COFFPseudoRelocs;
static bool COFFDebugDirectory;
static bool COFFDirectives;
static bool COFFExports;
@@ -305,6 +306,7 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types);
opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes);
opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc);
+ opts::COFFPseudoRelocs = Args.hasArg(OPT_coff_pseudoreloc);
opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory);
opts::COFFDirectives = Args.hasArg(OPT_coff_directives);
opts::COFFExports = Args.hasArg(OPT_coff_exports);
@@ -492,6 +494,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
Dumper->printCOFFDirectives();
if (opts::COFFBaseRelocs)
Dumper->printCOFFBaseReloc();
+ if (opts::COFFPseudoRelocs)
+ Dumper->printCOFFPseudoReloc();
if (opts::COFFDebugDirectory)
Dumper->printCOFFDebugDirectory();
if (opts::COFFTLSDirectory)
More information about the llvm-commits
mailing list