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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits