summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Fuzzer/CMakeLists.txt2
-rw-r--r--llvm/lib/Fuzzer/FuzzerDriver.cpp14
-rw-r--r--llvm/lib/Fuzzer/FuzzerExtFunctions.def23
-rw-r--r--llvm/lib/Fuzzer/FuzzerExtFunctions.h32
-rw-r--r--llvm/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp49
-rw-r--r--llvm/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp50
-rw-r--r--llvm/lib/Fuzzer/FuzzerInternal.h6
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp9
-rw-r--r--llvm/lib/Fuzzer/FuzzerMain.cpp6
9 files changed, 171 insertions, 20 deletions
diff --git a/llvm/lib/Fuzzer/CMakeLists.txt b/llvm/lib/Fuzzer/CMakeLists.txt
index e513ac7bbdd..16a769fafb9 100644
--- a/llvm/lib/Fuzzer/CMakeLists.txt
+++ b/llvm/lib/Fuzzer/CMakeLists.txt
@@ -12,6 +12,8 @@ if( LLVM_USE_SANITIZE_COVERAGE )
FuzzerCrossOver.cpp
FuzzerTraceState.cpp
FuzzerDriver.cpp
+ FuzzerExtFunctionsDlsym.cpp
+ FuzzerExtFunctionsWeak.cpp
FuzzerIO.cpp
FuzzerLoop.cpp
FuzzerMutate.cpp
diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp
index 3dc062b9311..de5e461eda5 100644
--- a/llvm/lib/Fuzzer/FuzzerDriver.cpp
+++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp
@@ -266,9 +266,13 @@ static bool AllInputsAreFiles() {
return true;
}
-static int FuzzerDriver(const std::vector<std::string> &Args,
- UserCallback Callback) {
+int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
using namespace fuzzer;
+ assert(argc && argv && "Argument pointers cannot be nullptr");
+ fuzzer::ExternalFunctions EF;
+ if (EF.LLVMFuzzerInitialize)
+ EF.LLVMFuzzerInitialize(argc, argv);
+ const std::vector<std::string> Args(*argv, *argv + *argc);
assert(!Args.empty());
ProgName = new std::string(Args[0]);
ParseFlags(Args);
@@ -417,10 +421,4 @@ static int FuzzerDriver(const std::vector<std::string> &Args,
exit(0); // Don't let F destroy itself.
}
-
-int FuzzerDriver(int argc, char **argv, UserCallback Callback) {
- std::vector<std::string> Args(argv, argv + argc);
- return FuzzerDriver(Args, Callback);
-}
-
} // namespace fuzzer
diff --git a/llvm/lib/Fuzzer/FuzzerExtFunctions.def b/llvm/lib/Fuzzer/FuzzerExtFunctions.def
new file mode 100644
index 00000000000..0a9046258db
--- /dev/null
+++ b/llvm/lib/Fuzzer/FuzzerExtFunctions.def
@@ -0,0 +1,23 @@
+//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This defines the external function pointers that
+// ``fuzzer::ExternalFunctions`` should contain and try to initialize. The
+// EXT_FUNC macro must be defined at the point of inclusion. The signature of
+// the macro is:
+//
+// EXT_FUNC(<name>, <return_type>, <function_signature>, <warn_if_missing>)
+//===----------------------------------------------------------------------===//
+
+// Optional user functions
+EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false);
+EXT_FUNC(LLVMFuzzerCustomMutator, size_t,
+ (uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed),
+ false);
+
+// TODO: Sanitizer functions
diff --git a/llvm/lib/Fuzzer/FuzzerExtFunctions.h b/llvm/lib/Fuzzer/FuzzerExtFunctions.h
new file mode 100644
index 00000000000..95b524027df
--- /dev/null
+++ b/llvm/lib/Fuzzer/FuzzerExtFunctions.h
@@ -0,0 +1,32 @@
+//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Defines an interface to (possibly optional) functions.
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H
+#define LLVM_FUZZER_EXT_FUNCTIONS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace fuzzer {
+
+struct ExternalFunctions {
+ // Initialize function pointers. Functions that are not available
+ // will be set to nullptr.
+ ExternalFunctions();
+
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
+ RETURN_TYPE(*NAME) FUNC_SIG = nullptr
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+};
+} // namespace fuzzer
+#endif
diff --git a/llvm/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp b/llvm/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp
new file mode 100644
index 00000000000..7b9681a6193
--- /dev/null
+++ b/llvm/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp
@@ -0,0 +1,49 @@
+//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Implementation for operating systems that support dlsym(). We only use it on
+// Apple platforms for now. We don't use this approach on Linux because it
+// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker.
+// That is a complication we don't wish to expose to clients right now.
+//===----------------------------------------------------------------------===//
+#include "FuzzerInternal.h"
+#if LIBFUZZER_APPLE
+
+#include "FuzzerExtFunctions.h"
+#include <dlfcn.h>
+
+using namespace fuzzer;
+
+template <typename T>
+static T GetFnPtr(const char *FnName, bool WarnIfMissing) {
+ dlerror(); // Clear any previous errors.
+ void *Fn = dlsym(RTLD_DEFAULT, FnName);
+ if (Fn == nullptr) {
+ if (WarnIfMissing) {
+ const char *ErrorMsg = dlerror();
+ Printf("WARNING: Failed to find function \"%s\".", FnName);
+ if (ErrorMsg)
+ Printf(" Reason %s.", ErrorMsg);
+ Printf("\n");
+ }
+ }
+ return reinterpret_cast<T>(Fn);
+}
+
+namespace fuzzer {
+
+ExternalFunctions::ExternalFunctions() {
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
+ this->NAME = GetFnPtr<decltype(ExternalFunctions::NAME)>(#NAME, WARN)
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+}
+} // namespace fuzzer
+#endif // LIBFUZZER_APPLE
diff --git a/llvm/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp b/llvm/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp
new file mode 100644
index 00000000000..75c0ed9f830
--- /dev/null
+++ b/llvm/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp
@@ -0,0 +1,50 @@
+//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Implementation for Linux. This relies on the linker's support for weak
+// symbols. We don't use this approach on Apple platforms because it requires
+// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow
+// weak symbols to be undefined. That is a complication we don't want to expose
+// to clients right now.
+//===----------------------------------------------------------------------===//
+#include "FuzzerInternal.h"
+#if LIBFUZZER_LINUX
+
+#include "FuzzerExtFunctions.h"
+
+extern "C" {
+// Declare these symbols as weak to allow them to be optionally defined.
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
+ __attribute__((weak)) RETURN_TYPE NAME FUNC_SIG
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+}
+
+using namespace fuzzer;
+
+static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) {
+ if (FnPtr == nullptr && WarnIfMissing) {
+ Printf("WARNING: Failed to find function \"%s\".\n", FnName);
+ }
+}
+
+namespace fuzzer {
+
+ExternalFunctions::ExternalFunctions() {
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
+ this->NAME = ::NAME; \
+ CheckFnPtr((void *)::NAME, #NAME, WARN);
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+}
+} // namespace fuzzer
+#endif // LIBFUZZER_LINUX
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h
index 5677bab1233..f1a98f2a648 100644
--- a/llvm/lib/Fuzzer/FuzzerInternal.h
+++ b/llvm/lib/Fuzzer/FuzzerInternal.h
@@ -25,6 +25,7 @@
#include <unordered_set>
#include <vector>
+#include "FuzzerExtFunctions.h"
#include "FuzzerInterface.h"
#include "FuzzerTracePC.h"
@@ -42,7 +43,7 @@
namespace fuzzer {
typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
-int FuzzerDriver(int argc, char **argv, UserCallback Callback);
+int FuzzerDriver(int *argc, char ***argv, UserCallback Callback);
using namespace std::chrono;
typedef std::vector<uint8_t> Unit;
@@ -468,6 +469,9 @@ private:
// Need to know our own thread.
static thread_local bool IsMyThread;
+
+ // Interface to functions that may or may not be available.
+ ExternalFunctions EF;
};
}; // namespace fuzzer
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index 357f1505c89..15a007b7438 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -47,9 +47,6 @@ __sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
__attribute__((weak)) uintptr_t
__sanitizer_get_coverage_pc_buffer(uintptr_t **data);
-__attribute__((weak)) size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
- size_t MaxSize,
- unsigned int Seed);
__attribute__((weak)) void __sanitizer_malloc_hook(void *ptr, size_t size);
__attribute__((weak)) void __sanitizer_free_hook(void *ptr);
__attribute__((weak)) void __lsan_enable();
@@ -695,9 +692,9 @@ void Fuzzer::MutateAndTestOne() {
for (int i = 0; i < Options.MutateDepth; i++) {
size_t NewSize = 0;
- if (LLVMFuzzerCustomMutator)
- NewSize = LLVMFuzzerCustomMutator(CurrentUnitData, Size,
- Options.MaxLen, MD.GetRand().Rand());
+ if (EF.LLVMFuzzerCustomMutator)
+ NewSize = EF.LLVMFuzzerCustomMutator(CurrentUnitData, Size,
+ Options.MaxLen, MD.GetRand().Rand());
else
NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);
assert(NewSize > 0 && "Mutator returned empty unit");
diff --git a/llvm/lib/Fuzzer/FuzzerMain.cpp b/llvm/lib/Fuzzer/FuzzerMain.cpp
index 0d5c1132ea5..55f1687b5f0 100644
--- a/llvm/lib/Fuzzer/FuzzerMain.cpp
+++ b/llvm/lib/Fuzzer/FuzzerMain.cpp
@@ -15,12 +15,8 @@
extern "C" {
// This function should be defined by the user.
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-// This function may optionally be defined by the user.
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
} // extern "C"
int main(int argc, char **argv) {
- if (LLVMFuzzerInitialize)
- LLVMFuzzerInitialize(&argc, &argv);
- return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput);
+ return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput);
}
OpenPOWER on IntegriCloud