[lld] 92fbb60 - [lld][AArch64] Add BTI landing pad to PLT entries when the symbol is exported.
Daniel Kiss via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 29 13:17:22 PDT 2023
Author: Daniel Kiss
Date: 2023-06-29T22:17:17+02:00
New Revision: 92fbb602f3b635110417e40e2f774b31798b0b1d
URL: https://github.com/llvm/llvm-project/commit/92fbb602f3b635110417e40e2f774b31798b0b1d
DIFF: https://github.com/llvm/llvm-project/commit/92fbb602f3b635110417e40e2f774b31798b0b1d.diff
LOG: [lld][AArch64] Add BTI landing pad to PLT entries when the symbol is exported.
With relative vtables the caller jumps directly to the plt entries in the shared object,
therefore landing pad is need for these entries.
Reproducer:
main.cpp
```
#include "v.hpp"
int main() {
A* a = new B();
a->do_something2();
return 0;
}
```
v.hpp
```
struct A {
virtual void do_something() = 0;
virtual void do_something2();
};
struct B : public A {
void do_something() override;
void do_something2() override;
};
```
v.cpp
```
#include "v.hpp"
void A::do_something2() { }
void B::do_something() { }
void B::do_something2() { }
```
```
CC="clang++ --target=aarch64-unknown-linux-gnu -fuse-ld=lld -mbranch-protection=bti"
F=-fexperimental-relative-c++-abi-vtables
${=CC} $F -shared v.cpp -o v.so -z force-bti
${=CC} $F main.cpp -L./ v.so -Wl,-rpath=. -z force-bti
qemu-aarch64-static -L /usr/aarch64-linux-gnu -cpu max ./a.out
```
For v.so, the regular vtable entry is relocated by an R_AARCH64_ABS64 relocation referencing _ZN1B13do_something2Ev.
```
_ZTV1B:
.xword _ZN1B13do_something2Ev
```
Using relative vtable entry for a DSO has a downside of creating many PLT entries and making their addresses escape.
The relative vtable entry references a PLT entry _ZN1B13do_something2Ev at plt.
```
.L_ZTV1A.local:
.word (_ZN1A13do_something2Ev at PLT-.L_ZTV1A.local)-8
```
fixes: #63580
Reviewed By: peter.smith, MaskRay
Differential Revision: https://reviews.llvm.org/D153264
Added:
Modified:
lld/ELF/Arch/AArch64.cpp
lld/test/ELF/aarch64-feature-bti.s
Removed:
################################################################################
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 0301508fea2398..c83a159e3f0530 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -136,7 +136,9 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
case R_AARCH64_CONDBR19:
case R_AARCH64_JUMP26:
case R_AARCH64_TSTBR14:
+ return R_PLT_PC;
case R_AARCH64_PLT32:
+ const_cast<Symbol &>(s).thunkAccessed = true;
return R_PLT_PC;
case R_AARCH64_PREL16:
case R_AARCH64_PREL32:
@@ -910,8 +912,9 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
// NEEDS_COPY indicates a non-ifunc canonical PLT entry whose address may
// escape to shared objects. isInIplt indicates a non-preemptible ifunc. Its
- // address may escape if referenced by a direct relocation. The condition is
- // conservative.
+ // address may escape if referenced by a direct relocation. If relative
+ // vtables are used then if the vtable is in a shared object the offsets will
+ // be to the PLT entry. The condition is conservative.
bool hasBti = btiHeader &&
(sym.hasFlag(NEEDS_COPY) || sym.isInIplt || sym.thunkAccessed);
if (hasBti) {
diff --git a/lld/test/ELF/aarch64-feature-bti.s b/lld/test/ELF/aarch64-feature-bti.s
index f364660351f28f..67291ad8670d97 100644
--- a/lld/test/ELF/aarch64-feature-bti.s
+++ b/lld/test/ELF/aarch64-feature-bti.s
@@ -1,6 +1,7 @@
# REQUIRES: aarch64
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu --defsym CANONICAL_PLT=1 %s -o %tcanon.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu --defsym RELVTABLE_PLT=1 %s -o %trelvtable.o
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-bti1.s -o %t1.o
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-bti.s -o %t3.o
@@ -154,6 +155,42 @@
# PIE-NEXT: nop
# PIE-NEXT: nop
+## We expect the same for R_AARCH64_PLT32, as the address of an plt entry escapes
+# RUN: ld.lld --shared %trelvtable.o -o %trelv.exe
+# RUN: llvm-readelf -n %trelv.exe | FileCheck --check-prefix=BTIPROP %s
+# RUN: llvm-readelf --dynamic-table -n %trelv.exe | FileCheck --check-prefix=BTIPROP %s
+# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+bti --no-show-raw-insn %trelv.exe | FileCheck --check-prefix=RELV %s
+
+# RELV: Disassembly of section .text:
+# RELV-LABEL: <func1>:
+# RELV-NEXT: 10380: bl 0x103b0 <func2 at plt>
+# RELV-NEXT: bl 0x103c8 <funcRelVtable at plt>
+# RELV-NEXT: ret
+# RELV: Disassembly of section .plt:
+# RELV-LABEL: <.plt>:
+# RELV-NEXT: 10390: bti c
+# RELV-NEXT: stp x16, x30, [sp, #-16]!
+# RELV-NEXT: adrp x16, 0x30000
+# RELV-NEXT: ldr x17, [x16, #1200]
+# RELV-NEXT: add x16, x16, #1200
+# RELV-NEXT: br x17
+# RELV-NEXT: nop
+# RELV-NEXT: nop
+# RELV-LABEL: <func2 at plt>:
+# RELV-NEXT: 103b0: adrp x16, 0x30000
+# RELV-NEXT: ldr x17, [x16, #1208]
+# RELV-NEXT: add x16, x16, #1208
+# RELV-NEXT: br x17
+# RELV-NEXT: nop
+# RELV-NEXT: nop
+# RELV-LABEL: <funcRelVtable at plt>:
+# RELV-NEXT: 103c8: bti c
+# RELV-NEXT: adrp x16, 0x30000 <_DYNAMIC+0xfc20>
+# RELV-NEXT: ldr x17, [x16, #1216]
+# RELV-NEXT: add x16, x16, #1216
+# RELV-NEXT: br x17
+# RELV-NEXT: nop
+
## Build and executable with not all relocatable inputs having the BTI
## .note.property, expect no bti c and no .note.gnu.property entry
@@ -241,5 +278,13 @@ func1:
add x0, x0, :lo12:func2
.else
bl func2
+.endif
+.ifdef RELVTABLE_PLT
+ bl funcRelVtable
.endif
ret
+
+.ifdef RELVTABLE_PLT
+// R_AARCH64_PLT32
+.word funcRelVtable at PLT - .
+.endif
More information about the llvm-commits
mailing list