emmettneyman updated this revision to Diff 156364.
emmettneyman added a comment.

- Cleaned up leftover code from mmap memcpy


Repository:
  rC Clang

https://reviews.llvm.org/D49526

Files:
  clang/tools/clang-fuzzer/CMakeLists.txt
  clang/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp
  clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
  clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.cpp
  clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.h
  clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
  clang/tools/clang-fuzzer/handle-llvm/handle_llvm.h

Index: clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
===================================================================
--- clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
+++ clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
@@ -7,33 +7,53 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Implements HandleLLVM for use by the Clang fuzzers. Mimics the llc tool to
-// compile an LLVM IR file to X86_64 assembly.
+// Implements HandleLLVM for use by the Clang fuzzers. First runs an loop
+// vectorizer optimization pass over the given IR code. Then mimics lli on both
+// versions to JIT the generated code and execute it. Currently, functions are 
+// executed on dummy inputs.
 //
 //===----------------------------------------------------------------------===//
 
 #include "handle_llvm.h"
 
 #include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/CommandFlags.inc"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/LegacyPassNameParser.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/IRReader/IRReader.h"
+#include "llvm/Pass.h"
 #include "llvm/PassRegistry.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetMachine.h"
-
-#include <cstdlib>
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/IPO.h"
 
 using namespace llvm;
 
+static cl::list<const PassInfo*, bool, PassNameParser>
+PassList(cl::desc("Optimizations available:"));
+
+static std::string OptIR;
+
+// Helper function to parse command line args and find the optimization level
 static void getOptLevel(const std::vector<const char *> &ExtraArgs,
                               CodeGenOpt::Level &OLvl) {
   // Find the optimization level from the command line args
@@ -53,59 +73,220 @@
   }
 }
 
-void clang_fuzzer::HandleLLVM(const std::string &S,
-                              const std::vector<const char *> &ExtraArgs) {
+// Helper function to call pass initialization functions
+void InitEverything() {
+  PassRegistry &Registry = *PassRegistry::getPassRegistry();
+  initializeCore(Registry);
+  initializeScalarOpts(Registry);
+  initializeVectorization(Registry);
+  initializeIPO(Registry);
+  initializeAnalysis(Registry);
+  initializeTransformUtils(Registry);
+  initializeInstCombine(Registry);
+  initializeAggressiveInstCombine(Registry);
+  initializeInstrumentation(Registry);
+  initializeTarget(Registry);
+}
+
+// Helper function to add optimization passes to the TargetMachine at the 
+// specified optimization level, OptLevel
+static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
+                                  legacy::FunctionPassManager &FPM,
+                                  unsigned OptLevel, unsigned SizeLevel) {
+  // Verify that input is correct by adding a verifier pass
+  FPM.add(createVerifierPass());
+
+  // Create and initializa a PassManagerBuilder
+  PassManagerBuilder Builder;
+  Builder.OptLevel = OptLevel;
+  Builder.SizeLevel = SizeLevel;
+  Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
+  Builder.LoopVectorize = true;
+  Builder.populateFunctionPassManager(FPM);
+  Builder.populateModulePassManager(MPM);
+}
+
+// Mimics the opt tool to run an optimization pass over the provided IR
+void OptLLVM(const std::string IR, CodeGenOpt::Level &OLvl) {
+  InitEverything();
+ 
+  // Mimic argc and argv and pass them to ParseCommandLineOptions to initilize
+  // PassList, ie which optimizations we want to run on the IR
+  // TODO: Find a better way of doing this
+  char *args[2];
+  char t[18] = "llvm-proto-fuzzer";
+  char s[16] = "-loop-vectorize";
+  args[0] = t;
+  args[1] = s;
+  cl::ParseCommandLineOptions(2, args, "");
+
+  // Create a module that will run the optimization passes
+  SMDiagnostic Err;
+  LLVMContext Context;
+  std::unique_ptr<Module> M = parseIR(MemoryBufferRef(IR, "IR"), Err, Context);
+  if (!M || verifyModule(*M, &errs())) {
+    errs() << "error: could not parse IR!\n";
+    std::exit(1);
+  }
+
+  Triple ModuleTriple(M->getTargetTriple());
+  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+  std::string CPUStr;
+  std::string FeaturesStr;
+  TargetMachine *Machine = nullptr;
+  std::unique_ptr<TargetMachine> TM(Machine);
+  setFunctionAttributes(CPUStr, FeaturesStr, *M);
+  
+  legacy::PassManager Passes;
+  TargetLibraryInfoImpl TLII(ModuleTriple);
+  Passes.add(new TargetLibraryInfoWrapperPass(TLII));
+  Passes.add(createTargetTransformInfoWrapperPass(TargetIRAnalysis()));
+  
+  std::unique_ptr<legacy::FunctionPassManager> FPasses;
+  FPasses.reset(new legacy::FunctionPassManager(M.get()));
+  FPasses->add(createTargetTransformInfoWrapperPass(TargetIRAnalysis()));
+
+  AddOptimizationPasses(Passes, *FPasses, 3, 0);
+  const PassInfo *PassInf = PassList[0];
+  Pass *P = nullptr;
+  
+  if (PassInf->getNormalCtor())
+    P = PassInf->getNormalCtor()();
+  else {
+    errs() << "cannot create pass: " << PassInf->getPassName() << "\n";
+    std::exit(1);
+  }
+
+  if (P)
+    Passes.add(P);
+
+  if (FPasses) {
+    FPasses->doInitialization();
+    for (Function &F : *M)
+      FPasses->run(F);
+    FPasses->doFinalization();
+  }
+  Passes.add(createVerifierPass());
+  
+  // Add a pass that writes the optimized IR to an output stream
+  std::string outString;
+  raw_string_ostream OS(outString);
+  Passes.add(createPrintModulePass(OS, "", false));
+
+  Passes.run(*M);
+
+  // Save the resulting IR to OptIR
+  OptIR = outString;
+}
+
+// Main fuzz target called by ExampleClangLLVMProtoFuzzer.cpp
+// 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)
   // Parse ExtraArgs to set the optimization level
   CodeGenOpt::Level OLvl;
   getOptLevel(ExtraArgs, OLvl);
