From 8fa4896bfc5ef7acf2dd41db824709ae60a932e5 Mon Sep 17 00:00:00 2001 From: kikairoya Date: Thu, 31 Jul 2025 21:58:09 +0900 Subject: [PATCH 01/22] 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@a2^cWjb0oU45_Fr>m{5Hxz>~cpf@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?WYoqw6EI9@q~m)2iFa}@0}cf$uWNwNT;p_gV!!H z=Ts$5`Vtq?sIDQx9Y{HFy$6pUN!$`6ujfj&`8!b%!X+C! k+pW#5s;oDwJ626Ls&?(Ev^SeADSz*-Zd(Y+@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; def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group; def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group; +def coff_pseudoreloc + : FF<"coff-pseudoreloc", "Display runtime pseudo-relocations">, + Group; def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group; def coff_directives : FF<"coff-directives", "Display .drectve section">, Group; def coff_exports : FF<"coff-exports", "Display export table">, Group; 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 Date: Wed, 30 Jul 2025 21:34:59 +0900 Subject: [PATCH 02/22] 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 Date: Thu, 31 Jul 2025 21:58:45 +0900 Subject: [PATCH 03/22] 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 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 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 RelocRecords( + reinterpret_cast( + 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 Date: Thu, 31 Jul 2025 23:22:55 +0900 Subject: [PATCH 04/22] 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 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 Date: Mon, 4 Aug 2025 18:35:07 +0900 Subject: [PATCH 05/22] 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 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 RelocRecords( reinterpret_cast( From 9ff81f6abbced8b2013faac38d283a718e9476d0 Mon Sep 17 00:00:00 2001 From: kikairoya Date: Mon, 4 Aug 2025 19:23:28 +0900 Subject: [PATCH 06/22] 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 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 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 Date: Wed, 6 Aug 2025 18:39:11 +0900 Subject: [PATCH 07/22] 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, Group; def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group; def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group; -def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group; -def coff_pseudoreloc - : FF<"coff-pseudoreloc", "Display runtime pseudo-relocations">, - Group; +def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, + Group; def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group; def coff_directives : FF<"coff-directives", "Display .drectve section">, Group; def coff_exports : FF<"coff-exports", "Display export table">, Group; def coff_imports : FF<"coff-imports", "Display import table">, Group; def coff_load_config : FF<"coff-load-config", "Display load config">, Group; +def coff_pseudoreloc + : FF<"coff-pseudoreloc", + "Display runtime pseudo-relocations (Cygwin/MinGW specific)">, + Group; def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group; def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group; From 6980cb12fa8981f01a9675a2acd601e967c08317 Mon Sep 17 00:00:00 2001 From: kikairoya Date: Wed, 6 Aug 2025 19:42:36 +0900 Subject: [PATCH 08/22] 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 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 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 Date: Wed, 6 Aug 2025 20:30:21 +0900 Subject: [PATCH 09/22] 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 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 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 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 Date: Wed, 6 Aug 2025 19:48:26 +0900 Subject: [PATCH 10/22] 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 ImportDirectories; DenseMap 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 Date: Wed, 6 Aug 2025 20:15:29 +0900 Subject: [PATCH 11/22] 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@a2^cWjb0oU45_Fr>m{5Hxz>~cpf@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?WYoqw6EI9@q~m)2iFa}@0}cf$uWNwNT;p_gV!!H z=Ts$5`Vtq?sIDQx9Y{HFy$6pUN!$`6ujfj&`8!b%!X+C! k+pW#5s;oDwJ626Ls&?(Ev^SeADSz*-Zd(Y+@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 +@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 +@sym1 = external dso_local global [4 x i8] +@sym2 = external dso_local global [4 x i8] +@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) +@local2a = private global ptr getelementptr (i8, ptr @sym2, i32 2) +@local3a = private global ptr getelementptr (i8, ptr @sym3, i32 1) +@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 Date: Wed, 6 Aug 2025 20:31:40 +0900 Subject: [PATCH 12/22] 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 Date: Tue, 5 Aug 2025 21:18:49 +0900 Subject: [PATCH 13/22] 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) -@local2a = private global ptr getelementptr (i8, ptr @sym2, i32 2) -@local3a = private global ptr getelementptr (i8, ptr @sym3, i32 1) +@local2a = dso_local global ptr getelementptr (i8, ptr @sym2, i32 2) +@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 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 Date: Sun, 10 Aug 2025 07:29:03 +0900 Subject: [PATCH 14/22] 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 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 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 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 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 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 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 Date: Sun, 10 Aug 2025 08:46:12 +0900 Subject: [PATCH 15/22] 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 RVASymbolMap; + SmallVector RVASymbolMap; COFFSymbolRef RelocBegin, RelocEnd; for (uint32_t i = 0; i < Count; ++i) { Expected 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 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 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 Date: Sun, 10 Aug 2025 08:00:44 +0900 Subject: [PATCH 16/22] 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 RVASymbolMap; COFFSymbolRef RelocBegin, RelocEnd; for (uint32_t i = 0; i < Count; ++i) { - Expected Sym = Obj->getSymbol(i); - if (!Sym) { - consumeError(Sym.takeError()); + COFFSymbolRef Sym; + if (Expected 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 Name = Obj->getSymbolName(*Sym); - if (!Name) { - consumeError(Name.takeError()); + + StringRef Name; + if (Expected 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 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 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 SecOrErr = + Obj->getSection(RelocBegin.getSectionNumber())) + Section = *SecOrErr; + else + return reportWarning(SecOrErr.takeError(), Obj->getFileName()); - Expected 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 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 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 Date: Sun, 10 Aug 2025 08:51:42 +0900 Subject: [PATCH 17/22] 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 Date: Sun, 10 Aug 2025 08:58:11 +0900 Subject: [PATCH 18/22] 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 < 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 Date: Sun, 10 Aug 2025 20:43:37 +0900 Subject: [PATCH 19/22] 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 < 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 Date: Mon, 11 Aug 2025 11:37:02 +0900 Subject: [PATCH 20/22] 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 < 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 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 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 Date: Mon, 11 Aug 2025 12:10:08 +0900 Subject: [PATCH 21/22] 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: From e9ab39658b8a74b1c908281d874005f350999c4a Mon Sep 17 00:00:00 2001 From: kikairoya Date: Mon, 11 Aug 2025 20:50:31 +0900 Subject: [PATCH 22/22] format, style, wording (nfc) --- .../tools/llvm-readobj/COFF/pseudoreloc.test | 16 ++-- llvm/tools/llvm-readobj/COFFDumper.cpp | 95 ++++++++++--------- llvm/tools/llvm-readobj/Opts.td | 3 +- 3 files changed, 62 insertions(+), 52 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test index 54715a31f31da..f9088b0e89b47 100644 --- a/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test +++ b/llvm/test/tools/llvm-readobj/COFF/pseudoreloc.test @@ -157,14 +157,16 @@ 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 -WARN-SECTIONDIFFERS-NEXT: the marker symbols for runtime pseudo-relocation must point a same section +WARN-LOWEREND-NEXT: the begin marker symbol for runtime pseudo-relocation must point to a lower address than where the end marker points +WARN-OUTOFRANGE-NEXT: the marker symbol of runtime pseudo-relocation points past the end of the section +WARN-SECTIONDIFFERS-NEXT: the marker symbols for runtime pseudo-relocation must point to the same section EMPTY-NEXT: ] -To regenerate Inputs/pseudoreloc.*.yaml, run following one-liner and review actual address map: - -$ split-file pseudoreloc.test /tmp/pseudoreloc && bash /tmp/pseudoreloc/generate.sh && cp /tmp/pseudoreloc/*.yaml Inputs/ +;; +;; 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)" @@ -211,7 +213,7 @@ generate() { } EOT - # Ensure the binaries generated from parameterized yaml and original one are exact same. + # Ensure the binaries generated from the parameterized yaml and original one are exactly the same. diff <(yaml2obj pseudoreloc.$arch.yaml.orig -o -) <(yaml2obj pseudoreloc.$arch.yaml -o -) } diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 1f44e810d57dd..7c158bd1ab08e 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -2005,7 +2005,7 @@ void COFFDumper::printCOFFPseudoReloc() { ListScope D(W, "PseudoReloc"); W.flush(); - // Pseudo-relocation is only meaningful for a PE image file. + // Pseudo-relocations are only meaningful with PE image files. if (!Obj->getDOSHeader()) return; @@ -2031,9 +2031,9 @@ void COFFDumper::printCOFFPseudoReloc() { COFFSymbolRef RelocBegin, RelocEnd; for (uint32_t i = 0; i < Count; ++i) { COFFSymbolRef Sym; - if (Expected SymOrErr = Obj->getSymbol(i)) + if (Expected SymOrErr = Obj->getSymbol(i)) { Sym = *SymOrErr; - else { + } else { reportWarning(SymOrErr.takeError(), Obj->getFileName()); continue; } @@ -2044,9 +2044,9 @@ void COFFDumper::printCOFFPseudoReloc() { continue; StringRef Name; - if (Expected NameOrErr = Obj->getSymbolName(Sym)) + if (Expected NameOrErr = Obj->getSymbolName(Sym)) { Name = *NameOrErr; - else { + } else { reportWarning(NameOrErr.takeError(), Obj->getFileName()); continue; } @@ -2058,9 +2058,9 @@ void COFFDumper::printCOFFPseudoReloc() { const coff_section *Sec = nullptr; if (Expected SecOrErr = - Obj->getSection(Sym.getSectionNumber())) + Obj->getSection(Sym.getSectionNumber())) { Sec = *SecOrErr; - else { + } else { reportWarning(SecOrErr.takeError(), Obj->getFileName()); continue; } @@ -2079,39 +2079,48 @@ void COFFDumper::printCOFFPseudoReloc() { const coff_section *Section = nullptr; if (Expected SecOrErr = - Obj->getSection(RelocBegin.getSectionNumber())) + Obj->getSection(RelocBegin.getSectionNumber())) { Section = *SecOrErr; - else - return reportWarning(SecOrErr.takeError(), Obj->getFileName()); + } else { + reportWarning(SecOrErr.takeError(), Obj->getFileName()); + return; + } - if (RelocBegin.getSectionNumber() != RelocEnd.getSectionNumber()) - return reportWarning( - createStringError( - "the marker symbols for runtime pseudo-relocation must " - "point a same section"), - Obj->getFileName()); + if (RelocBegin.getSectionNumber() != RelocEnd.getSectionNumber()) { + reportWarning(createStringError( + "the marker symbols for runtime pseudo-relocation must " + "point to the same section"), + Obj->getFileName()); + return; + } // Skip if the relocation list is empty. if (RelocBegin.getValue() == RelocEnd.getValue()) return; - if (RelocEnd.getValue() < RelocBegin.getValue()) - return reportWarning( + if (RelocEnd.getValue() < RelocBegin.getValue()) { + reportWarning( createStringError( "the begin marker symbol for runtime pseudo-relocation must point " - "lower address than where the end marker points"), + "to a lower address than where the end marker points"), Obj->getFileName()); + return; + } ArrayRef Data; - if (auto E = Obj->getSectionContents(Section, Data)) - return reportWarning(std::move(E), Obj->getFileName()); + if (auto E = Obj->getSectionContents(Section, Data)) { + reportWarning(std::move(E), Obj->getFileName()); + return; + } if (Data.size() <= RelocBegin.getValue() || - Data.size() <= RelocEnd.getValue()) - return reportWarning( + Data.size() <= RelocEnd.getValue()) { + reportWarning( createStringError("the marker symbol of runtime pseudo-relocation " - "points to out of the valid address space"), + "points past the end of the section"), Obj->getFileName()); + return; + } ArrayRef RawRelocs = Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue()); @@ -2124,10 +2133,12 @@ void COFFDumper::printCOFFPseudoReloc() { }; const PseudoRelocationHeader HeaderV2(1); if (RawRelocs.size() < sizeof(HeaderV2) || - (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) - return reportWarning( + (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) { + reportWarning( createStringError("invalid runtime pseudo-relocation records"), Obj->getFileName()); + return; + } struct alignas(4) PseudoRelocationRecord { support::ulittle32_t Symbol; @@ -2207,22 +2218,20 @@ void COFFDumper::printCOFFPseudoReloc() { DenseMap 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()); + llvm::stable_sort(RVASymbolMap, + [](const auto &x, const auto &y) { return x.RVA < y.RVA; }); + RVASymbolMap.erase( + llvm::unique(RVASymbolMap, + [](const auto &x, const auto &y) { return x.RVA == y.RVA; }), + RVASymbolMap.end()); for (const auto &Reloc : RelocRecords) { DictScope Entry(W, "Entry"); W.printHex("Symbol", Reloc.Symbol); - if (Expected SymOrErr = ImportedSymbols.find(Reloc.Symbol)) + if (Expected SymOrErr = ImportedSymbols.find(Reloc.Symbol)) { W.printString("SymbolName", *SymOrErr); - else { + } else { reportWarning(SymOrErr.takeError(), Obj->getFileName()); W.printString("SymbolName", "(missing)"); } @@ -2231,17 +2240,17 @@ void COFFDumper::printCOFFPseudoReloc() { if (auto Ite = llvm::upper_bound( RVASymbolMap, Reloc.Target.value(), [](uint32_t RVA, const auto &Sym) { return RVA < Sym.RVA; }); - Ite == RVASymbolMap.begin()) + Ite == RVASymbolMap.begin()) { W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target); - else if (const uint32_t Offset = Reloc.Target.value() - (--Ite)->RVA; - Offset == 0) + } else if (const uint32_t Offset = Reloc.Target.value() - (--Ite)->RVA; + Offset == 0) { W.printString("TargetSymbol", Ite->SymbolName); - else if (Offset < Ite->Section->VirtualSize) + } else if (Offset < Ite->Section->VirtualSize) { W.printSymbolOffset("TargetSymbol", Ite->SymbolName, Offset); - else if (++Ite == RVASymbolMap.end()) + } else if (++Ite == RVASymbolMap.end()) { W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target); - else if (Expected NameOrErr = - Obj->getSectionName(Ite->Section)) { + } else if (Expected NameOrErr = + Obj->getSectionName(Ite->Section)) { W.printSymbolOffset("TargetSymbol", *NameOrErr, Reloc.Target - Ite->Section->VirtualAddress); } else { diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index 71e1cae91d417..711522c4acb14 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -81,8 +81,7 @@ def codeview : FF<"codeview", "Display CodeView debug information">, Group, Group; def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group; def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group; -def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, - Group; +def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group; def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group; def coff_directives : FF<"coff-directives", "Display .drectve section">, Group; def coff_exports : FF<"coff-exports", "Display export table">, Group;