pengfei created this revision.
pengfei added reviewers: nickdesaulniers, craig.topper, LuoYuanke.
Herald added subscribers: StephenFan, hiraditya, kristof.beyls.
Herald added a project: All.
pengfei requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, MaskRay.
Herald added projects: clang, LLVM.

The patch addresses the feature request from #1633. The implementation
borrows the a lot from aarch64.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126137

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Driver/ToolChains/Arch/X86.cpp
  clang/test/Driver/x86-target-features.c
  llvm/lib/Target/X86/X86.td
  llvm/lib/Target/X86/X86AsmPrinter.cpp
  llvm/lib/Target/X86/X86AsmPrinter.h
  llvm/test/CodeGen/X86/speculation-hardening-sls.ll

Index: llvm/test/CodeGen/X86/speculation-hardening-sls.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/speculation-hardening-sls.ll
@@ -0,0 +1,93 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mattr=harden-sls-all -verify-machineinstrs -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
+
+define dso_local i32 @double_return(i32 %a, i32 %b) local_unnamed_addr {
+; CHECK-LABEL: double_return:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    testl %edi, %edi
+; CHECK-NEXT:    jle .LBB0_2
+; CHECK-NEXT:    int3
+; CHECK-NEXT:  # %bb.1: # %if.then
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    cltd
+; CHECK-NEXT:    idivl %esi
+; CHECK-NEXT:    retq
+; CHECK-NEXT:    int3
+; CHECK-NEXT:  .LBB0_2: # %if.else
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    cltd
+; CHECK-NEXT:    idivl %edi
+; CHECK-NEXT:    retq
+; CHECK-NEXT:    int3
+entry:
+  %cmp = icmp sgt i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %div = sdiv i32 %a, %b
+  ret i32 %div
+
+if.else:                                          ; preds = %entry
+  %div1 = sdiv i32 %b, %a
+  ret i32 %div1
+}
+
+@__const.indirect_branch.ptr = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@indirect_branch, %return), i8* blockaddress(@indirect_branch, %l2)], align 8
+
+; Function Attrs: norecurse nounwind readnone
+define dso_local i32 @indirect_branch(i32 %a, i32 %b, i32 %i) {
+; CHECK-LABEL: indirect_branch:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movslq %edx, %rax
+; CHECK-NEXT:    jmpq *.L__const.indirect_branch.ptr(,%rax,8)
+; CHECK-NEXT:  .Ltmp0: # Block address taken
+; CHECK-NEXT:  .LBB1_2: # %return
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    retq
+; CHECK-NEXT:    int3
+; CHECK-NEXT:  .Ltmp1: # Block address taken
+; CHECK-NEXT:  .LBB1_1: # %l2
+; CHECK-NEXT:    movl $1, %eax
+; CHECK-NEXT:    retq
+; CHECK-NEXT:    int3
+entry:
+  %idxprom = sext i32 %i to i64
+  %arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @__const.indirect_branch.ptr, i64 0, i64 %idxprom
+  %0 = load i8*, i8** %arrayidx, align 8
+  indirectbr i8* %0, [label %return, label %l2]
+
+l2:                                               ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %entry, %l2
+  %retval.0 = phi i32 [ 1, %l2 ], [ 0, %entry ]
+  ret i32 %retval.0
+}
+
+define i32 @asmgoto() {
+; CHECK-LABEL: asmgoto:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    jmp .Ltmp2
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    int3
+; CHECK-NEXT:  # %bb.1: # %asm.fallthrough
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    retq
+; CHECK-NEXT:    int3
+; CHECK-NEXT:  .Ltmp2: # Block address taken
+; CHECK-NEXT:  .LBB2_2: # %d
+; CHECK-NEXT:    movl $1, %eax
+; CHECK-NEXT:    retq
+; CHECK-NEXT:    int3
+entry:
+  callbr void asm sideeffect "jmp $0", "X"(i8* blockaddress(@asmgoto, %d))
+            to label %asm.fallthrough [label %d]
+     ; The asm goto above produces a direct branch:
+
+asm.fallthrough:               ; preds = %entry
+  ret i32 0
+
+d:                             ; preds = %asm.fallthrough, %entry
+  ret i32 1
+}
Index: llvm/lib/Target/X86/X86AsmPrinter.h
===================================================================
--- llvm/lib/Target/X86/X86AsmPrinter.h
+++ llvm/lib/Target/X86/X86AsmPrinter.h
@@ -131,10 +131,7 @@
 
   void emitInstruction(const MachineInstr *MI) override;
 
-  void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {
-    AsmPrinter::emitBasicBlockEnd(MBB);
-    SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
-  }
+  void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
 
   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                        const char *ExtraCode, raw_ostream &O) override;
Index: llvm/lib/Target/X86/X86AsmPrinter.cpp
===================================================================
--- llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -336,6 +336,15 @@
   }
 }
 
+void X86AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
+  MCInst TmpInst;
+  TmpInst.setOpcode(X86::INT3);
+  AsmPrinter::emitBasicBlockEnd(MBB);
+  if (Subtarget->hardenSlsAll() && !MBB.back().getDesc().isIndirectBranch())
+    EmitToStreamer(*OutStreamer, TmpInst);
+  SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
+}
+
 void X86AsmPrinter::PrintMemReference(const MachineInstr *MI, unsigned OpNo,
                                       raw_ostream &O, const char *Modifier) {
   assert(isMem(*MI, OpNo) && "Invalid memory reference!");
Index: llvm/lib/Target/X86/X86.td
===================================================================
--- llvm/lib/Target/X86/X86.td
+++ llvm/lib/Target/X86/X86.td
@@ -382,6 +382,12 @@
           "Use an instruction sequence for taking the address of a global "
           "that allows a memory tag in the upper address bits.">;
 
+// Control codegen mitigation against Straight Line Speculation vulnerability.
+def FeatureHardenSlsAll
+    : SubtargetFeature<
+          "harden-sls-all", "HardenSlsAll", "true",
+          "Harden against straight line speculation across RET and BR instructions.">;
+
 //===----------------------------------------------------------------------===//
 // X86 Subtarget Tuning features
 //===----------------------------------------------------------------------===//
Index: clang/test/Driver/x86-target-features.c
===================================================================
--- clang/test/Driver/x86-target-features.c
+++ clang/test/Driver/x86-target-features.c
@@ -304,3 +304,8 @@
 // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-crc32 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-CRC32 %s
 // CRC32: "-target-feature" "+crc32"
 // NO-CRC32: "-target-feature" "-crc32"
+
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mharden-sls=all %s -### -o %t.o 2>&1 | FileCheck -check-prefix=SLS %s
+// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mharden-sls=none %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SLS %s
+// SLS: "-target-feature" "+harden-sls-all"
+// NO-SLS-NOT: "harden-sls"
Index: clang/lib/Driver/ToolChains/Arch/X86.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -242,4 +242,11 @@
       Name = Name.substr(3);
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
+
+  // Enable/disable straight line speculation hardening.
+  if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
+    StringRef Scope = A->getValue();
+    if (Scope == "all")
+      Features.push_back("+harden-sls-all");
+  }
 }
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -368,6 +368,8 @@
 X86 Support in Clang
 --------------------
 
+- Support ``-mharden-sls=all`` for X86.
+
 DWARF Support in Clang
 ----------------------
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to