]> granicus.if.org Git - clang/commitdiff
Add stack protector support to clang. This generates the 'ssp' and 'sspreq'
authorBill Wendling <isanbard@gmail.com>
Sun, 28 Jun 2009 07:36:13 +0000 (07:36 +0000)
committerBill Wendling <isanbard@gmail.com>
Sun, 28 Jun 2009 07:36:13 +0000 (07:36 +0000)
function attributes. There are predefined macros that are defined when stack
protectors are used: __SSP__=1 with -fstack-protector and __SSP_ALL__=2 with
-fstack-protector-all.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74405 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/LangOptions.h
include/clang/Driver/ArgList.h
include/clang/Driver/Options.def
lib/Basic/Targets.cpp
lib/CodeGen/CGCall.cpp
lib/Driver/ArgList.cpp
lib/Driver/Tools.cpp
lib/Frontend/InitPreprocessor.cpp
test/CodeGen/stack-protector.c [new file with mode: 0644]
tools/clang-cc/clang-cc.cpp

index 543a0fff8e7bfbd39b122770aff86c46103869ba..9b308e1b322cd003021bc88d15fa80c7f8a34ef4 100644 (file)
@@ -84,6 +84,10 @@ public:
 
   unsigned OpenCL            : 1; // OpenCL C99 language extensions.
 
+  unsigned StackProtector    : 2; // Whether stack protectors are on:
+                                  //   0 - None
+                                  //   1 - On
+                                  //   2 - All
 
 private:
   unsigned GC : 2; // Objective-C Garbage Collection modes.  We declare
@@ -116,7 +120,7 @@ public:
     Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0;
     LaxVectorConversions = 1;
     HeinousExtensions = 0;
-    AltiVec = OpenCL = 0;
+    AltiVec = OpenCL = StackProtector = 0;
     
     SymbolVisibility = (unsigned) Default;
     
index 84e0329a375e0d789785ffe668a96a9ed9c0dd36..a9c890b0b899418006b7153e6c8120b7f9c4e975 100644 (file)
@@ -83,6 +83,8 @@ namespace driver {
     /// \arg Claim Whether the argument should be claimed, if it exists.
     Arg *getLastArg(options::ID Id, bool Claim=true) const;
     Arg *getLastArg(options::ID Id0, options::ID Id1, bool Claim=true) const;
+    Arg *getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
+                    bool Claim=true) const;
 
     /// getArgString - Return the input argument string at \arg Index.
     virtual const char *getArgString(unsigned Index) const = 0;
index abd07a92b1a26ee245028955ece8b5f97e846088..af108a85ebdd98b79bae36d14eaca6c8e2597787 100644 (file)
@@ -420,7 +420,7 @@ OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fno-show-column", fno_show_column, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fno-show-source-location", fno_show_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
-OPTION("-fno-stack-protector", fno_stack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-stack-protector", fno_stack_protector, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fno-strict-aliasing", fno_strict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fno-unit-at-a-time", fno_unit_at_a_time, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fno-unwind-tables", fno_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -450,7 +450,8 @@ OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
 OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0)
-OPTION("-fstack-protector", fstack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fstack-protector-all", fstack_protector_all, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fstack-protector", fstack_protector, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fstrict-aliasing", fstrict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fsyntax-only", fsyntax_only, Flag, INVALID, INVALID, "d", 0, 0, 0)
 OPTION("-ftemplate-depth-", ftemplate_depth_, Joined, f_Group, INVALID, "", 0, 0, 0)
index 9910e28fcda9e65d340cda94329c9a09c8672fbe..d1158a6c6fc20563deb49320b0e7552cce8db817 100644 (file)
@@ -235,11 +235,14 @@ static void GetDarwinLanguageOptions(LangOptions &Opts,
   if (!getDarwinNumber(Triple, Maj, Min, Rev))
     return;
 
-  // Blocks default to on for 10.6 (darwin10) and beyond.
-  // As does nonfragile-abi for 64bit mode
-  if (Maj > 9)
+  // Blocks and stack protectors default to on for 10.6 (darwin10) and beyond.
+  if (Maj > 9) {
     Opts.Blocks = 1;
+    Opts.StackProtector = 1;
+  }
 
+  // Non-fragile ABI (in 64-bit mode) default to on for 10.5 (darwin9) and
+  // beyond.
   if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6))
     Opts.ObjCNonFragileABI = 1;
 }
index 30c5d28c227eb4960a29fa2a61051e155915cd31..61b6737be11eeb799891b2389c4034b097465b57 100644 (file)
@@ -392,6 +392,11 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
   if (CompileOpts.NoImplicitFloat)
     FuncAttrs |= llvm::Attribute::NoImplicitFloat;
 
+  if (Features.StackProtector == 1)
+    FuncAttrs |= llvm::Attribute::StackProtect;
+  else if (Features.StackProtector == 2)
+    FuncAttrs |= llvm::Attribute::StackProtectReq;
+
   QualType RetTy = FI.getReturnType();
   unsigned Index = 1;
   const ABIArgInfo &RetAI = FI.getReturnInfo();
