[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
Sun Aug 10 20:10:49 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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);
   }
 }

>From 41c0e01bc85ac63c20bf27e5edcf02d7d39ca362 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 10 Aug 2025 07:29:03 +0900
Subject: [PATCH 14/21] reduce usage of auto

---
 llvm/tools/llvm-readobj/COFFDumper.cpp | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 35488777e23fb..a278844c0e960 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2015,7 +2015,7 @@ void COFFDumper::printCOFFPseudoReloc() {
                                      ? "___RUNTIME_PSEUDO_RELOC_LIST_END__"
                                      : "__RUNTIME_PSEUDO_RELOC_LIST_END__";
 
-  auto Count = Obj->getNumberOfSymbols();
+  uint32_t Count = Obj->getNumberOfSymbols();
   if (Count == 0) {
     W.startLine() << "the symbol table has been stripped\n";
     return;
@@ -2028,8 +2028,8 @@ void COFFDumper::printCOFFPseudoReloc() {
   };
   std::map<uint32_t, SymbolEntry> RVASymbolMap;
   COFFSymbolRef RelocBegin, RelocEnd;
-  for (auto i = 0u; i < Count; ++i) {
-    auto Sym = Obj->getSymbol(i);
+  for (uint32_t i = 0; i < Count; ++i) {
+    Expected<COFFSymbolRef> Sym = Obj->getSymbol(i);
     if (!Sym) {
       consumeError(Sym.takeError());
       continue;
@@ -2038,7 +2038,7 @@ void COFFDumper::printCOFFPseudoReloc() {
 
     if (Sym->getSectionNumber() <= 0)
       continue;
-    auto Name = Obj->getSymbolName(*Sym);
+    Expected<StringRef> Name = Obj->getSymbolName(*Sym);
     if (!Name) {
       consumeError(Name.takeError());
       continue;
@@ -2049,7 +2049,8 @@ void COFFDumper::printCOFFPseudoReloc() {
     else if (*Name == RelocEndName)
       RelocEnd = *Sym;
 
-    auto Sec = Obj->getSection(Sym->getSectionNumber());
+    Expected<const coff_section *> Sec =
+        Obj->getSection(Sym->getSectionNumber());
     if (!Sec) {
       consumeError(Sec.takeError());
       continue;
@@ -2070,7 +2071,8 @@ void COFFDumper::printCOFFPseudoReloc() {
     return;
   }
 
-  auto Section = Obj->getSection(RelocBegin.getSectionNumber());
+  Expected<const coff_section *> Section =
+      Obj->getSection(RelocBegin.getSectionNumber());
   if (auto E = Section.takeError()) {
     reportWarning(std::move(E), Obj->getFileName());
     return;
@@ -2152,13 +2154,12 @@ void COFFDumper::printCOFFPseudoReloc() {
         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()) {
+      for (auto S : Ite->EntryRef.imported_symbols()) {
         if (RVA == EntryRVA) {
           StringRef &NameDst = ImportedSymbols[RVA];
           if (auto E = S.getSymbolName(NameDst)) {
@@ -2186,7 +2187,7 @@ void COFFDumper::printCOFFPseudoReloc() {
     DictScope Entry(W, "Entry");
 
     W.printHex("Symbol", Reloc.Symbol);
-    if (const auto *Sym = ImportedSymbols.find(Reloc.Symbol))
+    if (const StringRef *Sym = ImportedSymbols.find(Reloc.Symbol))
       W.printString("SymbolName", *Sym);
 
     W.printHex("Target", Reloc.Target);
@@ -2200,11 +2201,12 @@ void COFFDumper::printCOFFPseudoReloc() {
       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,
+    else if (Expected<StringRef> NameOrErr =
+                 Obj->getSectionName(Ite->second.Section)) {
+      W.printSymbolOffset("TargetSymbol", *NameOrErr,
                           Reloc.Target - Ite->second.Section->VirtualAddress);
     } else {
-      consumeError(Name.takeError());
+      consumeError(NameOrErr.takeError());
       W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
     }
 

>From 93b46cdcf1f9bec373acf8cc74f9cd2b7d9e10fd Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 10 Aug 2025 08:46:12 +0900
Subject: [PATCH 15/21] use sorted vector

---
 llvm/tools/llvm-readobj/COFFDumper.cpp | 31 +++++++++++++++++---------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index a278844c0e960..49b53829d19b3 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2022,11 +2022,12 @@ void COFFDumper::printCOFFPseudoReloc() {
   }
 
   struct SymbolEntry {
+    uint32_t RVA;
     COFFSymbolRef Symbol;
     const coff_section *Section;
     StringRef SymbolName;
   };
-  std::map<uint32_t, SymbolEntry> RVASymbolMap;
+  SmallVector<SymbolEntry> RVASymbolMap;
   COFFSymbolRef RelocBegin, RelocEnd;
   for (uint32_t i = 0; i < Count; ++i) {
     Expected<COFFSymbolRef> Sym = Obj->getSymbol(i);
@@ -2055,8 +2056,8 @@ void COFFDumper::printCOFFPseudoReloc() {
       consumeError(Sec.takeError());
       continue;
     }
-    RVASymbolMap.emplace((*Sec)->VirtualAddress + Sym->getValue(),
-                         SymbolEntry{*Sym, *Sec, *Name});
+    RVASymbolMap.push_back(
+        {(*Sec)->VirtualAddress + Sym->getValue(), *Sym, *Sec, *Name});
   }
   if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
     W.startLine()
@@ -2181,6 +2182,14 @@ void COFFDumper::printCOFFPseudoReloc() {
     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());
 
   ListScope D(W, "PseudoReloc");
   for (const auto &Reloc : RelocRecords) {
@@ -2191,20 +2200,22 @@ void COFFDumper::printCOFFPseudoReloc() {
       W.printString("SymbolName", *Sym);
 
     W.printHex("Target", Reloc.Target);
-    if (auto Ite = RVASymbolMap.upper_bound(Reloc.Target.value());
+    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)->first;
+    else if (const uint32_t Offset = Reloc.Target.value() - (--Ite)->RVA;
              Offset == 0)
-      W.printString("TargetSymbol", Ite->second.SymbolName);
-    else if (Offset < Ite->second.Section->VirtualSize)
-      W.printSymbolOffset("TargetSymbol", Ite->second.SymbolName, Offset);
+      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->second.Section)) {
+                 Obj->getSectionName(Ite->Section)) {
       W.printSymbolOffset("TargetSymbol", *NameOrErr,
-                          Reloc.Target - Ite->second.Section->VirtualAddress);
+                          Reloc.Target - Ite->Section->VirtualAddress);
     } else {
       consumeError(NameOrErr.takeError());
       W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);

>From 09b643ed729da8c62d6e62c5abb524137b737df2 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 10 Aug 2025 08:00:44 +0900
Subject: [PATCH 16/21] reorganize warnings

---
 .../tools/llvm-readobj/COFF/pseudoreloc.test  |  26 ++--
 llvm/tools/llvm-readobj/COFFDumper.cpp        | 126 ++++++++++--------
 2 files changed, 83 insertions(+), 69 deletions(-)

diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index 70c616fa148b0..d767e41ebed5d 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -89,10 +89,10 @@ 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:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=NOHEADER
 
 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
+RUN:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
 
 NOHEADER: invalid runtime pseudo-relocation records
 
@@ -100,39 +100,35 @@ 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
+RUN:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=LOWEREND
 
-INVALREGION: the symbols for runtime pseudo-relocation don't consist a valid region
+LOWEREND: the begin marker symbol for runtime pseudo-relocation must point lower address than where the end marker points
 
 
 ; 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:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=OUTOFRANGE
 
 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
+RUN:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=OUTOFRANGE
 
-OUTOFRANGE: the region of runtime pseudo-relocation records points to out of the valid location
+OUTOFRANGE: the marker symbol of runtime pseudo-relocation points to out of the valid address space
 
 
 ; 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
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/imports.exe.coff-i386 2>&1 | FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
 
 
 ; check that warn if the relocation list is missing (intended for MSVC-made binaries)
 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
+RUN:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=NORELOC
 
-NORELOC: the symbols for runtime pseudo-relocation are not found
+NORELOC: the marker symbols for runtime pseudo-relocation were 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
+RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | FileCheck %s --check-prefix=EMPTY
 
 
 pseudoreloc.*.yaml is generated by following script:
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 49b53829d19b3..d517ca0642225 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2002,11 +2002,12 @@ void COFFDumper::printCOFFBaseReloc() {
 }
 
 void COFFDumper::printCOFFPseudoReloc() {
-  if (!Obj->getDOSHeader()) {
-    W.startLine()
-        << "pseudo-relocation is only meaningful for a PE image file\n";
+  ListScope D(W, "PseudoReloc");
+  W.flush();
+
+  // Pseudo-relocation is only meaningful for a PE image file.
+  if (!Obj->getDOSHeader())
     return;
-  }
 
   const StringRef RelocBeginName = Obj->getArch() == Triple::x86
                                        ? "___RUNTIME_PSEUDO_RELOC_LIST__"
@@ -2016,10 +2017,9 @@ void COFFDumper::printCOFFPseudoReloc() {
                                      : "__RUNTIME_PSEUDO_RELOC_LIST_END__";
 
   uint32_t Count = Obj->getNumberOfSymbols();
-  if (Count == 0) {
-    W.startLine() << "the symbol table has been stripped\n";
+  // Skip if no symbol was found (maybe stripped).
+  if (Count == 0)
     return;
-  }
 
   struct SymbolEntry {
     uint32_t RVA;
@@ -2030,68 +2030,88 @@ void COFFDumper::printCOFFPseudoReloc() {
   SmallVector<SymbolEntry> RVASymbolMap;
   COFFSymbolRef RelocBegin, RelocEnd;
   for (uint32_t i = 0; i < Count; ++i) {
-    Expected<COFFSymbolRef> Sym = Obj->getSymbol(i);
-    if (!Sym) {
-      consumeError(Sym.takeError());
+    COFFSymbolRef Sym;
+    if (Expected<COFFSymbolRef> SymOrErr = Obj->getSymbol(i))
+      Sym = *SymOrErr;
+    else {
+      reportWarning(SymOrErr.takeError(), Obj->getFileName());
       continue;
     }
-    i += Sym->getNumberOfAuxSymbols();
 
-    if (Sym->getSectionNumber() <= 0)
+    i += Sym.getNumberOfAuxSymbols();
+
+    if (Sym.getSectionNumber() <= 0)
       continue;
-    Expected<StringRef> Name = Obj->getSymbolName(*Sym);
-    if (!Name) {
-      consumeError(Name.takeError());
+
+    StringRef Name;
+    if (Expected<StringRef> NameOrErr = Obj->getSymbolName(Sym))
+      Name = *NameOrErr;
+    else {
+      reportWarning(NameOrErr.takeError(), Obj->getFileName());
       continue;
     }
 
-    if (*Name == RelocBeginName)
-      RelocBegin = *Sym;
-    else if (*Name == RelocEndName)
-      RelocEnd = *Sym;
-
-    Expected<const coff_section *> Sec =
-        Obj->getSection(Sym->getSectionNumber());
-    if (!Sec) {
-      consumeError(Sec.takeError());
+    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 {
+      reportWarning(SecOrErr.takeError(), Obj->getFileName());
       continue;
     }
+
     RVASymbolMap.push_back(
-        {(*Sec)->VirtualAddress + Sym->getValue(), *Sym, *Sec, *Name});
+        {Sec->VirtualAddress + Sym.getValue(), Sym, Sec, Name});
   }
+
   if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
-    W.startLine()
-        << "the symbols for runtime pseudo-relocation are not found\n";
+    reportWarning(
+        createStringError(
+            "the marker symbols for runtime pseudo-relocation were not found"),
+        Obj->getFileName());
     return;
   }
 
-  if (RelocEnd.getValue() < RelocBegin.getValue()) {
-    reportWarning(createStringError("the symbols for runtime pseudo-relocation "
-                                    "don't consist a valid region"),
-                  Obj->getFileName());
-    return;
-  }
+  const coff_section *Section = nullptr;
+  if (Expected<const coff_section *> SecOrErr =
+          Obj->getSection(RelocBegin.getSectionNumber()))
+    Section = *SecOrErr;
+  else
+    return reportWarning(SecOrErr.takeError(), Obj->getFileName());
 
-  Expected<const coff_section *> Section =
-      Obj->getSection(RelocBegin.getSectionNumber());
-  if (auto E = Section.takeError()) {
-    reportWarning(std::move(E), Obj->getFileName());
+  if (RelocBegin.getSectionNumber() != RelocEnd.getSectionNumber())
+    return reportWarning(
+        createStringError(
+            "the marker symbols for runtime pseudo-relocation must "
+            "point a same section"),
+        Obj->getFileName());
+
+  // Skip if the relocation list is empty.
+  if (RelocBegin.getValue() == RelocEnd.getValue())
     return;
-  }
+
+  if (RelocEnd.getValue() < RelocBegin.getValue())
+    return reportWarning(
+        createStringError(
+            "the begin marker symbol for runtime pseudo-relocation must point "
+            "lower address than where the end marker points"),
+        Obj->getFileName());
 
   ArrayRef<uint8_t> Data;
-  if (auto E = Obj->getSectionContents(*Section, Data)) {
-    reportWarning(std::move(E), Obj->getFileName());
-    return;
-  }
+  if (auto E = Obj->getSectionContents(Section, Data))
+    return reportWarning(std::move(E), Obj->getFileName());
+
   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"),
+      Data.size() <= RelocEnd.getValue())
+    return reportWarning(
+        createStringError("the marker symbol of runtime pseudo-relocation "
+                          "points to out of the valid address space"),
         Obj->getFileName());
-    return;
-  }
 
   ArrayRef<uint8_t> RawRelocs =
       Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());
@@ -2104,12 +2124,11 @@ void COFFDumper::printCOFFPseudoReloc() {
   };
   const PseudoRelocationHeader HeaderV2(1);
   if (RawRelocs.size() < sizeof(HeaderV2) ||
-      (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {
-    reportWarning(
+      (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0))
+    return reportWarning(
         createStringError("invalid runtime pseudo-relocation records"),
         Obj->getFileName());
-    return;
-  }
+
   struct alignas(4) PseudoRelocationRecord {
     support::ulittle32_t Symbol;
     support::ulittle32_t Target;
@@ -2191,7 +2210,6 @@ void COFFDumper::printCOFFPseudoReloc() {
                                   }),
                      RVASymbolMap.end());
 
-  ListScope D(W, "PseudoReloc");
   for (const auto &Reloc : RelocRecords) {
     DictScope Entry(W, "Entry");
 
@@ -2217,7 +2235,7 @@ void COFFDumper::printCOFFPseudoReloc() {
       W.printSymbolOffset("TargetSymbol", *NameOrErr,
                           Reloc.Target - Ite->Section->VirtualAddress);
     } else {
-      consumeError(NameOrErr.takeError());
+      reportWarning(NameOrErr.takeError(), Obj->getFileName());
       W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);
     }
 

>From f57fd35eb3eba42a7fa7300e627d554634e0f8ac Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 10 Aug 2025 08:51:42 +0900
Subject: [PATCH 17/21] reorganize test 1/2

- fix position of line breaks
- name intermediate output binary
- remove a sprious and doubled empty lines
---
 .../tools/llvm-readobj/COFF/pseudoreloc.test  | 145 +++++++++---------
 1 file changed, 73 insertions(+), 72 deletions(-)

diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index d767e41ebed5d..cfdd144c544e6 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} = 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} -DPREFIX=
+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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local} -DPREFIX=
 
 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} -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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local} -DPREFIX=_
 
 CHECK-X64:      Format: COFF-x86-64
 CHECK-X64-NEXT: Arch: x86_64
@@ -56,86 +56,90 @@ CHECK-NEXT:   BitWidth: [[#BW]]
 CHECK-NEXT:  }
 CHECK-NEXT: ]
 
-
-; 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
+; Test that llvm-readobj silently ignores missing imported symbol names.
+RUN: sed -E -e '/Name: *\.rdata/,/Name:/{/SectionData:/{s/%{addr1l}200000/30000000/;s/%{addr3l}200000/00FFFF00/}}' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN:   yaml2obj -o %t.corrupted-iat.exe-i386
+RUN: llvm-readobj  %t.corrupted-iat.exe-i386 --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]]
 
+; Assume the position of the relocation list for further tests.
+RUN: yaml2obj %p/Inputs/pseudoreloc.i386.yaml | llvm-readobj --syms - | \
+RUN:   FileCheck %s --check-prefix=RELOCPOS --match-full-lines
 
-; 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_END__
+RELOCPOS-NEXT: Value: 80
 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
-
-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=EMPTY --implicit-check-not=warning
-
-NOHEADER: invalid runtime pseudo-relocation records
-
-
-; check that warn if end < start
+; Test that llvm-readobj shows an empty list if 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 -o %t.empty-list.exe-i386
+RUN: llvm-readobj  %t.empty-list.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
+
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/8/}' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN:   yaml2obj -o %t.noheader.exe-i386
+RUN: llvm-readobj  %t.noheader.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefix=EMPTY --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 --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
+
+; 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 --implicit-check-not=warning
+
+; Test that llvm-readobj warns if the header of the relocation list is broken.
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/20/}' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN:   yaml2obj -o %t.corrupted-header.exe-i386
+RUN: llvm-readobj  %t.corrupted-header.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-INVALIDHEADER
+
+; Test that llvm-readobj warns 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=LOWEREND
-
-LOWEREND: the begin marker symbol for runtime pseudo-relocation must point lower address than where the end marker points
-
+RUN:        -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/20/}' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN:   yaml2obj -o %t.negative-size.exe-i386
+RUN: llvm-readobj  %t.negative-size.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-LOWEREND
 
-; check that warn if the relocation list points out of section space
+; Test that llvm-readobj warns if the marker symbol points out of the 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
+RUN:        -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/8888/}' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN:   yaml2obj -o %t.outofrange-both.exe-i386
+RUN: llvm-readobj  %t.outofrange-both.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE
 
-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
-
-OUTOFRANGE: the marker symbol of runtime pseudo-relocation points to out of the valid address space
-
-
-; check that warn if image is stripped
-RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/imports.exe.coff-i386 2>&1 | FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
-
-
-; check that warn if the relocation list is missing (intended for MSVC-made binaries)
-RUN: sed -e 's/__RUNTIME//' %p/Inputs/pseudoreloc.i386.yaml \
-RUN:   | yaml2obj | llvm-readobj --coff-pseudoreloc - 2>&1 | FileCheck %s --check-prefix=NORELOC
-
-NORELOC: the marker symbols for runtime pseudo-relocation were 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=EMPTY
+RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/9999/}' %p/Inputs/pseudoreloc.i386.yaml | \
+RUN:   yaml2obj -o %t.outofrange-end.exe-i386
+RUN: llvm-readobj  %t.outofrange-end.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE
 
+EMPTY:      Format: COFF-i386
+EMPTY-NEXT: Arch: i386
+EMPTY-NEXT: AddressSize: 32bit
+EMPTY-NEXT: PseudoReloc [
+WARN-MISSINGMARKER-NEXT: the marker symbols for runtime pseudo-relocation were not found
+WARN-INVALIDHEADER-NEXT: invalid runtime pseudo-relocation records
+WARN-LOWEREND-NEXT: the begin marker symbol for runtime pseudo-relocation must point lower address than where the end marker points
+WARN-OUTOFRANGE-NEXT: the marker symbol of runtime pseudo-relocation points to out of the valid address space
+EMPTY-NEXT: ]
 
-pseudoreloc.*.yaml is generated by following script:
+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
@@ -158,16 +162,13 @@ ld.lld -m i386pep -S import.x86_64.o export1.x86_64.dll export2.x86_64.dll -o ps
   --disable-dynamicbase --disable-reloc-section
 obj2yaml pseudoreloc.x86_64.exe -o pseudoreloc.x86_64.yaml
 
-
 #--- export1.ll
 @sym1 = dso_local dllexport global [4 x i8] c"\11\22\33\44"
 @sym2 = dso_local dllexport global [4 x i8] c"\55\66\77\88"
 
-
 #--- export2.ll
 @sym3 = dso_local dllexport global [4 x i8] c"\AA\BB\CC\DD"
 
-
 #--- import.ll
 @__RUNTIME_PSEUDO_RELOC_LIST__ = external dso_local constant ptr
 @__RUNTIME_PSEUDO_RELOC_LIST_END__ = external dso_local constant ptr

>From 45bcfeb6b2e33519b92547d8b7f331c9d02169d5 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 10 Aug 2025 08:58:11 +0900
Subject: [PATCH 18/21] reorganize test 2/2

- make parameter more symbolic a bit
- use parametrized yaml
  * sed while generating source rather than testing
---
 .../COFF/Inputs/pseudoreloc.i386.yaml         |   6 +-
 .../COFF/Inputs/pseudoreloc.x86_64.yaml       |   6 +-
 .../tools/llvm-readobj/COFF/pseudoreloc.test  | 137 ++++++++++--------
 3 files changed, 85 insertions(+), 64 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 1c3f858aa50f7..5537f2c84a84a 100644
--- a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
@@ -75,7 +75,7 @@ sections:
     Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
     VirtualAddress:  8192
     VirtualSize:     254
-    SectionData:     3377115566228844000000000000000001000000B02000000030000020000000B42000000430000020000000BC2000000830000020000000BC2000000C30000020000000B02000001030000020000000FFFFFFFF00000000FFFFFFFF000000009C2000000000000000000000DC200000B0200000A82000000000000000000000ED200000BC2000000000000000000000000000000000000000000000C4200000CC20000000000000D420000000000000C4200000CC20000000000000D420000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
+    SectionData:     3377115566228844000000000000000001000000[[SYMBOL0=B0200000]]0030000020000000[[SYMBOL1=B4200000]]0430000020000000BC2000000830000020000000BC2000000C30000020000000B02000001030000020000000FFFFFFFF00000000FFFFFFFF000000009C2000000000000000000000DC200000B0200000A82000000000000000000000ED200000BC2000000000000000000000000000000000000000000000C4200000CC20000000000000D420000000000000C4200000CC20000000000000D420000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
     SizeOfRawData:   512
   - Name:            .data
     Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
@@ -109,13 +109,13 @@ symbols:
     ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
   - Name:            ___RUNTIME_PSEUDO_RELOC_LIST_END__
-    Value:           80
+    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:           8
+    Value:           [[BEGIN=8]]
     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 b9f0c68b06f7a..eddf62620bd27 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
@@ -75,7 +75,7 @@ sections:
     Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
     VirtualAddress:  8192
     VirtualSize:     318
-    SectionData:     3377115566228844000000000000000001000000E82000000030000040000000F02000000830000040000000D82000001030000040000000D82000001830000040000000E82000002030000040000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000B0200000000000000000000018210000D8200000C020000000000000000000002B210000E82000000000000000000000000000000000000000000000000000000021000000000000000000000000000008210000000000001021000000000000000000000000000000210000000000000000000000000000082100000000000010210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
+    SectionData:     3377115566228844000000000000000001000000[[SYMBOL0=E8200000]]0030000040000000[[SYMBOL1=F0200000]]0830000040000000D82000001030000040000000D82000001830000040000000E82000002030000040000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000B0200000000000000000000018210000D8200000C020000000000000000000002B210000E82000000000000000000000000000000000000000000000000000000021000000000000000000000000000008210000000000001021000000000000000000000000000000210000000000000000000000000000082100000000000010210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
     SizeOfRawData:   512
   - Name:            .data
     Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
@@ -109,13 +109,13 @@ symbols:
     ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
   - Name:            __RUNTIME_PSEUDO_RELOC_LIST_END__
-    Value:           80
+    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:           8
+    Value:           [[BEGIN=8]]
     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 cfdd144c544e6..d26e36d69ab2e 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -1,17 +1,19 @@
-DEFINE: %{local} = 0x3000
-DEFINE: %{addr1l} = E8
-DEFINE: %{addr3l} = D8
+DEFINE: %{local1a_386} = 0x3000
+DEFINE: %{sym1_386} = 0x20B0
+DEFINE: %{sym3_386} = 0x20BC
+DEFINE: %{local1a_x64} = 0x3000
+DEFINE: %{sym1_x64} = 0x20E8
+DEFINE: %{sym3_x64} = 0x20D8
+
 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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local} -DPREFIX=
+RUN:     -D#WORD=8 -D#SYM1=%{sym1_x64} -D#SYM3=%{sym3_x64} -D#LOCAL1A=%{local1a_x64} -DPREFIX=
 
-REDEFINE: %{addr1l} = B0
-REDEFINE: %{addr3l} = BC
 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=0x20%{addr1l} -D#SYM3=0x20%{addr3l} -D#LOCAL1A=%{local} -DPREFIX=_
+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
@@ -57,34 +59,37 @@ CHECK-NEXT:  }
 CHECK-NEXT: ]
 
 ; Test that llvm-readobj silently ignores missing imported symbol names.
-RUN: sed -E -e '/Name: *\.rdata/,/Name:/{/SectionData:/{s/%{addr1l}200000/30000000/;s/%{addr3l}200000/00FFFF00/}}' %p/Inputs/pseudoreloc.i386.yaml | \
-RUN:   yaml2obj -o %t.corrupted-iat.exe-i386
-RUN: llvm-readobj  %t.corrupted-iat.exe-i386 --coff-pseudoreloc 2>&1 | \
-RUN:   FileCheck %s --check-prefix=INVALIDSYMBOL --match-full-lines -D#LOCAL1A=%{local} --implicit-check-not=warning
+RUN: yaml2obj  -o %t.corrupted-iat.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSYMBOL0=30000000 -DSYMBOL1=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: 0x30
 INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A]]
 INVALIDSYMBOL:      Symbol: 0xFFFF00
-INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+8]]
-
-; Assume the position of the relocation list for further tests.
-RUN: yaml2obj %p/Inputs/pseudoreloc.i386.yaml | llvm-readobj --syms - | \
-RUN:   FileCheck %s --check-prefix=RELOCPOS --match-full-lines
-
-RELOCPOS: Name: ___RUNTIME_PSEUDO_RELOC_LIST_END__
-RELOCPOS-NEXT: Value: 80
-RELOCPOS: Name: ___RUNTIME_PSEUDO_RELOC_LIST__
-RELOCPOS-NEXT: Value: 8
+INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+4]]
+
+; 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
+
+RELOCPOS:       - Name:            .rdata
+RELOCPOS-NEXT:    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+RELOCPOS-NEXT:    VirtualAddress:  8192
+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=80\]\]}}
+RELOCPOS:       - Name: ___RUNTIME_PSEUDO_RELOC_LIST__
+RELOCPOS-NEXT:    Value: {{\[\[BEGIN=8\]\]}}
 
 ; Test that llvm-readobj shows an empty list if 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 -o %t.empty-list.exe-i386
