diff options
-rw-r--r-- | llvm/cmake/modules/AddLLVM.cmake | 1 | ||||
-rw-r--r-- | llvm/include/llvm/FuzzMutate/FuzzerCLI.h | 39 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/FuzzMutate/FuzzerCLI.cpp | 63 | ||||
-rw-r--r-- | llvm/tools/llvm-isel-fuzzer/DummyISelFuzzer.cpp | 38 | ||||
-rw-r--r-- | llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp | 18 |
6 files changed, 109 insertions, 51 deletions
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index 93a55257e38..66abb2486d9 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -896,6 +896,7 @@ macro(add_llvm_fuzzer name) cmake_parse_arguments(ARG "" "DUMMY_MAIN" "" ${ARGN}) if( LLVM_USE_SANITIZE_COVERAGE ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer") + set(LLVM_OPTIONAL_SOURCES ${ARG_DUMMY_MAIN}) add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS}) set_target_properties(${name} PROPERTIES FOLDER "Fuzzers") elseif( ARG_DUMMY_MAIN ) diff --git a/llvm/include/llvm/FuzzMutate/FuzzerCLI.h b/llvm/include/llvm/FuzzMutate/FuzzerCLI.h new file mode 100644 index 00000000000..83c8356247e --- /dev/null +++ b/llvm/include/llvm/FuzzMutate/FuzzerCLI.h @@ -0,0 +1,39 @@ +//===-- FuzzerCLI.h - Common logic for CLIs of fuzzers ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common logic needed to implement LLVM's fuzz targets' CLIs - including LLVM +// concepts like cl::opt and libFuzzer concepts like -ignore_remaining_args=1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZMUTATE_FUZZER_CLI_H +#define LLVM_FUZZMUTATE_FUZZER_CLI_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// Parse cl::opts from a fuzz target commandline. +/// +/// This handles all arguments after -ignore_remaining_args=1 as cl::opts. +void parseFuzzerCLOpts(int ArgC, char *ArgV[]); + +using FuzzerTestFun = int (*)(const uint8_t *Data, size_t Size); +using FuzzerInitFun = int (*)(int *argc, char ***argv); + +/// Runs a fuzz target on the inputs specified on the command line. +/// +/// Useful for testing fuzz targets without linking to libFuzzer. Finds inputs +/// in the argument list in a libFuzzer compatible way. +int runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, + FuzzerInitFun Init = [](int *, char ***) { return 0; }); + +} // end llvm namespace + +#endif // LLVM_FUZZMUTATE_FUZZER_CLI_H diff --git a/llvm/lib/FuzzMutate/CMakeLists.txt b/llvm/lib/FuzzMutate/CMakeLists.txt index 4aec682b01f..1a1a9abb1c2 100644 --- a/llvm/lib/FuzzMutate/CMakeLists.txt +++ b/llvm/lib/FuzzMutate/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMFuzzMutate + FuzzerCLI.cpp IRMutator.cpp OpDescriptor.cpp Operations.cpp diff --git a/llvm/lib/FuzzMutate/FuzzerCLI.cpp b/llvm/lib/FuzzMutate/FuzzerCLI.cpp new file mode 100644 index 00000000000..3b71cde5af7 --- /dev/null +++ b/llvm/lib/FuzzMutate/FuzzerCLI.cpp @@ -0,0 +1,63 @@ +//===-- FuzzerCLI.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/FuzzMutate/FuzzerCLI.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) { + std::vector<const char *> CLArgs; + CLArgs.push_back(ArgV[0]); + + int I = 1; + while (I < ArgC) + if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1")) + break; + while (I < ArgC) + CLArgs.push_back(ArgV[I++]); + + 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" + << "*** No fuzzing will be performed.\n"; + if (int RC = Init(&ArgC, &ArgV)) { + errs() << "Initialization failed\n"; + return RC; + } + + for (int I = 1; I < ArgC; ++I) { + StringRef Arg(ArgV[I]); + if (Arg.startswith("-")) { + if (Arg.equals("-ignore_remaining_args=1")) + break; + continue; + } + + auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1, + /*RequiresNullTerminator=*/false); + if (std::error_code EC = BufOrErr.getError()) { + errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n"; + return 1; + } + std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); + errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n"; + TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), + Buf->getBufferSize()); + } + return 0; +} diff --git a/llvm/tools/llvm-isel-fuzzer/DummyISelFuzzer.cpp b/llvm/tools/llvm-isel-fuzzer/DummyISelFuzzer.cpp index 89c1c81cdbe..ec9c74e3040 100644 --- a/llvm/tools/llvm-isel-fuzzer/DummyISelFuzzer.cpp +++ b/llvm/tools/llvm-isel-fuzzer/DummyISelFuzzer.cpp @@ -11,43 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; +#include "llvm/FuzzMutate/FuzzerCLI.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv); - int main(int argc, char *argv[]) { - errs() << "*** This tool was not linked to libFuzzer.\n" - << "*** No fuzzing will be performed.\n"; - if (int RC = LLVMFuzzerInitialize(&argc, &argv)) { - errs() << "Initialization failed\n"; - return RC; - } - - for (int I = 1; I < argc; ++I) { - StringRef Arg(argv[I]); - if (Arg.startswith("-")) { - if (Arg.equals("-ignore_remaining_args=1")) - break; - continue; - } - - auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1, - /*RequiresNullTerminator=*/false); - if (std::error_code EC = BufOrErr.getError()) { - errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n"; - return 1; - } - std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); - errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n"; - LLVMFuzzerTestOneInput( - reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), - Buf->getBufferSize()); - } + return llvm::runFuzzerOnInputs(argc, argv, LLVMFuzzerTestOneInput, + LLVMFuzzerInitialize); } diff --git a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp index 1d16376bb87..314acdb5087 100644 --- a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp +++ b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp @@ -16,6 +16,7 @@ #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/CommandFlags.h" +#include "llvm/FuzzMutate/FuzzerCLI.h" #include "llvm/FuzzMutate/IRMutator.h" #include "llvm/FuzzMutate/Operations.h" #include "llvm/FuzzMutate/Random.h" @@ -133,21 +134,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } -/// Parse command line options, but ignore anything before '--'. -static void parseCLOptsAfterDashDash(int argc, char *argv[]) { - std::vector<const char *> CLArgs; - CLArgs.push_back(argv[0]); - - int I = 1; - while (I < argc) - if (StringRef(argv[I++]).equals("-ignore_remaining_args=1")) - break; - while (I < argc) - CLArgs.push_back(argv[I++]); - - cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); -} - static void handleLLVMFatalError(void *, const std::string &Message, bool) { // TODO: Would it be better to call into the fuzzer internals directly? dbgs() << "LLVM ERROR: " << Message << "\n" @@ -164,7 +150,7 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int *argc, InitializeAllAsmPrinters(); InitializeAllAsmParsers(); - parseCLOptsAfterDashDash(*argc, *argv); + parseFuzzerCLOpts(*argc, *argv); if (TargetTriple.empty()) { errs() << *argv[0] << ": -mtriple must be specified\n"; |