
This also adds support for auth stubs on MachO using __DATA,__auth_ptr. Some of the machinery for auth stubs is already implemented; this generalizes that a bit to support MachO, and moves some of the shared logic into MMIImpls. In particular, this originally had an AuthStubInfo struct, but we no longer need it beyond a single MCExpr. So this provides variants of the symbol stub helper type declarations and functions for "expr stubs", where a stub points at an arbitrary MCExpr, rather than a simple MCSymbol (and a bit).
381 lines
12 KiB
LLVM
381 lines
12 KiB
LLVM
; RUN: rm -rf %t && split-file %s %t && cd %t
|
|
|
|
;--- err1.ll
|
|
|
|
; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s
|
|
; RUN: not --crash llc < err1.ll -mtriple arm64-apple-ios -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s
|
|
|
|
@g = external global i32
|
|
|
|
define ptr @foo() {
|
|
; ERR1: LLVM ERROR: key in ptrauth global out of range [0, 3]
|
|
ret ptr ptrauth (ptr @g, i32 4)
|
|
}
|
|
|
|
;--- err2.ll
|
|
|
|
; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s
|
|
; RUN: not --crash llc < err2.ll -mtriple arm64-apple-ios -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s
|
|
|
|
@g = external global i32
|
|
|
|
define ptr @foo() {
|
|
; ERR2: LLVM ERROR: constant discriminator in ptrauth global out of range [0, 0xffff]
|
|
ret ptr ptrauth (ptr @g, i32 2, i64 65536)
|
|
}
|
|
|
|
;--- err3.ll
|
|
|
|
; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s
|
|
; RUN: not --crash llc < err3.ll -mtriple arm64-apple-ios -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s
|
|
|
|
@g_weak = extern_weak global i32
|
|
|
|
define ptr @foo() {
|
|
; ERR3: LLVM ERROR: unsupported non-zero offset in weak ptrauth global reference
|
|
ret ptr ptrauth (ptr getelementptr (i8, ptr @g_weak, i64 16), i32 2, i64 42)
|
|
}
|
|
|
|
;--- err4.ll
|
|
|
|
; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s
|
|
; RUN: not --crash llc < err4.ll -mtriple arm64-apple-ios -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s
|
|
|
|
@g_weak = extern_weak global i32
|
|
@g_weak.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g_weak, i32 2, i64 42, ptr @g_weak.ref.da.42.addr)
|
|
|
|
define ptr @foo() {
|
|
; ERR4: LLVM ERROR: unsupported weak addr-div ptrauth global
|
|
ret ptr ptrauth (ptr @g_weak, i32 0, i64 42, ptr @g_weak.ref.da.42.addr)
|
|
}
|
|
|
|
;--- err5.ll
|
|
|
|
; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \
|
|
; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR5 %s
|
|
|
|
@g = external global i32
|
|
|
|
define ptr @foo() {
|
|
; ERR5: LLVM ERROR: ptrauth global lowering only supported on MachO/ELF
|
|
ret ptr ptrauth (ptr @g, i32 0)
|
|
}
|
|
|
|
;--- ok.ll
|
|
|
|
; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
|
|
; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=ELF
|
|
; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \
|
|
; RUN: -verify-machineinstrs -filetype=obj
|
|
|
|
; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \
|
|
; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=MACHO
|
|
; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \
|
|
; RUN: -verify-machineinstrs -filetype=obj
|
|
|
|
@g = external global i32
|
|
@g_weak = extern_weak global i32
|
|
@g_strong_def = dso_local constant i32 42
|
|
|
|
define ptr @test_global_zero_disc() {
|
|
; ELF-LABEL: test_global_zero_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: paciza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_zero_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: paciza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g, i32 0)
|
|
}
|
|
|
|
define ptr @test_global_offset_zero_disc() {
|
|
; ELF-LABEL: test_global_offset_zero_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: add x16, x16, #16
|
|
; ELF-NEXT: pacdza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_offset_zero_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: add x16, x16, #16
|
|
; MACHO-NEXT: pacdza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2)
|
|
}
|
|
|
|
define ptr @test_global_neg_offset_zero_disc() {
|
|
; ELF-LABEL: test_global_neg_offset_zero_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: sub x16, x16, #576
|
|
; ELF-NEXT: sub x16, x16, #30, lsl #12
|
|
; ELF-NEXT: pacdza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_neg_offset_zero_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: sub x16, x16, #576
|
|
; MACHO-NEXT: sub x16, x16, #30, lsl #12
|
|
; MACHO-NEXT: pacdza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2)
|
|
}
|
|
|
|
define ptr @test_global_big_offset_zero_disc() {
|
|
; ELF-LABEL: test_global_big_offset_zero_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: mov x17, #1
|
|
; ELF-NEXT: movk x17, #32769, lsl #16
|
|
; ELF-NEXT: add x16, x16, x17
|
|
; ELF-NEXT: pacdza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_big_offset_zero_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: mov x17, #1
|
|
; MACHO-NEXT: movk x17, #32769, lsl #16
|
|
; MACHO-NEXT: add x16, x16, x17
|
|
; MACHO-NEXT: pacdza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2)
|
|
}
|
|
|
|
define ptr @test_global_big_neg_offset_zero_disc() {
|
|
; ELF-LABEL: test_global_big_neg_offset_zero_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: mov x17, #-52501
|
|
; ELF-NEXT: movk x17, #63652, lsl #16
|
|
; ELF-NEXT: add x16, x16, x17
|
|
; ELF-NEXT: pacdza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_big_neg_offset_zero_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: mov x17, #-52501
|
|
; MACHO-NEXT: movk x17, #63652, lsl #16
|
|
; MACHO-NEXT: add x16, x16, x17
|
|
; MACHO-NEXT: pacdza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2)
|
|
}
|
|
|
|
define ptr @test_global_huge_neg_offset_zero_disc() {
|
|
; ELF-LABEL: test_global_huge_neg_offset_zero_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: mov x17, #-65536
|
|
; ELF-NEXT: movk x17, #0, lsl #16
|
|
; ELF-NEXT: movk x17, #0, lsl #32
|
|
; ELF-NEXT: movk x17, #32768, lsl #48
|
|
; ELF-NEXT: add x16, x16, x17
|
|
; ELF-NEXT: pacdza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: mov x17, #-65536
|
|
; MACHO-NEXT: movk x17, #0, lsl #16
|
|
; MACHO-NEXT: movk x17, #0, lsl #32
|
|
; MACHO-NEXT: movk x17, #32768, lsl #48
|
|
; MACHO-NEXT: add x16, x16, x17
|
|
; MACHO-NEXT: pacdza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2)
|
|
}
|
|
|
|
define ptr @test_global_disc() {
|
|
; ELF-LABEL: test_global_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: mov x17, #42 // =0x2a
|
|
; ELF-NEXT: pacia x16, x17
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: mov x17, #42 ; =0x2a
|
|
; MACHO-NEXT: pacia x16, x17
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g, i32 0, i64 42)
|
|
}
|
|
|
|
@g.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr)
|
|
|
|
define ptr @test_global_addr_disc() {
|
|
; ELF-LABEL: test_global_addr_disc:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x8, g.ref.da.42.addr
|
|
; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: mov x17, x8
|
|
; ELF-NEXT: movk x17, #42, lsl #48
|
|
; ELF-NEXT: pacda x16, x17
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_addr_disc:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: Lloh{{.*}}:
|
|
; MACHO-NEXT: adrp x8, _g.ref.da.42.addr@PAGE
|
|
; MACHO-NEXT: Lloh{{.*}}:
|
|
; MACHO-NEXT: add x8, x8, _g.ref.da.42.addr@PAGEOFF
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: mov x17, x8
|
|
; MACHO-NEXT: movk x17, #42, lsl #48
|
|
; MACHO-NEXT: pacda x16, x17
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr)
|
|
}
|
|
|
|
define ptr @test_global_process_specific() {
|
|
; ELF-LABEL: test_global_process_specific:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, :got:g
|
|
; ELF-NEXT: ldr x16, [x16, :got_lo12:g]
|
|
; ELF-NEXT: pacizb x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_process_specific:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g@GOTPAGE
|
|
; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF]
|
|
; MACHO-NEXT: pacizb x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g, i32 1)
|
|
}
|
|
|
|
; Non-external symbols don't need to be accessed through the GOT.
|
|
|
|
define ptr @test_global_strong_def() {
|
|
; ELF-LABEL: test_global_strong_def:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x16, g_strong_def
|
|
; ELF-NEXT: add x16, x16, :lo12:g_strong_def
|
|
; ELF-NEXT: pacdza x16
|
|
; ELF-NEXT: mov x0, x16
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_strong_def:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x16, _g_strong_def@PAGE
|
|
; MACHO-NEXT: add x16, x16, _g_strong_def@PAGEOFF
|
|
; MACHO-NEXT: pacdza x16
|
|
; MACHO-NEXT: mov x0, x16
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g_strong_def, i32 2)
|
|
}
|
|
|
|
; weak symbols can't be assumed to be non-nil. Use $auth_ptr$ stub slot always.
|
|
; The alternative is to emit a null-check here, but that'd be redundant with
|
|
; whatever null-check follows in user code.
|
|
|
|
define ptr @test_global_weak() {
|
|
; ELF-LABEL: test_global_weak:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x0, g_weak$auth_ptr$ia$42
|
|
; ELF-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42]
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_weak:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x0, l_g_weak$auth_ptr$ia$42@PAGE
|
|
; MACHO-NEXT: ldr x0, [x0, l_g_weak$auth_ptr$ia$42@PAGEOFF]
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g_weak, i32 0, i64 42)
|
|
}
|
|
|
|
; Test another weak symbol to check that stubs are emitted in a stable order.
|
|
|
|
@g_weak_2 = extern_weak global i32
|
|
|
|
define ptr @test_global_weak_2() {
|
|
; ELF-LABEL: test_global_weak_2:
|
|
; ELF: // %bb.0:
|
|
; ELF-NEXT: adrp x0, g_weak_2$auth_ptr$ia$42
|
|
; ELF-NEXT: ldr x0, [x0, :lo12:g_weak_2$auth_ptr$ia$42]
|
|
; ELF-NEXT: ret
|
|
|
|
; MACHO-LABEL: _test_global_weak_2:
|
|
; MACHO: ; %bb.0:
|
|
; MACHO-NEXT: adrp x0, l_g_weak_2$auth_ptr$ia$42@PAGE
|
|
; MACHO-NEXT: ldr x0, [x0, l_g_weak_2$auth_ptr$ia$42@PAGEOFF]
|
|
; MACHO-NEXT: ret
|
|
|
|
ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42)
|
|
}
|
|
|
|
; ELF-LABEL: g_weak$auth_ptr$ia$42:
|
|
; ELF-NEXT: .xword g_weak@AUTH(ia,42)
|
|
; ELF-LABEL: g_weak_2$auth_ptr$ia$42:
|
|
; ELF-NEXT: .xword g_weak_2@AUTH(ia,42)
|
|
|
|
; MACHO-LABEL: l_g_weak$auth_ptr$ia$42:
|
|
; MACHO-NEXT: .quad _g_weak@AUTH(ia,42)
|
|
; MACHO-LABEL: l_g_weak_2$auth_ptr$ia$42:
|
|
; MACHO-NEXT: .quad _g_weak_2@AUTH(ia,42)
|