zzheng updated this revision to Diff 280210.
zzheng marked 3 inline comments as done.
zzheng edited the summary of this revision.
zzheng added a comment.

Using 'BLOCKED' now.

clang-formated RISCVFrameLowering.cpp

updated style of test/CodeGen/RISCV/shadowcallstack.ll


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D84414/new/

https://reviews.llvm.org/D84414

Files:
  clang/lib/Driver/SanitizerArgs.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/test/CodeGen/shadowcallstack-attr.c
  clang/test/Driver/sanitizer-ld.c
  llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
  llvm/test/CodeGen/RISCV/shadowcallstack.ll

Index: llvm/test/CodeGen/RISCV/shadowcallstack.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/shadowcallstack.ll
@@ -0,0 +1,179 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32-unknown-elf -mattr=+reserve-x18 -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefix=RV32
+
+; RUN: llc -mtriple=riscv64-unknown-elf -mattr=+reserve-x18 -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefix=RV64
+
+define void @f1() shadowcallstack {
+; RV32-LABEL: f1:
+; RV32:       # %bb.0:
+; RV32-NEXT:    ret
+; RV32-NOT:     x18
+;
+; RV64-LABEL: f1:
+; RV64:       # %bb.0:
+; RV64-NEXT:    ret
+; RV64-NOT:     x18
+  ret void
+}
+
+declare void @foo()
+
+define void @f2() shadowcallstack {
+; RV32-LABEL: f2:
+; RV32:       # %bb.0:
+; RV32-NEXT:    tail foo
+; RV32-NOT:     x18
+;
+; RV64-LABEL: f2:
+; RV64:       # %bb.0:
+; RV64-NEXT:    tail foo
+; RV64-NOT:     x18
+  tail call void @foo()
+  ret void
+}
+
+declare i32 @bar()
+
+define i32 @f3() shadowcallstack {
+; RV32-LABEL: f3:
+; RV32:       # %bb.0:
+; RV32-NEXT:    sw ra, 0(s2)
+; RV32-NEXT:    addi s2, s2, 4
+; RV32-NEXT:    addi sp, sp, -16
+; RV32-NEXT:    .cfi_def_cfa_offset 16
+; RV32-NEXT:    sw ra, 12(sp)
+; RV32-NEXT:    .cfi_offset ra, -4
+; RV32-NEXT:    call bar
+; RV32-NEXT:    lw ra, 12(sp)
+; RV32-NEXT:    addi sp, sp, 16
+; RV32-NEXT:    addi s2, s2, -4
+; RV32-NEXT:    lw ra, 0(s2)
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: f3:
+; RV64:       # %bb.0:
+; RV64-NEXT:    sw ra, 0(s2)
+; RV64-NEXT:    addi s2, s2, 8
+; RV64-NEXT:    addi sp, sp, -16
+; RV64-NEXT:    .cfi_def_cfa_offset 16
+; RV64-NEXT:    sd ra, 8(sp)
+; RV64-NEXT:    .cfi_offset ra, -8
+; RV64-NEXT:    call bar
+; RV64-NEXT:    ld ra, 8(sp)
+; RV64-NEXT:    addi sp, sp, 16
+; RV64-NEXT:    addi s2, s2, -8
+; RV64-NEXT:    lw ra, 0(s2)
+; RV64-NEXT:    ret
+  %res = call i32 @bar()
+  %res1 = add i32 %res, 1
+  ret i32 %res
+}
+
+define i32 @f4() shadowcallstack {
+; RV32-LABEL: f4:
+; RV32:       # %bb.0:
+; RV32-NEXT:    sw ra, 0(s2)
+; RV32-NEXT:    addi s2, s2, 4
+; RV32-NEXT:    addi sp, sp, -16
+; RV32-NEXT:    .cfi_def_cfa_offset 16
+; RV32-NEXT:    sw ra, 12(sp)
+; RV32-NEXT:    sw s0, 8(sp)
+; RV32-NEXT:    sw s1, 4(sp)
+; RV32-NEXT:    sw s3, 0(sp)
+; RV32-NEXT:    .cfi_offset ra, -4
+; RV32-NEXT:    .cfi_offset s0, -8
+; RV32-NEXT:    .cfi_offset s1, -12
+; RV32-NEXT:    .cfi_offset s3, -16
+; RV32-NEXT:    call bar
+; RV32-NEXT:    mv s3, a0
+; RV32-NEXT:    call bar
+; RV32-NEXT:    mv s1, a0
+; RV32-NEXT:    call bar
+; RV32-NEXT:    mv s0, a0
+; RV32-NEXT:    call bar
+; RV32-NEXT:    add a1, s3, s1
+; RV32-NEXT:    add a0, s0, a0
+; RV32-NEXT:    add a0, a1, a0
+; RV32-NEXT:    lw s3, 0(sp)
+; RV32-NEXT:    lw s1, 4(sp)
+; RV32-NEXT:    lw s0, 8(sp)
+; RV32-NEXT:    lw ra, 12(sp)
+; RV32-NEXT:    addi sp, sp, 16
+; RV32-NEXT:    addi s2, s2, -4
+; RV32-NEXT:    lw ra, 0(s2)
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: f4:
+; RV64:       # %bb.0:
+; RV64-NEXT:    sw ra, 0(s2)
+; RV64-NEXT:    addi s2, s2, 8
+; RV64-NEXT:    addi sp, sp, -32
+; RV64-NEXT:    .cfi_def_cfa_offset 32
+; RV64-NEXT:    sd ra, 24(sp)
+; RV64-NEXT:    sd s0, 16(sp)
+; RV64-NEXT:    sd s1, 8(sp)
+; RV64-NEXT:    sd s3, 0(sp)
+; RV64-NEXT:    .cfi_offset ra, -8
+; RV64-NEXT:    .cfi_offset s0, -16
+; RV64-NEXT:    .cfi_offset s1, -24
+; RV64-NEXT:    .cfi_offset s3, -32
+; RV64-NEXT:    call bar
+; RV64-NEXT:    mv s3, a0
+; RV64-NEXT:    call bar
+; RV64-NEXT:    mv s1, a0
+; RV64-NEXT:    call bar
+; RV64-NEXT:    mv s0, a0
+; RV64-NEXT:    call bar
+; RV64-NEXT:    add a1, s3, s1
+; RV64-NEXT:    add a0, s0, a0
+; RV64-NEXT:    addw a0, a1, a0
+; RV64-NEXT:    ld s3, 0(sp)
+; RV64-NEXT:    ld s1, 8(sp)
+; RV64-NEXT:    ld s0, 16(sp)
+; RV64-NEXT:    ld ra, 24(sp)
+; RV64-NEXT:    addi sp, sp, 32
+; RV64-NEXT:    addi s2, s2, -8
+; RV64-NEXT:    lw ra, 0(s2)
+; RV64-NEXT:    ret
+  %res1 = call i32 @bar()
+  %res2 = call i32 @bar()
+  %res3 = call i32 @bar()
+  %res4 = call i32 @bar()
+  %res12 = add i32 %res1, %res2
+  %res34 = add i32 %res3, %res4
+  %res1234 = add i32 %res12, %res34
+  ret i32 %res1234
+}
+
+define i32 @f5() shadowcallstack nounwind {
+; RV32-LABEL: f5:
+; RV32:       # %bb.0:
+; RV32-NEXT:    sw ra, 0(s2)
+; RV32-NEXT:    addi s2, s2, 4
+; RV32-NEXT:    addi sp, sp, -16
+; RV32-NEXT:    sw ra, 12(sp)
+; RV32-NEXT:    call bar
+; RV32-NEXT:    lw ra, 12(sp)
+; RV32-NEXT:    addi sp, sp, 16
+; RV32-NEXT:    addi s2, s2, -4
+; RV32-NEXT:    lw ra, 0(s2)
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: f5:
+; RV64:       # %bb.0:
+; RV64-NEXT:    sw ra, 0(s2)
+; RV64-NEXT:    addi s2, s2, 8
+; RV64-NEXT:    addi sp, sp, -16
+; RV64-NEXT:    sd ra, 8(sp)
+; RV64-NEXT:    call bar
+; RV64-NEXT:    ld ra, 8(sp)
+; RV64-NEXT:    addi sp, sp, 16
+; RV64-NEXT:    addi s2, s2, -8
+; RV64-NEXT:    lw ra, 0(s2)
+; RV64-NEXT:    ret
+  %res = call i32 @bar()
+  %res1 = add i32 %res, 1
+  ret i32 %res
+}
Index: llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -23,6 +23,80 @@
 
 using namespace llvm;
 
