[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