261 lines · plain
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=1002; 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=1003; 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=1004; 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=1005; 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=1006; 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=1007; 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=1008; 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=1009; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,NOHARDENARM -dump-input-context=10010; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,NOHARDENTHUMB11; 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,ISBDSB12; 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,ISBDSB13; 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,ISBDSB14; 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,ISBDSB15; 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,SB16; 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,SB17; 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,ISBDSB18; 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,ISBDSB19; 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,ISBDSB20; 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,ISBDSB21; 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,SB22; 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,SB23 24; Function Attrs: norecurse nounwind readnone25define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr {26entry:27 %cmp = icmp sgt i32 %a, 028 br i1 %cmp, label %if.then, label %if.else29 30if.then: ; preds = %entry31 ; Make a very easy, very likely to predicate return (BX LR), to test that32 ; it will not get predicated when sls-hardening is enabled.33 %mul = mul i32 %b, %a34 ret i32 %mul35; CHECK-LABEL: double_return:36; HARDEN: {{bx lr$}}37; NOHARDENARM: {{bxgt lr$}}38; NOHARDENTHUMB: {{bxgt lr$}}39; ISBDSB-NEXT: dsb sy40; ISBDSB-NEXT: isb41; SB-NEXT: {{ sb$}}42 43if.else: ; preds = %entry44 %div3 = sdiv i32 %a, %b45 %div2 = sdiv i32 %a, %div346 %div1 = sdiv i32 %a, %div247 ret i32 %div148 49; CHECK: {{bx lr$}}50; ISBDSB-NEXT: dsb sy51; ISBDSB-NEXT: isb52; SB-NEXT: {{ sb$}}53; CHECK-NEXT: .Lfunc_end54}55 56@__const.indirect_branch.ptr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirect_branch, %return), ptr blockaddress(@indirect_branch, %l2)], align 857 58; Function Attrs: norecurse nounwind readnone59define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) {60; CHECK-LABEL: indirect_branch:61entry:62 %idxprom = sext i32 %i to i6463 %arrayidx = getelementptr inbounds [2 x ptr], ptr @__const.indirect_branch.ptr, i64 0, i64 %idxprom64 %0 = load ptr, ptr %arrayidx, align 865 indirectbr ptr %0, [label %return, label %l2]66; ARM: bx r067; THUMB: mov pc, r068; ISBDSB-NEXT: dsb sy69; ISBDSB-NEXT: isb70; SB-NEXT: {{ sb$}}71 72l2: ; preds = %entry73 br label %return74; CHECK: {{bx lr$}}75; ISBDSB-NEXT: dsb sy76; ISBDSB-NEXT: isb77; SB-NEXT: {{ sb$}}78 79return: ; preds = %entry, %l280 %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ]81 ret i32 %retval.082; CHECK: {{bx lr$}}83; ISBDSB-NEXT: dsb sy84; ISBDSB-NEXT: isb85; SB-NEXT: {{ sb$}}86; CHECK-NEXT: .Lfunc_end87}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: {{bx lr$}}105; ISBDSB-NEXT: dsb sy106; ISBDSB-NEXT: isb107; SB-NEXT: {{ sb$}}108 109d: ; preds = %asm.fallthrough, %entry110 ret i32 1111; CHECK: {{bx lr$}}112; ISBDSB-NEXT: dsb sy113; ISBDSB-NEXT: isb114; SB-NEXT: {{ sb$}}115; CHECK-NEXT: .Lfunc_end116}117 118; Check that indirect branches produced through switch jump tables are also119; 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.bb125 i32 1, label %sw.bb1126 i32 3, label %sw.bb3127 i32 4, label %sw.bb5128 ]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 sy133; ISBDSB-NEXT: isb134; SB-NEXT: {{ sb$}}135 136 137sw.bb: ; preds = %entry138 %add = shl nsw i32 %a, 1139 br label %sw.bb1140 141sw.bb1: ; preds = %entry, %sw.bb142 %a.addr.0 = phi i32 [ %a, %entry ], [ %add, %sw.bb ]143 %add2 = shl nsw i32 %a.addr.0, 1144 br label %sw.bb3145 146sw.bb3: ; preds = %entry, %sw.bb1147 %a.addr.1 = phi i32 [ %a, %entry ], [ %add2, %sw.bb1 ]148 %add4 = shl nsw i32 %a.addr.1, 1149 br label %sw.bb5150 151sw.bb5: ; preds = %entry, %sw.bb3152 %a.addr.2 = phi i32 [ %a, %entry ], [ %add4, %sw.bb3 ]153 %add6 = shl nsw i32 %a.addr.2, 1154 br label %sw.epilog155 156sw.epilog: ; preds = %sw.bb5, %entry157 %a.addr.3 = phi i32 [ %a, %entry ], [ %add6, %sw.bb5 ]158 ret i32 %a.addr.3159; CHECK: {{bx lr$}}160; ISBDSB-NEXT: dsb sy161; ISBDSB-NEXT: isb162; 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, %call176 ret i32 %add177; CHECK: .Lfunc_end178}179 180; verify calling through a function pointer.181@a = dso_local local_unnamed_addr global ptr null, align 8182@b = dso_local local_unnamed_addr global i32 0, align 4183define dso_local void @indirect_call_global() local_unnamed_addr {184; CHECK-LABEL: indirect_call_global:185entry:186 %0 = load ptr, ptr @a, align 8187 %call = tail call i32 %0() nounwind188; 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 4191 ret void192; CHECK: .Lfunc_end193}194 195; Verify that neither r12 nor lr are used as registers in indirect call196; instructions when the sls-hardening-blr mitigation is enabled, as197; (a) a linker is allowed to clobber r12 on calls, and198; (b) the hardening transformation isn't correct if lr is the register holding199; 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 4204 ; Force f to be moved into r12205 %r12_f = tail call ptr asm "add $0, $1, #0", "={r12},{r12}"(ptr %f) nounwind206 %call = call i32 %r12_f()207; NOHARDENARM: blx r12208; NOHARDENTHUMB: blx r12209; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_r12}}210 ret i32 %call211; CHECK: .Lfunc_end212}213 214define i32 @check_lr(ptr %fp) {215entry:216; CHECK-LABEL: check_lr:217 %f = load ptr, ptr %fp, align 4218 ; Force f to be moved into lr219 %lr_f = tail call ptr asm "add $0, $1, #0", "={lr},{lr}"(ptr %f) nounwind220 %call = call i32 %lr_f()221; NOHARDENARM: blx lr222; NOHARDENTHUMB: blx lr223; HARDEN-NOT: bl {{__llvm_slsblr_thunk_(arm|thumb)_lr}}224 ret i32 %call225; CHECK: .Lfunc_end226}227 228; Verify that even when sls-harden-blr is enabled, "blx r12" is still an229; instruction that is accepted by the inline assembler230define 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) nounwind234; CHECK: blx r12235 ret void236; CHECK: {{bx lr$}}237; ISBDSB-NEXT: dsb sy238; ISBDSB-NEXT: isb239; SB-NEXT: {{ sb$}}240; CHECK: .Lfunc_end241}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}},%function247; 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}},%function251; HARDEN-label: {{__llvm_slsblr_thunk_(arm|thumb)_r5}}:252; HARDEN: bx r5253; ISBDSB-NEXT: dsb sy254; ISBDSB-NEXT: isb255; SB-NEXT: dsb sy256; SB-NEXT: isb257; HARDEN-NEXT: .Lfunc_end258 259; THUMB-NOT: __llvm_slsblr_thunk_arm260; ARM-NOT: __llvm_slsblr_thunk_thumb261