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,20 @@ } } + // 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"); + } + // 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 @@ -444,6 +444,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; 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,21 @@ 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 (llvm::StringRef(*i) == "-o") + i++; + else + SeedData.append(*i); + } + llvm::RandomNumberGenerator::EntropyData = SeedData; + // Execute the frontend actions. Success = ExecuteCompilerInvocation(Clang.get());