xref: /freebsd/contrib/llvm-project/llvm/lib/FuzzMutate/FuzzerCLI.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- FuzzerCLI.cpp -----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/FuzzMutate/FuzzerCLI.h"
105ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
110b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
120b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
130b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
1406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric using namespace llvm;
170b57cec5SDimitry Andric 
parseFuzzerCLOpts(int ArgC,char * ArgV[])180b57cec5SDimitry Andric void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
190b57cec5SDimitry Andric   std::vector<const char *> CLArgs;
200b57cec5SDimitry Andric   CLArgs.push_back(ArgV[0]);
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric   int I = 1;
230b57cec5SDimitry Andric   while (I < ArgC)
24*0fca6ea1SDimitry Andric     if (StringRef(ArgV[I++]) == "-ignore_remaining_args=1")
250b57cec5SDimitry Andric       break;
260b57cec5SDimitry Andric   while (I < ArgC)
270b57cec5SDimitry Andric     CLArgs.push_back(ArgV[I++]);
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric 
handleExecNameEncodedBEOpts(StringRef ExecName)320b57cec5SDimitry Andric void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
335ffd83dbSDimitry Andric   std::vector<std::string> Args{std::string(ExecName)};
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   auto NameAndArgs = ExecName.split("--");
360b57cec5SDimitry Andric   if (NameAndArgs.second.empty())
370b57cec5SDimitry Andric     return;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   SmallVector<StringRef, 4> Opts;
400b57cec5SDimitry Andric   NameAndArgs.second.split(Opts, '-');
410b57cec5SDimitry Andric   for (StringRef Opt : Opts) {
42*0fca6ea1SDimitry Andric     if (Opt == "gisel") {
430b57cec5SDimitry Andric       Args.push_back("-global-isel");
440b57cec5SDimitry Andric       // For now we default GlobalISel to -O0
450b57cec5SDimitry Andric       Args.push_back("-O0");
465f757f3fSDimitry Andric     } else if (Opt.starts_with("O")) {
470b57cec5SDimitry Andric       Args.push_back("-" + Opt.str());
480b57cec5SDimitry Andric     } else if (Triple(Opt).getArch()) {
490b57cec5SDimitry Andric       Args.push_back("-mtriple=" + Opt.str());
500b57cec5SDimitry Andric     } else {
510b57cec5SDimitry Andric       errs() << ExecName << ": Unknown option: " << Opt << ".\n";
520b57cec5SDimitry Andric       exit(1);
530b57cec5SDimitry Andric     }
540b57cec5SDimitry Andric   }
550b57cec5SDimitry Andric   errs() << NameAndArgs.first << ": Injected args:";
560b57cec5SDimitry Andric   for (int I = 1, E = Args.size(); I < E; ++I)
570b57cec5SDimitry Andric     errs() << " " << Args[I];
580b57cec5SDimitry Andric   errs() << "\n";
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   std::vector<const char *> CLArgs;
610b57cec5SDimitry Andric   CLArgs.reserve(Args.size());
620b57cec5SDimitry Andric   for (std::string &S : Args)
630b57cec5SDimitry Andric     CLArgs.push_back(S.c_str());
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
handleExecNameEncodedOptimizerOpts(StringRef ExecName)680b57cec5SDimitry Andric void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) {
690b57cec5SDimitry Andric   // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts'
705ffd83dbSDimitry Andric   std::vector<std::string> Args{std::string(ExecName)};
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   auto NameAndArgs = ExecName.split("--");
730b57cec5SDimitry Andric   if (NameAndArgs.second.empty())
740b57cec5SDimitry Andric     return;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   SmallVector<StringRef, 4> Opts;
770b57cec5SDimitry Andric   NameAndArgs.second.split(Opts, '-');
780b57cec5SDimitry Andric   for (StringRef Opt : Opts) {
790b57cec5SDimitry Andric     if (Opt == "instcombine") {
800b57cec5SDimitry Andric       Args.push_back("-passes=instcombine");
810b57cec5SDimitry Andric     } else if (Opt == "earlycse") {
820b57cec5SDimitry Andric       Args.push_back("-passes=early-cse");
830b57cec5SDimitry Andric     } else if (Opt == "simplifycfg") {
84fe6060f1SDimitry Andric       Args.push_back("-passes=simplifycfg");
850b57cec5SDimitry Andric     } else if (Opt == "gvn") {
860b57cec5SDimitry Andric       Args.push_back("-passes=gvn");
870b57cec5SDimitry Andric     } else if (Opt == "sccp") {
880b57cec5SDimitry Andric       Args.push_back("-passes=sccp");
890b57cec5SDimitry Andric     } else if (Opt == "loop_predication") {
900b57cec5SDimitry Andric       Args.push_back("-passes=loop-predication");
910b57cec5SDimitry Andric     } else if (Opt == "guard_widening") {
920b57cec5SDimitry Andric       Args.push_back("-passes=guard-widening");
930b57cec5SDimitry Andric     } else if (Opt == "loop_rotate") {
94647cbc5dSDimitry Andric       Args.push_back("-passes=loop-rotate");
950b57cec5SDimitry Andric     } else if (Opt == "loop_unswitch") {
96fe6060f1SDimitry Andric       Args.push_back("-passes=loop(simple-loop-unswitch)");
970b57cec5SDimitry Andric     } else if (Opt == "loop_unroll") {
980b57cec5SDimitry Andric       Args.push_back("-passes=unroll");
990b57cec5SDimitry Andric     } else if (Opt == "loop_vectorize") {
1000b57cec5SDimitry Andric       Args.push_back("-passes=loop-vectorize");
1010b57cec5SDimitry Andric     } else if (Opt == "licm") {
1020b57cec5SDimitry Andric       Args.push_back("-passes=licm");
1030b57cec5SDimitry Andric     } else if (Opt == "indvars") {
1040b57cec5SDimitry Andric       Args.push_back("-passes=indvars");
1050b57cec5SDimitry Andric     } else if (Opt == "strength_reduce") {
1065ffd83dbSDimitry Andric       Args.push_back("-passes=loop-reduce");
1070b57cec5SDimitry Andric     } else if (Opt == "irce") {
1080b57cec5SDimitry Andric       Args.push_back("-passes=irce");
109647cbc5dSDimitry Andric     } else if (Opt == "dse") {
110647cbc5dSDimitry Andric       Args.push_back("-passes=dse");
111647cbc5dSDimitry Andric     } else if (Opt == "loop_idiom") {
112647cbc5dSDimitry Andric       Args.push_back("-passes=loop-idiom");
113647cbc5dSDimitry Andric     } else if (Opt == "reassociate") {
114647cbc5dSDimitry Andric       Args.push_back("-passes=reassociate");
115647cbc5dSDimitry Andric     } else if (Opt == "lower_matrix_intrinsics") {
116647cbc5dSDimitry Andric       Args.push_back("-passes=lower-matrix-intrinsics");
117647cbc5dSDimitry Andric     } else if (Opt == "memcpyopt") {
118647cbc5dSDimitry Andric       Args.push_back("-passes=memcpyopt");
119647cbc5dSDimitry Andric     } else if (Opt == "sroa") {
120647cbc5dSDimitry Andric       Args.push_back("-passes=sroa");
1210b57cec5SDimitry Andric     } else if (Triple(Opt).getArch()) {
1220b57cec5SDimitry Andric       Args.push_back("-mtriple=" + Opt.str());
1230b57cec5SDimitry Andric     } else {
1240b57cec5SDimitry Andric       errs() << ExecName << ": Unknown option: " << Opt << ".\n";
1250b57cec5SDimitry Andric       exit(1);
1260b57cec5SDimitry Andric     }
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   errs() << NameAndArgs.first << ": Injected args:";
1300b57cec5SDimitry Andric   for (int I = 1, E = Args.size(); I < E; ++I)
1310b57cec5SDimitry Andric     errs() << " " << Args[I];
1320b57cec5SDimitry Andric   errs() << "\n";
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   std::vector<const char *> CLArgs;
1350b57cec5SDimitry Andric   CLArgs.reserve(Args.size());
1360b57cec5SDimitry Andric   for (std::string &S : Args)
1370b57cec5SDimitry Andric     CLArgs.push_back(S.c_str());
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
runFuzzerOnInputs(int ArgC,char * ArgV[],FuzzerTestFun TestOne,FuzzerInitFun Init)1420b57cec5SDimitry Andric int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
1430b57cec5SDimitry Andric                             FuzzerInitFun Init) {
1440b57cec5SDimitry Andric   errs() << "*** This tool was not linked to libFuzzer.\n"
1450b57cec5SDimitry Andric          << "*** No fuzzing will be performed.\n";
1460b57cec5SDimitry Andric   if (int RC = Init(&ArgC, &ArgV)) {
1470b57cec5SDimitry Andric     errs() << "Initialization failed\n";
1480b57cec5SDimitry Andric     return RC;
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   for (int I = 1; I < ArgC; ++I) {
1520b57cec5SDimitry Andric     StringRef Arg(ArgV[I]);
1535f757f3fSDimitry Andric     if (Arg.starts_with("-")) {
154*0fca6ea1SDimitry Andric       if (Arg == "-ignore_remaining_args=1")
1550b57cec5SDimitry Andric         break;
1560b57cec5SDimitry Andric       continue;
1570b57cec5SDimitry Andric     }
1580b57cec5SDimitry Andric 
159fe6060f1SDimitry Andric     auto BufOrErr = MemoryBuffer::getFile(Arg, /*IsText=*/false,
1600b57cec5SDimitry Andric                                           /*RequiresNullTerminator=*/false);
1610b57cec5SDimitry Andric     if (std::error_code EC = BufOrErr.getError()) {
1620b57cec5SDimitry Andric       errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
1630b57cec5SDimitry Andric       return 1;
1640b57cec5SDimitry Andric     }
1650b57cec5SDimitry Andric     std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
1660b57cec5SDimitry Andric     errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
1670b57cec5SDimitry Andric     TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
1680b57cec5SDimitry Andric             Buf->getBufferSize());
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric   return 0;
1710b57cec5SDimitry Andric }
172