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 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 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 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 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