Index: include/llvm/FuzzMutate/FuzzerCLI.h =================================================================== --- include/llvm/FuzzMutate/FuzzerCLI.h +++ include/llvm/FuzzMutate/FuzzerCLI.h @@ -15,6 +15,7 @@ #ifndef LLVM_FUZZMUTATE_FUZZER_CLI_H #define LLVM_FUZZMUTATE_FUZZER_CLI_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -24,6 +25,17 @@ /// This handles all arguments after -ignore_remaining_args=1 as cl::opts. void parseFuzzerCLOpts(int ArgC, char *ArgV[]); +/// Handle backend options that are encoded in the executable name. +/// +/// Parses some common backend options out of a specially crafted executable +/// name (argv[0]). For example, a name like llvm-foo-fuzzer:aarch64-gisel might +/// set up an AArch64 triple and the Global ISel selector. This should be called +/// *before* parseFuzzerCLOpts if calling both. +/// +/// This is meant to be used for environments like OSS-Fuzz that aren't capable +/// of passing in command line arguments in the normal way. +void handleExecNameEncodedBEOpts(StringRef ExecName); + using FuzzerTestFun = int (*)(const uint8_t *Data, size_t Size); using FuzzerInitFun = int (*)(int *argc, char ***argv); Index: lib/FuzzMutate/FuzzerCLI.cpp =================================================================== --- lib/FuzzMutate/FuzzerCLI.cpp +++ lib/FuzzMutate/FuzzerCLI.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/FuzzMutate/FuzzerCLI.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" @@ -31,6 +31,38 @@ cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); } +void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) { + std::vector Args{ExecName}; + + StringRef OptString = ExecName.split(':').second; + if (OptString.empty()) + return; + + SmallVector Opts; + OptString.split(Opts, '-'); + for (StringRef Opt : Opts) { + if (Opt.equals("gisel")) { + Args.push_back("-global-isel"); + // For now we default GlobalISel to -O0 + Args.push_back("-O0"); + } else if (Opt.startswith("O")) { + Args.push_back("-" + Opt.str()); + } else if (auto Arch = Triple::getArchTypeForLLVMName(Opt)) { + Args.push_back("-mtriple=" + Opt.str()); + } else { + errs() << ExecName << ": Unknown option: " << Opt << ".\n"; + exit(1); + } + } + + std::vector CLArgs; + CLArgs.reserve(Args.size()); + for (std::string &S : Args) + CLArgs.push_back(S.c_str()); + + cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); +} + int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, FuzzerInitFun Init) { errs() << "*** This tool was not linked to libFuzzer.\n" Index: test/tools/llvm-isel-fuzzer/execname-options.ll =================================================================== --- test/tools/llvm-isel-fuzzer/execname-options.ll +++ test/tools/llvm-isel-fuzzer/execname-options.ll @@ -0,0 +1,27 @@ +; REQUIRES: aarch64-registered-target + +; RUN: echo > %t.input + +; RUN: cp llvm-isel-fuzzer %t.bin:aarch64 +; RUN: %t.bin:aarch64 %t.input 2>&1 | FileCheck %s + +; RUN: mv %t.bin:aarch64 %t.bin:aarch64-O1 +; RUN: %t.bin:aarch64-O1 %t.input 2>&1 | FileCheck %s + +; RUN: mv %t.bin:aarch64-O1 %t.bin:O1-aarch64 +; RUN: %t.bin:O1-aarch64 %t.input 2>&1 | FileCheck %s + +; RUN: mv %t.bin:O1-aarch64 %t.bin:aarch64-gisel +; RUN: %t.bin:aarch64-gisel %t.input 2>&1 | FileCheck %s + +; CHECK: Running + +; RUN: mv %t.bin:aarch64-gisel %t.bin:gisel-O0 +; RUN: not %t.bin:gisel-O0 %t.input 2>&1 | FileCheck -check-prefix=NO-TRIPLE %s + +; NO-TRIPLE: -mtriple must be specified + +; RUN: mv %t.bin:gisel-O0 %t.bin:unexist +; RUN: not %t.bin:unexist %t.input 2>&1 | FileCheck -check-prefix=NO-OPT %s + +; NO-OPT: Unknown option: Index: tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp =================================================================== --- tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp +++ tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp @@ -150,6 +150,7 @@ InitializeAllAsmPrinters(); InitializeAllAsmParsers(); + handleExecNameEncodedBEOpts(*argv[0]); parseFuzzerCLOpts(*argc, *argv); if (TargetTriple.empty()) {