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