219 lines · plain
1; RUN: llc -mattr=harden-sls-retbr,harden-sls-blr -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,HARDEN,HARDEN-COMDAT,ISBDSB,ISBDSBDAGISEL2; RUN: llc -mattr=harden-sls-retbr,harden-sls-blr,harden-sls-nocomdat -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,HARDEN,HARDEN-COMDAT-OFF,ISBDSB,ISBDSBDAGISEL3; RUN: llc -mattr=harden-sls-retbr,harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,HARDEN,SB,SBDAGISEL4; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr,harden-sls-blr -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,HARDEN,HARDEN-COMDAT,ISBDSB5; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,NOHARDEN6; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr,harden-sls-blr,harden-sls-nocomdat -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,HARDEN,HARDEN-COMDAT-OFF,ISBDSB7; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr,harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,HARDEN,SB8 9; Function Attrs: norecurse nounwind readnone10define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr {11entry:12 %cmp = icmp sgt i32 %a, 013 br i1 %cmp, label %if.then, label %if.else14 15if.then: ; preds = %entry16 %div = sdiv i32 %a, %b17 ret i32 %div18 19if.else: ; preds = %entry20 %div1 = sdiv i32 %b, %a21 ret i32 %div122; CHECK-LABEL: double_return:23; CHECK: {{ret$}}24; ISBDSB-NEXT: dsb sy25; ISBDSB-NEXT: isb26; SB-NEXT: {{ sb$}}27; CHECK: {{ret$}}28; ISBDSB-NEXT: dsb sy29; ISBDSB-NEXT: isb30; SB-NEXT: {{ sb$}}31; CHECK-NEXT: .Lfunc_end32}33 34@__const.indirect_branch.ptr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirect_branch, %return), ptr blockaddress(@indirect_branch, %l2)], align 835 36; Function Attrs: norecurse nounwind readnone37define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) {38; CHECK-LABEL: indirect_branch:39entry:40 %idxprom = sext i32 %i to i6441 %arrayidx = getelementptr inbounds [2 x ptr], ptr @__const.indirect_branch.ptr, i64 0, i64 %idxprom42 %0 = load ptr, ptr %arrayidx, align 843 indirectbr ptr %0, [label %return, label %l2]44; CHECK: br x45; ISBDSB-NEXT: dsb sy46; ISBDSB-NEXT: isb47; SB-NEXT: {{ sb$}}48 49l2: ; preds = %entry50 br label %return51; CHECK: {{ret$}}52; ISBDSB-NEXT: dsb sy53; ISBDSB-NEXT: isb54; SB-NEXT: {{ sb$}}55 56return: ; preds = %entry, %l257 %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ]58 ret i32 %retval.059; CHECK: {{ret$}}60; ISBDSB-NEXT: dsb sy61; ISBDSB-NEXT: isb62; SB-NEXT: {{ sb$}}63; CHECK-NEXT: .Lfunc_end64}65 66; Check that RETAA and RETAB instructions are also protected as expected.67define dso_local i32 @ret_aa(i32 returned %a) local_unnamed_addr "target-features"="+neon,+v8.3a" "sign-return-address"="all" "sign-return-address-key"="a_key" {68entry:69; CHECK-LABEL: ret_aa:70; CHECK: {{ retaa$}}71; ISBDSB-NEXT: dsb sy72; ISBDSB-NEXT: isb73; SB-NEXT: {{ sb$}}74; CHECK-NEXT: .Lfunc_end75 ret i32 %a76}77 78define dso_local i32 @ret_ab(i32 returned %a) local_unnamed_addr "target-features"="+neon,+v8.3a" "sign-return-address"="all" "sign-return-address-key"="b_key" {79entry:80; CHECK-LABEL: ret_ab:81; CHECK: {{ retab$}}82; ISBDSB-NEXT: dsb sy83; ISBDSB-NEXT: isb84; SB-NEXT: {{ sb$}}85; CHECK-NEXT: .Lfunc_end86 ret i32 %a87}88 89define i32 @asmgoto() {90entry:91; CHECK-LABEL: asmgoto:92 callbr void asm sideeffect "B $0", "!i"()93 to label %asm.fallthrough [label %d]94 ; The asm goto above produces a direct branch:95; CHECK: //APP96; CHECK-NEXT: {{^[ \t]+b }}97; CHECK-NEXT: //NO_APP98 ; For direct branches, no mitigation is needed.99; ISDDSB-NOT: dsb sy100; SB-NOT: {{ sb$}}101 102asm.fallthrough: ; preds = %entry103 ret i32 0104; CHECK: {{ret$}}105; ISBDSB-NEXT: dsb sy106; ISBDSB-NEXT: isb107; SB-NEXT: {{ sb$}}108 109d: ; preds = %asm.fallthrough, %entry110 ret i32 1111; CHECK: {{ret$}}112; ISBDSB-NEXT: dsb sy113; ISBDSB-NEXT: isb114; SB-NEXT: {{ sb$}}115; CHECK-NEXT: .Lfunc_end116}117 118define dso_local i32 @indirect_call(119ptr nocapture %f1, ptr nocapture %f2) {120entry:121; CHECK-LABEL: indirect_call:122 %call = tail call i32 %f1()123; HARDEN: bl {{__llvm_slsblr_thunk_x[0-9]+$}}124 %call2 = tail call i32 %f2()125; HARDEN: bl {{__llvm_slsblr_thunk_x[0-9]+$}}126 %add = add nsw i32 %call2, %call127 ret i32 %add128; CHECK: .Lfunc_end129}130 131; verify calling through a function pointer.132@a = dso_local local_unnamed_addr global ptr null, align 8133@b = dso_local local_unnamed_addr global i32 0, align 4134define dso_local void @indirect_call_global() local_unnamed_addr {135; CHECK-LABEL: indirect_call_global:136entry:137 %0 = load ptr, ptr @a, align 8138 %call = tail call i32 %0() nounwind139; HARDEN: bl {{__llvm_slsblr_thunk_x[0-9]+$}}140 store i32 %call, ptr @b, align 4141 ret void142; CHECK: .Lfunc_end143}144 145; Verify that neither x16 nor x17 are used when the BLR mitigation is enabled,146; as a linker is allowed to clobber x16 or x17 on calls, which would break the147; correct execution of the code sequence produced by the mitigation. The below148; test attempts to force *%f into x16 using inline assembly.149define i64 @check_x16(ptr nocapture readonly %fp, ptr nocapture readonly %fp2) "target-features"="+neon,+reserve-x10,+reserve-x11,+reserve-x12,+reserve-x13,+reserve-x14,+reserve-x15,+reserve-x18,+reserve-x20,+reserve-x21,+reserve-x22,+reserve-x23,+reserve-x24,+reserve-x25,+reserve-x26,+reserve-x27,+reserve-x28,+reserve-x30,+reserve-x9" {150entry:151; CHECK-LABEL: check_x16:152 %f = load ptr, ptr %fp, align 8153 %x16_f = tail call ptr asm "add $0, $1, #0", "={x16},{x16}"(ptr %f) nounwind154 %call1 = call i64 %x16_f()155; NOHARDEN: blr x16156; ISBDSB-NOT: bl __llvm_slsblr_thunk_x16157; SB-NOT: bl __llvm_slsblr_thunk_x16158; CHECK159 ret i64 %call1160; CHECK: .Lfunc_end161}162 163; Verify that the transformation works correctly for x29 when it is not164; reserved to be used as a frame pointer.165; Since this is sensitive to register allocation choices, only check this with166; DAGIsel to avoid too much accidental breaking of this test that is a bit167; brittle.168define i64 @check_x29(ptr nocapture readonly %fp,169 ptr nocapture readonly %fp2,170 ptr nocapture readonly %fp3)171"target-features"="+neon,+reserve-x10,+reserve-x11,+reserve-x12,+reserve-x13,+reserve-x14,+reserve-x15,+reserve-x18,+reserve-x20,+reserve-x21,+reserve-x22,+reserve-x23,+reserve-x24,+reserve-x25,+reserve-x26,+reserve-x27,+reserve-x28,+reserve-x9"172"frame-pointer"="none"173{174entry:175; CHECK-LABEL: check_x29:176 %0 = load ptr, ptr %fp, align 8177 %1 = load ptr, ptr %fp2, align 8178 %2 = load ptr, ptr %fp2, align 8179 %3 = load ptr, ptr %fp3, align 8180 %4 = load ptr, ptr %fp3, align 8181 %5 = load ptr, ptr %fp, align 8182 %call = call i64 %0(ptr %1, ptr %3, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0)183 %call1 = call i64 %2(ptr %1, ptr %3, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0)184; NOHARDEN: blr x29185; ISBDSBDAGISEL: bl __llvm_slsblr_thunk_x29186; SBDAGISEL: bl __llvm_slsblr_thunk_x29187; CHECK188 %call2 = call i64 %4(ptr %1, ptr %5, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0)189 %add = add nsw i64 %call1, %call190 %add1 = add nsw i64 %call2, %add191 ret i64 %add1192; CHECK: .Lfunc_end193}194 195; HARDEN-label: __llvm_slsblr_thunk_x0:196; HARDEN: mov x16, x0197; HARDEN: br x16198; ISBDSB-NEXT: dsb sy199; ISBDSB-NEXT: isb200; SB-NEXT: dsb sy201; SB-NEXT: isb202; HARDEN-NEXT: .Lfunc_end203; HARDEN-COMDAT: .section .text.__llvm_slsblr_thunk_x19204; HARDEN-COMDAT: .hidden __llvm_slsblr_thunk_x19205; HARDEN-COMDAT: .weak __llvm_slsblr_thunk_x19206; HARDEN-COMDAT: .type __llvm_slsblr_thunk_x19,@function207; HARDEN-COMDAT-OFF-NOT: .section .text.__llvm_slsblr_thunk_x19208; HARDEN-COMDAT-OFF-NOT: .hidden __llvm_slsblr_thunk_x19209; HARDEN-COMDAT-OFF-NOT: .weak __llvm_slsblr_thunk_x19210; HARDEN-COMDAT-OFF: .type __llvm_slsblr_thunk_x19,@function211; HARDEN-label: __llvm_slsblr_thunk_x19:212; HARDEN: mov x16, x19213; HARDEN: br x16214; ISBDSB-NEXT: dsb sy215; ISBDSB-NEXT: isb216; SB-NEXT: dsb sy217; SB-NEXT: isb218; HARDEN-NEXT: .Lfunc_end219