[lld] [llvm] IRSymTab: Record _GLOBAL_OFFSET_TABLE_ for ELF x86 (PR #89463)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 19 15:22:06 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
In ELF, relocatable files generated for x86-32 and some code models of
x86-64 (medium, large) may reference the special symbol
`_GLOBAL_OFFSET_TABLE_` that is not used in the IR. In an LTO link, if
there is no regular relocatable file referencing the special symbol, the
linker may not define the symbol and lead to a spurious "undefined
symbol" error.
Fix #<!-- -->61101: record that `_GLOBAL_OFFSET_TABLE_` is used in the IR symbol
table. The `PreservedSymbols` mechanism
(https://reviews.llvm.org/D112595) that just sets `FB_used` is not
applicable.
---
Full diff: https://github.com/llvm/llvm-project/pull/89463.diff
8 Files Affected:
- (added) lld/test/ELF/lto/i386-global-offset-table.ll (+22)
- (added) lld/test/ELF/lto/x86-64-global-offset-table.ll (+57)
- (modified) llvm/lib/Object/ModuleSymbolTable.cpp (+14)
- (modified) llvm/test/LTO/X86/codemodel-2.ll (+1-1)
- (modified) llvm/test/LTO/X86/codemodel-3.ll (+2-1)
- (modified) llvm/test/LTO/X86/largedatathreshold-1.ll (+1-1)
- (modified) llvm/test/LTO/X86/largedatathreshold-2.ll (+1-1)
- (modified) llvm/test/LTO/X86/largedatathreshold-3.ll (+2-1)
``````````diff
diff --git a/lld/test/ELF/lto/i386-global-offset-table.ll b/lld/test/ELF/lto/i386-global-offset-table.ll
new file mode 100644
index 00000000000000..e470763a3eb2ec
--- /dev/null
+++ b/lld/test/ELF/lto/i386-global-offset-table.ll
@@ -0,0 +1,22 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.bc
+; RUN: ld.lld %t.bc -o %t
+
+target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+define dso_local void @f() {
+entry:
+ ret void
+}
+
+define dso_local void @_start() {
+entry:
+ call void @f()
+ ret void
+}
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 8, !"PIC Level", i32 2}
+!1 = !{i32 7, !"PIE Level", i32 2}
diff --git a/lld/test/ELF/lto/x86-64-global-offset-table.ll b/lld/test/ELF/lto/x86-64-global-offset-table.ll
new file mode 100644
index 00000000000000..1db1027e7a21c5
--- /dev/null
+++ b/lld/test/ELF/lto/x86-64-global-offset-table.ll
@@ -0,0 +1,57 @@
+; REQUIRES: x86
+; RUN: rm -rf %t && split-file %s %t && cd %t
+; RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
+
+; RUN: cat a.ll medium.ll | llvm-as - -o medium.bc
+; RUN: ld.lld -pie --no-relax medium.bc b.o -o medium
+; RUN: llvm-objdump -d medium | FileCheck %s
+
+; RUN: cat a.ll large.ll | llvm-as - -o large.bc
+; RUN: ld.lld -pie large.bc b.o -o large
+; RUN: llvm-objdump -d large | FileCheck %s
+
+; RUN: cat a.ll medium.ll ref.ll | llvm-as - -o ref.bc
+; RUN: ld.lld -pie --no-relax -u ref ref.bc b.o -o ref
+; RUN: llvm-objdump -d ref | FileCheck %s
+
+; CHECK: movabsq
+
+;--- a.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at i = external global i32
+
+define dso_local void @_start() {
+entry:
+ %0 = load i32, ptr @i
+ %inc = add nsw i32 %0, 1
+ store i32 %inc, ptr @i
+ ret void
+}
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 8, !"PIC Level", i32 2}
+!1 = !{i32 7, !"PIE Level", i32 2}
+!2 = !{i32 1, !"Large Data Threshold", i64 0}
+
+;--- medium.ll
+!3 = !{i32 1, !"Code Model", i32 3}
+
+;--- large.ll
+!3 = !{i32 1, !"Code Model", i32 4}
+
+;--- ref.ll
+ at _GLOBAL_OFFSET_TABLE_ = external global [0 x i8]
+
+define dso_local ptr @ref() {
+entry:
+ ret ptr @_GLOBAL_OFFSET_TABLE_
+}
+
+;--- b.s
+.data
+.globl i
+i:
+.long 0
diff --git a/llvm/lib/Object/ModuleSymbolTable.cpp b/llvm/lib/Object/ModuleSymbolTable.cpp
index 07f76688fa43e7..d8f520ad02c2f2 100644
--- a/llvm/lib/Object/ModuleSymbolTable.cpp
+++ b/llvm/lib/Object/ModuleSymbolTable.cpp
@@ -175,6 +175,20 @@ void ModuleSymbolTable::CollectAsmSymbols(
AsmSymbol(Key, BasicSymbolRef::Flags(Res));
}
});
+
+ // In ELF, object code generated for x86-32 and some code models of x86-64 may
+ // reference the special symbol _GLOBAL_OFFSET_TABLE_ that is not used in the
+ // IR. Record it like inline asm symbols.
+ Triple TT(M.getTargetTriple());
+ if (!TT.isOSBinFormatELF() || !TT.isX86())
+ return;
+ auto CM = M.getCodeModel();
+ if (TT.getArch() == Triple::x86 || CM == CodeModel::Medium ||
+ CM == CodeModel::Large) {
+ AsmSymbol("_GLOBAL_OFFSET_TABLE_",
+ BasicSymbolRef::Flags(BasicSymbolRef::SF_Undefined |
+ BasicSymbolRef::SF_Global));
+ }
}
void ModuleSymbolTable::CollectAsmSymvers(
diff --git a/llvm/test/LTO/X86/codemodel-2.ll b/llvm/test/LTO/X86/codemodel-2.ll
index 5cd9731606f2bd..fc1074bcf2235c 100644
--- a/llvm/test/LTO/X86/codemodel-2.ll
+++ b/llvm/test/LTO/X86/codemodel-2.ll
@@ -1,5 +1,5 @@
; RUN: llvm-as %s -o %t.o
-; RUN: llvm-lto2 run -r %t.o,_start,px %t.o -o %t.s
+; RUN: llvm-lto2 run -r %t.o,_start,px -r %t.o,_GLOBAL_OFFSET_TABLE_, %t.o -o %t.s
; RUN: llvm-objdump --no-print-imm-hex -d %t.s.0 | FileCheck %s --check-prefix=CHECK-LARGE
target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/LTO/X86/codemodel-3.ll b/llvm/test/LTO/X86/codemodel-3.ll
index 947221e9f36dc5..13702dfbca2da4 100644
--- a/llvm/test/LTO/X86/codemodel-3.ll
+++ b/llvm/test/LTO/X86/codemodel-3.ll
@@ -1,6 +1,7 @@
; RUN: llvm-as %s -o %t0.o
; RUN: llvm-as < %p/Inputs/codemodel-3.ll > %t1.o
-; RUN: not llvm-lto2 run -r %t0.o,_start,px -r %t1.o,bar,px %t0.o %t1.o -o %t2.s 2>&1 | FileCheck %s
+; RUN: not llvm-lto2 run -r %t0.o,_start,px -r %t1.o,bar,px -r %t0.o,_GLOBAL_OFFSET_TABLE_, \
+; RUN: -r %t1.o,_GLOBAL_OFFSET_TABLE_, %t0.o %t1.o -o %t2.s 2>&1 | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/LTO/X86/largedatathreshold-1.ll b/llvm/test/LTO/X86/largedatathreshold-1.ll
index e3be5c11baaac2..dfd8319511b617 100644
--- a/llvm/test/LTO/X86/largedatathreshold-1.ll
+++ b/llvm/test/LTO/X86/largedatathreshold-1.ll
@@ -1,5 +1,5 @@
; RUN: llvm-as %s -o %t.o
-; RUN: llvm-lto2 run -r %t.o,_start,px %t.o -o %t.s
+; RUN: llvm-lto2 run -r %t.o,_start,px -r %t.o,_GLOBAL_OFFSET_TABLE_, %t.o -o %t.s
; RUN: llvm-objdump -d %t.s.0 | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/LTO/X86/largedatathreshold-2.ll b/llvm/test/LTO/X86/largedatathreshold-2.ll
index 103c066b744d0f..59438bbdb5027f 100644
--- a/llvm/test/LTO/X86/largedatathreshold-2.ll
+++ b/llvm/test/LTO/X86/largedatathreshold-2.ll
@@ -1,5 +1,5 @@
; RUN: llvm-as %s -o %t.o
-; RUN: llvm-lto2 run -r %t.o,_start,px %t.o -o %t.s
+; RUN: llvm-lto2 run -r %t.o,_start,px -r %t.o,_GLOBAL_OFFSET_TABLE_, %t.o -o %t.s
; RUN: llvm-objdump -d %t.s.0 | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/LTO/X86/largedatathreshold-3.ll b/llvm/test/LTO/X86/largedatathreshold-3.ll
index 3c0653db334d85..fea7987ff15566 100644
--- a/llvm/test/LTO/X86/largedatathreshold-3.ll
+++ b/llvm/test/LTO/X86/largedatathreshold-3.ll
@@ -1,6 +1,7 @@
; RUN: llvm-as %s -o %t0.o
; RUN: llvm-as < %p/Inputs/largedatathreshold.ll > %t1.o
-; RUN: not llvm-lto2 run -r %t0.o,_start,px -r %t1.o,bar,px %t0.o %t1.o -o %t2.s 2>&1 | FileCheck %s
+; RUN: not llvm-lto2 run -r %t0.o,_start,px -r %t1.o,bar,px -r %t0.o,_GLOBAL_OFFSET_TABLE_, \
+; RUN: -r %t1.o,_GLOBAL_OFFSET_TABLE_, %t0.o %t1.o -o %t2.s 2>&1 | FileCheck %s
; CHECK: 'Large Data Threshold': IDs have conflicting values
``````````
</details>
https://github.com/llvm/llvm-project/pull/89463
More information about the llvm-commits
mailing list