+  
+  // First we optimize the IR by running a loop vectorizer pass
+  OptLLVM(IR, OLvl);
 
-  // Set the Module to include the the IR code to be compiled
+  // Create and initialize two modules, one for the optimized code and one
+  // for the unoptimized code
   SMDiagnostic Err;
-
   LLVMContext Context;
-  std::unique_ptr<Module> M = parseIR(MemoryBufferRef(S, "IR"), Err, Context);
-  if (!M) {
+  std::unique_ptr<Module> Owner1 = parseIR(MemoryBufferRef(OptIR, "IR"), Err,
+                                           Context);
+  std::unique_ptr<Module> Owner2 = parseIR(MemoryBufferRef(IR, "IR"), Err,
+                                           Context);
+  Module *M1 = Owner1.get();
+  Module *M2 = Owner2.get();
+  if (!M1 || !M2) {
     errs() << "error: could not parse IR!\n";
     std::exit(1);
   }
 
-  // Create a new Target
-  std::string Error;
-  const Target *TheTarget = TargetRegistry::lookupTarget(
-      sys::getDefaultTargetTriple(), Error);
-  if (!TheTarget) {
-    errs() << Error;
+  // Create and initialize two EngineBuilders from the Modules made above
+  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+  
+  std::string ErrorMsg1;
+  EngineBuilder builder1(std::move(Owner1));
+  builder1.setMArch(MArch);
+  builder1.setMCPU(getCPUStr());
+  builder1.setMAttrs(getFeatureList());
+  builder1.setErrorStr(&ErrorMsg1);
+  builder1.setEngineKind(EngineKind::JIT);
+  builder1.setUseOrcMCJITReplacement(false);
+  RTDyldMemoryManager *RTDyldMM1 = nullptr;
+  RTDyldMM1 = new SectionMemoryManager();
+  builder1.setMCJITMemoryManager(
+      std::unique_ptr<RTDyldMemoryManager>(RTDyldMM1));
+  builder1.setOptLevel(OLvl);
+  builder1.setTargetOptions(Options);
+
+  std::string ErrorMsg2;
+  EngineBuilder builder2(std::move(Owner2));
+  builder2.setMArch(MArch);
+  builder2.setMCPU(getCPUStr());
+  builder2.setMAttrs(getFeatureList());
+  builder2.setErrorStr(&ErrorMsg1);
+  builder2.setEngineKind(EngineKind::JIT);
+  builder2.setUseOrcMCJITReplacement(false);
+  RTDyldMemoryManager *RTDyldMM2 = nullptr;
+  RTDyldMM2 = new SectionMemoryManager();
+  builder2.setMCJITMemoryManager(
+      std::unique_ptr<RTDyldMemoryManager>(RTDyldMM2));
+  builder2.setOptLevel(CodeGenOpt::None);
+  builder2.setTargetOptions(Options);
+
+  std::unique_ptr<ExecutionEngine> EE1(builder1.create());
+  if (!EE1) {
+    if (!ErrorMsg1.empty())
+      errs() << "error creating EE1: " << ErrorMsg1 << "\n";
+    else
+      errs()  << "unknown error creating EE1!\n";
     std::exit(1);
   }
 
-  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+  std::unique_ptr<ExecutionEngine> EE2(builder2.create());
+  if (!EE2) {
+    if (!ErrorMsg2.empty())
+      errs() << "error creating EE2: " << ErrorMsg2 << "\n";
+    else
+      errs() << "unknown error creating EE2!\n";
+    std::exit(1);
+  }
 
-  // Create a new Machine
-  std::string CPUStr = getCPUStr();
-  std::string FeaturesStr = getFeaturesStr();
-  std::unique_ptr<TargetMachine> Target(TheTarget->createTargetMachine(
-      sys::getDefaultTargetTriple(), CPUStr, FeaturesStr, Options,
-      getRelocModel(), getCodeModel(), OLvl));
-
-  // Create a new PassManager
-  legacy::PassManager PM;
-  TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
-  PM.add(new TargetLibraryInfoWrapperPass(TLII));
-  M->setDataLayout(Target->createDataLayout());
- 
-  // Make sure the Module has no errors
-  if (verifyModule(*M, &errs())) {
-    errs() << "error: input module is broken!\n";
+  //Specify the functions we want to call from the IR
+  Function *EntryFunc1 = M1->getFunction("foo");
+  Function *EntryFunc2 = M2->getFunction("foo");
+  if (!EntryFunc1 || !EntryFunc2) {
+    errs() << '\'' << EntryFunc1 << "\' function not found in module.\n";
     std::exit(1);
-  } 
+  }
 
-  setFunctionAttributes(CPUStr, FeaturesStr, *M);
-  
-  raw_null_ostream OS;
-  Target->addPassesToEmitFile(PM, OS, nullptr, TargetMachine::CGFT_ObjectFile,
-                              false);
-  PM.run(*M);
+  typedef void (*func)(int*, int*, int*, int);
 
+  EE1->finalizeObject();
+  EE1->runStaticConstructorsDestructors(false);
+  func f1 = (func) EE1->getPointerToFunction(EntryFunc1); 
+
+  EE2->finalizeObject();
+  EE2->runStaticConstructorsDestructors(false);
+  func f2 = (func) EE2->getPointerToFunction(EntryFunc2);
+
+  // Clear instruction cache before code will be executed.
+  if(RTDyldMM1)
+    static_cast<SectionMemoryManager*>(RTDyldMM1)->invalidateInstructionCache();
+  if(RTDyldMM2)
+    static_cast<SectionMemoryManager*>(RTDyldMM2)->invalidateInstructionCache();
+
+  // Define some dummy arrays to use an input for now
+  int a[] = {1};
+  int b[] = {1};
+  int c[] = {1};
+  
+  (*f1)(a, b, c, 1);
+  (*f2)(a, b, c, 1);
+  
   return;
 }
-
Index: clang/tools/clang-fuzzer/handle-llvm/handle_llvm.h
===================================================================
--- clang/tools/clang-fuzzer/handle-llvm/handle_llvm.h
+++ clang/tools/clang-fuzzer/handle-llvm/handle_llvm.h
@@ -19,7 +19,8 @@
 
 namespace clang_fuzzer {
 void HandleLLVM(const std::string &S,
-               const std::vector<const char *> &ExtraArgs);
+               const std::vector<const char *> &ExtraArgs,
+               char *m1, char *m2);
 } // namespace clang_fuzzer
 
 #endif
