[compiler-rt] [libcxx] [mlir] [libc] [flang] [llvm] [clang] [openmp] [clang-tools-extra] [libunwind] [X86][ISel] Don't select MOV/ADD64ri32 for tglobaltlsaddr under large code models (PR #77175)
https://github.com/nmosier updated https://github.com/llvm/llvm-project/pull/77175 >From b6351e796868be27075518fb51830bf79c60cdf6 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Sat, 6 Jan 2024 03:36:03 + Subject: [PATCH] [X86][ISel] Select MOV/ADD64ri32 for tglobaltlsaddr only under small code models This patch fixes a bug (GitHub issue #77128) that caused the compiler to emit 32-bit (rather than 64-bit) relocations for TLS offsets under a medium/large code model for x86-64 targets, resulting in link-time errors. The root cause of the bug is an X86 instruction selection pattern that errantly matches tglobaltlsaddr SDNodes to target MOV64ri32/ADD64ri32 SDNodes during the Select phase of instruction selection, regardless of the code model. This patch adds the requirement `Requires<[NearData]>` to both X86 selection patterns, ensuring that they only match when the code model is tiny/small/kernel. It also adds a new test (llvm/test/CodeGen/X86/tls-largecode.ll) to ensure the patterns are not matched for medium/large code models. --- llvm/lib/Target/X86/X86InstrCompiler.td | 4 +-- llvm/test/CodeGen/X86/tls-codemodels.ll | 36 + 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/X86/tls-codemodels.ll diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index c77c77ee4a3eeb..67fb593e391d34 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -1267,10 +1267,10 @@ def : Pat<(i64 (X86RecoverFrameAlloc mcsym:$dst)), (MOV64ri mcsym:$dst)>; // tls has some funny stuff here... // This corresponds to movabs $foo@tpoff, %rax def : Pat<(i64 (X86Wrapper tglobaltlsaddr :$dst)), - (MOV64ri32 tglobaltlsaddr :$dst)>; + (MOV64ri32 tglobaltlsaddr :$dst)>, Requires<[NearData]>; // This corresponds to add $foo@tpoff, %rax def : Pat<(add GR64:$src1, (X86Wrapper tglobaltlsaddr :$dst)), - (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>; + (ADD64ri32 GR64:$src1, tglobaltlsaddr :$dst)>, Requires<[NearData]>; // Direct PC relative function call for small code model. 32-bit displacement diff --git a/llvm/test/CodeGen/X86/tls-codemodels.ll b/llvm/test/CodeGen/X86/tls-codemodels.ll new file mode 100644 index 00..644e07300f3928 --- /dev/null +++ b/llvm/test/CodeGen/X86/tls-codemodels.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -code-model=small | FileCheck %s --check-prefix=CHECK-SMALL +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -code-model=kernel | FileCheck %s --check-prefix=CHECK-KERNEL +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -code-model=medium | FileCheck %s --check-prefix=CHECK-MEDIUM +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -code-model=large | FileCheck %s --check-prefix=CHECK-LARGE + +@x = dso_local thread_local global i32 0, align 4 + +define dso_local void @test() local_unnamed_addr { +; CHECK-SMALL-LABEL: test: +; CHECK-SMALL: # %bb.0: # %entry +; CHECK-SMALL-NEXT:movl $0, %fs:x@TPOFF +; CHECK-SMALL-NEXT:retq +; +; CHECK-KERNEL-LABEL: test: +; CHECK-KERNEL: # %bb.0: # %entry +; CHECK-KERNEL-NEXT:movl $0, %fs:x@TPOFF +; CHECK-KERNEL-NEXT:retq +; +; CHECK-MEDIUM-LABEL: test: +; CHECK-MEDIUM: # %bb.0: # %entry +; CHECK-MEDIUM-NEXT:movl $0, %fs:x@TPOFF +; CHECK-MEDIUM-NEXT:retq +; +; CHECK-LARGE-LABEL: test: +; CHECK-LARGE: # %bb.0: # %entry +; CHECK-LARGE-NEXT:movabsq $x@TPOFF, %rax +; CHECK-LARGE-NEXT:movl $0, %fs:(%rax) +; CHECK-LARGE-NEXT:retq +entry: + %0 = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x) + store i32 0, ptr %0, align 4 + ret void +} + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [libcxx] [libc] [clang] [mlir] [llvm] [compiler-rt] [flang] [openmp] [libunwind] [X86][ISel] Don't select MOV/ADD64ri32 for tglobaltlsaddr under large code models (PR #77175)
https://github.com/nmosier closed https://github.com/llvm/llvm-project/pull/77175 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [openmp] [clang] [mlir] [lld] [libcxx] [compiler-rt] [X86] Add support for indirect branch tracking in jump tables (PR #77679)
https://github.com/nmosier updated https://github.com/llvm/llvm-project/pull/77679 >From 35f91b27825a81b1ba171860b47bf8b0477fd95a Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Wed, 10 Jan 2024 19:27:30 + Subject: [PATCH] [X86] Add support for indirect branch tracking in jump tables This patch adds support for protecting jump tables with indirect branch tracking (IBT). By default, indirect jump table branches are given a 'notrack' prefix and thus not protected with IBT. This default behavior is suitable for traditional threat models, assuming the compiler generates correct jump table code. However, for threat models encompassing speculative execution vulnerabilities (e.g., Spectre), such notrack'ed indirect branches potentially introduce Spectre-v2-style vulnerabilites by allowing them to mis-speculatively jump to arbitrary target addresses, not just ENDBRANCH instructions. To enable indirect branch tracking for jump tables, this patch allows the `cf-protection-branch` module flag's value to indicate the level of indirect branch protection required. If `cf-protection-branch == 0` or `cf-protection-branch` is missing entirely, then branch protections are applied. If `cf-protection-branch == 1`, then branch protections are applied for all indirect branches except for those that cannot under any circumstances non-speculatively jump to the wrong target (namely, indirect jump table branches). If `cf-protection-branch >= 2`, then branch protections are applied to all indirect branches, including indirect jump table branches. To summarize the new interpretation of the `cf-protection-branch` module flag under this patch: * `cf-protection-branch == 1` (currently emitted by clang when passed flag `-fcf-protection=branch`) is suitable for hardening code against non-speculative control-flow hijacks. * `cf-protection-branch >= 2` is suitable for additionally hardening code against speculative control-flow hijacks (e.g., Spectre v2). --- llvm/lib/Target/X86/X86.h | 1 + llvm/lib/Target/X86/X86ISelLowering.cpp | 21 +++ .../Target/X86/X86IndirectBranchTracking.cpp | 29 --- llvm/lib/Target/X86/X86TargetMachine.cpp | 1 + .../X86/indirect-branch-tracking-jt.mir | 35 +++ 5 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 llvm/test/CodeGen/X86/indirect-branch-tracking-jt.mir diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h index 21623a805f5568..277259c74abae2 100644 --- a/llvm/lib/Target/X86/X86.h +++ b/llvm/lib/Target/X86/X86.h @@ -199,6 +199,7 @@ void initializeX86ReturnThunksPass(PassRegistry &); void initializeX86SpeculativeExecutionSideEffectSuppressionPass(PassRegistry &); void initializeX86SpeculativeLoadHardeningPassPass(PassRegistry &); void initializeX86TileConfigPass(PassRegistry &); +void initializeX86IndirectBranchTrackingPassPass(PassRegistry &); namespace X86AS { enum : unsigned { diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5f6f500e49dd2a..71a20b439b5fad 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -56365,12 +56365,21 @@ SDValue X86TargetLowering::expandIndirectJTBranch(const SDLoc &dl, int JTI, SelectionDAG &DAG) const { const Module *M = DAG.getMachineFunction().getMMI().getModule(); - Metadata *IsCFProtectionSupported = M->getModuleFlag("cf-protection-branch"); - if (IsCFProtectionSupported) { -// In case control-flow branch protection is enabled, we need to add -// notrack prefix to the indirect branch. -// In order to do that we create NT_BRIND SDNode. -// Upon ISEL, the pattern will convert it to jmp with NoTrack prefix. + + uint64_t CFProtectionBranchLevel = 0; + if (Metadata *CFProtectionBranchEnabled = + M->getModuleFlag("cf-protection-branch")) +CFProtectionBranchLevel = +cast(CFProtectionBranchEnabled) +->getValue() +->getUniqueInteger() +.getLimitedValue(); + + if (CFProtectionBranchLevel == 1) { +// In case control-flow branch protection is enabled but we are not +// protecting jump table branches, we need to add notrack prefix to the +// indirect branch. In order to do that we create NT_BRIND SDNode. Upon +// ISEL, the pattern will convert it to jmp with NoTrack prefix. SDValue JTInfo = DAG.getJumpTableDebugInfo(JTI, Value, dl); return DAG.getNode(X86ISD::NT_BRIND, dl, MVT::Other, JTInfo, Addr); } diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp index 785bdd83cd998b..0710af3af8469a 100644 --- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp +++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp @@ -22,11 +22,13 @@ #include "llvm/ADT/Statistic.h"
[llvm] [flang] [clang] [clang-tools-extra] [compiler-rt] [libc] [lldb] [libcxxabi] [mlir] [lld] [openmp] [libcxx] [X86] Add support for indirect branch tracking in jump tables (PR #77679)
https://github.com/nmosier updated https://github.com/llvm/llvm-project/pull/77679 >From 35f91b27825a81b1ba171860b47bf8b0477fd95a Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Wed, 10 Jan 2024 19:27:30 + Subject: [PATCH] [X86] Add support for indirect branch tracking in jump tables This patch adds support for protecting jump tables with indirect branch tracking (IBT). By default, indirect jump table branches are given a 'notrack' prefix and thus not protected with IBT. This default behavior is suitable for traditional threat models, assuming the compiler generates correct jump table code. However, for threat models encompassing speculative execution vulnerabilities (e.g., Spectre), such notrack'ed indirect branches potentially introduce Spectre-v2-style vulnerabilites by allowing them to mis-speculatively jump to arbitrary target addresses, not just ENDBRANCH instructions. To enable indirect branch tracking for jump tables, this patch allows the `cf-protection-branch` module flag's value to indicate the level of indirect branch protection required. If `cf-protection-branch == 0` or `cf-protection-branch` is missing entirely, then branch protections are applied. If `cf-protection-branch == 1`, then branch protections are applied for all indirect branches except for those that cannot under any circumstances non-speculatively jump to the wrong target (namely, indirect jump table branches). If `cf-protection-branch >= 2`, then branch protections are applied to all indirect branches, including indirect jump table branches. To summarize the new interpretation of the `cf-protection-branch` module flag under this patch: * `cf-protection-branch == 1` (currently emitted by clang when passed flag `-fcf-protection=branch`) is suitable for hardening code against non-speculative control-flow hijacks. * `cf-protection-branch >= 2` is suitable for additionally hardening code against speculative control-flow hijacks (e.g., Spectre v2). --- llvm/lib/Target/X86/X86.h | 1 + llvm/lib/Target/X86/X86ISelLowering.cpp | 21 +++ .../Target/X86/X86IndirectBranchTracking.cpp | 29 --- llvm/lib/Target/X86/X86TargetMachine.cpp | 1 + .../X86/indirect-branch-tracking-jt.mir | 35 +++ 5 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 llvm/test/CodeGen/X86/indirect-branch-tracking-jt.mir diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h index 21623a805f5568..277259c74abae2 100644 --- a/llvm/lib/Target/X86/X86.h +++ b/llvm/lib/Target/X86/X86.h @@ -199,6 +199,7 @@ void initializeX86ReturnThunksPass(PassRegistry &); void initializeX86SpeculativeExecutionSideEffectSuppressionPass(PassRegistry &); void initializeX86SpeculativeLoadHardeningPassPass(PassRegistry &); void initializeX86TileConfigPass(PassRegistry &); +void initializeX86IndirectBranchTrackingPassPass(PassRegistry &); namespace X86AS { enum : unsigned { diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5f6f500e49dd2a..71a20b439b5fad 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -56365,12 +56365,21 @@ SDValue X86TargetLowering::expandIndirectJTBranch(const SDLoc &dl, int JTI, SelectionDAG &DAG) const { const Module *M = DAG.getMachineFunction().getMMI().getModule(); - Metadata *IsCFProtectionSupported = M->getModuleFlag("cf-protection-branch"); - if (IsCFProtectionSupported) { -// In case control-flow branch protection is enabled, we need to add -// notrack prefix to the indirect branch. -// In order to do that we create NT_BRIND SDNode. -// Upon ISEL, the pattern will convert it to jmp with NoTrack prefix. + + uint64_t CFProtectionBranchLevel = 0; + if (Metadata *CFProtectionBranchEnabled = + M->getModuleFlag("cf-protection-branch")) +CFProtectionBranchLevel = +cast(CFProtectionBranchEnabled) +->getValue() +->getUniqueInteger() +.getLimitedValue(); + + if (CFProtectionBranchLevel == 1) { +// In case control-flow branch protection is enabled but we are not +// protecting jump table branches, we need to add notrack prefix to the +// indirect branch. In order to do that we create NT_BRIND SDNode. Upon +// ISEL, the pattern will convert it to jmp with NoTrack prefix. SDValue JTInfo = DAG.getJumpTableDebugInfo(JTI, Value, dl); return DAG.getNode(X86ISD::NT_BRIND, dl, MVT::Other, JTInfo, Addr); } diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp index 785bdd83cd998b..0710af3af8469a 100644 --- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp +++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp @@ -22,11 +22,13 @@ #include "llvm/ADT/Statistic.h"