1; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,ISBDSB -dump-input-context=100 2; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,ISBDSB -dump-input-context=100 3; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,SB -dump-input-context=100 4; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,SB -dump-input-context=100 5; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,ISBDSB -dump-input-context=100 6; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,ISBDSB -dump-input-context=100 7; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,SB -dump-input-context=100 8; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,SB -dump-input-context=100 9; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,NOHARDENARM -dump-input-context=100 10; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,NOHARDENTHUMB 11; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,ISBDSB 12; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,ISBDSB 13; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-nocomdat -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,ISBDSB 14; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-nocomdat -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,ISBDSB 15; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB 16; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,SB 17; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT,ISBDSB 18; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT,ISBDSB 19; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,HARDEN-COMDAT-OFF,ISBDSB 20; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=harden-sls-nocomdat -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,HARDEN-COMDAT-OFF,ISBDSB 21; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB 22; RUN: llc -fast-isel -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,SB 23 24; Function Attrs: norecurse nounwind readnone 25define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr { 26entry: 27 %cmp = icmp sgt i32 %a, 0 28 br i1 %cmp, label %if.then, label %if.else 29 30if.then: ; preds = %entry 31 ; Make a very easy, very likely to predicate return (BX LR), to test that 32 ; it will not get predicated when sls-hardening is enabled. 33 %mul = mul i32 %b, %a 34 ret i32 %mul 35; CHECK-LABEL: double_return: 36; HARDEN: {{bx lr$}} 37; NOHARDENARM: {{bxgt lr$}} 38; NOHARDENTHUMB: {{bxgt lr$}} 39; ISBDSB-NEXT: dsb sy 40; ISBDSB-NEXT: isb 41; SB-NEXT: {{ sb$}} 42 43if.else: ; preds = %entry 44 %div3 = sdiv i32 %a, %b 45 %div2 = sdiv i32 %a, %div3 46 %div1 = sdiv i32 %a, %div2 47 ret i32 %div1 48 49; CHECK: {{bx lr$}} 50; ISBDSB-NEXT: dsb sy 51; ISBDSB-NEXT: isb 52; SB-NEXT: {{ sb$}} 53; CHECK-NEXT: .Lfunc_end 54} 55 56@__const.indirect_branch.ptr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirect_branch, %return), ptr blockaddress(@indirect_branch, %l2)], align 8 57 58; Function Attrs: norecurse nounwind readnone 59define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) { 60; CHECK-LABEL: indirect_branch: 61entry: 62 %idxprom = sext i32 %i to i64 63 %arrayidx = getelementptr inbounds [2 x ptr], ptr @__const.indirect_branch.ptr, i64 0, i64 %idxprom 64 %0 = load ptr, ptr %arrayidx, align 8 65 indirectbr ptr %0, [label %return, label %l2] 66; ARM: bx r0 67; THUMB: mov pc, r0 68; ISBDSB-NEXT: dsb sy 69; ISBDSB-NEXT: isb 70; SB-NEXT: {{ sb$}} 71 72l2: ; preds = %entry 73 br label %return 74; CHECK: {{bx lr$}} 75; ISBDSB-NEXT: dsb sy 76; ISBDSB-NEXT: isb 77; SB-NEXT: {{ sb$}} 78 79return: ; preds = %entry, %l2 80 %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ] 81 ret i32 %retval.0 82; CHECK: {{bx lr$}} 83; ISBDSB-NEXT: dsb sy 84; ISBDSB-NEXT: isb 85; SB-NEXT: {{ sb$}} 86; CHECK-NEXT: .Lfunc_end 87} 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: @APP 96; CHECK-NEXT: {{^[ \t]+b }} 97; CHECK-NEXT: @NO_APP 98 ; For direct branches, no mitigation is needed. 99; ISDDSB-NOT: dsb sy 100; SB-NOT: {{ sb$}} 101 102asm.fallthrough: ; preds = %entry 103 ret i32 0 104; CHECK: {{bx lr$}} 105; ISBDSB-NEXT: dsb sy 106; ISBDSB-NEXT: isb 107; SB-NEXT: {{ sb$}} 108 109d: ; preds = %asm.fallthrough, %entry 110 ret i32 1 111; CHECK: {{bx lr$}} 112; ISBDSB-NEXT: dsb sy 113; ISBDSB-NEXT: isb 114; SB-NEXT: {{ sb$}} 115; CHECK-NEXT: .Lfunc_end 116} 117 118; Check that indirect branches produced through switch jump tables are also 119; hardened: 120define dso_local i32 @jumptable(i32 %a, i32 %b) { 121; CHECK-LABEL: jumptable: 122entry: 123 switch i32 %b, label %sw.epilog [ 124 i32 0, label %sw.bb 125 i32 1, label %sw.bb1 126 i32 3, label %sw.bb3 127 i32 4, label %sw.bb5 128 ] 129; ARM: ldr pc, [{{r[0-9]}}, {{r[0-9]}}, lsl #2] 130; NOHARDENTHUMB: tbb [pc, {{r[0-9]}}] 131; HARDENTHUMB: mov pc, {{r[0-9]}} 132; ISBDSB-NEXT: dsb sy 133; ISBDSB-NEXT: isb 134; SB-NEXT: {{ sb$}} 135 136 137sw.bb: ; preds = %entry 138 %add = shl nsw i32 %a, 1 139 br label %sw.bb1 140 141sw.bb1: ; preds = %entry, %sw.bb 142 %a.addr.0 = phi i32 [ %a, %entry ], [ %add, %sw.bb ] 143 %add2 = shl nsw i32 %a.addr.0, 1 144 br label %sw.bb3 145 146sw.bb3: ; preds = %entry, %sw.bb1 147 %a.addr.1 = phi i32 [ %a, %entry ], [ %add2, %sw.bb1 ] 148 %add4 = shl nsw i32 %a.addr.1, 1 149 br label %sw.bb5 150 151sw.bb5: ; preds = %entry, %sw.bb3 152 %a.addr.2 = phi i32 [ %a, %entry ], [ %add4, %sw.bb3 ] 153 %add6 = shl nsw i32 %a.addr.2, 1 154 br label %sw.epilog 155 156sw.epilog: ; preds = %sw.bb5, %entry 157 %a.addr.3 = phi i32 [ %a, %entry ], [ %add6, %sw.bb5 ] 158 ret i32 %a.addr.3 159; CHECK: {{bx lr$}} 160; ISBDSB-NEXT: dsb sy 161; ISBDSB-NEXT: isb 162; SB-NEXT: {{ sb$}} 163} 164 165define dso_local i32 @indirect_call( 166ptr nocapture %f1, ptr nocapture %f2) { 167entry: 168; CHECK-LABEL: indirect_call: 169 %call = tail call i32 %f1() 170; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}} 171; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}} 172 %call2 = tail call i32 %f2() 173; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}} 174; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}} 175 %add = add nsw i32 %call2, %call 176 ret i32 %add 177; CHECK: .Lfunc_end 178} 179 180; verify calling through a function pointer. 181@a = dso_local local_unnamed_addr global ptr null, align 8 182@b = dso_local local_unnamed_addr global i32 0, align 4 183define dso_local void @indirect_call_global() local_unnamed_addr { 184; CHECK-LABEL: indirect_call_global: 185entry: 186 %0 = load ptr, ptr @a, align 8 187 %call = tail call i32 %0() nounwind 188; HARDENARM: bl {{__llvm_slsblr_thunk_arm_r[0-9]+$}} 189; HARDENTHUMB: bl {{__llvm_slsblr_thunk_thumb_r[0-9]+$}} 190 store i32 %call, ptr @b, align 4 191 ret void 192; CHECK: .Lfunc_end 193} 194 195; Verify that neither r12 nor lr are used as registers in indirect call 196; instructions when the sls-hardening-blr mitigation is enabled, as 197; (a) a linker is allowed to clobber r12 on calls, and 198; (b) the hardening transformation isn't correct if lr is the register holding 199; the address of the function called. 200define i32 @check_r12(ptr %fp) { 201entry: 202; CHECK-LABEL: check_r12: 203 %f = load ptr, ptr %fp, align 4 204 ; Force f to be moved into r12 205 %r12_f = tail call ptr asm "add $0, $1, #0", "={r12},{r12}"(ptr %f) nounwind 206 %call = call i32 %r12_f() 207; NOHARDENARM: blx r12 208; NOHARDENTHUMB: blx r12 209; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_r12}} 210 ret i32 %call 211; CHECK: .Lfunc_end 212} 213 214define i32 @check_lr(ptr %fp) { 215entry: 216; CHECK-LABEL: check_lr: 217 %f = load ptr, ptr %fp, align 4 218 ; Force f to be moved into lr 219 %lr_f = tail call ptr asm "add $0, $1, #0", "={lr},{lr}"(ptr %f) nounwind 220 %call = call i32 %lr_f() 221; NOHARDENARM: blx lr 222; NOHARDENTHUMB: blx lr 223; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_lr}} 224 ret i32 %call 225; CHECK: .Lfunc_end 226} 227 228; Verify that even when sls-harden-blr is enabled, "blx r12" is still an 229; instruction that is accepted by the inline assembler 230define void @verify_inline_asm_blx_r12(ptr %g) { 231entry: 232; CHECK-LABEL: verify_inline_asm_blx_r12: 233 tail call void asm sideeffect "blx $0", "{r12}"(ptr %g) nounwind 234; CHECK: blx r12 235 ret void 236; CHECK: {{bx lr$}} 237; ISBDSB-NEXT: dsb sy 238; ISBDSB-NEXT: isb 239; SB-NEXT: {{ sb$}} 240; CHECK: .Lfunc_end 241} 242 243; HARDEN-COMDAT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}} 244; HARDEN-COMDAT: .hidden {{__llvm_slsblr_thunk_(arm|thumb)_r5}} 245; HARDEN-COMDAT: .weak {{__llvm_slsblr_thunk_(arm|thumb)_r5}} 246; HARDEN-COMDAT: .type {{__llvm_slsblr_thunk_(arm|thumb)_r5}},%function 247; HARDEN-COMDAT-OFF-NOT: .section {{.text.__llvm_slsblr_thunk_(arm|thumb)_r5}} 248; HARDEN-COMDAT-OFF-NOT: .hidden {{__llvm_slsblr_thunk_(arm|thumb)_r5}} 249; HARDEN-COMDAT-OFF-NOT: .weak {{__llvm_slsblr_thunk_(arm|thumb)_r5}} 250; HARDEN-COMDAT-OFF: .type {{__llvm_slsblr_thunk_(arm|thumb)_r5}},%function 251; HARDEN-label: {{__llvm_slsblr_thunk_(arm|thumb)_r5}}: 252; HARDEN: bx r5 253; ISBDSB-NEXT: dsb sy 254; ISBDSB-NEXT: isb 255; SB-NEXT: dsb sy 256; SB-NEXT: isb 257; HARDEN-NEXT: .Lfunc_end 258 259; THUMB-NOT: __llvm_slsblr_thunk_arm 260; ARM-NOT: __llvm_slsblr_thunk_thumb 261