[llvm-branch-commits] [llvm] [AArch64][PAC] Move emission of LR checks in tail calls to AsmPrinter (PR #110705)
Daniil Kovalev via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Oct 6 23:50:17 PDT 2024
kovdan01 wrote:
@atrosinenko Here is a reproducer IR code.
<details>
```
define void @_ZN7myshape4moveEv(ptr %this) #0 {
entry:
%0 = load ptr, ptr %this, align 8
%vtable = load ptr, ptr %0, align 8
%1 = ptrtoint ptr %0 to i64
%2 = tail call i64 @llvm.ptrauth.blend(i64 %1, i64 50297)
%3 = ptrtoint ptr %vtable to i64
%4 = tail call i64 @llvm.ptrauth.auth(i64 %3, i32 2, i64 %2)
%5 = inttoptr i64 %4 to ptr
%6 = load ptr, ptr %5, align 8
%7 = tail call i64 @llvm.ptrauth.blend(i64 %4, i64 36564)
tail call void %6(ptr noundef nonnull align 8 dereferenceable(8) %0) [ "ptrauth"(i32 0, i64 %7) ]
%r = getelementptr inbounds i8, ptr %this, i64 8
%8 = load ptr, ptr %r, align 8
%vtable2 = load ptr, ptr %8, align 8
%9 = ptrtoint ptr %8 to i64
%10 = tail call i64 @llvm.ptrauth.blend(i64 %9, i64 50297)
%11 = ptrtoint ptr %vtable2 to i64
%12 = tail call i64 @llvm.ptrauth.auth(i64 %11, i32 2, i64 %10)
%13 = inttoptr i64 %12 to ptr
%14 = load ptr, ptr %13, align 8
%15 = tail call i64 @llvm.ptrauth.blend(i64 %12, i64 36564)
tail call void %14(ptr noundef nonnull align 8 dereferenceable(8) %8) [ "ptrauth"(i32 0, i64 %15) ]
ret void
}
declare i64 @llvm.ptrauth.blend(i64, i64)
declare i64 @llvm.ptrauth.auth(i64, i32 immarg, i64)
attributes #0 = { "ptrauth-auth-traps" "ptrauth-calls" "ptrauth-returns" }
```
</details>
When compiled with `llc -O3 -mtriple aarch64-linux-gnu -mattr=+pauth`, the following assembly is generated. X16 register is clobbered during check inserted under `else if (Method == AuthCheckMethod::HighBitsNoTBI)`. The previous value (containing pointer for address discrimination) is not spilled before and not restored after that. So, the last `braa` instructio uses incorrect discrimination value in X16 register, which results in authentication failure and trying to pass control to an address with non-zero pac field, causing a segfault. nProbably, a different scratch register (e.g. X17) should be used for check sequence if X16 is already in use for address discrimination.
<details>
```
_ZN7myshape4moveEv: // @_ZN7myshape4moveEv
.cfi_startproc
// %bb.0: // %entry
.cfi_b_key_frame
pacibsp
stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
.cfi_negate_ra_state
.cfi_def_cfa_offset 16
.cfi_offset w19, -8
.cfi_offset w30, -16
mov x19, x0
ldr x0, [x0]
ldr x16, [x0]
mov x17, x0
movk x17, #50297, lsl #48
autda x16, x17
mov x17, x16
xpacd x17
cmp x16, x17
b.eq .Lauth_success_0
brk #0xc472
.Lauth_success_0:
ldr x9, [x16]
mov x8, x16
mov x17, x8
movk x17, #36564, lsl #48
blraa x9, x17
ldr x0, [x19, #8]
ldr x16, [x0]
mov x17, x0
movk x17, #50297, lsl #48
autda x16, x17
mov x17, x16
xpacd x17
cmp x16, x17
b.eq .Lauth_success_1
brk #0xc472
.Lauth_success_1:
ldr x1, [x16]
ldp x30, x19, [sp], #16 // 16-byte Folded Reload
autibsp
eor x16, x30, x30, lsl #1
tbz x16, #62, .Lauth_success_2
brk #0xc471
.Lauth_success_2:
movk x16, #36564, lsl #48
braa x1, x16
```
</details>
The IR corresponds to the following C++ code.
<details>
```
struct shape {
virtual void move() = 0;
};
struct line : public shape {
void move () override;
};
struct myshape {
line *l;
line *r;
void move();
};
void myshape::move() {
l->move();
r->move();
}
```
</details>
https://github.com/llvm/llvm-project/pull/110705
More information about the llvm-branch-commits
mailing list