Skip to content

Commit 92fbb60

Browse files
[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@plt. ``` .L_ZTV1A.local: .word ([email protected]_ZTV1A.local)-8 ``` fixes: llvm#63580 Reviewed By: peter.smith, MaskRay Differential Revision: https://reviews.llvm.org/D153264
1 parent fcdc3c9 commit 92fbb60

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

lld/ELF/Arch/AArch64.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
136136
case R_AARCH64_CONDBR19:
137137
case R_AARCH64_JUMP26:
138138
case R_AARCH64_TSTBR14:
139+
return R_PLT_PC;
139140
case R_AARCH64_PLT32:
141+
const_cast<Symbol &>(s).thunkAccessed = true;
140142
return R_PLT_PC;
141143
case R_AARCH64_PREL16:
142144
case R_AARCH64_PREL32:
@@ -910,8 +912,9 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
910912

911913
// NEEDS_COPY indicates a non-ifunc canonical PLT entry whose address may
912914
// escape to shared objects. isInIplt indicates a non-preemptible ifunc. Its
913-
// address may escape if referenced by a direct relocation. The condition is
914-
// conservative.
915+
// address may escape if referenced by a direct relocation. If relative
916+
// vtables are used then if the vtable is in a shared object the offsets will
917+
// be to the PLT entry. The condition is conservative.
915918
bool hasBti = btiHeader &&
916919
(sym.hasFlag(NEEDS_COPY) || sym.isInIplt || sym.thunkAccessed);
917920
if (hasBti) {

lld/test/ELF/aarch64-feature-bti.s

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# REQUIRES: aarch64
22
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
33
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu --defsym CANONICAL_PLT=1 %s -o %tcanon.o
4+
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu --defsym RELVTABLE_PLT=1 %s -o %trelvtable.o
45
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-bti1.s -o %t1.o
56
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o
67
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-bti.s -o %t3.o
@@ -154,6 +155,42 @@
154155
# PIE-NEXT: nop
155156
# PIE-NEXT: nop
156157

158+
## We expect the same for R_AARCH64_PLT32, as the address of an plt entry escapes
159+
# RUN: ld.lld --shared %trelvtable.o -o %trelv.exe
160+
# RUN: llvm-readelf -n %trelv.exe | FileCheck --check-prefix=BTIPROP %s
161+
# RUN: llvm-readelf --dynamic-table -n %trelv.exe | FileCheck --check-prefix=BTIPROP %s
162+
# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+bti --no-show-raw-insn %trelv.exe | FileCheck --check-prefix=RELV %s
163+
164+
# RELV: Disassembly of section .text:
165+
# RELV-LABEL: <func1>:
166+
# RELV-NEXT: 10380: bl 0x103b0 <func2@plt>
167+
# RELV-NEXT: bl 0x103c8 <funcRelVtable@plt>
168+
# RELV-NEXT: ret
169+
# RELV: Disassembly of section .plt:
170+
# RELV-LABEL: <.plt>:
171+
# RELV-NEXT: 10390: bti c
172+
# RELV-NEXT: stp x16, x30, [sp, #-16]!
173+
# RELV-NEXT: adrp x16, 0x30000
174+
# RELV-NEXT: ldr x17, [x16, #1200]
175+
# RELV-NEXT: add x16, x16, #1200
176+
# RELV-NEXT: br x17
177+
# RELV-NEXT: nop
178+
# RELV-NEXT: nop
179+
# RELV-LABEL: <func2@plt>:
180+
# RELV-NEXT: 103b0: adrp x16, 0x30000
181+
# RELV-NEXT: ldr x17, [x16, #1208]
182+
# RELV-NEXT: add x16, x16, #1208
183+
# RELV-NEXT: br x17
184+
# RELV-NEXT: nop
185+
# RELV-NEXT: nop
186+
# RELV-LABEL: <funcRelVtable@plt>:
187+
# RELV-NEXT: 103c8: bti c
188+
# RELV-NEXT: adrp x16, 0x30000 <_DYNAMIC+0xfc20>
189+
# RELV-NEXT: ldr x17, [x16, #1216]
190+
# RELV-NEXT: add x16, x16, #1216
191+
# RELV-NEXT: br x17
192+
# RELV-NEXT: nop
193+
157194
## Build and executable with not all relocatable inputs having the BTI
158195
## .note.property, expect no bti c and no .note.gnu.property entry
159196

@@ -241,5 +278,13 @@ func1:
241278
add x0, x0, :lo12:func2
242279
.else
243280
bl func2
281+
.endif
282+
.ifdef RELVTABLE_PLT
283+
bl funcRelVtable
244284
.endif
245285
ret
286+
287+
.ifdef RELVTABLE_PLT
288+
// R_AARCH64_PLT32
289+
.word funcRelVtable@PLT - .
290+
.endif

0 commit comments

Comments
 (0)