Index: clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.h
===================================================================
--- clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.h
+++ clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.h
@@ -1,25 +1,19 @@
-//==-- handle_llvm.h - Helper function for Clang fuzzers -------------------==//
+//==-- fuzzer_initialize.h - Fuzz Clang ------------------------------------==//
 //
 //                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
-// Defines HandleLLVM for use by the Clang fuzzers.
+// Defines a function that returns the command line arguments for a specific
+// call to the fuzz target.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H
-#define LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H
-
-#include <string>
 #include <vector>
 
 namespace clang_fuzzer {
-void HandleLLVM(const std::string &S,
-               const std::vector<const char *> &ExtraArgs);
-} // namespace clang_fuzzer
-
-#endif
+const std::vector<const char *>& GetCLArgs();
+}
Index: clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.cpp
===================================================================
--- /dev/null
+++ clang/tools/clang-fuzzer/handle-llvm/fuzzer_initialize.cpp
@@ -0,0 +1,52 @@
+//===-- fuzzer_initialize.cpp - Fuzz Clang --------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a few functions: one that returns the command line
+/// arguments for a given call to the fuzz target and one that initializes
+/// the fuzzer with the correct command line arguments. It also initializes two
+/// regions in memory for the fuzzer to use to insert and execute generated
+/// code. Getter methods for those two regions are also included.
+///
+//===----------------------------------------------------------------------===//
+
+#include "fuzzer_initialize.h"
+
+#include "llvm/Support/TargetSelect.h"
+#include <cstring>
+#include <sys/mman.h>
+
+using namespace clang_fuzzer;
+
+
+namespace clang_fuzzer {
+
+static std::vector<const char *> CLArgs;
+
+const std::vector<const char *>& GetCLArgs() {
+  return CLArgs;
+}
+}
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllAsmPrinters();
+  llvm::InitializeAllAsmParsers();
+
+  CLArgs.push_back("-O2");
+  for (int I = 1; I < *argc; I++) {
+    if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) {
+      for (I++; I < *argc; I++)
+        CLArgs.push_back((*argv)[I]);
+      break;
+    }
+  }
+  return 0;
+}
Index: clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
===================================================================
--- clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
+++ clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
@@ -1,5 +1,29 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support)
+set(LLVM_LINK_COMPONENTS
+  CodeGen
+  Core
+  ExecutionEngine
+  IRReader
+  MC
+  MCJIT
+  Object
+  RuntimeDyld
+  SelectionDAG
+  Support
+  Target
+  TransformUtils
+  native
+)
+
+# Depend on LLVM IR instrinsic generation.
+set(handle_llvm_deps intrinsics_gen)
+if (CLANG_BUILT_STANDALONE)
+  set(handle_llvm_deps)
+endif()
 
 add_clang_library(clangHandleLLVM
   handle_llvm.cpp
+  fuzzer_initialize.cpp
+  
+  DEPENDS
+  ${handle_llvm_deps}
   )
