<div dir="ltr">Hi Dan,<div><br></div><div>So this is causing warnings and breaking Werror builds:</div><div><br></div><div><div>/usr/local/google/home/echristo/sources/llvm/lib/Fuzzer/FuzzerExtFunctions.def:29:10: warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [-Wpedantic]</div><div> EXT_FUNC(__lsan_enable, void, (), false);</div><div>          ^</div><div>/usr/local/google/home/echristo/sources/llvm/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp:44:24: note: in definition of macro ‘EXT_FUNC’</div><div>   CheckFnPtr((void *)::NAME, #NAME, WARN);</div><div>                        ^</div></div><div><br></div><div>Feel like fixing? :)</div><div><br></div><div>-eric</div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Jun 1, 2016 at 10:54 PM Dan Liew via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: delcypher<br>
Date: Thu Jun  2 00:48:02 2016<br>
New Revision: 271491<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=271491&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=271491&view=rev</a><br>
Log:<br>
[LibFuzzer] Reimplement how the optional user functions are called.<br>
<br>
The motivation for this change is to fix linking issues on OSX.<br>
However this only partially fixes linking issues (the uninstrumented<br>
tests and a few others  won't succesfully link yet).<br>
<br>
This change introduces a struct of function pointers<br>
(``fuzzer::ExternalFuntions``) which when initialised will point to the<br>
optional functions if they are available.  Currently these<br>
``LLVMFuzzerInitialize`` and ``LLVMFuzzerCustomMutator`` functions.<br>
<br>
Two implementations of ``fuzzer::ExternalFunctions`` constructor are<br>
provided one for Linux and one for OSX.<br>
<br>
The OSX implementation uses ``dlsym()`` because the prior implementation<br>
using weak symbols does not work unless the additional flags are passed<br>
to the linker.<br>
<br>
The Linux implementation continues to use weak symbols because the<br>
``dlsym()`` approach does not work unless additional flags are passed<br>
to the linker.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D20741" rel="noreferrer" target="_blank">http://reviews.llvm.org/D20741</a><br>
<br>
Added:<br>
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def<br>
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h<br>
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp<br>
    llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp<br>
Modified:<br>
    llvm/trunk/lib/Fuzzer/CMakeLists.txt<br>
    llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp<br>
    llvm/trunk/lib/Fuzzer/FuzzerInternal.h<br>
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp<br>
    llvm/trunk/lib/Fuzzer/FuzzerMain.cpp<br>
<br>
Modified: llvm/trunk/lib/Fuzzer/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=271491&r1=271490&r2=271491&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=271491&r1=271490&r2=271491&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Fuzzer/CMakeLists.txt Thu Jun  2 00:48:02 2016<br>
@@ -12,6 +12,8 @@ if( LLVM_USE_SANITIZE_COVERAGE )<br>
     FuzzerCrossOver.cpp<br>
     FuzzerTraceState.cpp<br>
     FuzzerDriver.cpp<br>
+    FuzzerExtFunctionsDlsym.cpp<br>
+    FuzzerExtFunctionsWeak.cpp<br>
     FuzzerIO.cpp<br>
     FuzzerLoop.cpp<br>
     FuzzerMutate.cpp<br>
<br>
Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=271491&r1=271490&r2=271491&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=271491&r1=271490&r2=271491&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Thu Jun  2 00:48:02 2016<br>
@@ -266,9 +266,13 @@ static bool AllInputsAreFiles() {<br>
   return true;<br>
 }<br>
<br>
-static int FuzzerDriver(const std::vector<std::string> &Args,<br>
-                        UserCallback Callback) {<br>
+int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {<br>
   using namespace fuzzer;<br>
+  assert(argc && argv && "Argument pointers cannot be nullptr");<br>
+  fuzzer::ExternalFunctions EF;<br>
+  if (EF.LLVMFuzzerInitialize)<br>
+    EF.LLVMFuzzerInitialize(argc, argv);<br>
+  const std::vector<std::string> Args(*argv, *argv + *argc);<br>
   assert(!Args.empty());<br>
   ProgName = new std::string(Args[0]);<br>
   ParseFlags(Args);<br>
@@ -417,10 +421,4 @@ static int FuzzerDriver(const std::vecto<br>
<br>
   exit(0);  // Don't let F destroy itself.<br>
 }<br>
-<br>
-int FuzzerDriver(int argc, char **argv, UserCallback Callback) {<br>
-  std::vector<std::string> Args(argv, argv + argc);<br>
-  return FuzzerDriver(Args, Callback);<br>
-}<br>
-<br>
 }  // namespace fuzzer<br>
<br>
Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def?rev=271491&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def?rev=271491&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def (added)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.def Thu Jun  2 00:48:02 2016<br>
@@ -0,0 +1,23 @@<br>
+//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+// This defines the external function pointers that<br>
+// ``fuzzer::ExternalFunctions`` should contain and try to initialize.  The<br>
+// EXT_FUNC macro must be defined at the point of inclusion. The signature of<br>
+// the macro is:<br>
+//<br>
+// EXT_FUNC(<name>, <return_type>, <function_signature>, <warn_if_missing>)<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+// Optional user functions<br>
+EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false);<br>
+EXT_FUNC(LLVMFuzzerCustomMutator, size_t,<br>
+         (uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed),<br>
+         false);<br>
+<br>
+// TODO: Sanitizer functions<br>
<br>
Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h?rev=271491&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h?rev=271491&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h (added)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctions.h Thu Jun  2 00:48:02 2016<br>
@@ -0,0 +1,32 @@<br>
+//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+// Defines an interface to (possibly optional) functions.<br>
+//===----------------------------------------------------------------------===//<br>
+#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H<br>
+#define LLVM_FUZZER_EXT_FUNCTIONS_H<br>
+<br>
+#include <stddef.h><br>
+#include <stdint.h><br>
+<br>
+namespace fuzzer {<br>
+<br>
+struct ExternalFunctions {<br>
+  // Initialize function pointers. Functions that are not available<br>
+  // will be set to nullptr.<br>
+  ExternalFunctions();<br>
+<br>
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)                            \<br>
+  RETURN_TYPE(*NAME) FUNC_SIG = nullptr<br>
+<br>
+#include "FuzzerExtFunctions.def"<br>
+<br>
+#undef EXT_FUNC<br>
+};<br>
+} // namespace fuzzer<br>
+#endif<br>
<br>
Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp?rev=271491&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp?rev=271491&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp (added)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsDlsym.cpp Thu Jun  2 00:48:02 2016<br>
@@ -0,0 +1,49 @@<br>
+//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+// Implementation for operating systems that support dlsym(). We only use it on<br>
+// Apple platforms for now. We don't use this approach on Linux because it<br>
+// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker.<br>
+// That is a complication we don't wish to expose to clients right now.<br>
+//===----------------------------------------------------------------------===//<br>
+#include "FuzzerInternal.h"<br>
+#if LIBFUZZER_APPLE<br>
+<br>
+#include "FuzzerExtFunctions.h"<br>
+#include <dlfcn.h><br>
+<br>
+using namespace fuzzer;<br>
+<br>
+template <typename T><br>
+static T GetFnPtr(const char *FnName, bool WarnIfMissing) {<br>
+  dlerror(); // Clear any previous errors.<br>
+  void *Fn = dlsym(RTLD_DEFAULT, FnName);<br>
+  if (Fn == nullptr) {<br>
+    if (WarnIfMissing) {<br>
+      const char *ErrorMsg = dlerror();<br>
+      Printf("WARNING: Failed to find function \"%s\".", FnName);<br>
+      if (ErrorMsg)<br>
+        Printf(" Reason %s.", ErrorMsg);<br>
+      Printf("\n");<br>
+    }<br>
+  }<br>
+  return reinterpret_cast<T>(Fn);<br>
+}<br>
+<br>
+namespace fuzzer {<br>
+<br>
+ExternalFunctions::ExternalFunctions() {<br>
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)                            \<br>
+  this->NAME = GetFnPtr<decltype(ExternalFunctions::NAME)>(#NAME, WARN)<br>
+<br>
+#include "FuzzerExtFunctions.def"<br>
+<br>
+#undef EXT_FUNC<br>
+}<br>
+} // namespace fuzzer<br>
+#endif // LIBFUZZER_APPLE<br>
<br>
Added: llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp?rev=271491&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp?rev=271491&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp (added)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerExtFunctionsWeak.cpp Thu Jun  2 00:48:02 2016<br>
@@ -0,0 +1,50 @@<br>
+//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+// Implementation for Linux. This relies on the linker's support for weak<br>
+// symbols. We don't use this approach on Apple platforms because it requires<br>
+// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow<br>
+// weak symbols to be undefined. That is a complication we don't want to expose<br>
+// to clients right now.<br>
+//===----------------------------------------------------------------------===//<br>
+#include "FuzzerInternal.h"<br>
+#if LIBFUZZER_LINUX<br>
+<br>
+#include "FuzzerExtFunctions.h"<br>
+<br>
+extern "C" {<br>
+// Declare these symbols as weak to allow them to be optionally defined.<br>
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)                            \<br>
+  __attribute__((weak)) RETURN_TYPE NAME FUNC_SIG<br>
+<br>
+#include "FuzzerExtFunctions.def"<br>
+<br>
+#undef EXT_FUNC<br>
+}<br>
+<br>
+using namespace fuzzer;<br>
+<br>
+static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) {<br>
+  if (FnPtr == nullptr && WarnIfMissing) {<br>
+    Printf("WARNING: Failed to find function \"%s\".\n", FnName);<br>
+  }<br>
+}<br>
+<br>
+namespace fuzzer {<br>
+<br>
+ExternalFunctions::ExternalFunctions() {<br>
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)                            \<br>
+  this->NAME = ::NAME;                                                         \<br>
+  CheckFnPtr((void *)::NAME, #NAME, WARN);<br>
+<br>
+#include "FuzzerExtFunctions.def"<br>
+<br>
+#undef EXT_FUNC<br>
+}<br>
+} // namespace fuzzer<br>
+#endif // LIBFUZZER_LINUX<br>
<br>
Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=271491&r1=271490&r2=271491&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=271491&r1=271490&r2=271491&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Thu Jun  2 00:48:02 2016<br>
@@ -25,6 +25,7 @@<br>
 #include <unordered_set><br>
 #include <vector><br>
