aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorMartin Storsjö <martin@martin.st>2023-07-06 01:04:12 +0300
committerMartin Storsjö <martin@martin.st>2023-07-11 23:43:34 +0300
commit6daa4b90e28ef4789ae0eb3163c6770c110d3a28 (patch)
tree607be1c3587d096c64c293f6fc4eb6235d0fad98 /lld
parent1776dc81240cab4e365d55bc720b552823697081 (diff)
downloadllvm-6daa4b90e28ef4789ae0eb3163c6770c110d3a28.zip
llvm-6daa4b90e28ef4789ae0eb3163c6770c110d3a28.tar.gz
llvm-6daa4b90e28ef4789ae0eb3163c6770c110d3a28.tar.bz2
[LLD] [COFF] Warn about pseudo relocations that are too narrow
In 64 bit mode, any references to symbols that might end up autoimported must be made via full 64 bit pointers (usually in .refptr stubs generated by the compiler). If referenced via e.g. a 32 bit rip relative offset, it might work as long as DLLs are loaded close together in the 64 bit address space, but will fail surprisingly later if they happen to be loaded further apart. Any cases of that happening is usually a toolchain error, and the sooner we can warn about it, the easier it is to diagnose. Differential Revision: https://reviews.llvm.org/D154777
Diffstat (limited to 'lld')
-rw-r--r--lld/COFF/Chunks.cpp7
-rw-r--r--lld/test/CMakeLists.txt1
-rw-r--r--lld/test/COFF/autoimport-nowarn.s19
-rw-r--r--lld/test/COFF/autoimport-warn.s29
4 files changed, 56 insertions, 0 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 5f9c17e..e17b64d 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -661,6 +661,13 @@ void SectionChunk::getRuntimePseudoRelocs(
toString(file));
continue;
}
+ int addressSizeInBits = file->ctx.config.is64() ? 64 : 32;
+ if (sizeInBits < addressSizeInBits) {
+ warn("runtime pseudo relocation in " + toString(file) + " against " +
+ "symbol " + target->getName() + " is too narrow (only " +
+ Twine(sizeInBits) + " bits wide); this can fail at runtime " +
+ "depending on memory layout");
+ }
// sizeInBits is used to initialize the Flags field; currently no
// other flags are defined.
res.emplace_back(target, this, rel.VirtualAddress, sizeInBits);
diff --git a/lld/test/CMakeLists.txt b/lld/test/CMakeLists.txt
index 8d70903..56490a7 100644
--- a/lld/test/CMakeLists.txt
+++ b/lld/test/CMakeLists.txt
@@ -51,6 +51,7 @@ if (NOT LLD_BUILT_STANDALONE)
llvm-config
llvm-cvtres
llvm-dis
+ llvm-dlltool
llvm-dwarfdump
llvm-lib
llvm-lipo
diff --git a/lld/test/COFF/autoimport-nowarn.s b/lld/test/COFF/autoimport-nowarn.s
new file mode 100644
index 0000000..a205499
--- /dev/null
+++ b/lld/test/COFF/autoimport-nowarn.s
@@ -0,0 +1,19 @@
+# REQUIRES: x86
+
+# RUN: echo -e "EXPORTS\nvariable" > %t-lib.def
+# RUN: llvm-dlltool -m i386 -d %t-lib.def -D lib.dll -l %t-lib.lib
+
+# RUN: llvm-mc -triple=i386-windows-gnu %s -filetype=obj -o %t.obj
+# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose 2>&1 | FileCheck --allow-empty %s
+
+# CHECK-NOT: runtime pseudo relocation {{.*}} is too narrow
+
+ .global _main
+ .text
+_main:
+ movl _variable, %eax
+ ret
+
+relocs:
+ .long ___RUNTIME_PSEUDO_RELOC_LIST__
+ .long ___RUNTIME_PSEUDO_RELOC_LIST_END__
diff --git a/lld/test/COFF/autoimport-warn.s b/lld/test/COFF/autoimport-warn.s
new file mode 100644
index 0000000..9c363ed
--- /dev/null
+++ b/lld/test/COFF/autoimport-warn.s
@@ -0,0 +1,29 @@
+# REQUIRES: x86
+
+# RUN: echo -e "EXPORTS\nvariable1 DATA\nvariable2 DATA" > %t-lib.def
+# RUN: llvm-dlltool -m i386:x86-64 -d %t-lib.def -D lib.dll -l %t-lib.lib
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
+# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose 2>&1 | FileCheck %s
+
+# CHECK-NOT: runtime pseudo relocation {{.*}} against symbol variable1
+# CHECK: warning: runtime pseudo relocation in {{.*}}.obj against symbol variable2 is too narrow (only 32 bits wide); this can fail at runtime depending on memory layout
+# CHECK-NOT: runtime pseudo relocation {{.*}} against symbol variable1
+
+ .global main
+ .text
+main:
+ movq .refptr.variable1(%rip), %rax
+ movl (%rax), %eax
+ movl variable2(%rip), %ecx
+ addl %ecx, %eax
+ ret
+
+ .section .rdata$.refptr.variable1,"dr",discard,.refptr.variable1
+ .global .refptr.variable1
+.refptr.variable1:
+ .quad variable1
+
+relocs:
+ .quad __RUNTIME_PSEUDO_RELOC_LIST__
+ .quad __RUNTIME_PSEUDO_RELOC_LIST_END__