-RUN: llvm-readobj  %t.empty-list.exe-i386 --coff-pseudoreloc 2>&1 | \
+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 --implicit-check-not=warning
 
-RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/8/}' %p/Inputs/pseudoreloc.i386.yaml | \
-RUN:   yaml2obj -o %t.noheader.exe-i386
-RUN: llvm-readobj  %t.noheader.exe-i386 --coff-pseudoreloc 2>&1 | \
+; 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=8
+RUN: llvm-readobj %t.no-header.exe-i386 --coff-pseudoreloc 2>&1 | \
 RUN:   FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
 
 ; Test that llvm-readobj shows an empty list if the image is stripped.
@@ -102,28 +107,22 @@ RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | \
 RUN:   FileCheck %s --check-prefix=EMPTY --implicit-check-not=warning
 
 ; Test that llvm-readobj warns if the header of the relocation list is broken.
-RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Name:/{/Value:/s/[0-9]+/20/}' %p/Inputs/pseudoreloc.i386.yaml | \
-RUN:   yaml2obj -o %t.corrupted-header.exe-i386
-RUN: llvm-readobj  %t.corrupted-header.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: yaml2obj  -o %t.broken-header.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=20 -DEND=48
+RUN: llvm-readobj %t.broken-header.exe-i386 --coff-pseudoreloc 2>&1 | \
 RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-INVALIDHEADER
 
 ; Test that llvm-readobj warns 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 -o %t.negative-size.exe-i386
-RUN: llvm-readobj  %t.negative-size.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: yaml2obj  -o %t.negative-size.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=20 -DEND=8
+RUN: llvm-readobj %t.negative-size.exe-i386 --coff-pseudoreloc 2>&1 | \
 RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-LOWEREND
 
 ; Test that llvm-readobj warns if the marker symbol points out of the 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 -o %t.outofrange-both.exe-i386
-RUN: llvm-readobj  %t.outofrange-both.exe-i386 --coff-pseudoreloc 2>&1 | \
+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
 
-RUN: sed -E -e '/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Name:/{/Value:/s/[0-9]+/9999/}' %p/Inputs/pseudoreloc.i386.yaml | \
-RUN:   yaml2obj -o %t.outofrange-end.exe-i386
-RUN: llvm-readobj  %t.outofrange-end.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN: yaml2obj  -o %t.outofrange-end.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=9999
+RUN: llvm-readobj %t.outofrange-end.exe-i386 --coff-pseudoreloc 2>&1 | \
 RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE
 
 EMPTY:      Format: COFF-i386
@@ -144,23 +143,45 @@ $ split-file pseudoreloc.test /tmp/pseudoreloc && bash /tmp/pseudoreloc/generate
 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
+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
+  #  - the referenced symbol in 1st and 2nd relocation entry parametarizable
+  #  - the marker symbols' value parameterizable
+  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})/\\1[[SYMBOL0=\\2]]\\3[[SYMBOL1=\\4]]/
+}
+/__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Value:/{
+  /Value:/s/([0-9]+)/[[END=\1]]/
+}
+/__RUNTIME_PSEUDO_RELOC_LIST__/,/Value:/{
+  /Value:/s/([0-9]+)/[[BEGIN=\1]]/
+}
+EOT
+
+  # Ensure the binaries generated from parameterized yaml and original one are exact same.
+  diff <(yaml2obj pseudoreloc.$arch.yaml.orig -o -) <(yaml2obj pseudoreloc.$arch.yaml -o -)
+}
+
+generate i386 i386pe
+generate x86_64 i386pep
 
 #--- export1.ll
 @sym1 = dso_local dllexport global [4 x i8] c"\11\22\33\44"

