1 //===-- FuzzerCLI.cpp -----------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/FuzzMutate/FuzzerCLI.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/Bitcode/BitcodeReader.h"
13 #include "llvm/Bitcode/BitcodeWriter.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/MemoryBuffer.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "llvm/Support/raw_ostream.h"
24 void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
25 std::vector<const char *> CLArgs;
26 CLArgs.push_back(ArgV[0]);
30 if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1"))
33 CLArgs.push_back(ArgV[I++]);
35 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
38 void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
39 std::vector<std::string> Args{ExecName};
41 auto NameAndArgs = ExecName.split("--");
42 if (NameAndArgs.second.empty())
45 SmallVector<StringRef, 4> Opts;
46 NameAndArgs.second.split(Opts, '-');
47 for (StringRef Opt : Opts) {
48 if (Opt.equals("gisel")) {
49 Args.push_back("-global-isel");
50 // For now we default GlobalISel to -O0
51 Args.push_back("-O0");
52 } else if (Opt.startswith("O")) {
53 Args.push_back("-" + Opt.str());
54 } else if (Triple(Opt).getArch()) {
55 Args.push_back("-mtriple=" + Opt.str());
57 errs() << ExecName << ": Unknown option: " << Opt << ".\n";
61 errs() << NameAndArgs.first << ": Injected args:";
62 for (int I = 1, E = Args.size(); I < E; ++I)
63 errs() << " " << Args[I];
66 std::vector<const char *> CLArgs;
67 CLArgs.reserve(Args.size());
68 for (std::string &S : Args)
69 CLArgs.push_back(S.c_str());
71 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
74 void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) {
75 // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts'
76 std::vector<std::string> Args{ExecName};
78 auto NameAndArgs = ExecName.split("--");
79 if (NameAndArgs.second.empty())
82 SmallVector<StringRef, 4> Opts;
83 NameAndArgs.second.split(Opts, '-');
84 for (StringRef Opt : Opts) {
85 if (Opt.startswith("instcombine")) {
86 Args.push_back("-passes=instcombine");
87 } else if (Triple(Opt).getArch()) {
88 Args.push_back("-mtriple=" + Opt.str());
90 errs() << ExecName << ": Unknown option: " << Opt << ".\n";
95 errs() << NameAndArgs.first << ": Injected args:";
96 for (int I = 1, E = Args.size(); I < E; ++I)
97 errs() << " " << Args[I];
100 std::vector<const char *> CLArgs;
101 CLArgs.reserve(Args.size());
102 for (std::string &S : Args)
103 CLArgs.push_back(S.c_str());
105 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
108 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
109 FuzzerInitFun Init) {
110 errs() << "*** This tool was not linked to libFuzzer.\n"
111 << "*** No fuzzing will be performed.\n";
112 if (int RC = Init(&ArgC, &ArgV)) {
113 errs() << "Initialization failed\n";
117 for (int I = 1; I < ArgC; ++I) {
118 StringRef Arg(ArgV[I]);
119 if (Arg.startswith("-")) {
120 if (Arg.equals("-ignore_remaining_args=1"))
125 auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1,
126 /*RequiresNullTerminator=*/false);
127 if (std::error_code EC = BufOrErr.getError()) {
128 errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
131 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
132 errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
133 TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
134 Buf->getBufferSize());
139 std::unique_ptr<Module> llvm::parseModule(
140 const uint8_t *Data, size_t Size, LLVMContext &Context) {
143 // We get bogus data given an empty corpus - just create a new module.
144 return llvm::make_unique<Module>("M", Context);
146 auto Buffer = MemoryBuffer::getMemBuffer(
147 StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
148 /*RequiresNullTerminator=*/false);
151 auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
152 if (Error E = M.takeError()) {
153 errs() << toString(std::move(E)) << "\n";
156 return std::move(M.get());
159 size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
162 raw_string_ostream OS(Buf);
163 WriteBitcodeToFile(&M, OS);
165 if (Buf.size() > MaxSize)
167 memcpy(Dest, Buf.data(), Buf.size());