<br>
+#include "FuzzerExtFunctions.h"<br>
 #include "FuzzerInterface.h"<br>
 #include "FuzzerTracePC.h"<br>
<br>
@@ -42,7 +43,7 @@<br>
 namespace fuzzer {<br>
<br>
 typedef int (*UserCallback)(const uint8_t *Data, size_t Size);<br>
-int FuzzerDriver(int argc, char **argv, UserCallback Callback);<br>
+int FuzzerDriver(int *argc, char ***argv, UserCallback Callback);<br>
<br>
 using namespace std::chrono;<br>
 typedef std::vector<uint8_t> Unit;<br>
@@ -468,6 +469,9 @@ private:<br>
<br>
   // Need to know our own thread.<br>
   static thread_local bool IsMyThread;<br>
+<br>
+  // Interface to functions that may or may not be available.<br>
+  ExternalFunctions EF;<br>
 };<br>
<br>
 }; // namespace fuzzer<br>
<br>
Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=271491&r1=271490&r2=271491&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=271491&r1=271490&r2=271491&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Thu Jun  2 00:48:02 2016<br>
@@ -47,9 +47,6 @@ __sanitizer_update_counter_bitset_and_cl<br>
 __attribute__((weak)) uintptr_t<br>
 __sanitizer_get_coverage_pc_buffer(uintptr_t **data);<br>
