[llvm] [llvm-readobj][COFF] Implement --coff-pseudoreloc in llvm-readobj to dump runtime pseudo-relocation records (PR #151816)
Tomohiro Kashiwada via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 6 05:07:46 PDT 2025
https://github.com/kikairoya updated https://github.com/llvm/llvm-project/pull/151816
>From 8fa4896bfc5ef7acf2dd41db824709ae60a932e5 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Thu, 31 Jul 2025 21:58:09 +0900
Subject: [PATCH 01/13] implement llvm-readobj --coff-pseudoreloc stub
---
.../llvm-readobj/COFF/Inputs/pseudoreloc.exe | Bin 0 -> 4096 bytes
.../tools/llvm-readobj/COFF/pseudoreloc.test | 68 ++++++++++++++++++
llvm/tools/llvm-readobj/COFFDumper.cpp | 3 +
llvm/tools/llvm-readobj/ObjDumper.h | 1 +
llvm/tools/llvm-readobj/Opts.td | 3 +
llvm/tools/llvm-readobj/llvm-readobj.cpp | 4 ++
6 files changed, 79 insertions(+)
create mode 100644 llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.exe
create mode 100644 llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
diff --git a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.exe b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.exe
new file mode 100644
index 0000000000000000000000000000000000000000..d4106e99d96f357920d24b3cb206bedbaccfb17d
GIT binary patch
literal 4096
zcmeHK&ubG=5T1=uQ-7otya?64LJx|tY$}Q;S?cCc*ft?aFJ4|Z&0-cd*|6DQdefUw
z5dQ!V&HvDYco3l=Jy`H4c=12cZ{F^Pr6qduVBC+Loq6BPzI`)1-jA(kW73GI2+6|C
zHfGpk at a2^cWjb0oU45_Fr>m{5Hxz>~cpf at EvFG&rK_uF)2uFS4^@UYyieAuh^);e;
zmB`jE(vg4Ar83cF^!0-Z+EopW0ve^{r%TW*3TAA>e<@*7O}ikHBrcHoN(HL#@Jha)
zc7sq;5Z#5Ii8>L6Nn{W$&kQ>6hy>BK^YoO_BX=C3b)Oj?5a)WP_=0Fx4?9le5FNrz
zAXMBmStgMK9=$#C{EpXo$OOi!;?mkN2bdfecNdQhgo?WYoq<X8Ne^8=*h_Lp4OHBj
zgb=rp`7Ag8;R;Mjrb&w*OOv9~OA}I>w6EI9 at q~m)2iFa}@0}cf$uWNwNT;p_gV!!H
z<K<=yyO`L_mlFFYKtQUy at TGVQTlJ9=8T}Hz*APb5CK~SdD$GK!6Agy$s1v9~NbmSQ
zJ97Nx3aC98|0qCiL6&*X!yeLTTFt|6pWnRu?nv9VMBUoZd7k8$p9+kyw(mn;Kyv(t
z6~GzvCeqf71>=Ts$5`Vtq?sI<jiOQFc8<BNfE-3n$QKfT*Y*NQoc|ra(&kG9UrbVF
zUA3}I#eqACNv+#3;(nM};TKRygy;z at o>DQx9Y{HFy$6pUN!$`6ujfj&`8!b%!X+C!
k+pW#5s;oDwJ626Ls&?(Ev^SeADSz*-Zd(Y+ at rMfh0-HAh+yDRo
literal 0
HcmV?d00001
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..9568afca1d924
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -0,0 +1,68 @@
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/pseudoreloc.exe | FileCheck %s
+
+CHECK: Format: COFF-i386
+CHECK-NEXT: Arch: i386
+CHECK-NEXT: AddressSize: 32bit
+CHECK-NEXT: PseudoReloc [
+CHECK-NEXT: ]
+
+pseudoreloc.exe is generated by following script:
+
+#--- generate.sh
+llvm-mc -triple i386-mingw32 -filetype obj pseudoreloc.dll.s -o pseudoreloc.dll.o
+ld.lld -m i386pe --dll pseudoreloc.dll.o -o pseudoreloc.dll -entry=
+llvm-mc -triple i386-mingw32 -filetype obj pseudoreloc.s -o pseudoreloc.o
+ld.lld -m i386pe pseudoreloc.o pseudoreloc.dll -o pseudoreloc.exe -entry=start
+
+#--- pseudoreloc.dll.s
+ .data
+ .globl _sym1
+_sym1:
+ .long 0x11223344
+ .globl _sym2
+_sym2:
+ .long 0x55667788
+ .section .drectve
+ .ascii " -export:sym1,data "
+ .ascii " -export:sym2,data "
+ .addrsig
+
+#--- pseudoreloc.s
+ .text
+ .globl _start
+_start:
+ mov _local1b, %eax
+ movsb (%eax), %ecx
+ mov _local2, %eax
+ movsb (%eax), %edx
+ mov _local1a, %eax
+ movsb (%eax), %eax
+ add %edx, %eax
+ add %ecx, %eax
+ ret
+
+ .globl __pei386_runtime_relocator
+__pei386_runtime_relocator:
+ mov ___RUNTIME_PSEUDO_RELOC_LIST__, %eax
+ mov ___RUNTIME_PSEUDO_RELOC_LIST_END__, %ecx
+ sub %ecx, %eax
+ ret
+
+ .data
+ .globl _local1a
+ .p2align 2
+_local1a:
+ .long _sym1+1
+
+ .globl _local2
+ .p2align 2
+_local2:
+ .long _sym2+1
+
+ .globl _local1b
+ .p2align 2
+_local1b:
+ .long _sym1+3
+
+ .addrsig
+
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 96e0a634648e4..3c1317590f539 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,8 @@ void COFFDumper::printCOFFBaseReloc() {
}
}
+void COFFDumper::printCOFFPseudoReloc() { ListScope D(W, "PseudoReloc"); }
+
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..d519e34a72983 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -82,6 +82,9 @@ def codeview_ghash : FF<"codeview-ghash", "Enable global hashing for CodeView ty
def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group<grp_coff>;
def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group<grp_coff>;
def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group<grp_coff>;
+def coff_pseudoreloc
+ : FF<"coff-pseudoreloc", "Display runtime pseudo-relocations">,
+ Group<grp_coff>;
def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group<grp_coff>;
def coff_directives : FF<"coff-directives", "Display .drectve section">, Group<grp_coff>;
def coff_exports : FF<"coff-exports", "Display export table">, 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)
>From 48f4280548ef82826b3e01273cf50a923905b7b5 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 30 Jul 2025 21:34:59 +0900
Subject: [PATCH 02/13] find pseudo-reloc symbols
---
.../tools/llvm-readobj/COFF/pseudoreloc.test | 11 +++++++
llvm/tools/llvm-readobj/COFFDumper.cpp | 33 ++++++++++++++++++-
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index 9568afca1d924..b2bc7a4553298 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -1,4 +1,6 @@
RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/pseudoreloc.exe | FileCheck %s
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/nop.exe.coff-x86-64 | FileCheck %s --check-prefix=NOSYM
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 | FileCheck %s --check-prefix=NORELOC
CHECK: Format: COFF-i386
CHECK-NEXT: Arch: i386
@@ -6,6 +8,15 @@ CHECK-NEXT: AddressSize: 32bit
CHECK-NEXT: PseudoReloc [
CHECK-NEXT: ]
+NOSYM-NOT: PseudoReloc
+NOSYM: The symbol table has been stripped
+NOSYM-NOT: PseudoReloc
+
+NORELOC-NOT: PseudoReloc
+NORELOC: The symbols for runtime pseudo-relocation are not found
+NORELOC-NOT: PseudoReloc
+
+
pseudoreloc.exe is generated by following script:
#--- generate.sh
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 3c1317590f539..a997e3519cc2d 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2001,7 +2001,38 @@ void COFFDumper::printCOFFBaseReloc() {
}
}
-void COFFDumper::printCOFFPseudoReloc() { ListScope D(W, "PseudoReloc"); }
+void COFFDumper::printCOFFPseudoReloc() {
+ 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__";
+
+ COFFSymbolRef RelocBegin, RelocEnd;
+ auto Count = Obj->getNumberOfSymbols();
+ if (Count == 0) {
+ W.startLine() << "The symbol table has been stripped\n";
+ return;
+ }
+ for (auto i = 0u;
+ i < Count && (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()); ++i) {
+ auto Sym = Obj->getSymbol(i);
+ if (Sym.takeError())
+ continue;
+ auto Name = Obj->getSymbolName(*Sym);
+ if (*Name == RelocBeginName)
+ RelocBegin = *Sym;
+ else if (*Name == RelocEndName)
+ RelocEnd = *Sym;
+ }
+ if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
+ W.startLine()
+ << "The symbols for runtime pseudo-relocation are not found\n";
+ return;
+ }
+ ListScope D(W, "PseudoReloc");
+}
void COFFDumper::printCOFFResources() {
ListScope ResourcesD(W, "Resources");
>From fff11ce555dc1705f1522f3381918dd64d6d10f4 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Thu, 31 Jul 2025 21:58:45 +0900
Subject: [PATCH 03/13] dump raw reloc data
---
.../tools/llvm-readobj/COFF/pseudoreloc.test | 15 +++++
llvm/tools/llvm-readobj/COFFDumper.cpp | 55 +++++++++++++++++--
2 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index b2bc7a4553298..2989053a8e040 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -6,6 +6,21 @@ CHECK: Format: COFF-i386
CHECK-NEXT: Arch: i386
CHECK-NEXT: AddressSize: 32bit
CHECK-NEXT: PseudoReloc [
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: BitWidth: {{[0-9]+}}
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: BitWidth: {{[0-9]+}}
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: BitWidth: {{[0-9]+}}
+CHECK-NEXT: }
CHECK-NEXT: ]
NOSYM-NOT: PseudoReloc
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index a997e3519cc2d..e3cc9d7e7e5c9 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2021,17 +2021,64 @@ void COFFDumper::printCOFFPseudoReloc() {
if (Sym.takeError())
continue;
auto Name = Obj->getSymbolName(*Sym);
- if (*Name == RelocBeginName)
- RelocBegin = *Sym;
- else if (*Name == RelocEndName)
- RelocEnd = *Sym;
+ if (Name.takeError())
+ continue;
+ if (*Name == RelocBeginName) {
+ if (Sym->getSectionNumber() > 0)
+ RelocBegin = *Sym;
+ } else if (*Name == RelocEndName) {
+ if (Sym->getSectionNumber() > 0)
+ RelocEnd = *Sym;
+ }
}
if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
W.startLine()
<< "The symbols for runtime pseudo-relocation are not found\n";
return;
}
+
+ ArrayRef<uint8_t> Data;
+ auto Section = Obj->getSection(RelocBegin.getSectionNumber());
+ if (auto E = Section.takeError()) {
+ reportError(std::move(E), Obj->getFileName());
+ return;
+ }
+ if (auto E = Obj->getSectionContents(*Section, Data)) {
+ reportError(std::move(E), Obj->getFileName());
+ return;
+ }
+ ArrayRef<uint8_t> RawRelocs =
+ Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());
+ struct alignas(4) PseudoRelocationHeader {
+ uint32_t Zero1;
+ uint32_t Zero2;
+ uint32_t Signature;
+ };
+ static const PseudoRelocationHeader HeaderV2 = {0, 0, 1};
+ if (RawRelocs.size() < sizeof(HeaderV2) ||
+ (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {
+ reportWarning(
+ createStringError("Invalid runtime pseudo-relocation records"),
+ Obj->getFileName());
+ return;
+ }
+ struct alignas(4) PseudoRelocationRecord {
+ uint32_t Symbol;
+ uint32_t Target;
+ uint32_t BitSize;
+ };
+ ArrayRef<PseudoRelocationRecord> RelocRecords(
+ reinterpret_cast<const PseudoRelocationRecord *>(
+ RawRelocs.data() + sizeof(PseudoRelocationHeader)),
+ (RawRelocs.size() - sizeof(PseudoRelocationHeader)) /
+ sizeof(PseudoRelocationRecord));
ListScope D(W, "PseudoReloc");
+ for (const auto &Reloc : RelocRecords) {
+ DictScope Entry(W, "Entry");
+ W.printHex("Symbol", Reloc.Symbol);
+ W.printHex("Target", Reloc.Target);
+ W.printNumber("BitWidth", Reloc.BitSize);
+ }
}
void COFFDumper::printCOFFResources() {
>From be77e1c7e180b985c87c1c0cd3b0f6ea1e36bdd1 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Thu, 31 Jul 2025 23:22:55 +0900
Subject: [PATCH 04/13] show symbol name
---
.../tools/llvm-readobj/COFF/pseudoreloc.test | 3 ++
llvm/tools/llvm-readobj/COFFDumper.cpp | 28 +++++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index 2989053a8e040..f3db464b4ae69 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -8,16 +8,19 @@ CHECK-NEXT: AddressSize: 32bit
CHECK-NEXT: PseudoReloc [
CHECK-NEXT: Entry {
CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: SymbolName: sym1
CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
CHECK-NEXT: BitWidth: {{[0-9]+}}
CHECK-NEXT: }
CHECK-NEXT: Entry {
CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: SymbolName: sym2
CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
CHECK-NEXT: BitWidth: {{[0-9]+}}
CHECK-NEXT: }
CHECK-NEXT: Entry {
CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: SymbolName: sym1
CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
CHECK-NEXT: BitWidth: {{[0-9]+}}
CHECK-NEXT: }
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index e3cc9d7e7e5c9..45ca018b714f2 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2072,10 +2072,38 @@ void COFFDumper::printCOFFPseudoReloc() {
RawRelocs.data() + sizeof(PseudoRelocationHeader)),
(RawRelocs.size() - sizeof(PseudoRelocationHeader)) /
sizeof(PseudoRelocationRecord));
+
+ // Cache of symbol searched at least once in IAT
+ DenseMap<uint32_t, StringRef> ImportedSymbols;
+
ListScope D(W, "PseudoReloc");
for (const auto &Reloc : RelocRecords) {
DictScope Entry(W, "Entry");
W.printHex("Symbol", Reloc.Symbol);
+
+ // find and print the pointed symbol from IAT
+ [&]() {
+ for (auto D : Obj->import_directories()) {
+ uint32_t RVA;
+ if (auto E = D.getImportAddressTableRVA(RVA))
+ reportError(std::move(E), Obj->getFileName());
+ if (Reloc.Symbol < RVA)
+ continue;
+ for (auto S : D.imported_symbols()) {
+ if (RVA == Reloc.Symbol) {
+ if (auto E = S.getSymbolName(ImportedSymbols[RVA]))
+ reportError(std::move(E), Obj->getFileName());
+ return;
+ }
+ RVA += Obj->is64() ? 8 : 4;
+ }
+ }
+ }();
+ if (auto Ite = ImportedSymbols.find(Reloc.Symbol);
+ Ite != ImportedSymbols.end()) {
+ W.printString("SymbolName", Ite->second);
+ }
+
W.printHex("Target", Reloc.Target);
W.printNumber("BitWidth", Reloc.BitSize);
}
>From 145c3e4729ec3faa27c1821a175fd5353b4af284 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Mon, 4 Aug 2025 18:35:07 +0900
Subject: [PATCH 05/13] use support::ulittle32_t
---
llvm/tools/llvm-readobj/COFFDumper.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 45ca018b714f2..39a9ed6842870 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2050,11 +2050,13 @@ void COFFDumper::printCOFFPseudoReloc() {
ArrayRef<uint8_t> RawRelocs =
Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());
struct alignas(4) PseudoRelocationHeader {
- uint32_t Zero1;
- uint32_t Zero2;
- uint32_t Signature;
+ PseudoRelocationHeader(uint32_t Signature)
+ : Zero1(0), Zero2(0), Signature(Signature) {}
+ support::ulittle32_t Zero1;
+ support::ulittle32_t Zero2;
+ support::ulittle32_t Signature;
};
- static const PseudoRelocationHeader HeaderV2 = {0, 0, 1};
+ const PseudoRelocationHeader HeaderV2(1);
if (RawRelocs.size() < sizeof(HeaderV2) ||
(memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {
reportWarning(
@@ -2063,9 +2065,9 @@ void COFFDumper::printCOFFPseudoReloc() {
return;
}
struct alignas(4) PseudoRelocationRecord {
- uint32_t Symbol;
- uint32_t Target;
- uint32_t BitSize;
+ support::ulittle32_t Symbol;
+ support::ulittle32_t Target;
+ support::ulittle32_t BitSize;
};
ArrayRef<PseudoRelocationRecord> RelocRecords(
reinterpret_cast<const PseudoRelocationRecord *>(
>From 9ff81f6abbced8b2013faac38d283a718e9476d0 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Mon, 4 Aug 2025 19:23:28 +0900
Subject: [PATCH 06/13] use named functor instead of unnamed lambda
---
llvm/tools/llvm-readobj/COFFDumper.cpp | 40 +++++++++++++++-----------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 39a9ed6842870..b72605f7c3419 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2075,37 +2075,43 @@ void COFFDumper::printCOFFPseudoReloc() {
(RawRelocs.size() - sizeof(PseudoRelocationHeader)) /
sizeof(PseudoRelocationRecord));
- // Cache of symbol searched at least once in IAT
- DenseMap<uint32_t, StringRef> ImportedSymbols;
+ struct CachingImportedSymbolLookup {
+ const StringRef *find(const COFFObjectFile *Obj, uint32_t EntryRVA) {
+ if (auto Ite = ImportedSymbols.find(EntryRVA);
+ Ite != ImportedSymbols.end())
+ return &Ite->second;
- ListScope D(W, "PseudoReloc");
- for (const auto &Reloc : RelocRecords) {
- DictScope Entry(W, "Entry");
- W.printHex("Symbol", Reloc.Symbol);
-
- // find and print the pointed symbol from IAT
- [&]() {
for (auto D : Obj->import_directories()) {
uint32_t RVA;
if (auto E = D.getImportAddressTableRVA(RVA))
reportError(std::move(E), Obj->getFileName());
- if (Reloc.Symbol < RVA)
+ if (EntryRVA < RVA)
continue;
for (auto S : D.imported_symbols()) {
- if (RVA == Reloc.Symbol) {
- if (auto E = S.getSymbolName(ImportedSymbols[RVA]))
+ if (RVA == EntryRVA) {
+ StringRef &NameDst = ImportedSymbols[RVA];
+ if (auto E = S.getSymbolName(NameDst))
reportError(std::move(E), Obj->getFileName());
- return;
+ return &NameDst;
}
RVA += Obj->is64() ? 8 : 4;
}
}
- }();
- if (auto Ite = ImportedSymbols.find(Reloc.Symbol);
- Ite != ImportedSymbols.end()) {
- W.printString("SymbolName", Ite->second);
+
+ return nullptr;
}
+ private:
+ DenseMap<uint32_t, StringRef> ImportedSymbols;
+ };
+ CachingImportedSymbolLookup ImportedSymbols;
+
+ ListScope D(W, "PseudoReloc");
+ for (const auto &Reloc : RelocRecords) {
+ DictScope Entry(W, "Entry");
+ W.printHex("Symbol", Reloc.Symbol);
+ if (const auto *Sym = ImportedSymbols.find(Obj, Reloc.Symbol))
+ W.printString("SymbolName", *Sym);
W.printHex("Target", Reloc.Target);
W.printNumber("BitWidth", Reloc.BitSize);
}
>From 4cd5e29ce9b0280c625c91f84f65fe43e5e6a5eb Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 6 Aug 2025 18:39:11 +0900
Subject: [PATCH 07/13] note the option "Cygwin/MinGW specific" and reorder
alphabetically
---
llvm/tools/llvm-readobj/Opts.td | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index d519e34a72983..71e1cae91d417 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -81,15 +81,17 @@ def codeview : FF<"codeview", "Display CodeView debug information">, Group<grp_c
def codeview_ghash : FF<"codeview-ghash", "Enable global hashing for CodeView type stream de-duplication">, Group<grp_coff>;
def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group<grp_coff>;
def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group<grp_coff>;
-def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group<grp_coff>;
-def coff_pseudoreloc
- : FF<"coff-pseudoreloc", "Display runtime pseudo-relocations">,
- Group<grp_coff>;
+def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">,
+ Group<grp_coff>;
def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group<grp_coff>;
def coff_directives : FF<"coff-directives", "Display .drectve section">, Group<grp_coff>;
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>;
>From 6980cb12fa8981f01a9675a2acd601e967c08317 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 6 Aug 2025 19:42:36 +0900
Subject: [PATCH 08/13] fix handling of errors
- ignore properly
- use reportWarning instead of reportError
- uncapitalize message
---
.../tools/llvm-readobj/COFF/pseudoreloc.test | 4 ++--
llvm/tools/llvm-readobj/COFFDumper.cpp | 22 +++++++++++--------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index f3db464b4ae69..453527ad38e6f 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -27,11 +27,11 @@ CHECK-NEXT: }
CHECK-NEXT: ]
NOSYM-NOT: PseudoReloc
-NOSYM: The symbol table has been stripped
+NOSYM: the symbol table has been stripped
NOSYM-NOT: PseudoReloc
NORELOC-NOT: PseudoReloc
-NORELOC: The symbols for runtime pseudo-relocation are not found
+NORELOC: the symbols for runtime pseudo-relocation are not found
NORELOC-NOT: PseudoReloc
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index b72605f7c3419..8438c072c7790 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2012,17 +2012,21 @@ void COFFDumper::printCOFFPseudoReloc() {
COFFSymbolRef RelocBegin, RelocEnd;
auto Count = Obj->getNumberOfSymbols();
if (Count == 0) {
- W.startLine() << "The symbol table has been stripped\n";
+ W.startLine() << "the symbol table has been stripped\n";
return;
}
for (auto i = 0u;
i < Count && (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()); ++i) {
auto Sym = Obj->getSymbol(i);
- if (Sym.takeError())
+ if (!Sym) {
+ consumeError(Sym.takeError());
continue;
+ }
auto Name = Obj->getSymbolName(*Sym);
- if (Name.takeError())
+ if (!Name) {
+ consumeError(Name.takeError());
continue;
+ }
if (*Name == RelocBeginName) {
if (Sym->getSectionNumber() > 0)
RelocBegin = *Sym;
@@ -2033,18 +2037,18 @@ void COFFDumper::printCOFFPseudoReloc() {
}
if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
W.startLine()
- << "The symbols for runtime pseudo-relocation are not found\n";
+ << "the symbols for runtime pseudo-relocation are not found\n";
return;
}
ArrayRef<uint8_t> Data;
auto Section = Obj->getSection(RelocBegin.getSectionNumber());
if (auto E = Section.takeError()) {
- reportError(std::move(E), Obj->getFileName());
+ reportWarning(std::move(E), Obj->getFileName());
return;
}
if (auto E = Obj->getSectionContents(*Section, Data)) {
- reportError(std::move(E), Obj->getFileName());
+ reportWarning(std::move(E), Obj->getFileName());
return;
}
ArrayRef<uint8_t> RawRelocs =
@@ -2060,7 +2064,7 @@ void COFFDumper::printCOFFPseudoReloc() {
if (RawRelocs.size() < sizeof(HeaderV2) ||
(memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {
reportWarning(
- createStringError("Invalid runtime pseudo-relocation records"),
+ createStringError("invalid runtime pseudo-relocation records"),
Obj->getFileName());
return;
}
@@ -2084,14 +2088,14 @@ void COFFDumper::printCOFFPseudoReloc() {
for (auto D : Obj->import_directories()) {
uint32_t RVA;
if (auto E = D.getImportAddressTableRVA(RVA))
- reportError(std::move(E), Obj->getFileName());
+ reportWarning(std::move(E), Obj->getFileName());
if (EntryRVA < RVA)
continue;
for (auto S : D.imported_symbols()) {
if (RVA == EntryRVA) {
StringRef &NameDst = ImportedSymbols[RVA];
if (auto E = S.getSymbolName(NameDst))
- reportError(std::move(E), Obj->getFileName());
+ reportWarning(std::move(E), Obj->getFileName());
return &NameDst;
}
RVA += Obj->is64() ? 8 : 4;
>From 8a5a7f886835e8bf3173833a9599bdb235210c79 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 6 Aug 2025 20:30:21 +0900
Subject: [PATCH 09/13] range check for reloc record region
---
llvm/tools/llvm-readobj/COFFDumper.cpp | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 8438c072c7790..223a471884e11 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2041,16 +2041,33 @@ void COFFDumper::printCOFFPseudoReloc() {
return;
}
- ArrayRef<uint8_t> Data;
+ if (RelocEnd.getValue() < RelocBegin.getValue()) {
+ reportWarning(createStringError("the symbols for runtime pseudo-relocation "
+ "don't consist a valid region"),
+ Obj->getFileName());
+ return;
+ }
+
auto Section = Obj->getSection(RelocBegin.getSectionNumber());
if (auto E = Section.takeError()) {
reportWarning(std::move(E), Obj->getFileName());
return;
}
+
+ ArrayRef<uint8_t> Data;
if (auto E = Obj->getSectionContents(*Section, Data)) {
reportWarning(std::move(E), Obj->getFileName());
return;
}
+ if (Data.size() <= RelocBegin.getValue() ||
+ Data.size() <= RelocEnd.getValue()) {
+ reportWarning(
+ createStringError("the region of runtime pseudo-relocation records "
+ "points to out of the valid location"),
+ Obj->getFileName());
+ return;
+ }
+
ArrayRef<uint8_t> RawRelocs =
Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());
struct alignas(4) PseudoRelocationHeader {
>From 8e02d4a329f65c7dcde194b66b8e689d5b2348c5 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 6 Aug 2025 19:48:26 +0900
Subject: [PATCH 10/13] cache import directory size
---
llvm/tools/llvm-readobj/COFFDumper.cpp | 64 +++++++++++++++++++-------
1 file changed, 48 insertions(+), 16 deletions(-)
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 223a471884e11..6af0dacbff9a2 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2097,41 +2097,73 @@ void COFFDumper::printCOFFPseudoReloc() {
sizeof(PseudoRelocationRecord));
struct CachingImportedSymbolLookup {
- const StringRef *find(const COFFObjectFile *Obj, uint32_t EntryRVA) {
+ 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;
+ });
+ }
+
+ const StringRef *find(uint32_t EntryRVA) {
if (auto Ite = ImportedSymbols.find(EntryRVA);
Ite != ImportedSymbols.end())
return &Ite->second;
- for (auto D : Obj->import_directories()) {
- uint32_t RVA;
- if (auto E = D.getImportAddressTableRVA(RVA))
- reportWarning(std::move(E), Obj->getFileName());
- if (EntryRVA < RVA)
- continue;
- for (auto S : D.imported_symbols()) {
- if (RVA == EntryRVA) {
- StringRef &NameDst = ImportedSymbols[RVA];
- if (auto E = S.getSymbolName(NameDst))
- reportWarning(std::move(E), Obj->getFileName());
- return &NameDst;
+ auto Ite = llvm::upper_bound(
+ ImportDirectories, EntryRVA,
+ [](uint32_t RVA, const auto &D) { return RVA < D.StartRVA; });
+ if (Ite == ImportDirectories.begin())
+ return nullptr;
+
+ --Ite;
+ const auto &D = Ite->EntryRef;
+ uint32_t RVA = Ite->StartRVA;
+ if (Ite->EndRVA != 0 && Ite->EndRVA <= RVA)
+ return nullptr;
+ // Search with linear iteration to care if padding or garbage exist
+ // between ImportDirectoryEntry
+ for (auto S : D.imported_symbols()) {
+ if (RVA == EntryRVA) {
+ StringRef &NameDst = ImportedSymbols[RVA];
+ if (auto E = S.getSymbolName(NameDst)) {
+ reportWarning(std::move(E), Obj->getFileName());
+ NameDst = "(no symbol)";
}
- RVA += Obj->is64() ? 8 : 4;
+ return &NameDst;
}
+ RVA += Obj->is64() ? 8 : 4;
}
+ Ite->EndRVA = RVA;
return nullptr;
}
private:
+ const COFFObjectFile *Obj;
+ SmallVector<SizedImportDirectoryEntry> ImportDirectories;
DenseMap<uint32_t, StringRef> ImportedSymbols;
};
- CachingImportedSymbolLookup ImportedSymbols;
+ CachingImportedSymbolLookup ImportedSymbols(Obj);
ListScope D(W, "PseudoReloc");
for (const auto &Reloc : RelocRecords) {
DictScope Entry(W, "Entry");
W.printHex("Symbol", Reloc.Symbol);
- if (const auto *Sym = ImportedSymbols.find(Obj, Reloc.Symbol))
+ if (const auto *Sym = ImportedSymbols.find(Reloc.Symbol))
W.printString("SymbolName", *Sym);
W.printHex("Target", Reloc.Target);
W.printNumber("BitWidth", Reloc.BitSize);
>From 0dcc26d2c9fbc0570e21fbd00610b55de5a2cb39 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 6 Aug 2025 20:15:29 +0900
Subject: [PATCH 11/13] reorganize test
- use --implicit-check-not
- use obj2yaml
- use numeric capture pattern
---
.../llvm-readobj/COFF/Inputs/pseudoreloc.exe | Bin 4096 -> 0 bytes
.../COFF/Inputs/pseudoreloc.i386.yaml | 111 ++++++++
.../COFF/Inputs/pseudoreloc.x86_64.yaml | 111 ++++++++
.../tools/llvm-readobj/COFF/pseudoreloc.test | 251 ++++++++++++------
4 files changed, 397 insertions(+), 76 deletions(-)
delete mode 100644 llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.exe
create mode 100644 llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
create mode 100644 llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
diff --git a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.exe b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.exe
deleted file mode 100644
index d4106e99d96f357920d24b3cb206bedbaccfb17d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4096
zcmeHK&ubG=5T1=uQ-7otya?64LJx|tY$}Q;S?cCc*ft?aFJ4|Z&0-cd*|6DQdefUw
z5dQ!V&HvDYco3l=Jy`H4c=12cZ{F^Pr6qduVBC+Loq6BPzI`)1-jA(kW73GI2+6|C
zHfGpk at a2^cWjb0oU45_Fr>m{5Hxz>~cpf at EvFG&rK_uF)2uFS4^@UYyieAuh^);e;
zmB`jE(vg4Ar83cF^!0-Z+EopW0ve^{r%TW*3TAA>e<@*7O}ikHBrcHoN(HL#@Jha)
zc7sq;5Z#5Ii8>L6Nn{W$&kQ>6hy>BK^YoO_BX=C3b)Oj?5a)WP_=0Fx4?9le5FNrz
zAXMBmStgMK9=$#C{EpXo$OOi!;?mkN2bdfecNdQhgo?WYoq<X8Ne^8=*h_Lp4OHBj
zgb=rp`7Ag8;R;Mjrb&w*OOv9~OA}I>w6EI9 at q~m)2iFa}@0}cf$uWNwNT;p_gV!!H
z<K<=yyO`L_mlFFYKtQUy at TGVQTlJ9=8T}Hz*APb5CK~SdD$GK!6Agy$s1v9~NbmSQ
zJ97Nx3aC98|0qCiL6&*X!yeLTTFt|6pWnRu?nv9VMBUoZd7k8$p9+kyw(mn;Kyv(t
z6~GzvCeqf71>=Ts$5`Vtq?sI<jiOQFc8<BNfE-3n$QKfT*Y*NQoc|ra(&kG9UrbVF
zUA3}I#eqACNv+#3;(nM};TKRygy;z at o>DQx9Y{HFy$6pUN!$`6ujfj&`8!b%!X+C!
k+pW#5s;oDwJ626Ls&?(Ev^SeADSz*-Zd(Y+ at rMfh0-HAh+yDRo
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..85370adedb19f
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
@@ -0,0 +1,111 @@
+--- !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: 8276
+ 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: 8356
+ 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: A1003040000FBE008B0D043040000FBE0901C1A1083040000FBE10A10C3040000FBE0001D001C8C39090909090909090A1442040002B0508204000C3
+ SizeOfRawData: 512
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 8192
+ VirtualSize: 242
+ SectionData: 3377115566228844000000000000000001000000A42000000030000020000000A82000000430000020000000B02000000830000020000000A42000000C30000020000000FFFFFFFF00000000FFFFFFFF00000000902000000000000000000000D0200000A42000009C2000000000000000000000E1200000B02000000000000000000000000000000000000000000000B8200000C020000000000000C820000000000000B8200000C020000000000000C820000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
+ SizeOfRawData: 512
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ VirtualAddress: 12288
+ VirtualSize: 16
+ SectionData: A5204000AA204000B1204000A6204000
+ 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: __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: 68
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: ___RUNTIME_PSEUDO_RELOC_LIST__
+ Value: 8
+ SectionNumber: 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..46bc1c5ce17a8
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
@@ -0,0 +1,111 @@
+--- !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: 8296
+ 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: 8400
+ 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: 488B05F91F00000FBE00488B0DF71F00000FBE0901C1488B05F31F00000FBE10488B05F11F00000FBE0001D001C8C3908B050E1000002B05CC0F0000C3
+ SizeOfRawData: 512
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 8192
+ VirtualSize: 310
+ SectionData: 3377115566228844000000000000000001000000E02000000030000040000000E82000000830000040000000D02000001030000040000000E0200000183000004000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000A8200000000000000000000010210000D0200000B8200000000000000000000023210000E0200000000000000000000000000000000000000000000000000000F8200000000000000000000000000000002100000000000008210000000000000000000000000000F8200000000000000000000000000000002100000000000008210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
+ SizeOfRawData: 512
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ VirtualAddress: 12288
+ VirtualSize: 32
+ SectionData: E120004001000000EA20004001000000D120004001000000E220004001000000
+ 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: _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: 68
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __RUNTIME_PSEUDO_RELOC_LIST__
+ Value: 8
+ SectionNumber: 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
index 453527ad38e6f..2f83cb81437e0 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -1,97 +1,196 @@
-RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/pseudoreloc.exe | FileCheck %s
-RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/nop.exe.coff-x86-64 | FileCheck %s --check-prefix=NOSYM
-RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 | FileCheck %s --check-prefix=NORELOC
+REQUIRE: x86-registered-target
-CHECK: Format: COFF-i386
-CHECK-NEXT: Arch: i386
-CHECK-NEXT: AddressSize: 32bit
+DEFINE: %{local} = 0x3000
+DEFINE: %{addr1l} = E0
+DEFINE: %{addr3l} = D0
+RUN: yaml2obj %p/Inputs/pseudoreloc.x86_64.yaml | llvm-readobj --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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local}
+
+REDEFINE: %{addr1l} = A4
+REDEFINE: %{addr3l} = B0
+RUN: yaml2obj %p/Inputs/pseudoreloc.i386.yaml | llvm-readobj --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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local}
+
+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{{[0-9A-Z]+}}
+CHECK-NEXT: Symbol: 0x[[#%X,SYM1]]
CHECK-NEXT: SymbolName: sym1
-CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
-CHECK-NEXT: BitWidth: {{[0-9]+}}
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A]]
+CHECK-NEXT: BitWidth: [[#BW]]
CHECK-NEXT: }
CHECK-NEXT: Entry {
-CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: Symbol: 0x[[#%X,SYM1+mul(1,WORD)]]
CHECK-NEXT: SymbolName: sym2
-CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
-CHECK-NEXT: BitWidth: {{[0-9]+}}
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(1,WORD)]]
+CHECK-NEXT: BitWidth: [[#BW]]
CHECK-NEXT: }
CHECK-NEXT: Entry {
-CHECK-NEXT: Symbol: 0x{{[0-9A-Z]+}}
+CHECK-NEXT: Symbol: 0x[[#%X,SYM3]]
+CHECK-NEXT: SymbolName: sym3
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(2,WORD)]]
+CHECK-NEXT: BitWidth: [[#BW]]
+CHECK-NEXT: }
+CHECK-NEXT: Entry {
+CHECK-NEXT: Symbol: 0x[[#%X,SYM1]]
CHECK-NEXT: SymbolName: sym1
-CHECK-NEXT: Target: 0x{{[0-9A-Z]+}}
-CHECK-NEXT: BitWidth: {{[0-9]+}}
+CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(3,WORD)]]
+CHECK-NEXT: BitWidth: [[#BW]]
CHECK-NEXT: }
CHECK-NEXT: ]
-NOSYM-NOT: PseudoReloc
+
+; check that silently ignore when imported symbol name is not found
+RUN: sed -E -e '/Name: *\.rdata/,/Name:/{/SectionData:/{s/%{addr1l}200000/30000000/;s/%{addr3l}200000/00FFFF00/}}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 \
+RUN: | FileCheck %s --check-prefix=INVALIDSYMBOL --match-full-lines -D#LOCAL1A=%{local} --implicit-check-not=warning
+
+INVALIDSYMBOL: Symbol: 0x30
+INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A]]
+INVALIDSYMBOL: Symbol: 0xFFFF00
+INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+8]]
+
+
+; check that shows empty list when the relocation list has no contents
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/20/}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 \
+RUN: | FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
+
+EMPTY: Format: COFF-i386
+EMPTY-NEXT: Arch: i386
+EMPTY-NEXT: AddressSize: 32bit
+EMPTY-NEXT: PseudoReloc [
+EMPTY-NEXT: ]
+
+
+; assume position of the relocation list for further tests
+RUN: yaml2obj %p/Inputs/pseudoreloc.i386.yaml | llvm-readobj --syms - | FileCheck %s --check-prefix=RELOCPOS --match-full-lines
+
+RELOCPOS: Name: ___RUNTIME_PSEUDO_RELOC_LIST__
+RELOCPOS-NEXT: Value: 8
+
+
+; check that shows message if the header of the relocation list is broken or missing
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/20/}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=NOHEADER --implicit-check-not=PseudoReloc
+
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/8/}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=NOHEADER --implicit-check-not=PseudoReloc
+
+NOHEADER: invalid runtime pseudo-relocation records
+
+
+; check that warn if end < start
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/8/}' \
+RUN: -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/20/}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=INVALREGION --implicit-check-not=PseudoReloc
+
+INVALREGION: the symbols for runtime pseudo-relocation don't consist a valid region
+
+
+; check that warn if the relocation list points out of section space
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/9999/}' \
+RUN: -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/8888/}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=OUTOFRANGE --implicit-check-not=PseudoReloc
+
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/9999/}' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=OUTOFRANGE --implicit-check-not=PseudoReloc
+
+OUTOFRANGE: the region of runtime pseudo-relocation records points to out of the valid location
+
+
+; check that warn if image is stripped
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/nop.exe.coff-x86-64 2>&1 | FileCheck %s --check-prefix=NOSYM --implicit-check-not=PseudoReloc
+
NOSYM: the symbol table has been stripped
-NOSYM-NOT: PseudoReloc
-NORELOC-NOT: PseudoReloc
+
+; check that warn if the relocation list is missing (intended for MSVC-made binaries)
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | FileCheck %s --check-prefix=NORELOC --implicit-check-not=PseudoReloc
+
NORELOC: the symbols for runtime pseudo-relocation are not found
-NORELOC-NOT: PseudoReloc
-pseudoreloc.exe is generated by following script:
+pseudoreloc.*.yaml is generated by following script:
+
+$ split-file pseudoreloc.test /tmp/pseudoreloc && bash /tmp/pseudoreloc/generate.sh && cp /tmp/pseudoreloc/*.yaml Inputs/
+
#--- generate.sh
-llvm-mc -triple i386-mingw32 -filetype obj pseudoreloc.dll.s -o pseudoreloc.dll.o
-ld.lld -m i386pe --dll pseudoreloc.dll.o -o pseudoreloc.dll -entry=
-llvm-mc -triple i386-mingw32 -filetype obj pseudoreloc.s -o pseudoreloc.o
-ld.lld -m i386pe pseudoreloc.o pseudoreloc.dll -o pseudoreloc.exe -entry=start
-
-#--- pseudoreloc.dll.s
- .data
- .globl _sym1
-_sym1:
- .long 0x11223344
- .globl _sym2
-_sym2:
- .long 0x55667788
- .section .drectve
- .ascii " -export:sym1,data "
- .ascii " -export:sym2,data "
- .addrsig
-
-#--- pseudoreloc.s
- .text
- .globl _start
-_start:
- mov _local1b, %eax
- movsb (%eax), %ecx
- mov _local2, %eax
- movsb (%eax), %edx
- mov _local1a, %eax
- movsb (%eax), %eax
- add %edx, %eax
- add %ecx, %eax
- ret
-
- .globl __pei386_runtime_relocator
-__pei386_runtime_relocator:
- mov ___RUNTIME_PSEUDO_RELOC_LIST__, %eax
- mov ___RUNTIME_PSEUDO_RELOC_LIST_END__, %ecx
- sub %ecx, %eax
- ret
-
- .data
- .globl _local1a
- .p2align 2
-_local1a:
- .long _sym1+1
-
- .globl _local2
- .p2align 2
-_local2:
- .long _sym2+1
-
- .globl _local1b
- .p2align 2
-_local1b:
- .long _sym1+3
-
- .addrsig
+cd "$(dirname $0)"
+set -e
+
+llc -mtriple i386-mingw32 -filetype obj export1.ll -o export1.i386.o
+ld.lld -m i386pe --dll export1.i386.o -o export1.i386.dll -entry=
+llc -mtriple i386-mingw32 -filetype obj export2.ll -o export2.i386.o
+ld.lld -m i386pe --dll export2.i386.o -o export2.i386.dll -entry=
+llc -mtriple i386-mingw32 -filetype obj import.ll -o import.i386.o
+ld.lld -m i386pe -S import.i386.o export1.i386.dll export2.i386.dll -o pseudoreloc.i386.exe -entry=start \
+ --disable-dynamicbase --disable-reloc-section
+obj2yaml pseudoreloc.i386.exe -o pseudoreloc.i386.yaml
+
+llc -mtriple x86_64-mingw32 -filetype obj export1.ll -o export1.x86_64.o
+ld.lld -m i386pep --dll export1.x86_64.o -o export1.x86_64.dll -entry=
+llc -mtriple x86_64-mingw32 -filetype obj export2.ll -o export2.x86_64.o
+ld.lld -m i386pep --dll export2.x86_64.o -o export2.x86_64.dll -entry=
+llc -mtriple x86_64-mingw32 -filetype obj import.ll -o import.x86_64.o
+ld.lld -m i386pep -S import.x86_64.o export1.x86_64.dll export2.x86_64.dll -o pseudoreloc.x86_64.exe -entry=start \
+ --disable-dynamicbase --disable-reloc-section
+obj2yaml pseudoreloc.x86_64.exe -o pseudoreloc.x86_64.yaml
+
+
+#--- 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 = private global ptr getelementptr (i8, ptr @sym2, i32 2)
+ at local3a = private global 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
+}
>From b182e0e7484cff7342f573a1ec513cca4b7a7326 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Wed, 6 Aug 2025 20:31:40 +0900
Subject: [PATCH 12/13] early exit when not a PE
---
llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test | 9 ++++++++-
llvm/tools/llvm-readobj/COFFDumper.cpp | 6 ++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index 2f83cb81437e0..1906cfafe408d 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -112,11 +112,18 @@ NOSYM: the symbol table has been stripped
; check that warn if the relocation list is missing (intended for MSVC-made binaries)
-RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | FileCheck %s --check-prefix=NORELOC --implicit-check-not=PseudoReloc
+RUN: sed -e 's/__RUNTIME//' %p/Inputs/pseudoreloc.i386.yaml \
+RUN: | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=NORELOC --implicit-check-not=PseudoReloc
NORELOC: the symbols for runtime pseudo-relocation are not found
+; check that warn if .obj is specified
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | FileCheck %s --check-prefix=NOTPE --implicit-check-not=PseudoReloc
+
+NOTPE: pseudo-relocation is only meaningful for a PE image file
+
+
pseudoreloc.*.yaml is generated by following script:
$ split-file pseudoreloc.test /tmp/pseudoreloc && bash /tmp/pseudoreloc/generate.sh && cp /tmp/pseudoreloc/*.yaml Inputs/
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 6af0dacbff9a2..98a88d5d65d2c 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2002,6 +2002,12 @@ void COFFDumper::printCOFFBaseReloc() {
}
void COFFDumper::printCOFFPseudoReloc() {
+ if (!Obj->getDOSHeader()) {
+ W.startLine()
+ << "pseudo-relocation is only meaningful for a PE image file\n";
+ return;
+ }
+
const StringRef RelocBeginName = Obj->getArch() == Triple::x86
? "___RUNTIME_PSEUDO_RELOC_LIST__"
: "__RUNTIME_PSEUDO_RELOC_LIST__";
>From f48e21ae5edfac6e48cb56011f11c82e73e7dc98 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Tue, 5 Aug 2025 21:18:49 +0900
Subject: [PATCH 13/13] dump target symbol
---
.../COFF/Inputs/pseudoreloc.i386.yaml | 28 +++++++---
.../COFF/Inputs/pseudoreloc.x86_64.yaml | 28 +++++++---
.../tools/llvm-readobj/COFF/pseudoreloc.test | 29 ++++++----
llvm/tools/llvm-readobj/COFFDumper.cpp | 54 +++++++++++++++----
4 files changed, 105 insertions(+), 34 deletions(-)
diff --git a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
index 85370adedb19f..1c3f858aa50f7 100644
--- a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
@@ -20,7 +20,7 @@ OptionalHeader:
RelativeVirtualAddress: 0
Size: 0
ImportTable:
- RelativeVirtualAddress: 8276
+ RelativeVirtualAddress: 8288
Size: 60
ResourceTable:
RelativeVirtualAddress: 0
@@ -53,7 +53,7 @@ OptionalHeader:
RelativeVirtualAddress: 0
Size: 0
IAT:
- RelativeVirtualAddress: 8356
+ RelativeVirtualAddress: 8368
Size: 20
DelayImportDescriptor:
RelativeVirtualAddress: 0
@@ -69,19 +69,19 @@ sections:
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
VirtualAddress: 4096
VirtualSize: 60
- SectionData: A1003040000FBE008B0D043040000FBE0901C1A1083040000FBE10A10C3040000FBE0001D001C8C39090909090909090A1442040002B0508204000C3
+ SectionData: A1003040000FBE008B0D043040000FBE0901C1A1083040000FBE10A1103040000FBE0001D001C8C39090909090909090A1502040002B0508204000C3
SizeOfRawData: 512
- Name: .rdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
VirtualAddress: 8192
- VirtualSize: 242
- SectionData: 3377115566228844000000000000000001000000A42000000030000020000000A82000000430000020000000B02000000830000020000000A42000000C30000020000000FFFFFFFF00000000FFFFFFFF00000000902000000000000000000000D0200000A42000009C2000000000000000000000E1200000B02000000000000000000000000000000000000000000000B8200000C020000000000000C820000000000000B8200000C020000000000000C820000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
+ VirtualSize: 254
+ SectionData: 3377115566228844000000000000000001000000B02000000030000020000000B42000000430000020000000BC2000000830000020000000BC2000000C30000020000000B02000001030000020000000FFFFFFFF00000000FFFFFFFF000000009C2000000000000000000000DC200000B0200000A82000000000000000000000ED200000BC2000000000000000000000000000000000000000000000C4200000CC20000000000000D420000000000000C4200000CC20000000000000D420000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
SizeOfRawData: 512
- Name: .data
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
VirtualAddress: 12288
- VirtualSize: 16
- SectionData: A5204000AA204000B1204000A6204000
+ VirtualSize: 20
+ SectionData: B1204000B6204000BD204000BD204000B2204000
SizeOfRawData: 512
symbols:
- Name: _start
@@ -90,6 +90,18 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _local2a
+ Value: 4
+ SectionNumber: 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
@@ -97,7 +109,7 @@ symbols:
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: ___RUNTIME_PSEUDO_RELOC_LIST_END__
- Value: 68
+ Value: 80
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
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
index 46bc1c5ce17a8..b9f0c68b06f7a 100644
--- a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.x86_64.yaml
@@ -20,7 +20,7 @@ OptionalHeader:
RelativeVirtualAddress: 0
Size: 0
ImportTable:
- RelativeVirtualAddress: 8296
+ RelativeVirtualAddress: 8304
Size: 60
ResourceTable:
RelativeVirtualAddress: 0
@@ -53,7 +53,7 @@ OptionalHeader:
RelativeVirtualAddress: 0
Size: 0
IAT:
- RelativeVirtualAddress: 8400
+ RelativeVirtualAddress: 8408
Size: 40
DelayImportDescriptor:
RelativeVirtualAddress: 0
@@ -69,19 +69,19 @@ sections:
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
VirtualAddress: 4096
VirtualSize: 61
- SectionData: 488B05F91F00000FBE00488B0DF71F00000FBE0901C1488B05F31F00000FBE10488B05F11F00000FBE0001D001C8C3908B050E1000002B05CC0F0000C3
+ SectionData: 488B05F91F00000FBE00488B0DF71F00000FBE0901C1488B05F31F00000FBE10488B05F91F00000FBE0001D001C8C3908B051A1000002B05CC0F0000C3
SizeOfRawData: 512
- Name: .rdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
VirtualAddress: 8192
- VirtualSize: 310
- SectionData: 3377115566228844000000000000000001000000E02000000030000040000000E82000000830000040000000D02000001030000040000000E0200000183000004000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000A8200000000000000000000010210000D0200000B8200000000000000000000023210000E0200000000000000000000000000000000000000000000000000000F8200000000000000000000000000000002100000000000008210000000000000000000000000000F8200000000000000000000000000000002100000000000008210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
+ VirtualSize: 318
+ SectionData: 3377115566228844000000000000000001000000E82000000030000040000000F02000000830000040000000D82000001030000040000000D82000001830000040000000E82000002030000040000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000B0200000000000000000000018210000D8200000C020000000000000000000002B210000E82000000000000000000000000000000000000000000000000000000021000000000000000000000000000008210000000000001021000000000000000000000000000000210000000000000000000000000000082100000000000010210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
SizeOfRawData: 512
- Name: .data
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
VirtualAddress: 12288
- VirtualSize: 32
- SectionData: E120004001000000EA20004001000000D120004001000000E220004001000000
+ VirtualSize: 40
+ SectionData: E920004001000000F220004001000000D920004001000000D920004001000000EA20004001000000
SizeOfRawData: 512
symbols:
- Name: start
@@ -90,6 +90,18 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: local2a
+ Value: 8
+ SectionNumber: 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
@@ -97,7 +109,7 @@ symbols:
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: __RUNTIME_PSEUDO_RELOC_LIST_END__
- Value: 68
+ Value: 80
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index 1906cfafe408d..70c616fa148b0 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -1,17 +1,17 @@
REQUIRE: x86-registered-target
DEFINE: %{local} = 0x3000
-DEFINE: %{addr1l} = E0
-DEFINE: %{addr3l} = D0
+DEFINE: %{addr1l} = E8
+DEFINE: %{addr3l} = D8
RUN: yaml2obj %p/Inputs/pseudoreloc.x86_64.yaml | llvm-readobj --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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local}
+RUN: -D#WORD=8 -D#SYM1=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local} -DPREFIX=
-REDEFINE: %{addr1l} = A4
-REDEFINE: %{addr3l} = B0
+REDEFINE: %{addr1l} = B0
+REDEFINE: %{addr3l} = BC
RUN: yaml2obj %p/Inputs/pseudoreloc.i386.yaml | llvm-readobj --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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local}
+RUN: -D#WORD=4 -D#SYM1=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local} -DPREFIX=_
CHECK-X64: Format: COFF-x86-64
CHECK-X64-NEXT: Arch: x86_64
@@ -23,24 +23,35 @@ 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(3,WORD)]]
+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: ]
@@ -169,8 +180,8 @@ obj2yaml pseudoreloc.x86_64.exe -o pseudoreloc.x86_64.yaml
@sym3 = external dso_local global [4 x i8]
@dummy_to_bump_address = private constant i64 u0x4488226655117733
@local1a = private global ptr getelementptr (i8, ptr @sym1, i32 1)
- at local2a = private global ptr getelementptr (i8, ptr @sym2, i32 2)
- at local3a = private global ptr getelementptr (i8, ptr @sym3, 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)]
@local1b = private global ptr getelementptr (i8, ptr @sym1, i32 2)
define dso_local i32 @start() noinline nounwind {
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 98a88d5d65d2c..35488777e23fb 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2015,31 +2015,47 @@ void COFFDumper::printCOFFPseudoReloc() {
? "___RUNTIME_PSEUDO_RELOC_LIST_END__"
: "__RUNTIME_PSEUDO_RELOC_LIST_END__";
- COFFSymbolRef RelocBegin, RelocEnd;
auto Count = Obj->getNumberOfSymbols();
if (Count == 0) {
W.startLine() << "the symbol table has been stripped\n";
return;
}
- for (auto i = 0u;
- i < Count && (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()); ++i) {
+
+ struct SymbolEntry {
+ COFFSymbolRef Symbol;
+ const coff_section *Section;
+ StringRef SymbolName;
+ };
+ std::map<uint32_t, SymbolEntry> RVASymbolMap;
+ COFFSymbolRef RelocBegin, RelocEnd;
+ for (auto i = 0u; i < Count; ++i) {
auto Sym = Obj->getSymbol(i);
if (!Sym) {
consumeError(Sym.takeError());
continue;
}
+ i += Sym->getNumberOfAuxSymbols();
+
+ if (Sym->getSectionNumber() <= 0)
+ continue;
auto Name = Obj->getSymbolName(*Sym);
if (!Name) {
consumeError(Name.takeError());
continue;
}
- if (*Name == RelocBeginName) {
- if (Sym->getSectionNumber() > 0)
- RelocBegin = *Sym;
- } else if (*Name == RelocEndName) {
- if (Sym->getSectionNumber() > 0)
- RelocEnd = *Sym;
+
+ if (*Name == RelocBeginName)
+ RelocBegin = *Sym;
+ else if (*Name == RelocEndName)
+ RelocEnd = *Sym;
+
+ auto Sec = Obj->getSection(Sym->getSectionNumber());
+ if (!Sec) {
+ consumeError(Sec.takeError());
+ continue;
}
+ RVASymbolMap.emplace((*Sec)->VirtualAddress + Sym->getValue(),
+ SymbolEntry{*Sym, *Sec, *Name});
}
if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
W.startLine()
@@ -2168,10 +2184,30 @@ void COFFDumper::printCOFFPseudoReloc() {
ListScope D(W, "PseudoReloc");
for (const auto &Reloc : RelocRecords) {
DictScope Entry(W, "Entry");
+
W.printHex("Symbol", Reloc.Symbol);
if (const auto *Sym = ImportedSymbols.find(Reloc.Symbol))
W.printString("SymbolName", *Sym);
+
W.printHex("Target", Reloc.Target);
+ if (auto Ite = RVASymbolMap.upper_bound(Reloc.Target.value());
+ Ite == RVASymbolMap.begin())
+ W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
+ else if (const uint32_t Offset = Reloc.Target.value() - (--Ite)->first;
+ Offset == 0)
+ W.printString("TargetSymbol", Ite->second.SymbolName);
+ else if (Offset < Ite->second.Section->VirtualSize)
+ W.printSymbolOffset("TargetSymbol", Ite->second.SymbolName, Offset);
+ else if (++Ite == RVASymbolMap.end())
+ W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
+ else if (auto Name = Obj->getSectionName(Ite->second.Section)) {
+ W.printSymbolOffset("TargetSymbol", *Name,
+ Reloc.Target - Ite->second.Section->VirtualAddress);
+ } else {
+ consumeError(Name.takeError());
+ W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
+ }
+
W.printNumber("BitWidth", Reloc.BitSize);
}
}
More information about the llvm-commits
mailing list