>From 56d51f63d6c9b3c23c144c5217daa194c9f72871 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Sun, 10 Aug 2025 20:43:37 +0900
Subject: [PATCH 19/21] add missing tests

---
 .../COFF/Inputs/pseudoreloc.i386.yaml         |  4 +--
 .../COFF/Inputs/pseudoreloc.x86_64.yaml       |  4 +--
 .../tools/llvm-readobj/COFF/pseudoreloc.test  | 32 +++++++++++++++++--
 3 files changed, 33 insertions(+), 7 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 5537f2c84a84a..a7befd3b6f464 100644
--- a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
@@ -92,7 +92,7 @@ symbols:
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
   - Name:            _local2a
     Value:           4
-    SectionNumber:   3
+    SectionNumber:   [[SECTION_OF_LOCAL2A=3]]
     SimpleType:      IMAGE_SYM_TYPE_NULL
     ComplexType:     IMAGE_SYM_DTYPE_NULL
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
@@ -116,7 +116,7 @@ symbols:
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
   - Name:            ___RUNTIME_PSEUDO_RELOC_LIST__
     Value:           [[BEGIN=8]]
-    SectionNumber:   2
+    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
index eddf62620bd27..54fe9e51052a8 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
@@ -92,7 +92,7 @@ symbols:
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
   - Name:            local2a
     Value:           8
