diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -212,6 +212,14 @@ Alignment = std::max(Alignment, STI->getTargetLowering()->getPrefFunctionAlignment()); + // -fsanitize=function and -fsanitize=kcfi instrument indirect function calls + // to load a type hash before the function label. Ensure functions are aligned + // by a least 4 to avoid unaligned access, which is especially important for + // -mno-unaligned-access. + if (F.hasMetadata(LLVMContext::MD_func_sanitize) || + F.getMetadata(LLVMContext::MD_kcfi_type)) + Alignment = std::max(Alignment, Align(4)); + if (AlignAllFunctions) Alignment = Align(1ULL << AlignAllFunctions); diff --git a/llvm/test/CodeGen/ARM/func-sanitizer.ll b/llvm/test/CodeGen/ARM/func-sanitizer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/func-sanitizer.ll @@ -0,0 +1,41 @@ +; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s + +; CHECK-LABEL: .globl nosan +; CHECK-NEXT: .p2align 1 +; CHECK-NEXT: .type nosan,%function +; CHECK-NEXT: .code 16 +; CHECK-NEXT: .thumb_func +; CHECK-NEXT: nosan: +define dso_local void @nosan() nounwind { + ret void +} + +;; The alignment is at least 4 to avoid unaligned type hash loads when this +;; instrumented function is indirectly called. +; CHECK-LABEL: .globl foo +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .type foo,%function +; CHECK-NEXT: .long 3238382334 +; CHECK-NEXT: .long 3170468932 +; CHECK-NEXT: .code 16 +; CHECK-NEXT: .thumb_func +; CHECK-NEXT: foo: +define dso_local void @foo() nounwind !func_sanitize !0 { + ret void +} + +;; If "align" is smaller than 4 (required alignment from !func_sanitize), use 4. +; CHECK-LABEL: .globl align2 +; CHECK-NEXT: .p2align 2 +define dso_local void @align2() nounwind align 2 !func_sanitize !0 { + ret void +} + +;; If "align" is larger than 4, use its value. +; CHECK-LABEL: .globl align8 +; CHECK-NEXT: .p2align 3 +define dso_local void @align8() nounwind align 8 !func_sanitize !0 { + ret void +} + +!0 = !{i32 -1056584962, i32 -1124498364} diff --git a/llvm/test/CodeGen/ARM/kcfi.ll b/llvm/test/CodeGen/ARM/kcfi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/kcfi.ll @@ -0,0 +1,28 @@ +; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s + +; CHECK-LABEL: .globl nosan +; CHECK-NEXT: .p2align 1 +; CHECK-NEXT: .type nosan,%function +; CHECK-NEXT: .code 16 +; CHECK-NEXT: .thumb_func +; CHECK-NEXT: nosan: +define dso_local void @nosan() nounwind { + ret void +} + +;; The alignment is at least 4 to avoid unaligned type hash loads when this +;; instrumented function is indirectly called. +; CHECK-LABEL: .globl f1 +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .type f1,%function +; CHECK-NEXT: .long 3170468932 +; CHECK-NEXT: .code 16 +; CHECK-NEXT: .thumb_func +; CHECK-NEXT: f1: +define void @f1(ptr noundef %x) !kcfi_type !1 { + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 4, !"kcfi", i32 1} +!1 = !{i32 -1124498364} diff --git a/llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll b/llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll --- a/llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll +++ b/llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll @@ -1,8 +1,10 @@ ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,NOC ; RUN: llc -mtriple=riscv64 -mattr=+c -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,C -; NOC: .p2align 2 -; C: .p2align 1 +;; The alignment is at least 4 to avoid unaligned type hash loads when this +;; instrumented function is indirectly called. +; CHECK-LABEL: .globl f1 +; CHECK: .p2align 2 ; CHECK-NOT: nop ; CHECK: .word 12345678 ; CHECK-LABEL: f1: @@ -12,6 +14,7 @@ ret void } +; CHECK-LABEL: .globl f2 ; NOC: .p2align 2 ; C: .p2align 1 ; CHECK-NOT: .word @@ -23,8 +26,8 @@ ret void } -; NOC: .p2align 2 -; C: .p2align 1 +; CHECK-LABEL: .globl f3 +; CHECK: .p2align 2 ; CHECK: .word 12345678 ; CHECK-COUNT-11: nop ; CHECK-LABEL: f3: @@ -35,6 +38,7 @@ ret void } +; CHECK-LABEL: .globl f4 ; NOC: .p2align 2 ; C: .p2align 1 ; CHECK-NOT: .word