<br>
-__attribute__((weak)) size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,<br>
-                                                     size_t MaxSize,<br>
-                                                     unsigned int Seed);<br>
 __attribute__((weak)) void __sanitizer_malloc_hook(void *ptr, size_t size);<br>
 __attribute__((weak)) void __sanitizer_free_hook(void *ptr);<br>
 __attribute__((weak)) void __lsan_enable();<br>
@@ -695,9 +692,9 @@ void Fuzzer::MutateAndTestOne() {<br>
<br>
   for (int i = 0; i < Options.MutateDepth; i++) {<br>
     size_t NewSize = 0;<br>
-    if (LLVMFuzzerCustomMutator)<br>
-      NewSize = LLVMFuzzerCustomMutator(CurrentUnitData, Size,<br>
-                                        Options.MaxLen, MD.GetRand().Rand());<br>
+    if (EF.LLVMFuzzerCustomMutator)<br>
+      NewSize = EF.LLVMFuzzerCustomMutator(CurrentUnitData, Size,<br>
+                                           Options.MaxLen, MD.GetRand().Rand());<br>
     else<br>
       NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);<br>
     assert(NewSize > 0 && "Mutator returned empty unit");<br>
<br>
Modified: llvm/trunk/lib/Fuzzer/FuzzerMain.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMain.cpp?rev=271491&r1=271490&r2=271491&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMain.cpp?rev=271491&r1=271490&r2=271491&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Fuzzer/FuzzerMain.cpp (original)<br>
+++ llvm/trunk/lib/Fuzzer/FuzzerMain.cpp Thu Jun  2 00:48:02 2016<br>
@@ -15,12 +15,8 @@<br>
 extern "C" {<br>
 // This function should be defined by the user.<br>
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);<br>
-// This function may optionally be defined by the user.<br>
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);<br>
 }  // extern "C"<br>
<br>
 int main(int argc, char **argv) {<br>
-  if (LLVMFuzzerInitialize)<br>
-    LLVMFuzzerInitialize(&argc, &argv);<br>
-  return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput);<br>
+  return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput);<br>
 }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>