+// For now we use x18, a.k.a s2, as pointer to shadow call stack.
+// User should explicitly set -ffixed-x18 and not use x18 in their asm.
+static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
+                            MachineBasicBlock::iterator MI) {
+  if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack))
+    return;
+
+  std::vector<CalleeSavedInfo> &CSI = MF.getFrameInfo().getCalleeSavedInfo();
+  if (std::none_of(CSI.begin(), CSI.end(), [](CalleeSavedInfo &CSR) {
+        return CSR.getReg() == RISCV::X1;
+      }))
+    return;
+
+  const auto &STI = MF.getSubtarget<RISCVSubtarget>();
+  // Emit an error message and bail out.
+  if (!STI.isRegisterReservedByUser(RISCV::X18)) {
+    MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
+        MF.getFunction(), "x18 not reserved by user for Shadow Call Stack."});
+    return;
+  }
+
+  DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
+
+  const RISCVInstrInfo *TII = STI.getInstrInfo();
+  int64_t SlotSize = STI.getXLen() / 8;
+  // Store return address to shadow call stack
+  // sw   ra, 0(s2)
+  // addi s2, s2, 4
+  BuildMI(MBB, MI, DL, TII->get(RISCV::SW))
+      .addReg(RISCV::X1)
+      .addReg(RISCV::X18)
+      .addImm(0);
+  BuildMI(MBB, MI, DL, TII->get(RISCV::ADDI))
+      .addReg(RISCV::X18, RegState::Define)
+      .addReg(RISCV::X18)
+      .addImm(SlotSize);
+}
+
+static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
+                            MachineBasicBlock::iterator MI) {
+  if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack))
+    return;
+
+  std::vector<CalleeSavedInfo> &CSI = MF.getFrameInfo().getCalleeSavedInfo();
+  if (std::none_of(CSI.begin(), CSI.end(), [](CalleeSavedInfo &CSR) {
+        return CSR.getReg() == RISCV::X1;
+      }))
+    return;
+
+  const auto &STI = MF.getSubtarget<RISCVSubtarget>();
+  // Emit an error message and bail out.
+  if (!STI.isRegisterReservedByUser(RISCV::X18)) {
+    MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
+        MF.getFunction(), "x18 not reserved by user for Shadow Call Stack."});
+    return;
+  }
+
+  DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
+
+  const RISCVInstrInfo *TII = STI.getInstrInfo();
+  int64_t SlotSize = STI.getXLen() / 8;
+  // Load return address from shadow call stack
+  // addi s2, s2, -4
+  // lw   ra, 0(s2)
+  BuildMI(MBB, MI, DL, TII->get(RISCV::ADDI))
+      .addReg(RISCV::X18, RegState::Define)
+      .addReg(RISCV::X18)
+      .addImm(-SlotSize);
+  BuildMI(MBB, MI, DL, TII->get(RISCV::LW))
+      .addReg(RISCV::X1, RegState::Define)
+      .addReg(RISCV::X18)
+      .addImm(0);
+}
+
 // Get the ID of the libcall used for spilling and restoring callee saved
 // registers. The ID is representative of the number of registers saved or
 // restored by the libcall, except it is zero-indexed - ID 0 corresponds to a
