17f28d732SJustin Bogner //===-- FuzzerCLI.cpp -----------------------------------------------------===//
27f28d732SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67f28d732SJustin Bogner //
77f28d732SJustin Bogner //===----------------------------------------------------------------------===//
87f28d732SJustin Bogner
97f28d732SJustin Bogner #include "llvm/FuzzMutate/FuzzerCLI.h"
1024ac6a2dSSimon Pilgrim #include "llvm/ADT/StringRef.h"
119ea7fbd1SJustin Bogner #include "llvm/ADT/Triple.h"
127f28d732SJustin Bogner #include "llvm/Support/CommandLine.h"
137f28d732SJustin Bogner #include "llvm/Support/MemoryBuffer.h"
147f28d732SJustin Bogner #include "llvm/Support/raw_ostream.h"
157f28d732SJustin Bogner
167f28d732SJustin Bogner using namespace llvm;
177f28d732SJustin Bogner
parseFuzzerCLOpts(int ArgC,char * ArgV[])187f28d732SJustin Bogner void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
197f28d732SJustin Bogner std::vector<const char *> CLArgs;
207f28d732SJustin Bogner CLArgs.push_back(ArgV[0]);
217f28d732SJustin Bogner
227f28d732SJustin Bogner int I = 1;
237f28d732SJustin Bogner while (I < ArgC)
247f28d732SJustin Bogner if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1"))
257f28d732SJustin Bogner break;
267f28d732SJustin Bogner while (I < ArgC)
277f28d732SJustin Bogner CLArgs.push_back(ArgV[I++]);
287f28d732SJustin Bogner
297f28d732SJustin Bogner cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
307f28d732SJustin Bogner }
317f28d732SJustin Bogner
handleExecNameEncodedBEOpts(StringRef ExecName)329ea7fbd1SJustin Bogner void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
33adcd0268SBenjamin Kramer std::vector<std::string> Args{std::string(ExecName)};
349ea7fbd1SJustin Bogner
358bc23ab6SMatt Morehouse auto NameAndArgs = ExecName.split("--");
369ea7fbd1SJustin Bogner if (NameAndArgs.second.empty())
379ea7fbd1SJustin Bogner return;
389ea7fbd1SJustin Bogner
399ea7fbd1SJustin Bogner SmallVector<StringRef, 4> Opts;
409ea7fbd1SJustin Bogner NameAndArgs.second.split(Opts, '-');
419ea7fbd1SJustin Bogner for (StringRef Opt : Opts) {
429ea7fbd1SJustin Bogner if (Opt.equals("gisel")) {
439ea7fbd1SJustin Bogner Args.push_back("-global-isel");
449ea7fbd1SJustin Bogner // For now we default GlobalISel to -O0
459ea7fbd1SJustin Bogner Args.push_back("-O0");
469ea7fbd1SJustin Bogner } else if (Opt.startswith("O")) {
479ea7fbd1SJustin Bogner Args.push_back("-" + Opt.str());
4845623bd0SJustin Bogner } else if (Triple(Opt).getArch()) {
499ea7fbd1SJustin Bogner Args.push_back("-mtriple=" + Opt.str());
509ea7fbd1SJustin Bogner } else {
519ea7fbd1SJustin Bogner errs() << ExecName << ": Unknown option: " << Opt << ".\n";
529ea7fbd1SJustin Bogner exit(1);
539ea7fbd1SJustin Bogner }
549ea7fbd1SJustin Bogner }
559ea7fbd1SJustin Bogner errs() << NameAndArgs.first << ": Injected args:";
569ea7fbd1SJustin Bogner for (int I = 1, E = Args.size(); I < E; ++I)
579ea7fbd1SJustin Bogner errs() << " " << Args[I];
589ea7fbd1SJustin Bogner errs() << "\n";
599ea7fbd1SJustin Bogner
609ea7fbd1SJustin Bogner std::vector<const char *> CLArgs;
619ea7fbd1SJustin Bogner CLArgs.reserve(Args.size());
629ea7fbd1SJustin Bogner for (std::string &S : Args)
639ea7fbd1SJustin Bogner CLArgs.push_back(S.c_str());
649ea7fbd1SJustin Bogner
659ea7fbd1SJustin Bogner cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
669ea7fbd1SJustin Bogner }
679ea7fbd1SJustin Bogner
handleExecNameEncodedOptimizerOpts(StringRef ExecName)6813cc995cSIgor Laevsky void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) {
6913cc995cSIgor Laevsky // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts'
70adcd0268SBenjamin Kramer std::vector<std::string> Args{std::string(ExecName)};
7113cc995cSIgor Laevsky
7213cc995cSIgor Laevsky auto NameAndArgs = ExecName.split("--");
7313cc995cSIgor Laevsky if (NameAndArgs.second.empty())
7413cc995cSIgor Laevsky return;
7513cc995cSIgor Laevsky
7613cc995cSIgor Laevsky SmallVector<StringRef, 4> Opts;
7713cc995cSIgor Laevsky NameAndArgs.second.split(Opts, '-');
7813cc995cSIgor Laevsky for (StringRef Opt : Opts) {
79fd3a56e8SIgor Laevsky if (Opt == "instcombine") {
8013cc995cSIgor Laevsky Args.push_back("-passes=instcombine");
81fd3a56e8SIgor Laevsky } else if (Opt == "earlycse") {
8250acecf2SIgor Laevsky Args.push_back("-passes=early-cse");
83fd3a56e8SIgor Laevsky } else if (Opt == "simplifycfg") {
84472462c4SBjorn Pettersson Args.push_back("-passes=simplifycfg");
85fd3a56e8SIgor Laevsky } else if (Opt == "gvn") {
8650acecf2SIgor Laevsky Args.push_back("-passes=gvn");
87fd3a56e8SIgor Laevsky } else if (Opt == "sccp") {
8850acecf2SIgor Laevsky Args.push_back("-passes=sccp");
89fd3a56e8SIgor Laevsky
90fd3a56e8SIgor Laevsky } else if (Opt == "loop_predication") {
91fd3a56e8SIgor Laevsky Args.push_back("-passes=loop-predication");
92fd3a56e8SIgor Laevsky } else if (Opt == "guard_widening") {
93fd3a56e8SIgor Laevsky Args.push_back("-passes=guard-widening");
94fd3a56e8SIgor Laevsky } else if (Opt == "loop_rotate") {
95fd3a56e8SIgor Laevsky Args.push_back("-passes=loop(rotate)");
96fd3a56e8SIgor Laevsky } else if (Opt == "loop_unswitch") {
97*3485e9bfSBjorn Pettersson Args.push_back("-passes=loop(simple-loop-unswitch)");
98fd3a56e8SIgor Laevsky } else if (Opt == "loop_unroll") {
99fd3a56e8SIgor Laevsky Args.push_back("-passes=unroll");
100fd3a56e8SIgor Laevsky } else if (Opt == "loop_vectorize") {
101fd3a56e8SIgor Laevsky Args.push_back("-passes=loop-vectorize");
102fd3a56e8SIgor Laevsky } else if (Opt == "licm") {
103fd3a56e8SIgor Laevsky Args.push_back("-passes=licm");
104fd3a56e8SIgor Laevsky } else if (Opt == "indvars") {
105fd3a56e8SIgor Laevsky Args.push_back("-passes=indvars");
106fd3a56e8SIgor Laevsky } else if (Opt == "strength_reduce") {
1073d12e790SArthur Eubanks Args.push_back("-passes=loop-reduce");
1083ce2d7f2SIgor Laevsky } else if (Opt == "irce") {
1093ce2d7f2SIgor Laevsky Args.push_back("-passes=irce");
110fd3a56e8SIgor Laevsky
11113cc995cSIgor Laevsky } else if (Triple(Opt).getArch()) {
11213cc995cSIgor Laevsky Args.push_back("-mtriple=" + Opt.str());
11313cc995cSIgor Laevsky } else {
11413cc995cSIgor Laevsky errs() << ExecName << ": Unknown option: " << Opt << ".\n";
11513cc995cSIgor Laevsky exit(1);
11613cc995cSIgor Laevsky }
11713cc995cSIgor Laevsky }
11813cc995cSIgor Laevsky
11913cc995cSIgor Laevsky errs() << NameAndArgs.first << ": Injected args:";
12013cc995cSIgor Laevsky for (int I = 1, E = Args.size(); I < E; ++I)
12113cc995cSIgor Laevsky errs() << " " << Args[I];
12213cc995cSIgor Laevsky errs() << "\n";
12313cc995cSIgor Laevsky
12413cc995cSIgor Laevsky std::vector<const char *> CLArgs;
12513cc995cSIgor Laevsky CLArgs.reserve(Args.size());
12613cc995cSIgor Laevsky for (std::string &S : Args)
12713cc995cSIgor Laevsky CLArgs.push_back(S.c_str());
12813cc995cSIgor Laevsky
12913cc995cSIgor Laevsky cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
13013cc995cSIgor Laevsky }
13113cc995cSIgor Laevsky
runFuzzerOnInputs(int ArgC,char * ArgV[],FuzzerTestFun TestOne,FuzzerInitFun Init)1327f28d732SJustin Bogner int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
1337f28d732SJustin Bogner FuzzerInitFun Init) {
1347f28d732SJustin Bogner errs() << "*** This tool was not linked to libFuzzer.\n"
1357f28d732SJustin Bogner << "*** No fuzzing will be performed.\n";
1367f28d732SJustin Bogner if (int RC = Init(&ArgC, &ArgV)) {
1377f28d732SJustin Bogner errs() << "Initialization failed\n";
1387f28d732SJustin Bogner return RC;
1397f28d732SJustin Bogner }
1407f28d732SJustin Bogner
1417f28d732SJustin Bogner for (int I = 1; I < ArgC; ++I) {
1427f28d732SJustin Bogner StringRef Arg(ArgV[I]);
1437f28d732SJustin Bogner if (Arg.startswith("-")) {
1447f28d732SJustin Bogner if (Arg.equals("-ignore_remaining_args=1"))
1457f28d732SJustin Bogner break;
1467f28d732SJustin Bogner continue;
1477f28d732SJustin Bogner }
1487f28d732SJustin Bogner
149c83cd8feSAbhina Sreeskantharajan auto BufOrErr = MemoryBuffer::getFile(Arg, /*IsText=*/false,
1507f28d732SJustin Bogner /*RequiresNullTerminator=*/false);
1517f28d732SJustin Bogner if (std::error_code EC = BufOrErr.getError()) {
1527f28d732SJustin Bogner errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
1537f28d732SJustin Bogner return 1;
1547f28d732SJustin Bogner }
1557f28d732SJustin Bogner std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
1567f28d732SJustin Bogner errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
1577f28d732SJustin Bogner TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
1587f28d732SJustin Bogner Buf->getBufferSize());
1597f28d732SJustin Bogner }
1607f28d732SJustin Bogner return 0;
1617f28d732SJustin Bogner }
162