[llvm] [bolt] Account for stubs with symbols in plt. (PR #192716)
Hemant Kulkarni via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 28 08:03:06 PDT 2026
https://github.com/awshkulkar updated https://github.com/llvm/llvm-project/pull/192716
>From 165970d29e11fbb39f7652683f2c846baa0e4c5b Mon Sep 17 00:00:00 2001
From: Hemant Kulkarni <hkulkar at amazon.com>
Date: Fri, 3 Apr 2026 15:07:11 +0000
Subject: [PATCH 1/2] [bolt] Account for stubs with symbols in plt.
LLD and bfd do not generate functions symbols for stubs
in PLT. However, mold does and trips the object discovery
to create two functions (BF then PLTFunc). This can cause
symbol to be resoved with BF with incorrect ADRP immediate field in
AArch64.
---
bolt/lib/Rewrite/RewriteInstance.cpp | 7 ++-
bolt/test/AArch64/Inputs/plt-mold-lib.c | 2 +
bolt/test/AArch64/plt-mold-func-symbols.s | 60 +++++++++++++++++++++++
bolt/test/X86/plt-mold.test | 2 +-
4 files changed, 68 insertions(+), 3 deletions(-)
create mode 100644 bolt/test/AArch64/Inputs/plt-mold-lib.c
create mode 100644 bolt/test/AArch64/plt-mold-func-symbols.s
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 43d4421e06928..10326f89671e1 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1041,8 +1041,11 @@ void RewriteInstance::discoverFileObjects() {
FileSymRefs.emplace(SymbolAddress, Symbol);
- // Skip section symbols that will be registered by disassemblePLT().
- if (SymbolType == SymbolRef::ST_Debug) {
+ // Skip symbols in PLT sections that will be registered by disassemblePLT().
+ // ST_Debug covers section markers (lld/GNU ld), ST_Function covers
+ // explicit stub symbols emitted by mold (e.g., malloc$plt).
+ if (SymbolType == SymbolRef::ST_Debug ||
+ SymbolType == SymbolRef::ST_Function) {
ErrorOr<BinarySection &> BSection =
BC->getSectionForAddress(SymbolAddress);
if (BSection && getPLTSectionInfo(BSection->getName()))
diff --git a/bolt/test/AArch64/Inputs/plt-mold-lib.c b/bolt/test/AArch64/Inputs/plt-mold-lib.c
new file mode 100644
index 0000000000000..0c1caa7faf5a0
--- /dev/null
+++ b/bolt/test/AArch64/Inputs/plt-mold-lib.c
@@ -0,0 +1,2 @@
+// Minimal shared library providing printf for plt-mold-func-symbols.s test.
+int printf(const char *fmt, ...) { return 0; }
diff --git a/bolt/test/AArch64/plt-mold-func-symbols.s b/bolt/test/AArch64/plt-mold-func-symbols.s
new file mode 100644
index 0000000000000..4f5350ce3bf54
--- /dev/null
+++ b/bolt/test/AArch64/plt-mold-func-symbols.s
@@ -0,0 +1,60 @@
+## Test that BOLT correctly skips mold-style STT_FUNC symbols in PLT sections.
+# REQUIRES: system-linux
+
+# Build shared lib providing printf
+# RUN: %clang --target=aarch64-linux-gnu -shared -fPIC -o %t.so \
+# RUN: -fuse-ld=lld -nostdlib %S/Inputs/plt-mold-lib.c
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-linux %s -o %t.o
+# RUN: ld.lld -pie --emit-relocs -o %t.exe %t.o %t.so
+
+# Inject mold-style STT_FUNC symbol at the first PLT entry (offset 0x20
+# into .plt — AArch64 lld PLT header is 0x20 bytes, entries are 0x10 each)
+# RUN: llvm-objcopy --add-symbol 'printf$plt=.plt:0x20,local,function' \
+# RUN: %t.exe %t.mold
+
+# Verify the injected symbol exists
+# RUN: llvm-readelf -s %t.mold | FileCheck --check-prefix=SYM %s
+# SYM: FUNC LOCAL {{.*}} printf$plt
+
+# Run BOLT — should skip printf$plt and use printf at PLT
+# RUN: llvm-bolt %t.mold --print-cfg --print-only=main -o /dev/null \
+# RUN: 2>&1 | FileCheck %s
+
+# The call should resolve to printf at PLT, not printf$plt
+# CHECK: bl printf at PLT
+
+# RUN: llvm-readobj --symbols %t.mold | FileCheck --check-prefix=MOLD-SYMS %s
+
+# MOLD-SYMS: Name: printf$plt
+# MOLD-SYMS-NEXT: Value:
+# MOLD-SYMS-NEXT: Size: 0
+# MOLD-SYMS-NEXT: Binding: Local
+# MOLD-SYMS-NEXT: Type: Function
+# MOLD-SYMS-NEXT: Other: 0
+# MOLD-SYMS-NEXT: Section: .plt
+ .text
+ .globl _start
+ .type _start, %function
+_start:
+ bl main
+ mov w8, #93
+ svc #0
+ .size _start, .-_start
+
+ .globl main
+ .type main, %function
+main:
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ adrp x0, .Lstr
+ add x0, x0, :lo12:.Lstr
+ bl printf
+ mov w0, #0
+ ldp x29, x30, [sp], #16
+ ret
+ .size main, .-main
+
+ .section .rodata,"a"
+.Lstr:
+ .asciz "hello\n"
diff --git a/bolt/test/X86/plt-mold.test b/bolt/test/X86/plt-mold.test
index 75c8c023cf3c2..8ef21e87b3453 100644
--- a/bolt/test/X86/plt-mold.test
+++ b/bolt/test/X86/plt-mold.test
@@ -3,4 +3,4 @@
## Check that llvm-bolt correctly parses PLT created by mold linker.
## The only call instruction in main() should be a call to printf() in PLT.
-CHECK: callq "printf$plt
+CHECK: callq printf at PLT
>From a2264f7996b83a0371d151b52adad6d20d787703 Mon Sep 17 00:00:00 2001
From: Hemant Kulkarni <hkulkar at amazon.com>
Date: Fri, 3 Apr 2026 15:07:11 +0000
Subject: [PATCH 2/2] [bolt] Account for stubs with symbols in plt.
LLD and bfd do not generate functions symbols for stubs
in PLT. However, mold does and trips the object discovery
to create two functions (BF then PLTFunc). This can cause
symbol to be resoved with BF with incorrect ADRP immediate field in
AArch64.
---
bolt/test/AArch64/plt-mold-func-symbols.s | 82 +++++++++--------------
1 file changed, 33 insertions(+), 49 deletions(-)
diff --git a/bolt/test/AArch64/plt-mold-func-symbols.s b/bolt/test/AArch64/plt-mold-func-symbols.s
index 4f5350ce3bf54..9d9e80bfb704e 100644
--- a/bolt/test/AArch64/plt-mold-func-symbols.s
+++ b/bolt/test/AArch64/plt-mold-func-symbols.s
@@ -1,60 +1,44 @@
-## Test that BOLT correctly skips mold-style STT_FUNC symbols in PLT sections.
-# REQUIRES: system-linux
-
-# Build shared lib providing printf
-# RUN: %clang --target=aarch64-linux-gnu -shared -fPIC -o %t.so \
-# RUN: -fuse-ld=lld -nostdlib %S/Inputs/plt-mold-lib.c
+# Test that BOLT correctly skips mold-style STT_FUNC symbols in PLT sections.
+# REQUIRES: system-linux
# RUN: llvm-mc -filetype=obj -triple aarch64-linux %s -o %t.o
-# RUN: ld.lld -pie --emit-relocs -o %t.exe %t.o %t.so
-
-# Inject mold-style STT_FUNC symbol at the first PLT entry (offset 0x20
-# into .plt — AArch64 lld PLT header is 0x20 bytes, entries are 0x10 each)
-# RUN: llvm-objcopy --add-symbol 'printf$plt=.plt:0x20,local,function' \
-# RUN: %t.exe %t.mold
+# RUN: ld.lld -pie %t.o -o %t --emit-relocs
+# RUN: llvm-bolt %t -o %t.bolt --print-cfg --print-only=_start 2>&1 | FileCheck %s
+# RUN: llvm-readobj --syms %t.bolt | grep -A6 printf$plt | FileCheck %s --check-prefix=CHECK-SYM
-# Verify the injected symbol exists
-# RUN: llvm-readelf -s %t.mold | FileCheck --check-prefix=SYM %s
-# SYM: FUNC LOCAL {{.*}} printf$plt
+# CHECK-NOT: bl printf$plt
+# CHECK: bl printf
+# CHECK-SYM: Section: .plt
-# Run BOLT — should skip printf$plt and use printf at PLT
-# RUN: llvm-bolt %t.mold --print-cfg --print-only=main -o /dev/null \
-# RUN: 2>&1 | FileCheck %s
-
-# The call should resolve to printf at PLT, not printf$plt
-# CHECK: bl printf at PLT
-
-# RUN: llvm-readobj --symbols %t.mold | FileCheck --check-prefix=MOLD-SYMS %s
-
-# MOLD-SYMS: Name: printf$plt
-# MOLD-SYMS-NEXT: Value:
-# MOLD-SYMS-NEXT: Size: 0
-# MOLD-SYMS-NEXT: Binding: Local
-# MOLD-SYMS-NEXT: Type: Function
-# MOLD-SYMS-NEXT: Other: 0
-# MOLD-SYMS-NEXT: Section: .plt
.text
.globl _start
.type _start, %function
_start:
- bl main
- mov w8, #93
- svc #0
- .size _start, .-_start
-
- .globl main
- .type main, %function
-main:
- stp x29, x30, [sp, #-16]!
- mov x29, sp
- adrp x0, .Lstr
- add x0, x0, :lo12:.Lstr
bl printf
- mov w0, #0
- ldp x29, x30, [sp], #16
ret
- .size main, .-main
+ .size _start, .-_start
+
+ ## Hand-crafted .plt mimicking mold's output
+ .section .plt, "ax", @progbits
+ .p2align 4
+ .space 32
+
+ .type printf$plt, @function
+printf$plt:
+ adrp x16, .L_GOT
+ ldr x17, [x16, :lo12:.L_GOT]
+ br x17
+ .size printf$plt, .-printf$plt
- .section .rodata,"a"
-.Lstr:
- .asciz "hello\n"
+ ## Fake GOT slot
+ .section .got, "aw", @progbits
+.L_GOT:
+ .quad printf
+
+ ## printf definition
+ .text
+ .globl printf
+ .type printf, @function
+printf:
+ ret
+ .size printf, .-printf
More information about the llvm-commits
mailing list