Index: clang/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp
===================================================================
--- clang/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp
+++ clang/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp
@@ -15,7 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "cxx_loop_proto.pb.h"
-#include "fuzzer-initialize/fuzzer_initialize.h"
+#include "handle-llvm/fuzzer_initialize.h"
 #include "handle-llvm/handle_llvm.h"
 #include "proto-to-llvm/loop_proto_to_llvm.h"
 #include "src/libfuzzer/libfuzzer_macro.h"
Index: clang/tools/clang-fuzzer/CMakeLists.txt
===================================================================
--- clang/tools/clang-fuzzer/CMakeLists.txt
+++ clang/tools/clang-fuzzer/CMakeLists.txt
@@ -79,19 +79,20 @@
     ${ProtobufMutator_LIBRARIES}
     ${PROTOBUF_LIBRARIES}
     ${LLVM_LIB_FUZZING_ENGINE}
-    clangFuzzerInitialize
     )
 
   target_link_libraries(clang-proto-fuzzer
     PRIVATE
     ${COMMON_PROTO_FUZZ_LIBRARIES}
+    clangFuzzerInitialize
     clangHandleCXX
     clangCXXProto
     clangProtoToCXX
     )
   target_link_libraries(clang-loop-proto-fuzzer
     PRIVATE
     ${COMMON_PROTO_FUZZ_LIBRARIES}
+    clangFuzzerInitialize
     clangHandleCXX
     clangCXXLoopProto
     clangLoopProtoToCXX
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to