index 593694cfbbf678850513fdceb83c7de8541883fc..54dd4bb77538218421a17b1811c93196fd27d398 100644 (file)
@@ -49,6 +49,35 @@ Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const {
   return Res;
 }
 
+Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
+                         bool Claim) const {
+  Arg *Res = 0;
+  Arg *A0 = getLastArg(Id0, false);
+  Arg *A1 = getLastArg(Id1, false);
+  Arg *A2 = getLastArg(Id2, false);
+
+  int A0Idx = A0 ? A0->getIndex() : -1;
+  int A1Idx = A1 ? A1->getIndex() : -1;
+  int A2Idx = A2 ? A2->getIndex() : -1;
+
+  if (A0Idx > A1Idx) {
+    if (A0Idx > A2Idx)
+      Res = A0;
+    else if (A2Idx != -1)
+      Res = A2;
+  } else {
+    if (A1Idx > A2Idx)
+      Res = A1;
+    else if (A2Idx != -1)
+      Res = A2;
+  }
+
+  if (Claim && Res)
+    Res->claim();
+
+  return Res;
+}
+
 bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const {
   if (Arg *A = getLastArg(Pos, Neg))
     return A->getOption().matches(Pos);
index bfc247a015ff37ec832fef046d0508963e60e3e4..ac07906c8fd58b8d3d18459c831cd819aa6e09a2 100644 (file)
@@ -498,6 +498,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_fvisibility_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
 
+  // Forward stack protector flags.
+  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+                               options::OPT_fstack_protector_all,
+                               options::OPT_fstack_protector)) {
+    if (A->getOption().matches(options::OPT_fno_stack_protector))
+      CmdArgs.push_back("--stack-protector=0");
+    else if (A->getOption().matches(options::OPT_fstack_protector))
+      CmdArgs.push_back("--stack-protector=1");
+    else
+      CmdArgs.push_back("--stack-protector=2");
+  }
+
   // Forward -f options with positive and negative forms; we translate
   // these by hand.
 
index 730414e448221ecc9c9e903c393fd1fef25d09ba..554868fd27378557655d3bad377f82fdc231d5bf 100644 (file)
@@ -423,7 +423,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
   sprintf(MacroBuf, "__DECIMAL_DIG__=%d",
           PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36));
   DefineBuiltinMacro(Buf, MacroBuf);
-  
+
+  if (LangOpts.StackProtector == 1)
+    DefineBuiltinMacro(Buf, "__SSP__=1");
+  else if (LangOpts.StackProtector == 2)
+    DefineBuiltinMacro(Buf, "__SSP_ALL__=2");
+
   // Get other target #defines.
   TI.getTargetDefines(LangOpts, Buf);
 }
diff --git a/test/CodeGen/stack-protector.c b/test/CodeGen/stack-protector.c
new file mode 100644 (file)
index 0000000..bdac853
--- /dev/null
@@ -0,0 +1,22 @@
+// RUN: clang-cc -triple i686-unknown-unknown -emit-llvm -o %t %s &&
+// RUN: not grep 'ssp' %t &&
+// RUN: clang-cc -triple i686-apple-darwin9 -emit-llvm -o %t %s &&
+// RUN: not grep 'ssp' %t &&
+// RUN: clang-cc -triple i686-apple-darwin10 -emit-llvm -o %t %s &&
+// RUN: grep 'ssp' %t &&
+// RUN: clang -fstack-protector-all -emit-llvm -S -o %t %s &&
+// RUN: grep 'sspreq' %t &&
+// RUN: clang -fstack-protector -emit-llvm -S -o %t %s &&
+// RUN: grep 'ssp' %t &&
+// RUN: clang -fno-stack-protector -emit-llvm -S -o %t %s &&
+// RUN: not grep 'ssp' %t &&
+// RUN: true
+
+#include <stdio.h>
+#include <string.h>
+
+void test1(const char *msg) {
+  char a[strlen(msg) + 1];
+  strcpy(a, msg);
+  printf("%s\n", a);
+}
index a3ffb48281d12572adbab4cda7caca360f4a4707..a1efe0101d7053ec42fcb5c4c7ee89e4404e441b 100644 (file)
@@ -660,6 +660,11 @@ PICLevel("pic-level", llvm::cl::desc("Value for __PIC__"));
 static llvm::cl::opt<bool>
 StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
 
+static llvm::cl::opt<int>
+StackProtector("stack-protector",
+               llvm::cl::desc("Enable stack protectors"),
+               llvm::cl::init(-1));
+
 static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
                                        TargetInfo *Target,
                                        const llvm::StringMap<bool> &Features) {
@@ -814,6 +819,10 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
 
   Options.Static = StaticDefine;
 
+  assert(StackProtector <= 2 && "Invalid value for -stack-protector");
+  if (StackProtector != -1)
+    Options.StackProtector = StackProtector;
+
   if (MainFileName.getPosition())
     Options.setMainFileName(MainFileName.c_str());
 }