diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -858,6 +858,12 @@ exit(0); // Don't let F destroy itself. } +extern "C" ATTRIBUTE_INTERFACE int +LLVMFuzzerRunDriver(int *argc, char ***argv, + int (*UserCb)(const uint8_t *Data, size_t Size)) { + return FuzzerDriver(argc, argv, UserCb); +} + // Storage for global ExternalFunctions object. ExternalFunctions *EF = nullptr; diff --git a/llvm/docs/LibFuzzer.rst b/llvm/docs/LibFuzzer.rst --- a/llvm/docs/LibFuzzer.rst +++ b/llvm/docs/LibFuzzer.rst @@ -617,6 +617,35 @@ return 0; } +Using libFuzzer as a library +---------------------------- +If the code being fuzzed must provide its own `main`, it's possible to +invoke libFuzzer as a library. Be sure to pass ``-fsanitize=fuzzer-no-link`` +during compilation, and link your binary against the no-main version of +libFuzzer. On Linux installations, this is typically located at: + +.. code-block:: bash + + /usr/lib//lib/clang//lib/linux/libclang_rt.fuzzer_no_main-.a + +If building libFuzzer from source, this is located at the following path +in the build output directory: + +.. code-block:: bash + + lib/linux/libclang_rt.fuzzer_no_main-.a + +From here, the code can do whatever setup it requires, and when it's ready +to start fuzzing, it can call `LLVMFuzzerRunDriver`, passing in the program +arguments and a callback. This callback is invoked just like +`LLVMFuzzerTestOneInput`, and has the same signature. + +.. code-block:: c++ + + extern "C" int LLVMFuzzerRunDriver(int *argc, char ***argv, + int (*UserCb)(const uint8_t *Data, size_t Size)); + + Leaks -----