@@ -222,6 +296,9 @@
   Register SPReg = getSPReg(STI);
   Register BPReg = RISCVABI::getBPReg();
 
+  // Emit prologue for shadow call stack.
+  emitSCSPrologue(MF, MBB, MBBI);
+
   // Since spillCalleeSavedRegisters may have inserted a libcall, skip past
   // any instructions marked as FrameSetup
   while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup))
@@ -457,6 +534,9 @@
 
   // Deallocate stack
   adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
+
+  // Emit epilogue for shadow call stack.
+  emitSCSEpilogue(MF, MBB, MBBI);
 }
 
 int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
Index: clang/test/Driver/sanitizer-ld.c
===================================================================
--- clang/test/Driver/sanitizer-ld.c
+++ clang/test/Driver/sanitizer-ld.c
@@ -615,6 +615,16 @@
 // CHECK-SHADOWCALLSTACK-LINUX-AARCH64: '-fsanitize=shadow-call-stack' only allowed with '-ffixed-x18'
 
 // RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN:     -target riscv32-unknown-elf -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-ELF-RISCV32 %s
+// CHECK-SHADOWCALLSTACK-ELF-RISCV32: '-fsanitize=shadow-call-stack' only allowed with '-ffixed-x18'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN:     -target riscv64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-RISCV64 %s
+// CHECK-SHADOWCALLSTACK-LINUX-RISCV64: '-fsanitize=shadow-call-stack' only allowed with '-ffixed-x18'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
 // RUN:     -target aarch64-unknown-linux -fuse-ld=ld -ffixed-x18 \
 // RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-AARCH64-X18 %s
 // RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
