[lld] [LLD] [COFF] Warn if the runtime pseudo relocation function is missing (PR #88573)

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 13 14:23:28 PDT 2024


https://github.com/mstorsjo updated https://github.com/llvm/llvm-project/pull/88573

>From 283a730ef7195bb03c272ec38103fc5c4fda2a92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Fri, 12 Apr 2024 23:16:27 +0300
Subject: [PATCH] =?UTF-8?q?[LLD]=C2=A0[COFF]=20Error=20out=20if=20the=20ru?=
 =?UTF-8?q?ntime=20pseudo=20relocation=20function=20is=20missing?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When then linker creates runtime pseudo relocations, it places them
in a list with the assumption that the runtime will fix these
relocations later, when the image gets loaded. If the relevant
runtime function doesn't seem to be present in the linked image,
error out.

Normally when linking the mingw-w64 runtime libraries, this function
always is available. However, if linking without including the
mingw-w64 CRT startup files, and the image needs runtime pseudo
relocations, make it clear that this won't work as expected at
runtime.

With ld.bfd, this situation is a hard error too; ld.bfd adds an
undefined reference to this symbol if runtime pseudo relocations
are needed.

A later alternative would be to actually try to pull in the symbol
(if seen in a static library, but not included yet). This would
allow decoupling the function from the main CRT startup code
(making it optional, only running if the linker actually produced
runtime pseudo relocations). Doing that would require restructuring
the code (gathering pseudo relocations earlier, in order to be able
to continue linking in more object files if the initial set did
require pseudo relocations) though.

Also, ld.bfd doesn't currently successfully pull in more object
files to satisfy the dependency on _pei386_runtime_relocator,
so with that in mind, there's not much extra value in making LLD
do it currently either.

This fixes one issue brought up in
https://github.com/llvm/llvm-project/issues/84424.
---
 lld/COFF/Writer.cpp                     | 10 ++++++-
 lld/test/COFF/autoimport-arm-data.s     |  3 +++
 lld/test/COFF/autoimport-arm64-data.s   |  3 +++
 lld/test/COFF/autoimport-gnu-implib.s   |  3 +++
 lld/test/COFF/autoimport-handler-func.s | 36 +++++++++++++++++++++++++
 lld/test/COFF/autoimport-warn.s         |  3 +++
 lld/test/COFF/autoimport-x86.s          |  3 +++
 7 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 lld/test/COFF/autoimport-handler-func.s

diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 9c20bbb83d86d1..05a13c20200053 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -2072,8 +2072,16 @@ void Writer::createRuntimePseudoRelocs() {
     return;
   }
 
-  if (!rels.empty())
+  if (!rels.empty()) {
     log("Writing " + Twine(rels.size()) + " runtime pseudo relocations");
+    const char *symbolName = "_pei386_runtime_relocator";
+    Symbol *relocator = ctx.symtab.findUnderscore(symbolName);
+    if (!relocator)
+      error("output image has runtime pseudo relocations, but the function " +
+           Twine(symbolName) +
+           " is missing; it is needed for fixing the relocations at runtime");
+  }
+
   PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);
   rdataSec->addChunk(table);
   EmptyChunk *endOfList = make<EmptyChunk>();
diff --git a/lld/test/COFF/autoimport-arm-data.s b/lld/test/COFF/autoimport-arm-data.s
index 74604aa5c82343..82c66f0989d490 100644
--- a/lld/test/COFF/autoimport-arm-data.s
+++ b/lld/test/COFF/autoimport-arm-data.s
@@ -33,6 +33,9 @@
     .text
     .thumb
 main:
+    bx lr
+    .global _pei386_runtime_relocator
+_pei386_runtime_relocator:
     bx lr
     .data
 ptr:
diff --git a/lld/test/COFF/autoimport-arm64-data.s b/lld/test/COFF/autoimport-arm64-data.s
index fa3654be3a71d7..b49bd4f89c97c2 100644
--- a/lld/test/COFF/autoimport-arm64-data.s
+++ b/lld/test/COFF/autoimport-arm64-data.s
@@ -33,6 +33,9 @@
     .global main
     .text
 main:
+    ret
+    .global _pei386_runtime_relocator
+_pei386_runtime_relocator:
     ret
     .data
 ptr:
diff --git a/lld/test/COFF/autoimport-gnu-implib.s b/lld/test/COFF/autoimport-gnu-implib.s
index d7d4ed626e83ae..d9dc9d7a38fdc3 100644
--- a/lld/test/COFF/autoimport-gnu-implib.s
+++ b/lld/test/COFF/autoimport-gnu-implib.s
@@ -27,5 +27,8 @@
     .text
 main:
     movl data(%rip), %eax
+    ret
+    .global _pei386_runtime_relocator
+_pei386_runtime_relocator:
     ret
     .data
diff --git a/lld/test/COFF/autoimport-handler-func.s b/lld/test/COFF/autoimport-handler-func.s
new file mode 100644
index 00000000000000..02d040bfa274ce
--- /dev/null
+++ b/lld/test/COFF/autoimport-handler-func.s
@@ -0,0 +1,36 @@
+# REQUIRES: x86
+# RUN: split-file %s %t.dir
+
+# RUN: llvm-dlltool -m i386:x86-64 -d %t.dir/lib.def -D lib.dll -l %t.dir/lib.lib
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/main.s -filetype=obj -o %t.dir/main.obj
+# RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/func.s -filetype=obj -o %t.dir/func.obj
+# RUN: env LLD_IN_TEST=1 not lld-link -lldmingw -out:%t.dir/main.exe -entry:main %t.dir/main.obj %t.dir/lib.lib 2>&1 | FileCheck %s --check-prefix=ERR
+
+# RUN: lld-link -lldmingw -out:%t.dir/main.exe -entry:main %t.dir/main.obj %t.dir/func.obj %t.dir/lib.lib 2>&1 | FileCheck %s --check-prefix=NOERR --allow-empty
+
+# ERR: error: output image has runtime pseudo relocations, but the function _pei386_runtime_relocator is missing; it is needed for fixing the relocations at runtime
+
+# NOERR-NOT: error
+
+#--- main.s
+    .global main
+    .text
+main:
+    ret
+
+    .data
+    .long 1
+    .quad variable
+    .long 2
+
+#--- func.s
+    .global _pei386_runtime_relocator
+    .text
+_pei386_runtime_relocator:
+    ret
+
+#--- lib.def
+EXPORTS
+variable DATA
+
diff --git a/lld/test/COFF/autoimport-warn.s b/lld/test/COFF/autoimport-warn.s
index 9c363ed30f2459..eead0fed861f8f 100644
--- a/lld/test/COFF/autoimport-warn.s
+++ b/lld/test/COFF/autoimport-warn.s
@@ -18,6 +18,9 @@ main:
     movl variable2(%rip), %ecx
     addl %ecx, %eax
     ret
+    .global _pei386_runtime_relocator
+_pei386_runtime_relocator:
+    ret
 
     .section .rdata$.refptr.variable1,"dr",discard,.refptr.variable1
     .global .refptr.variable1
diff --git a/lld/test/COFF/autoimport-x86.s b/lld/test/COFF/autoimport-x86.s
index fa36f10e9ca912..5d7c9c2c3fa580 100644
--- a/lld/test/COFF/autoimport-x86.s
+++ b/lld/test/COFF/autoimport-x86.s
@@ -55,6 +55,9 @@
     .text
 main:
     movl variable(%rip), %eax
+    ret
+    .global _pei386_runtime_relocator
+_pei386_runtime_relocator:
     ret
     .data
 ptr:



More information about the llvm-commits mailing list