-    SectionNumber:   3
+    SectionNumber:   [[SECTION_OF_LOCAL2A=3]]
     SimpleType:      IMAGE_SYM_TYPE_NULL
     ComplexType:     IMAGE_SYM_DTYPE_NULL
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
@@ -116,7 +116,7 @@ symbols:
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
   - Name:            __RUNTIME_PSEUDO_RELOC_LIST__
     Value:           [[BEGIN=8]]
-    SectionNumber:   2
+    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
index d26e36d69ab2e..66da9d33dad32 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -71,6 +71,10 @@ INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+4]]
 ; 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
 
+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
@@ -81,6 +85,14 @@ RELOCPOS:       - Name: ___RUNTIME_PSEUDO_RELOC_LIST_END__
 RELOCPOS-NEXT:    Value: {{\[\[END=80\]\]}}
 RELOCPOS:       - Name: ___RUNTIME_PSEUDO_RELOC_LIST__
 RELOCPOS-NEXT:    Value: {{\[\[BEGIN=8\]\]}}
+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
+
+WARN-NOSECTION: 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
@@ -125,6 +137,11 @@ RUN: yaml2obj  -o %t.outofrange-end.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DE
 RUN: llvm-readobj %t.outofrange-end.exe-i386 --coff-pseudoreloc 2>&1 | \
 RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE
 
