From 45483f7a1b3e57b4603b141bee80596b2d4dd443 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Sun, 28 Jun 2009 07:36:13 +0000 Subject: [PATCH] Add stack protector support to clang. This generates the 'ssp' and 'sspreq' 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 | 6 +++++- include/clang/Driver/ArgList.h | 2 ++ include/clang/Driver/Options.def | 5 +++-- lib/Basic/Targets.cpp | 9 ++++++--- lib/CodeGen/CGCall.cpp | 5 +++++ lib/Driver/ArgList.cpp | 29 +++++++++++++++++++++++++++++ lib/Driver/Tools.cpp | 12 ++++++++++++ lib/Frontend/InitPreprocessor.cpp | 7 ++++++- test/CodeGen/stack-protector.c | 22 ++++++++++++++++++++++ tools/clang-cc/clang-cc.cpp | 9 +++++++++ 10 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 test/CodeGen/stack-protector.c diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 543a0fff8e..9b308e1b32 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -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; diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 84e0329a37..a9c890b0b8 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -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; diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index abd07a92b1..af108a85eb 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -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) diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 9910e28fcd..d1158a6c6f 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -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; } diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 30c5d28c22..61b6737be1 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -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(); diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp index 593694cfbb..54dd4bb775 100644 --- a/lib/Driver/ArgList.cpp +++ b/lib/Driver/ArgList.cpp @@ -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); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index bfc247a015..ac07906c8f 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -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. diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 730414e448..554868fd27 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -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 index 0000000000..bdac853aed --- /dev/null +++ b/test/CodeGen/stack-protector.c @@ -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 +#include + +void test1(const char *msg) { + char a[strlen(msg) + 1]; + strcpy(a, msg); + printf("%s\n", a); +} diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index a3ffb48281..a1efe0101d 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -660,6 +660,11 @@ PICLevel("pic-level", llvm::cl::desc("Value for __PIC__")); static llvm::cl::opt StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined")); +static llvm::cl::opt +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 &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()); }