[llvm] r271491 - [LibFuzzer] Reimplement how the optional user functions are called.

Dan Liew via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 1 22:48:02 PDT 2016


Author: delcypher
Date: Thu Jun  2 00:48:02 2016
New Revision: 271491

URL: http://llvm.org/viewvc/llvm-project?rev=271491&view=rev
Log:
[LibFuzzer] Reimplement how the optional user functions are called.

The motivation for this change is to fix linking issues on OSX.
However this only partially fixes linking issues (the uninstrumented
tests and a few others  won't succesfully link yet).

This change introduces a struct of function pointers
(``fuzzer::ExternalFuntions``) which when initialised will point to the
optional functions if they are available.  Currently these
``LLVMFuzzerInitialize`` and ``LLVMFuzzerCustomMutator`` functions.

Two implementations of ``fuzzer::ExternalFunctions`` constructor are
provided one for Linux and one for OSX.

The OSX implementation uses ``dlsym()`` because the prior implementation
using weak symbols does not work unless the additional flags are passed
to the linker.

The Linux implementation continues to use weak symbols because the
``dlsym()`` approach does not work unless additional flags are passed
to the linker.

Differential Revision: http://reviews.llvm.org/D20741

Added:
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp
Modified:
    llvm/trunk/lib/Fuzzer/CMakeLists.txt
    llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
    llvm/trunk/lib/Fuzzer/FuzzerInternal.h
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
    llvm/trunk/lib/Fuzzer/FuzzerMain.cpp

Modified: llvm/trunk/lib/Fuzzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=271491&r1=271490&r2=271491&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/CMakeLists.txt Thu Jun  2 00:48:02 2016
@@ -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

Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=271491&r1=271490&r2=271491&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Thu Jun  2 00:48:02 2016
@@ -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::vecto
 
   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

Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def?rev=271491&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def Thu Jun  2 00:48:02 2016
@@ -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

Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h?rev=271491&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h Thu Jun  2 00:48:02 2016
@@ -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

Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp?rev=271491&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp Thu Jun  2 00:48:02 2016
@@ -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

Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp?rev=271491&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp Thu Jun  2 00:48:02 2016
@@ -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

Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=271491&r1=271490&r2=271491&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Thu Jun  2 00:48:02 2016
@@ -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

Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=271491&r1=271490&r2=271491&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Thu Jun  2 00:48:02 2016
@@ -47,9 +47,6 @@ __sanitizer_update_counter_bitset_and_cl
 __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");

Modified: llvm/trunk/lib/Fuzzer/FuzzerMain.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMain.cpp?rev=271491&r1=271490&r2=271491&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerMain.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerMain.cpp Thu Jun  2 00:48:02 2016
@@ -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);
 }




More information about the llvm-commits mailing list