+; Test that llvm-readobj warns if the marker symbols point different sections.
+RUN: yaml2obj  -o %t.section-differs.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSECTION_OF_BEGIN=1
+RUN: llvm-readobj %t.section-differs.exe-i386 --coff-pseudoreloc 2>&1 | \
+RUN:   FileCheck %s --check-prefixes=EMPTY,WARN-SECTIONDIFFERS
+
 EMPTY:      Format: COFF-i386
 EMPTY-NEXT: Arch: i386
 EMPTY-NEXT: AddressSize: 32bit
@@ -133,6 +150,7 @@ WARN-MISSINGMARKER-NEXT: the marker symbols for runtime pseudo-relocation were n
 WARN-INVALIDHEADER-NEXT: invalid runtime pseudo-relocation records
 WARN-LOWEREND-NEXT: the begin marker symbol for runtime pseudo-relocation must point lower address than where the end marker points
 WARN-OUTOFRANGE-NEXT: the marker symbol of runtime pseudo-relocation points to out of the valid address space
+WARN-SECTIONDIFFERS-NEXT: the marker symbols for runtime pseudo-relocation must point a same section
 EMPTY-NEXT: ]
 
 To regenerate Inputs/pseudoreloc.*.yaml, run following one-liner and review actual address map:
@@ -161,9 +179,11 @@ generate() {
   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
-  #  - the referenced symbol in 1st and 2nd relocation entry parametarizable
-  #  - the marker symbols' value parameterizable
+  # Make these parameterizable:
+  #  - the referenced symbol in 1st and 2nd 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})/\\1[[SYMBOL0=\\2]]\\3[[SYMBOL1=\\4]]/
@@ -174,6 +194,12 @@ generate() {
 /__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 parameterized yaml and original one are exact same.

>From 46cb5bc523eb5af38b712679b9c358a2e08f8fe0 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Mon, 11 Aug 2025 11:37:02 +0900
Subject: [PATCH 20/21] warn about missing imported symbol

---
 .../COFF/Inputs/pseudoreloc.i386.yaml         |  2 +-
 .../COFF/Inputs/pseudoreloc.x86_64.yaml       |  2 +-
 .../tools/llvm-readobj/COFF/pseudoreloc.test  | 19 +++++++++++-----
 llvm/tools/llvm-readobj/COFFDumper.cpp        | 22 ++++++++++++-------
 4 files changed, 30 insertions(+), 15 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 a7befd3b6f464..9eb56dd7f9794 100644
--- a/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/Inputs/pseudoreloc.i386.yaml
@@ -75,7 +75,7 @@ sections:
     Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
     VirtualAddress:  8192
     VirtualSize:     254
-    SectionData:     3377115566228844000000000000000001000000[[SYMBOL0=B0200000]]0030000020000000[[SYMBOL1=B4200000]]0430000020000000BC2000000830000020000000BC2000000C30000020000000B02000001030000020000000FFFFFFFF00000000FFFFFFFF000000009C2000000000000000000000DC200000B0200000A82000000000000000000000ED200000BC2000000000000000000000000000000000000000000000C4200000CC20000000000000D420000000000000C4200000CC20000000000000D420000000000000000073796D310000000073796D320000000073796D3300006578706F7274312E693338362E646C6C006578706F7274322E693338362E646C6C00
+    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 ]
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 54fe9e51052a8..e31f61c17fd3d 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
@@ -75,7 +75,7 @@ sections:
     Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
     VirtualAddress:  8192
     VirtualSize:     318
-    SectionData:     3377115566228844000000000000000001000000[[SYMBOL0=E8200000]]0030000040000000[[SYMBOL1=F0200000]]0830000040000000D82000001030000040000000D82000001830000040000000E82000002030000040000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000B0200000000000000000000018210000D8200000C020000000000000000000002B210000E82000000000000000000000000000000000000000000000000000000021000000000000000000000000000008210000000000001021000000000000000000000000000000210000000000000000000000000000082100000000000010210000000000000000000000000000000073796D330000000073796D310000000073796D3200006578706F7274322E7838365F36342E646C6C006578706F7274312E7838365F36342E646C6C00
+    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 ]
diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
index 66da9d33dad32..54715a31f31da 100644
--- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
+++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test
@@ -58,15 +58,24 @@ CHECK-NEXT:   BitWidth: [[#BW]]
 CHECK-NEXT:  }
 CHECK-NEXT: ]
 
