Skip to content

Commit ca57e8f

Browse files
[RISCV] Support -mstack-protector-guard=tls (#108942)
Add support for using a thread-local variable with a specified offset for holding the stack guard canary value. Closes: #46685
1 parent f35c213 commit ca57e8f

File tree

6 files changed

+144
-4
lines changed

6 files changed

+144
-4
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

+25-3
Original file line numberDiff line numberDiff line change
@@ -3604,7 +3604,8 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
36043604
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
36053605
StringRef Value = A->getValue();
36063606
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
3607-
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
3607+
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
3608+
!EffectiveTriple.isRISCV())
36083609
D.Diag(diag::err_drv_unsupported_opt_for_target)
36093610
<< A->getAsString(Args) << TripleStr;
36103611
if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
@@ -3644,13 +3645,28 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
36443645
<< A->getOption().getName() << Value << "sysreg global";
36453646
return;
36463647
}
3648+
if (EffectiveTriple.isRISCV()) {
3649+
if (Value != "tls" && Value != "global") {
3650+
D.Diag(diag::err_drv_invalid_value_with_suggestion)
3651+
<< A->getOption().getName() << Value << "tls global";
3652+
return;
3653+
}
3654+
if (Value == "tls") {
3655+
if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
3656+
D.Diag(diag::err_drv_ssp_missing_offset_argument)
3657+
<< A->getAsString(Args);
3658+
return;
3659+
}
3660+
}
3661+
}
36473662
A->render(Args, CmdArgs);
36483663
}
36493664

36503665
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
36513666
StringRef Value = A->getValue();
36523667
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
3653-
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
3668+
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
3669+
!EffectiveTriple.isRISCV())
36543670
D.Diag(diag::err_drv_unsupported_opt_for_target)
36553671
<< A->getAsString(Args) << TripleStr;
36563672
int Offset;
@@ -3669,7 +3685,8 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
36693685

36703686
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) {
36713687
StringRef Value = A->getValue();
3672-
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
3688+
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
3689+
!EffectiveTriple.isRISCV())
36733690
D.Diag(diag::err_drv_unsupported_opt_for_target)
36743691
<< A->getAsString(Args) << TripleStr;
36753692
if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
@@ -3681,6 +3698,11 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
36813698
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
36823699
return;
36833700
}
3701+
if (EffectiveTriple.isRISCV() && Value != "tp") {
3702+
D.Diag(diag::err_drv_invalid_value_with_suggestion)
3703+
<< A->getOption().getName() << Value << "tp";
3704+
return;
3705+
}
36843706
A->render(Args, CmdArgs);
36853707
}
36863708

