LLVM  14.0.0git
FuzzerCLI.cpp
Go to the documentation of this file.
1 //===-- FuzzerCLI.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/ADT/Triple.h"
14 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/Error.h"
19 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/IR/Verifier.h"
22 
23 using namespace llvm;
24 
25 void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
26  std::vector<const char *> CLArgs;
27  CLArgs.push_back(ArgV[0]);
28 
29  int I = 1;
30  while (I < ArgC)
31  if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1"))
32  break;
33  while (I < ArgC)
34  CLArgs.push_back(ArgV[I++]);
35 
36  cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
37 }
38 
40  std::vector<std::string> Args{std::string(ExecName)};
41 
42  auto NameAndArgs = ExecName.split("--");
43  if (NameAndArgs.second.empty())
44  return;
45 
47  NameAndArgs.second.split(Opts, '-');
48  for (StringRef Opt : Opts) {
49  if (Opt.equals("gisel")) {
50  Args.push_back("-global-isel");
51  // For now we default GlobalISel to -O0
52  Args.push_back("-O0");
53  } else if (Opt.startswith("O")) {
54  Args.push_back("-" + Opt.str());
55  } else if (Triple(Opt).getArch()) {
56  Args.push_back("-mtriple=" + Opt.str());
57  } else {
58  errs() << ExecName << ": Unknown option: " << Opt << ".\n";
59  exit(1);
60  }
61  }
62  errs() << NameAndArgs.first << ": Injected args:";
63  for (int I = 1, E = Args.size(); I < E; ++I)
64  errs() << " " << Args[I];
65  errs() << "\n";
66 
67  std::vector<const char *> CLArgs;
68  CLArgs.reserve(Args.size());
69  for (std::string &S : Args)
70  CLArgs.push_back(S.c_str());
71 
72  cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
73 }
74 
76  // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts'
77  std::vector<std::string> Args{std::string(ExecName)};
78 
79  auto NameAndArgs = ExecName.split("--");
80  if (NameAndArgs.second.empty())
81  return;
82 
84  NameAndArgs.second.split(Opts, '-');
85  for (StringRef Opt : Opts) {
86  if (Opt == "instcombine") {
87  Args.push_back("-passes=instcombine");
88  } else if (Opt == "earlycse") {
89  Args.push_back("-passes=early-cse");
90  } else if (Opt == "simplifycfg") {
91  Args.push_back("-passes=simplifycfg");
92  } else if (Opt == "gvn") {
93  Args.push_back("-passes=gvn");
94  } else if (Opt == "sccp") {
95  Args.push_back("-passes=sccp");
96 
97  } else if (Opt == "loop_predication") {
98  Args.push_back("-passes=loop-predication");
99  } else if (Opt == "guard_widening") {
100  Args.push_back("-passes=guard-widening");
101  } else if (Opt == "loop_rotate") {
102  Args.push_back("-passes=loop(rotate)");
103  } else if (Opt == "loop_unswitch") {
104  Args.push_back("-passes=loop(simple-loop-unswitch)");
105  } else if (Opt == "loop_unroll") {
106  Args.push_back("-passes=unroll");
107  } else if (Opt == "loop_vectorize") {
108  Args.push_back("-passes=loop-vectorize");
109  } else if (Opt == "licm") {
110  Args.push_back("-passes=licm");
111  } else if (Opt == "indvars") {
112  Args.push_back("-passes=indvars");
113  } else if (Opt == "strength_reduce") {
114  Args.push_back("-passes=loop-reduce");
115  } else if (Opt == "irce") {
116  Args.push_back("-passes=irce");
117 
118  } else if (Triple(Opt).getArch()) {
119  Args.push_back("-mtriple=" + Opt.str());
120  } else {
121  errs() << ExecName << ": Unknown option: " << Opt << ".\n";
122  exit(1);
123  }
124  }
125 
126  errs() << NameAndArgs.first << ": Injected args:";
127  for (int I = 1, E = Args.size(); I < E; ++I)
128  errs() << " " << Args[I];
129  errs() << "\n";
130 
131  std::vector<const char *> CLArgs;
132  CLArgs.reserve(Args.size());
133  for (std::string &S : Args)
134  CLArgs.push_back(S.c_str());
135 
136  cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
137 }
138 
139 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
141  errs() << "*** This tool was not linked to libFuzzer.\n"
142  << "*** No fuzzing will be performed.\n";
143  if (int RC = Init(&ArgC, &ArgV)) {
144  errs() << "Initialization failed\n";
145  return RC;
146  }
147 
148  for (int I = 1; I < ArgC; ++I) {
149  StringRef Arg(ArgV[I]);
150  if (Arg.startswith("-")) {
151  if (Arg.equals("-ignore_remaining_args=1"))
152  break;
153  continue;
154  }
155 
156  auto BufOrErr = MemoryBuffer::getFile(Arg, /*IsText=*/false,
157  /*RequiresNullTerminator=*/false);
158  if (std::error_code EC = BufOrErr.getError()) {
159  errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
160  return 1;
161  }
162  std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
163  errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
164  TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
165  Buf->getBufferSize());
166  }
167  return 0;
168 }
169 
170 std::unique_ptr<Module> llvm::parseModule(
171  const uint8_t *Data, size_t Size, LLVMContext &Context) {
172 
173  if (Size <= 1)
174  // We get bogus data given an empty corpus - just create a new module.
175  return std::make_unique<Module>("M", Context);
176 
177  auto Buffer = MemoryBuffer::getMemBuffer(
178  StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
179  /*RequiresNullTerminator=*/false);
180 
181  SMDiagnostic Err;
182  auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
183  if (Error E = M.takeError()) {
184  errs() << toString(std::move(E)) << "\n";
185  return nullptr;
186  }
187  return std::move(M.get());
188 }
189 
190 size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
191  std::string Buf;
192  {
193  raw_string_ostream OS(Buf);
194  WriteBitcodeToFile(M, OS);
195  }
196  if (Buf.size() > MaxSize)
197  return 0;
198  memcpy(Dest, Buf.data(), Buf.size());
199  return Buf.size();
200 }
201 
202 std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
203  LLVMContext &Context) {
204  auto M = parseModule(Data, Size, Context);
205  if (!M || verifyModule(*M, &errs()))
206  return nullptr;
207 
208  return M;
209 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
MemoryBuffer.h
llvm::parseModule
std::unique_ptr< Module > parseModule(const uint8_t *Data, size_t Size, LLVMContext &Context)
Fuzzer friendly interface for the llvm bitcode parser.
Definition: FuzzerCLI.cpp:170
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
StringRef.h
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:1020
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
Error.h
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::handleExecNameEncodedOptimizerOpts
void handleExecNameEncodedOptimizerOpts(StringRef ExecName)
Handle optimizer options which are encoded in the executable name.
Definition: FuzzerCLI.cpp:75
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:206
CommandLine.h
llvm::MemoryBuffer::getFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Definition: MemoryBuffer.cpp:246
llvm::MemoryBuffer::getMemBuffer
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition: MemoryBuffer.cpp:113
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::StringRef::split
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:749
BitcodeWriter.h
llvm::cl::ParseCommandLineOptions
bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview="", raw_ostream *Errs=nullptr, const char *EnvVar=nullptr, bool LongOptionsUseDoubleDash=false)
Definition: CommandLine.cpp:1297
llvm::SMDiagnostic
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition: SourceMgr.h:251
llvm::FuzzerInitFun
int(*)(int *argc, char ***argv) FuzzerInitFun
Definition: FuzzerCLI.h:45
SourceMgr.h
llvm::parseBitcodeFile
Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, DataLayoutCallbackTy DataLayoutCallback=[](StringRef) { return None;})
Read the specified bitcode file, returning the module.
Definition: BitcodeReader.cpp:7011
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
I
#define I(x, y, z)
Definition: MD5.cpp:59
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
Triple.h
llvm::WriteBitcodeToFile
void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder=false, const ModuleSummaryIndex *Index=nullptr, bool GenerateHash=false, ModuleHash *ModHash=nullptr)
Write the specified module to the specified raw output stream.
Definition: BitcodeWriter.cpp:4639
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
FuzzerCLI.h
llvm::handleExecNameEncodedBEOpts
void handleExecNameEncodedBEOpts(StringRef ExecName)
Handle backend options that are encoded in the executable name.
Definition: FuzzerCLI.cpp:39
Compiler.h
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::Init
Definition: Record.h:271
Verifier.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::parseFuzzerCLOpts
void parseFuzzerCLOpts(int ArgC, char *ArgV[])
Parse cl::opts from a fuzz target commandline.
Definition: FuzzerCLI.cpp:25
exit
declare void exit(i32) noreturn nounwind This compiles into
Definition: README.txt:1072
llvm::FuzzerTestFun
int(*)(const uint8_t *Data, size_t Size) FuzzerTestFun
Definition: FuzzerCLI.h:44
LLVMContext.h
llvm::runFuzzerOnInputs
int runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, FuzzerInitFun Init=[](int *, char ***) { return 0;})
Runs a fuzz target on the inputs specified on the command line.
Definition: FuzzerCLI.cpp:139
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
BitcodeReader.h
raw_ostream.h
llvm::writeModule
size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize)
Fuzzer friendly interface for the llvm bitcode printer.
Definition: FuzzerCLI.cpp:190
llvm::parseAndVerify
std::unique_ptr< Module > parseAndVerify(const uint8_t *Data, size_t Size, LLVMContext &Context)
Try to parse module and verify it.
Definition: FuzzerCLI.cpp:202
llvm::verifyModule
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
Definition: Verifier.cpp:5786