-; Test that llvm-readobj silently ignores missing imported symbol names.
-RUN: yaml2obj  -o %t.corrupted-iat.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSYMBOL0=30000000 -DSYMBOL1=00FFFF00
+; 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: 0x30
+INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the reference of the symbol points out of the import table
+INVALIDSYMBOL-NEXT: SymbolName: (missing)
 INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A]]
-INVALIDSYMBOL:      Symbol: 0xFFFF00
+INVALIDSYMBOL:      Symbol: 0x20B2
+INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the reference of the symbol doesn't point imported symbol properly
+INVALIDSYMBOL-NEXT: SymbolName: (missing)
 INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+4]]
+INVALIDSYMBOL:      Symbol: 0xFFFF00
+INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the reference of the symbol points out of the import table
+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
@@ -180,13 +189,13 @@ generate() {
   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 and 2nd relocation entry
+  #  - 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})/\\1[[SYMBOL0=\\2]]\\3[[SYMBOL1=\\4]]/
+  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]]/
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index d517ca0642225..102cc64aa0730 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2162,21 +2162,21 @@ void COFFDumper::printCOFFPseudoReloc() {
       });
     }
 
-    const StringRef *find(uint32_t EntryRVA) {
+    Expected<StringRef> find(uint32_t EntryRVA) {
       if (auto Ite = ImportedSymbols.find(EntryRVA);
           Ite != ImportedSymbols.end())
-        return &Ite->second;
+        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 nullptr;
+        return createStringError("the reference of the symbol points out of the import table");
 
       --Ite;
       uint32_t RVA = Ite->StartRVA;
       if (Ite->EndRVA != 0 && Ite->EndRVA <= RVA)
-        return nullptr;
+        return createStringError("the reference of the symbol points out of the import table");
       // Search with linear iteration to care if padding or garbage exist
       // between ImportDirectoryEntry
       for (auto S : Ite->EntryRef.imported_symbols()) {
@@ -2186,13 +2186,15 @@ void COFFDumper::printCOFFPseudoReloc() {
             reportWarning(std::move(E), Obj->getFileName());
             NameDst = "(no symbol)";
           }
-          return &NameDst;
+          return NameDst;
         }
         RVA += Obj->is64() ? 8 : 4;
+        if (EntryRVA < RVA)
+          return createStringError("the reference of the symbol doesn't point imported symbol properly");
       }
       Ite->EndRVA = RVA;
 
-      return nullptr;
+      return createStringError("the reference of the symbol points out of the import table");
     }
 
   private:
@@ -2214,8 +2216,12 @@ void COFFDumper::printCOFFPseudoReloc() {
     DictScope Entry(W, "Entry");
 
     W.printHex("Symbol", Reloc.Symbol);
-    if (const StringRef *Sym = ImportedSymbols.find(Reloc.Symbol))
-      W.printString("SymbolName", *Sym);
+    if (Expected<StringRef> SymOrErr = ImportedSymbols.find(Reloc.Symbol))
+      W.printString("SymbolName", *SymOrErr);
+    else {
+      reportWarning(SymOrErr.takeError(), Obj->getFileName());
+      W.printString("SymbolName", "(missing)");
+    }
 
     W.printHex("Target", Reloc.Target);
     if (auto Ite = llvm::upper_bound(

>From 6e6e760cc0caaf28fdb68b7fc4527cc93735c6c3 Mon Sep 17 00:00:00 2001
From: kikairoya <kikairoya at gmail.com>
Date: Mon, 11 Aug 2025 12:10:08 +0900
Subject: [PATCH 21/21] format

---
 llvm/tools/llvm-readobj/COFFDumper.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 102cc64aa0730..1f44e810d57dd 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -2171,12 +2171,14 @@ void COFFDumper::printCOFFPseudoReloc() {
           ImportDirectories, EntryRVA,
           [](uint32_t RVA, const auto &D) { return RVA < D.StartRVA; });
       if (Ite == ImportDirectories.begin())
-        return createStringError("the reference of the symbol points out of the import table");
+        return createStringError(
+            "the reference of the symbol points out of the import table");
 
       --Ite;
       uint32_t RVA = Ite->StartRVA;
       if (Ite->EndRVA != 0 && Ite->EndRVA <= RVA)
-        return createStringError("the reference of the symbol points out of the import table");
+        return createStringError(
+            "the reference of the symbol points out of the import table");
       // Search with linear iteration to care if padding or garbage exist
       // between ImportDirectoryEntry
       for (auto S : Ite->EntryRef.imported_symbols()) {
@@ -2190,11 +2192,13 @@ void COFFDumper::printCOFFPseudoReloc() {
         }
         RVA += Obj->is64() ? 8 : 4;
         if (EntryRVA < RVA)
-          return createStringError("the reference of the symbol doesn't point imported symbol properly");
+          return createStringError("the reference of the symbol doesn't point "
+                                   "imported symbol properly");
       }
       Ite->EndRVA = RVA;
 
-      return createStringError("the reference of the symbol points out of the import table");
+      return createStringError(
+          "the reference of the symbol points out of the import table");
     }
 
   private:



More information about the llvm-commits mailing list