]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
Vendor import of llvm trunk r338150:
[FreeBSD/FreeBSD.git] / tools / llvm-isel-fuzzer / llvm-isel-fuzzer.cpp
1 //===--- llvm-isel-fuzzer.cpp - Fuzzer for instruction selection ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Tool to fuzz instruction selection using libFuzzer.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Analysis/TargetLibraryInfo.h"
16 #include "llvm/Bitcode/BitcodeReader.h"
17 #include "llvm/Bitcode/BitcodeWriter.h"
18 #include "llvm/CodeGen/CommandFlags.inc"
19 #include "llvm/FuzzMutate/FuzzerCLI.h"
20 #include "llvm/FuzzMutate/IRMutator.h"
21 #include "llvm/FuzzMutate/Operations.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/LLVMContext.h"
24 #include "llvm/IR/LegacyPassManager.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/IR/Verifier.h"
27 #include "llvm/IRReader/IRReader.h"
28 #include "llvm/Support/DataTypes.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/SourceMgr.h"
31 #include "llvm/Support/TargetRegistry.h"
32 #include "llvm/Support/TargetSelect.h"
33 #include "llvm/Target/TargetMachine.h"
34
35 #define DEBUG_TYPE "isel-fuzzer"
36
37 using namespace llvm;
38
39 static cl::opt<char>
40 OptLevel("O",
41          cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
42                   "(default = '-O2')"),
43          cl::Prefix,
44          cl::ZeroOrMore,
45          cl::init(' '));
46
47 static cl::opt<std::string>
48 TargetTriple("mtriple", cl::desc("Override target triple for module"));
49
50 static std::unique_ptr<TargetMachine> TM;
51 static std::unique_ptr<IRMutator> Mutator;
52
53 std::unique_ptr<IRMutator> createISelMutator() {
54   std::vector<TypeGetter> Types{
55       Type::getInt1Ty,  Type::getInt8Ty,  Type::getInt16Ty, Type::getInt32Ty,
56       Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
57
58   std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
59   Strategies.emplace_back(
60       new InjectorIRStrategy(InjectorIRStrategy::getDefaultOps()));
61   Strategies.emplace_back(new InstDeleterIRStrategy());
62
63   return llvm::make_unique<IRMutator>(std::move(Types), std::move(Strategies));
64 }
65
66 extern "C" LLVM_ATTRIBUTE_USED size_t LLVMFuzzerCustomMutator(
67     uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
68   LLVMContext Context;
69   std::unique_ptr<Module> M;
70   if (Size <= 1)
71     // We get bogus data given an empty corpus - just create a new module.
72     M.reset(new Module("M", Context));
73   else
74     M = parseModule(Data, Size, Context);
75
76   Mutator->mutateModule(*M, Seed, Size, MaxSize);
77
78   return writeModule(*M, Data, MaxSize);
79 }
80
81 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
82   if (Size <= 1)
83     // We get bogus data given an empty corpus - ignore it.
84     return 0;
85
86   LLVMContext Context;
87   auto M = parseAndVerify(Data, Size, Context);
88   if (!M) {
89     errs() << "error: input module is broken!\n";
90     return 0;
91   }
92
93   // Set up the module to build for our target.
94   M->setTargetTriple(TM->getTargetTriple().normalize());
95   M->setDataLayout(TM->createDataLayout());
96
97   // Build up a PM to do instruction selection.
98   legacy::PassManager PM;
99   TargetLibraryInfoImpl TLII(TM->getTargetTriple());
100   PM.add(new TargetLibraryInfoWrapperPass(TLII));
101   raw_null_ostream OS;
102   TM->addPassesToEmitFile(PM, OS, nullptr, TargetMachine::CGFT_Null);
103   PM.run(*M);
104
105   return 0;
106 }
107
108 static void handleLLVMFatalError(void *, const std::string &Message, bool) {
109   // TODO: Would it be better to call into the fuzzer internals directly?
110   dbgs() << "LLVM ERROR: " << Message << "\n"
111          << "Aborting to trigger fuzzer exit handling.\n";
112   abort();
113 }
114
115 extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int *argc,
116                                                         char ***argv) {
117   EnableDebugBuffering = true;
118
119   InitializeAllTargets();
120   InitializeAllTargetMCs();
121   InitializeAllAsmPrinters();
122   InitializeAllAsmParsers();
123
124   handleExecNameEncodedBEOpts(*argv[0]);
125   parseFuzzerCLOpts(*argc, *argv);
126
127   if (TargetTriple.empty()) {
128     errs() << *argv[0] << ": -mtriple must be specified\n";
129     exit(1);
130   }
131
132   Triple TheTriple = Triple(Triple::normalize(TargetTriple));
133
134   // Get the target specific parser.
135   std::string Error;
136   const Target *TheTarget =
137       TargetRegistry::lookupTarget(MArch, TheTriple, Error);
138   if (!TheTarget) {
139     errs() << argv[0] << ": " << Error;
140     return 1;
141   }
142
143   // Set up the pipeline like llc does.
144   std::string CPUStr = getCPUStr(), FeaturesStr = getFeaturesStr();
145
146   CodeGenOpt::Level OLvl = CodeGenOpt::Default;
147   switch (OptLevel) {
148   default:
149     errs() << argv[0] << ": invalid optimization level.\n";
150     return 1;
151   case ' ': break;
152   case '0': OLvl = CodeGenOpt::None; break;
153   case '1': OLvl = CodeGenOpt::Less; break;
154   case '2': OLvl = CodeGenOpt::Default; break;
155   case '3': OLvl = CodeGenOpt::Aggressive; break;
156   }
157
158   TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
159   TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr,
160                                           FeaturesStr, Options, getRelocModel(),
161                                           getCodeModel(), OLvl));
162   assert(TM && "Could not allocate target machine!");
163
164   // Make sure we print the summary and the current unit when LLVM errors out.
165   install_fatal_error_handler(handleLLVMFatalError, nullptr);
166
167   // Finally, create our mutator.
168   Mutator = createISelMutator();
169   return 0;
170 }