Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -167,6 +167,8 @@ HelpText<"Turn off Type Based Alias Analysis">; def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, HelpText<"Turn on struct-path aware Type Based Alias Analysis">; +def nop_insertion : Flag<["-"], "nop-insertion">, + HelpText<"Randomly insert NOPs">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -407,6 +407,7 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">, Group, Flags<[CC1Option]>, HelpText<"Print a template comparison tree for differing templates">; +def fdiversify : Flag<["-"], "fdiversify">, Group; def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group, HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>; def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group; @@ -719,7 +720,7 @@ def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group; def fprofile_generate : Flag<["-"], "fprofile-generate">, Group; def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>; -def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group; +def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group, Flags<[CC1Option]>; def freg_struct_return : Flag<["-"], "freg-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Override the default ABI to return small structs in registers">; def frtti : Flag<["-"], "frtti">, Group; Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -111,6 +111,9 @@ /// file, for example with -save-temps. std::string MainFileName; + /// Random seed used for the random number generator + uint64_t RandomSeed; + /// The name for the split debug info file that we'll break out. This is used /// in the backend for setting the name in the skeleton cu. std::string SplitDwarfFile; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -151,6 +151,8 @@ CODEGENOPT(SanitizeRecover, 1, 1) ///< Attempt to recover from sanitizer checks ///< by continuing execution when possible +CODEGENOPT(NOPInsertion, 1, 0) ///< Randomly add NOPs + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -470,6 +470,7 @@ Options.TrapFuncName = CodeGenOpts.TrapFuncName; Options.PositionIndependentExecutable = LangOpts.PIELevel != 0; Options.EnableSegmentedStacks = CodeGenOpts.EnableSegmentedStacks; + Options.NOPInsertion = CodeGenOpts.NOPInsertion; TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr, Options, Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -3017,6 +3018,22 @@ } } +#if LLVM_ENABLE_RNG + // Translate -frandom-seed to seed the LLVM RNG + if (Args.hasArg(options::OPT_frandom_seed_EQ)) { + StringRef seed = Args.getLastArgValue(options::OPT_frandom_seed_EQ); + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back(Args.MakeArgString("-rng-seed=" + seed)); + } + + if (Args.hasArg(options::OPT_fdiversify)) { + CmdArgs.push_back("-nop-insertion"); + + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-sched-randomize"); + } +#endif + // Forward -f options with positive and negative forms; we translate // these by hand. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -35,7 +35,9 @@ #include "llvm/Support/Process.h" #include "llvm/Support/system_error.h" #include +#include "llvm/Support/raw_ostream.h" using namespace clang; +using namespace llvm; //===----------------------------------------------------------------------===// // Initialization. @@ -444,6 +446,8 @@ Opts.SSPBufferSize = getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); + Opts.NOPInsertion = Args.hasArg(OPT_nop_insertion); + if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) { StringRef Val = A->getValue(); unsigned StackAlignment = Opts.StackAlignment; @@ -1367,6 +1371,8 @@ OPT_fno_deprecated_macro, Opts.Deprecated); + + // FIXME: Eliminate this dependency. unsigned Opt = getOptimizationLevel(Args, IK, Diags), OptSize = getOptimizationLevelSize(Args); @@ -1635,7 +1641,7 @@ } // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of // PCH file and find the original header name. Remove the need to do that in - // ParsePreprocessorArgs and remove the FileManager + // ParsePreprocessorArgs and remove the FileManager // parameters from the function and the "FileManager.h" #include. FileManager FileMgr(Res.getFileSystemOpts()); ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags); Index: tools/driver/cc1_main.cpp =================================================================== --- tools/driver/cc1_main.cpp +++ tools/driver/cc1_main.cpp @@ -28,6 +28,7 @@ #include "llvm/Option/OptTable.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" @@ -96,6 +97,24 @@ if (!Success) return 1; + // Collect seeding data for the RNG + std::string seeddata; + for (const char** i = ArgBegin; i != ArgEnd; ++i) { + // tmjackso: Skip the -o option because clang (and GCC) generate a + // random temp file to hold a compiled object if one isn't + // specified. This happens if you combine compilation and linking + // into one step. There may be a cleaner way of doing this, but + // this is explicit and obvious. + if (strncmp(*i, "-o", 2) == 0) { + i++; + } + else{ + // Concatenate options for seeding. + seeddata.append(*i); + } + } + llvm::RandomNumberGenerator::EntropyData = seeddata; + // Execute the frontend actions. Success = ExecuteCompilerInvocation(Clang.get());