clang/test/CodeGen/stack-protector-guard.c

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
// RUN: %clang_cc1 -mstack-protector-guard=sysreg -triple aarch64-linux-gnu \
1010
// RUN: -mstack-protector-guard-offset=1024 -mstack-protector-guard-reg=sp_el0 \
1111
// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=AARCH64
12+
// RUN: %clang_cc1 -mstack-protector-guard=tls -triple riscv64-unknown-elf \
13+
// RUN: -mstack-protector-guard-offset=44 -mstack-protector-guard-reg=tp \
14+
// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=RISCV
1215
void foo(int*);
1316
void bar(int x) {
1417
int baz[x];
@@ -23,3 +26,8 @@ void bar(int x) {
2326
// AARCH64: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"sysreg"}
2427
// AARCH64: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"}
2528
// AARCH64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 1024}
29+
30+
// RISCV: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]], [[ATTR4:![0-9]+]]}
31+
// RISCV: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"tls"}
32+
// RISCV: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tp"}
33+
// RISCV: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 44}

clang/test/Driver/stack-protector-guard.c

+19
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,22 @@
8585
// CHECK-AARCH64: "-cc1" {{.*}}"-mstack-protector-guard=sysreg" "-mstack-protector-guard-offset=0" "-mstack-protector-guard-reg=sp_el0"
8686
// INVALID-VALUE-AARCH64: error: invalid value 'tls' in 'mstack-protector-guard=', expected one of: sysreg global
8787
// INVALID-REG-AARCH64: error: invalid value 'foo' in 'mstack-protector-guard-reg='
88+
89+
// RUN: %clang -### -target riscv64-unknown-elf -mstack-protector-guard=tls -mstack-protector-guard-offset=24 -mstack-protector-guard-reg=tp %s 2>&1 | \
90+
// RUN: FileCheck -v -check-prefix=CHECK-TLS-RISCV %s
91+
// RUN: %clang -### -target riscv64-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
92+
// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s
93+
94+
// CHECK-TLS-RISCV: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=tp"
95+
96+
// RUN: not %clang -target riscv64-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
97+
// RUN: FileCheck -check-prefix=MISSING-OFFSET %s
98+
99+
// RUN: not %clang -target riscv64-unknown-elf -mstack-protector-guard=sysreg %s 2>&1 | \
100+
// RUN: FileCheck -check-prefix=INVALID-VALUE2 %s
101+
102+
// RUN: not %clang -target riscv64-unknown-elf -mstack-protector-guard=tls \
103+
// RUN: -mstack-protector-guard-offset=20 -mstack-protector-guard-reg=sp %s 2>&1 | \
104+
// RUN: FileCheck -check-prefix=INVALID-REG-RISCV %s
105+
106+
// INVALID-REG-RISCV: error: invalid value 'sp' in 'mstack-protector-guard-reg=', expected one of: tp

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -21304,7 +21304,7 @@ bool RISCVTargetLowering::preferScalarizeSplat(SDNode *N) const {
2130421304
}
2130521305

2130621306
static Value *useTpOffset(IRBuilderBase &IRB, unsigned Offset) {
21307-
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
21307+
Module *M = IRB.GetInsertBlock()->getModule();
2130821308
Function *ThreadPointerFunc =
2130921309
Intrinsic::getDeclaration(M, Intrinsic::thread_pointer);
2131021310
return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
@@ -21323,6 +21323,14 @@ Value *RISCVTargetLowering::getIRStackGuard(IRBuilderBase &IRB) const {
2132321323
if (Subtarget.isTargetAndroid())
2132421324
return useTpOffset(IRB, -0x18);
2132521325

21326+
Module *M = IRB.GetInsertBlock()->getModule();
21327+
21328+
if (M->getStackProtectorGuard() == "tls") {
21329+
// Users must specify the offset explicitly
21330+
int Offset = M->getStackProtectorGuardOffset();
21331+
return useTpOffset(IRB, Offset);
21332+
}
21333+
2132621334
return TargetLowering::getIRStackGuard(IRB);
2132721335
}
2132821336

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
3+
; RUN: | FileCheck %s
4+
5+
define void @foo(i64 %t) sspstrong nounwind {
6+
; CHECK-LABEL: foo:
7+
; CHECK: # %bb.0:
8+
; CHECK-NEXT: addi sp, sp, -32
9+
; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
10+
; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
11+
; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
12+
; CHECK-NEXT: addi s0, sp, 32
13+
; CHECK-NEXT: lui s1, %hi(__stack_chk_guard)
14+
; CHECK-NEXT: ld a1, %lo(__stack_chk_guard)(s1)
15+
; CHECK-NEXT: sd a1, -32(s0)
16+
; CHECK-NEXT: slli a0, a0, 2
17+
; CHECK-NEXT: addi a0, a0, 15
18+
; CHECK-NEXT: andi a0, a0, -16
19+
; CHECK-NEXT: sub a0, sp, a0
20+
; CHECK-NEXT: mv sp, a0
21+
; CHECK-NEXT: call baz
22+
; CHECK-NEXT: ld a0, %lo(__stack_chk_guard)(s1)
23+
; CHECK-NEXT: ld a1, -32(s0)
24+
; CHECK-NEXT: bne a0, a1, .LBB0_2
25+
; CHECK-NEXT: # %bb.1:
26+
; CHECK-NEXT: addi sp, s0, -32
27+
; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
28+
; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
29+
; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
30+
; CHECK-NEXT: addi sp, sp, 32
31+
; CHECK-NEXT: ret
32+
; CHECK-NEXT: .LBB0_2:
33+
; CHECK-NEXT: call __stack_chk_fail
34+
%vla = alloca i32, i64 %t, align 4
35+
call void @baz(ptr %vla)
36+
ret void
37+
}
38+
39+
declare void @baz(ptr)
40+
41+
!llvm.module.flags = !{!1}
42+
!1 = !{i32 2, !"stack-protector-guard", !"global"}
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
3+
; RUN: | FileCheck %s
4+
5+
define void @foo(i64 %t) sspstrong nounwind {
6+
; CHECK-LABEL: foo:
7+
; CHECK: # %bb.0:
8+
; CHECK-NEXT: addi sp, sp, -32
9+
; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
10+
; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
11+
; CHECK-NEXT: addi s0, sp, 32
12+
; CHECK-NEXT: ld a1, 500(tp)
13+
; CHECK-NEXT: sd a1, -24(s0)
14+
; CHECK-NEXT: slli a0, a0, 2
15+
; CHECK-NEXT: addi a0, a0, 15
16+
; CHECK-NEXT: andi a0, a0, -16
17+
; CHECK-NEXT: sub a0, sp, a0
18+
; CHECK-NEXT: mv sp, a0
19+
; CHECK-NEXT: call baz
20+
; CHECK-NEXT: ld a0, 500(tp)
21+
; CHECK-NEXT: ld a1, -24(s0)
22+
; CHECK-NEXT: bne a0, a1, .LBB0_2
23+
; CHECK-NEXT: # %bb.1: # %SP_return
24+
; CHECK-NEXT: addi sp, s0, -32
25+
; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
26+
; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
27+
; CHECK-NEXT: addi sp, sp, 32
28+
; CHECK-NEXT: ret
29+
; CHECK-NEXT: .LBB0_2: # %CallStackCheckFailBlk
30+
; CHECK-NEXT: call __stack_chk_fail
31+
%vla = alloca i32, i64 %t, align 4
32+
call void @baz(ptr %vla)
33+
ret void
34+
}
35+
36+
declare void @baz(ptr)
37+
38+
!llvm.module.flags = !{!1, !2, !3}
39+
!1 = !{i32 2, !"stack-protector-guard", !"tls"}
40+
!2 = !{i32 2, !"stack-protector-guard-reg", !"tp"}
41+
!3 = !{i32 2, !"stack-protector-guard-offset", i32 500}

0 commit comments

Comments
 (0)