[llvm] 7c3fea7 - [X86] Support customizing stack protector guard
Xiang1 Zhang via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 21 19:08:56 PDT 2020
Author: Xiang1 Zhang
Date: 2020-10-22T10:08:14+08:00
New Revision: 7c3fea7721e421de235917d9454d448f976500fc
URL: https://github.com/llvm/llvm-project/commit/7c3fea7721e421de235917d9454d448f976500fc
DIFF: https://github.com/llvm/llvm-project/commit/7c3fea7721e421de235917d9454d448f976500fc.diff
LOG: [X86] Support customizing stack protector guard
Reviewed By: nickdesaulniers, MaskRay
Differential Revision: https://reviews.llvm.org/D88631
Added:
clang/test/Driver/stack-protector-guard.c
llvm/test/CodeGen/X86/stack-protector-3.ll
Modified:
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Basic/CodeGenOptions.h
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/BackendUtil.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Frontend/CompilerInvocation.cpp
llvm/include/llvm/CodeGen/CommandFlags.h
llvm/include/llvm/Target/TargetOptions.h
llvm/lib/CodeGen/CommandFlags.cpp
llvm/lib/CodeGen/StackProtector.cpp
llvm/lib/Target/X86/X86ISelLowering.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 641b99edaed1..0ab9054f0bb5 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -356,6 +356,9 @@ ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
/// Bit size of immediate TLS offsets (0 == use the default).
VALUE_CODEGENOPT(TLSSize, 8, 0)
+/// The default stack protector guard offset to use.
+VALUE_CODEGENOPT(StackProtectorGuardOffset, 32, (unsigned)-1)
+
/// Number of path components to strip when emitting checks. (0 == full
/// filename)
VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0)
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index ca391bf8f186..f658c9b8a781 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -327,6 +327,15 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// by sanitizer coverage pass.
std::vector<std::string> SanitizeCoverageAllowlistFiles;
+ /// The guard style used for stack protector to get a initial value, this
+ /// value usually be gotten from TLS or get from __stack_chk_guard, or some
+ /// other styles we may implement in the future.
+ std::string StackProtectorGuard;
+
+ /// The TLS base register when StackProtectorGuard is "tls".
+ /// On x86 this can be "fs" or "gs".
+ std::string StackProtectorGuardReg;
+
/// Path to blocklist file specifying which objects
/// (files, functions) listed for instrumentation by sanitizer
/// coverage pass should actually not be instrumented.
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29bc19e5a84e..ced2d4435cfe 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -213,6 +213,7 @@ def err_drv_dllexport_inlines_and_fallback : Error<
def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
+def err_drv_invalid_value_with_suggestion : Error<"invalid value '%1' in '%0','%2'">;
def err_drv_invalid_remap_file : Error<
"invalid option '%0' not of the form <from-file>;<to-file>">;
def err_drv_invalid_gcc_output_type : Error<
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index ff3681852efd..fd2cf008cb18 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2606,6 +2606,12 @@ def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">;
+def mstack_protector_guard_EQ : Joined<["-"], "mstack-protector-guard=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the given guard (global, tls) for addressing the stack-protector guard">;
+def mstack_protector_guard_offset_EQ : Joined<["-"], "mstack-protector-guard-offset=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the given offset for addressing the stack-protector guard">;
+def mstack_protector_guard_reg_EQ : Joined<["-"], "mstack-protector-guard-reg=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the given reg for addressing the stack-protector guard">;
def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>,
Flags<[CC1Option]>,
HelpText<"Use copy relocations support for PIE builds">;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index b409773c1521..b9c90eee64ed 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -521,6 +521,14 @@ static void initTargetOptions(DiagnosticsEngine &Diags,
Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
Options.UniqueBasicBlockSectionNames =
CodeGenOpts.UniqueBasicBlockSectionNames;
+ Options.StackProtectorGuard =
+ llvm::StringSwitch<llvm::StackProtectorGuards>(CodeGenOpts
+ .StackProtectorGuard)
+ .Case("tls", llvm::StackProtectorGuards::TLS)
+ .Case("global", llvm::StackProtectorGuards::Global)
+ .Default(llvm::StackProtectorGuards::None);
+ Options.StackProtectorGuardOffset = CodeGenOpts.StackProtectorGuardOffset;
+ Options.StackProtectorGuardReg = CodeGenOpts.StackProtectorGuardReg;
Options.TLSSize = CodeGenOpts.TLSSize;
Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 34ccc8cffb79..0d3d7a47a3a8 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2984,8 +2984,9 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
}
-static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs, bool KernelOrKext) {
+static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ bool KernelOrKext) {
const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple();
// NVPTX doesn't support stack protectors; from the compiler's perspective, it
@@ -3030,6 +3031,50 @@ static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
A->claim();
}
}
+
+ // First support "tls" and "global" for X86 target.
+ // TODO: Support "sysreg" for AArch64.
+ const std::string &TripleStr = EffectiveTriple.getTriple();
+ if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
+ StringRef Value = A->getValue();
+ if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ if (Value != "tls" && Value != "global") {
+ D.Diag(diag::err_drv_invalid_value_with_suggestion)
+ << A->getOption().getName() << Value
+ << "valid arguments to '-mstack-protector-guard=' are:tls global";
+ return;
+ }
+ A->render(Args, CmdArgs);
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
+ StringRef Value = A->getValue();
+ if (!EffectiveTriple.isX86())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ unsigned Offset;
+ if (Value.getAsInteger(10, Offset)) {
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
+ return;
+ }
+ A->render(Args, CmdArgs);
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) {
+ StringRef Value = A->getValue();
+ if (!EffectiveTriple.isX86())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
+ D.Diag(diag::err_drv_invalid_value_with_suggestion)
+ << A->getOption().getName() << Value
+ << "for X86, valid arguments to '-mstack-protector-guard-reg=' are:fs gs";
+ return;
+ }
+ A->render(Args, CmdArgs);
+ }
}
static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
@@ -5467,7 +5512,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_mno_speculative_load_hardening, false))
CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
- RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext);
+ RenderSSPOptions(D, TC, Args, CmdArgs, KernelOrKext);
RenderSCPOptions(TC, Args, CmdArgs);
RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index f61a39363884..ff0df26dc1dd 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1254,6 +1254,21 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
Opts.SSPBufferSize =
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
+
+ Opts.StackProtectorGuard =
+ std::string(Args.getLastArgValue(OPT_mstack_protector_guard_EQ));
+
+ if (Arg *A = Args.getLastArg(OPT_mstack_protector_guard_offset_EQ)) {
+ StringRef Val = A->getValue();
+ unsigned Offset = Opts.StackProtectorGuardOffset;
+ Val.getAsInteger(10, Offset);
+ Opts.StackProtectorGuardOffset = Offset;
+ }
+
+ Opts.StackProtectorGuardReg =
+ std::string(Args.getLastArgValue(OPT_mstack_protector_guard_reg_EQ,
+ "none"));
+
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) {
StringRef Val = A->getValue();
diff --git a/clang/test/Driver/stack-protector-guard.c b/clang/test/Driver/stack-protector-guard.c
new file mode 100644
index 000000000000..f2bb8cd8555d
--- /dev/null
+++ b/clang/test/Driver/stack-protector-guard.c
@@ -0,0 +1,43 @@
+// RUN: %clang -### -target x86_64-unknown-unknown -mstack-protector-guard=tls %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-TLS %s
+// RUN: %clang -### -target x86_64-unknown-unknown -mstack-protector-guard=global %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s
+// RUN: %clang -### -target x86_64-unknown-unknown -mstack-protector-guard=local %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-VALUE %s
+
+// CHECK-TLS: "-cc1" {{.*}}"-mstack-protector-guard=tls"
+// CHECK-GLOBAL: "-cc1" {{.*}}"-mstack-protector-guard=global"
+// INVALID-VALUE: error: invalid value 'local' in 'mstack-protector-guard=','valid arguments to '-mstack-protector-guard=' are:tls global'
+
+// RUN: %clang -### -target x86_64-unknown-unknown -mstack-protector-guard-reg=fs %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-FS %s
+// RUN: %clang -### -target x86_64-unknown-unknown -mstack-protector-guard-reg=gs %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-GS %s
+
+// Invalid arch
+// RUN: not %clang -target arm-eabi-c -mstack-protector-guard=tls %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-ARCH %s
+// INVALID-ARCH: unsupported option '-mstack-protector-guard=tls' for target
+
+// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard-reg=fs %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-ARCH2 %s
+// INVALID-ARCH2: unsupported option '-mstack-protector-guard-reg=fs' for target
+
+// RUN: not %clang -target aarch64-linux-gnu -mstack-protector-guard-offset=10 %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-ARCH3 %s
+// INVALID-ARCH3: unsupported option '-mstack-protector-guard-offset=10' for target
+
+// Invalid option value
+// RUN: not %clang -target x86_64-unknown-unknown -c -mstack-protector-guard-reg=cs %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-REG %s
+// RUN: not %clang -target x86_64-unknown-unknown -c -mstack-protector-guard-reg=ds %s 2>&1 | \
+// RUN: FileCheck -check-prefix=INVALID-REG %s
+
+// CHECK-FS: "-cc1" {{.*}}"-mstack-protector-guard-reg=fs"
+// CHECK-GS: "-cc1" {{.*}}"-mstack-protector-guard-reg=gs"
+// INVALID-REG: error: invalid value {{.*}} in 'mstack-protector-guard-reg=','for X86, valid arguments to '-mstack-protector-guard-reg=' are:fs gs'
+
+// RUN: %clang -### -target x86_64-unknown-unknown -mstack-protector-guard-offset=30 %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-OFFSET %s
+
+// CHECK-OFFSET: "-cc1" {{.*}}"-mstack-protector-guard-offset=30"
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h
index b58fe2d43cdb..dd9a74cad8d7 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -99,6 +99,10 @@ bool getIgnoreXCOFFVisibility();
std::string getBBSections();
+std::string getStackProtectorGuard();
+unsigned getStackProtectorGuardOffset();
+std::string getStackProtectorGuardReg();
+
unsigned getTLSSize();
bool getEmulatedTLS();
@@ -135,6 +139,9 @@ struct RegisterCodeGenFlags {
llvm::BasicBlockSection getBBSectionsMode(llvm::TargetOptions &Options);
+llvm::StackProtectorGuards
+getStackProtectorGuardMode(llvm::TargetOptions &Options);
+
/// Common utility function tightly tied to the options listed here. Initializes
/// a TargetOptions object with CodeGen flags and returns it.
/// \p TheTriple is used to determine the default value for options if
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 049f5eff25e0..4c27ce0e09b8 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -73,6 +73,12 @@ namespace llvm {
None // Do not use Basic Block Sections.
};
+ enum class StackProtectorGuards {
+ None,
+ TLS,
+ Global
+ };
+
enum class EABI {
Unknown,
Default, // Default means not specified
@@ -307,6 +313,16 @@ namespace llvm {
/// Emit XRay Function Index section
unsigned XRayOmitFunctionIndex : 1;
+ /// Stack protector guard offset to use.
+ unsigned StackProtectorGuardOffset : 32;
+
+ /// Stack protector guard mode to use, e.g. tls, global.
+ StackProtectorGuards StackProtectorGuard =
+ StackProtectorGuards::None;
+
+ /// Stack protector guard reg to use, e.g. usually fs or gs in X86.
+ std::string StackProtectorGuardReg = "None";
+
/// FloatABIType - This setting is set by -float-abi=xxx option is specfied
/// on the command line. This setting may either be Default, Soft, or Hard.
/// Default selects the target's default behavior. Soft selects the ABI for
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp
index a9093586d696..bb15ff286d7c 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -76,6 +76,9 @@ CGOPT_EXP(bool, DataSections)
CGOPT_EXP(bool, FunctionSections)
CGOPT(bool, IgnoreXCOFFVisibility)
CGOPT(std::string, BBSections)
+CGOPT(std::string, StackProtectorGuard)
+CGOPT(unsigned, StackProtectorGuardOffset)
+CGOPT(std::string, StackProtectorGuardReg)
CGOPT(unsigned, TLSSize)
CGOPT(bool, EmulatedTLS)
CGOPT(bool, UniqueSectionNames)
@@ -348,6 +351,21 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
cl::init("none"));
CGBINDOPT(BBSections);
+ static cl::opt<std::string> StackProtectorGuard(
+ "stack-protector-guard", cl::desc("Stack protector guard mode"),
+ cl::init("none"));
+ CGBINDOPT(StackProtectorGuard);
+
+ static cl::opt<std::string> StackProtectorGuardReg(
+ "stack-protector-guard-reg", cl::desc("Stack protector guard register"),
+ cl::init("none"));
+ CGBINDOPT(StackProtectorGuardReg);
+
+ static cl::opt<unsigned> StackProtectorGuardOffset(
+ "stack-protector-guard-offset", cl::desc("Stack protector guard offset"),
+ cl::init((unsigned)-1));
+ CGBINDOPT(StackProtectorGuardOffset);
+
static cl::opt<unsigned> TLSSize(
"tls-size", cl::desc("Bit size of immediate TLS offsets"), cl::init(0));
CGBINDOPT(TLSSize);
@@ -459,6 +477,24 @@ codegen::getBBSectionsMode(llvm::TargetOptions &Options) {
}
}
+llvm::StackProtectorGuards
+codegen::getStackProtectorGuardMode(llvm::TargetOptions &Options) {
+ if (getStackProtectorGuard() == "tls")
+ return StackProtectorGuards::TLS;
+ if (getStackProtectorGuard() == "global")
+ return StackProtectorGuards::Global;
+ if (getStackProtectorGuard() != "none") {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
+ MemoryBuffer::getFile(getStackProtectorGuard());
+ if (!MBOrErr)
+ errs() << "error illegal stack protector guard mode: "
+ << MBOrErr.getError().message() << "\n";
+ else
+ Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
+ }
+ return StackProtectorGuards::None;
+}
+
// Common utility function tightly tied to the options listed here. Initializes
// a TargetOptions object with CodeGen flags and returns it.
TargetOptions
@@ -493,6 +529,9 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
Options.BBSections = getBBSectionsMode(Options);
Options.UniqueSectionNames = getUniqueSectionNames();
Options.UniqueBasicBlockSectionNames = getUniqueBasicBlockSectionNames();
+ Options.StackProtectorGuard = getStackProtectorGuardMode(Options);
+ Options.StackProtectorGuardOffset = getStackProtectorGuardOffset();
+ Options.StackProtectorGuardReg = getStackProtectorGuardReg();
Options.TLSSize = getTLSSize();
Options.EmulatedTLS = getEmulatedTLS();
Options.ExplicitEmulatedTLS = EmulatedTLSView->getNumOccurrences() > 0;
diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index 3d961af8ec3e..8074793bc627 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -381,7 +381,10 @@ bool StackProtector::RequiresStackProtector() {
static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
IRBuilder<> &B,
bool *SupportsSelectionDAGSP = nullptr) {
- if (Value *Guard = TLI->getIRStackGuard(B))
+ Value *Guard = TLI->getIRStackGuard(B);
+ auto GuardMode = TLI->getTargetMachine().Options.StackProtectorGuard;
+ if ((GuardMode == llvm::StackProtectorGuards::TLS ||
+ GuardMode == llvm::StackProtectorGuards::None) && Guard)
return B.CreateLoad(B.getInt8PtrTy(), Guard, true, "StackGuard");
// Use SelectionDAG SSP handling, since there isn't an IR guard.
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 036ad48cb935..14d308a384c1 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -2469,13 +2469,23 @@ Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const {
// <zircon/tls.h> defines ZX_TLS_STACK_GUARD_OFFSET with this value.
return SegmentOffset(IRB, 0x10, getAddressSpace());
} else {
+ unsigned AddressSpace = getAddressSpace();
+ // Specially, some users may customize the base reg and offset.
+ unsigned Offset = getTargetMachine().Options.StackProtectorGuardOffset;
+ // If we don't set -stack-protector-guard-offset value:
// %fs:0x28, unless we're using a Kernel code model, in which case
// it's %gs:0x28. gs:0x14 on i386.
- unsigned Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14;
- return SegmentOffset(IRB, Offset, getAddressSpace());
+ if (Offset == (unsigned)-1)
+ Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14;
+
+ auto GuardReg = getTargetMachine().Options.StackProtectorGuardReg;
+ if (GuardReg == "fs")
+ AddressSpace = X86AS::FS;
+ else if (GuardReg == "gs")
+ AddressSpace = X86AS::GS;
+ return SegmentOffset(IRB, Offset, AddressSpace);
}
}
-
return TargetLowering::getIRStackGuard(IRB);
}
@@ -2497,8 +2507,13 @@ void X86TargetLowering::insertSSPDeclarations(Module &M) const {
}
return;
}
+
+ auto GuardMode = getTargetMachine().Options.StackProtectorGuard;
+
// glibc, bionic, and Fuchsia have a special slot for the stack guard.
- if (hasStackGuardSlotTLS(Subtarget.getTargetTriple()))
+ if ((GuardMode == llvm::StackProtectorGuards::TLS ||
+ GuardMode == llvm::StackProtectorGuards::None)
+ && hasStackGuardSlotTLS(Subtarget.getTargetTriple()))
return;
TargetLowering::insertSSPDeclarations(M);
}
diff --git a/llvm/test/CodeGen/X86/stack-protector-3.ll b/llvm/test/CodeGen/X86/stack-protector-3.ll
new file mode 100644
index 000000000000..96b1a0860e6b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-protector-3.ll
@@ -0,0 +1,67 @@
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %s | FileCheck --check-prefix=CHECK-TLS-FS-40 %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard=tls -o - < %s | FileCheck --check-prefix=CHECK-TLS-FS-40 %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard=global -o - < %s | FileCheck --check-prefix=CHECK-GLOBAL %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-reg=fs -o - < %s | FileCheck --check-prefix=CHECK-TLS-FS-40 %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-reg=gs -o - < %s | FileCheck --check-prefix=CHECK-GS %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-offset=20 -o - < %s | FileCheck --check-prefix=CHECK-OFFSET %s
+
+; CHECK-TLS-FS-40: movq %fs:40, %rax
+; CHECK-TLS-FS-40: movq %fs:40, %rax
+; CHECK-TLS-FS-40-NEXT: cmpq 16(%rsp), %rax
+; CHECK-TLS-FS-40-NEXT: jne .LBB0_2
+; CHECK-TLS-FS-40: .LBB0_2:
+; CHECK-TLS-FS-40-NEXT: .cfi_def_cfa_offset 32
+; CHECK-TLS-FS-40-NEXT: callq __stack_chk_fail
+
+; CHECK-GS: movq %gs:40, %rax
+; CHECK-GS: movq %gs:40, %rax
+; CHECK-GS-NEXT: cmpq 16(%rsp), %rax
+; CHECK-GS-NEXT: jne .LBB0_2
+; CHECK-GS: .LBB0_2:
+; CHECK-GS-NEXT: .cfi_def_cfa_offset 32
+; CHECK-GS-NEXT: callq __stack_chk_fail
+
+; CHECK-OFFSET: movq %fs:20, %rax
+; CHECK-OFFSET: movq %fs:20, %rax
+; CHECK-OFFSET-NEXT: cmpq 16(%rsp), %rax
+; CHECK-OFFSET-NEXT: jne .LBB0_2
+; CHECK-OFFSET: .LBB0_2:
+; CHECK-OFFSET-NEXT: .cfi_def_cfa_offset 32
+; CHECK-OFFSET-NEXT: callq __stack_chk_fail
+
+; CHECK-GLOBAL: movq __stack_chk_guard(%rip), %rax
+; CHECK-GLOBAL: movq __stack_chk_guard(%rip), %rax
+; CHECK-GLOBAL-NEXT: cmpq 16(%rsp), %rax
+; CHECK-GLOBAL-NEXT: jne .LBB0_2
+; CHECK-GLOBAL: .LBB0_2:
+; CHECK-GLOBAL-NEXT: .cfi_def_cfa_offset 32
+; CHECK-GLOBAL-NEXT: callq __stack_chk_fail
+
+; ModuleID = 't.c'
+ at .str = private unnamed_addr constant [14 x i8] c"stackoverflow\00", align 1
+ at a = dso_local local_unnamed_addr global i8* null, align 8
+
+; Function Attrs: nounwind sspreq uwtable writeonly
+define dso_local i32 @main() local_unnamed_addr #0 {
+entry:
+ %array = alloca [5 x i8], align 1
+ %0 = getelementptr inbounds [5 x i8], [5 x i8]* %array, i64 0, i64 0
+ call void @llvm.lifetime.start.p0i8(i64 5, i8* nonnull %0) #2
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(14) %0, i8* nonnull align 1 dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0), i64 14, i1 false) #2
+ store i8* %0, i8** @a, align 8
+ call void @llvm.lifetime.end.p0i8(i64 5, i8* nonnull %0) #2
+ ret i32 0
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1
+
+attributes #0 = { nounwind sspreq uwtable writeonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { nounwind }
More information about the llvm-commits
mailing list