diff options
Diffstat (limited to 'tools/clang-fuzzer/handle-llvm/handle_llvm.cpp')
-rw-r--r-- | tools/clang-fuzzer/handle-llvm/handle_llvm.cpp | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp index ef544ae711aba..86df06ab8b4b9 100644 --- a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp +++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "handle_llvm.h" +#include "input_arrays.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -48,6 +49,9 @@ using namespace llvm; +// Define a type for the functions that are compiled and executed +typedef void (*LLVMFunc)(int*, int*, int*, int); + // Helper function to parse command line args and find the optimization level static void getOptLevel(const std::vector<const char *> &ExtraArgs, CodeGenOpt::Level &OLvl) { @@ -68,7 +72,7 @@ static void getOptLevel(const std::vector<const char *> &ExtraArgs, } } -void ErrorAndExit(std::string message) { +static void ErrorAndExit(std::string message) { errs()<< "ERROR: " << message << "\n"; std::exit(1); } @@ -88,7 +92,7 @@ static void AddOptimizationPasses(legacy::PassManagerBase &MPM, } // Mimics the opt tool to run an optimization pass over the provided IR -std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) { +static std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) { // Create a module that will run the optimization passes SMDiagnostic Err; LLVMContext Context; @@ -96,17 +100,29 @@ std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) { if (!M || verifyModule(*M, &errs())) ErrorAndExit("Could not parse IR"); + Triple ModuleTriple(M->getTargetTriple()); + const TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); + std::string E; + const Target *TheTarget = TargetRegistry::lookupTarget(MArch, ModuleTriple, E); + TargetMachine *Machine = + TheTarget->createTargetMachine(M->getTargetTriple(), getCPUStr(), + getFeaturesStr(), Options, getRelocModel(), + getCodeModel(), OLvl); + std::unique_ptr<TargetMachine> TM(Machine); setFunctionAttributes(getCPUStr(), getFeaturesStr(), *M); - + legacy::PassManager Passes; - Triple ModuleTriple(M->getTargetTriple()); Passes.add(new TargetLibraryInfoWrapperPass(ModuleTriple)); - Passes.add(createTargetTransformInfoWrapperPass(TargetIRAnalysis())); + Passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); + + LLVMTargetMachine <M = static_cast<LLVMTargetMachine &>(*TM); + Passes.add(LTM.createPassConfig(Passes)); + Passes.add(createVerifierPass()); AddOptimizationPasses(Passes, OLvl, 0); - + // Add a pass that writes the optimized IR to an output stream std::string outString; raw_string_ostream OS(outString); @@ -117,11 +133,19 @@ std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) { return OS.str(); } -void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) { +// Takes a function and runs it on a set of inputs +// First determines whether f is the optimized or unoptimized function +static void RunFuncOnInputs(LLVMFunc f, int Arr[kNumArrays][kArraySize]) { + for (int i = 0; i < kNumArrays / 3; i++) + f(Arr[i], Arr[i + (kNumArrays / 3)], Arr[i + (2 * kNumArrays / 3)], + kArraySize); +} + +// Takes a string of IR and compiles it using LLVM's JIT Engine +static void CreateAndRunJITFunc(const std::string &IR, CodeGenOpt::Level OLvl) { SMDiagnostic Err; LLVMContext Context; - std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err, - Context); + std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err, Context); if (!M) ErrorAndExit("Could not parse IR"); @@ -148,14 +172,26 @@ void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) { EE->finalizeObject(); EE->runStaticConstructorsDestructors(false); - typedef void (*func)(int*, int*, int*, int); - func f = reinterpret_cast<func>(EE->getPointerToFunction(EntryFunc)); - - // Define some dummy arrays to use an input for now - int a[] = {1}; - int b[] = {1}; - int c[] = {1}; - f(a, b, c, 1); +#if defined(__GNUC__) && !defined(__clang) && \ + ((__GNUC__ == 4) && (__GNUC_MINOR__ < 9)) +// Silence +// +// warning: ISO C++ forbids casting between pointer-to-function and +// pointer-to-object [-Wpedantic] +// +// Since C++11 this casting is conditionally supported and GCC versions +// starting from 4.9.0 don't warn about the cast. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + LLVMFunc f = reinterpret_cast<LLVMFunc>(EE->getPointerToFunction(EntryFunc)); +#if defined(__GNUC__) && !defined(__clang) && \ + ((__GNUC__ == 4) && (__GNUC_MINOR__ < 9)) +#pragma GCC diagnostic pop +#endif + + // Figure out if we are running the optimized func or the unoptimized func + RunFuncOnInputs(f, (OLvl == CodeGenOpt::None) ? UnoptArrays : OptArrays); EE->runStaticConstructorsDestructors(true); } @@ -164,6 +200,10 @@ void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) { // Mimics the lli tool to JIT the LLVM IR code and execute it void clang_fuzzer::HandleLLVM(const std::string &IR, const std::vector<const char *> &ExtraArgs) { + // Populate OptArrays and UnoptArrays with the arrays from InputArrays + memcpy(OptArrays, InputArrays, kTotalSize); + memcpy(UnoptArrays, InputArrays, kTotalSize); + // Parse ExtraArgs to set the optimization level CodeGenOpt::Level OLvl; getOptLevel(ExtraArgs, OLvl); @@ -171,8 +211,11 @@ void clang_fuzzer::HandleLLVM(const std::string &IR, // First we optimize the IR by running a loop vectorizer pass std::string OptIR = OptLLVM(IR, OLvl); - CreateAndRunJITFun(OptIR, OLvl); - CreateAndRunJITFun(IR, CodeGenOpt::None); - + CreateAndRunJITFunc(OptIR, OLvl); + CreateAndRunJITFunc(IR, CodeGenOpt::None); + + if (memcmp(OptArrays, UnoptArrays, kTotalSize)) + ErrorAndExit("!!!BUG!!!"); + return; } |