Index: clang/test/CodeGen/shadowcallstack-attr.c
===================================================================
--- clang/test/CodeGen/shadowcallstack-attr.c
+++ clang/test/CodeGen/shadowcallstack-attr.c
@@ -1,9 +1,23 @@
-// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=UNBLACKLISTED %s
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=UNBLOCKLISTED %s
 
-// RUN: %clang_cc1 -D ATTR -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLACKLISTED %s
+// RUN: %clang_cc1 -D ATTR -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLOCKLISTED %s
 
 // RUN: echo -e "[shadow-call-stack]\nfun:foo" > %t
-// RUN: %clang_cc1 -fsanitize-blacklist=%t -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLACKLISTED %s
+// RUN: %clang_cc1 -fsanitize-blacklist=%t -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLOCKLISTED %s
+
+// RUN: %clang_cc1 -triple riscv32-linux-gnu -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=UNBLOCKLISTED %s
+
+// RUN: %clang_cc1 -D ATTR -triple riscv32-linux-gnu -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLOCKLISTED %s
+
+// RUN: echo -e "[shadow-call-stack]\nfun:foo" > %t
+// RUN: %clang_cc1 -fsanitize-blacklist=%t -triple riscv32-linux-gnu -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLOCKLISTED %s
+
+// RUN: %clang_cc1 -triple riscv64-linux-gnu -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=UNBLOCKLISTED %s
+
+// RUN: %clang_cc1 -D ATTR -triple riscv64-linux-gnu -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLOCKLISTED %s
+
+// RUN: echo -e "[shadow-call-stack]\nfun:foo" > %t
+// RUN: %clang_cc1 -fsanitize-blacklist=%t -triple riscv64-linux-gnu -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLOCKLISTED %s
 
 #ifdef ATTR
 __attribute__((no_sanitize("shadow-call-stack")))
@@ -12,5 +26,5 @@
 
 // CHECK: define i32 @foo(i32* %a)
 
-// BLACKLISTED-NOT: attributes {{.*}}shadowcallstack{{.*}}
-// UNBLACKLISTED: attributes {{.*}}shadowcallstack{{.*}}
+// BLOCKLISTED-NOT: attributes {{.*}}shadowcallstack{{.*}}
+// UNBLOCKLISTED: attributes {{.*}}shadowcallstack{{.*}}
Index: clang/lib/Driver/ToolChain.cpp
===================================================================
--- clang/lib/Driver/ToolChain.cpp
+++ clang/lib/Driver/ToolChain.cpp
@@ -1024,7 +1024,8 @@
       getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||
       getTriple().isAArch64())
     Res |= SanitizerKind::CFIICall;
-  if (getTriple().getArch() == llvm::Triple::x86_64 || getTriple().isAArch64())
+  if (getTriple().getArch() == llvm::Triple::x86_64 ||
+      getTriple().isAArch64() || getTriple().isRISCV())
     Res |= SanitizerKind::ShadowCallStack;
   if (getTriple().isAArch64())
     Res |= SanitizerKind::MemTag;
Index: clang/lib/Driver/SanitizerArgs.cpp
===================================================================
--- clang/lib/Driver/SanitizerArgs.cpp
+++ clang/lib/Driver/SanitizerArgs.cpp
@@ -491,8 +491,10 @@
         << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
   }
 
-  if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
-      !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
+  if ((Kinds & SanitizerKind::ShadowCallStack) &&
+      ((TC.getTriple().isAArch64() &&
+        !llvm::AArch64::isX18ReservedByDefault(TC.getTriple())) ||
+       TC.getTriple().isRISCV()) &&
       !Args.hasArg(options::OPT_ffixed_x18)) {
     D.Diag(diag::err_drv_argument_only_allowed_with)
         << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to