Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LLD] [COFF] Error out if the runtime pseudo relocation function is missing #88573

Merged
merged 1 commit into from
Apr 16, 2024

Conversation

mstorsjo
Copy link
Member

@mstorsjo mstorsjo commented Apr 12, 2024

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 #84424.

@llvmbot
Copy link
Collaborator

llvmbot commented Apr 12, 2024

@llvm/pr-subscribers-platform-windows
@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-coff

Author: Martin Storsjö (mstorsjo)

Changes

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, print a warning.

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, try to make the user aware of the situation.

This just prints a warning to alert the user about this situation. Alternatively, we could also make this situation a hard error.

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

Yet another 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
#84424.


Full diff: https://github.com/llvm/llvm-project/pull/88573.diff

2 Files Affected:

  • (modified) lld/COFF/Writer.cpp (+9-1)
  • (added) lld/test/COFF/autoimport-warn-func.s (+36)
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 9c20bbb83d86d1..f2194616b93a63 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)
+      warn("output image has pseudo relocations, but function " +
+           Twine(symbolName) +
+           " missing; the relocations might not get fixed at runtime");
+  }
+
   PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);
   rdataSec->addChunk(table);
   EmptyChunk *endOfList = make<EmptyChunk>();
diff --git a/lld/test/COFF/autoimport-warn-func.s b/lld/test/COFF/autoimport-warn-func.s
new file mode 100644
index 00000000000000..94e1238376b710
--- /dev/null
+++ b/lld/test/COFF/autoimport-warn-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: lld-link -lldmingw -out:%t.dir/main.exe -entry:main %t.dir/main.obj %t.dir/lib.lib 2>&1 | FileCheck %s --check-prefix=WARN
+
+# 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=NOWARN --allow-empty
+
+# WARN: warning: output image has pseudo relocations, but function _pei386_runtime_relocator missing; the relocations might not get fixed at runtime
+
+# NOWARN-NOT: warning
+
+#--- 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
+

@mstorsjo
Copy link
Member Author

CC @mati865 @jeremyd2019

What do others think - should we make this a hard error, or just a friendly warning? (This issue was brought up in #84424 (comment).)

Ideally I'd like to make the linker try to pull in this function once we realize we need runtime pseudo relocs; I have a WIP patch for that since a long time, but I feel that it's a bit messy, and as long as ld.bfd isn't fixed to work in the same way, we can't really make use of it.

@Keno
Copy link
Member

Keno commented Apr 12, 2024

Alternatively, we could also make this situation a hard error.

I think a hard error is probably better since non-application of the pseudo relocation ends up exposing the wrong symbol address. I think the situation would be different if the pseudo relocations where still being applied if the library was ultimately opened by an application that is linked against the mingw runtime, but that's not the case - the only question is whether the startup files are linked into the .dll, which we can detect here.

@jeremyd2019
Copy link
Contributor

Alternatively, we could also make this situation a hard error.

I think a hard error is probably better ...

I agree. Since I have been dealing with it lately, I am a little concerned if this will be an issue for rust. I imagine not, because it does usually work with ld.bfd, and this is a hard error there.

@mstorsjo mstorsjo changed the title [LLD] [COFF] Warn if the runtime pseudo relocation function is missing [LLD] [COFF] Error out if the runtime pseudo relocation function is missing Apr 13, 2024
@mstorsjo
Copy link
Member Author

Thanks for the input! I changed this to be a hard error now - adjusting both commit message and the tone of the output message slightly.

Copy link

github-actions bot commented Apr 13, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

…issing

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
llvm#84424.
@mati865
Copy link
Contributor

mati865 commented Apr 13, 2024

Normally it's nice to have a warning for one release to make migration easier but in this case looks like the outputs are always more or less broken, so the hard error makes sense.

Copy link
Contributor

@cjacek cjacek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mstorsjo mstorsjo merged commit a169d4c into llvm:main Apr 16, 2024
4 checks passed
@mstorsjo mstorsjo deleted the lld-warn-missing-relocator branch April 16, 2024 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants