1*b5893f02SDimitry Andric //=== FuzzerExtWindows.cpp - Interface to external functions --------------===//
2*b5893f02SDimitry Andric //
3*b5893f02SDimitry Andric //                     The LLVM Compiler Infrastructure
4*b5893f02SDimitry Andric //
5*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
7*b5893f02SDimitry Andric //
8*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
9*b5893f02SDimitry Andric // Implementation of FuzzerExtFunctions for Windows. Uses alternatename when
10*b5893f02SDimitry Andric // compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately
11*b5893f02SDimitry Andric // the method each compiler supports is not supported by the other.
12*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
13*b5893f02SDimitry Andric #include "FuzzerDefs.h"
14*b5893f02SDimitry Andric #if LIBFUZZER_WINDOWS
15*b5893f02SDimitry Andric 
16*b5893f02SDimitry Andric #include "FuzzerExtFunctions.h"
17*b5893f02SDimitry Andric #include "FuzzerIO.h"
18*b5893f02SDimitry Andric 
19*b5893f02SDimitry Andric using namespace fuzzer;
20*b5893f02SDimitry Andric 
21*b5893f02SDimitry Andric // Intermediate macro to ensure the parameter is expanded before stringified.
22*b5893f02SDimitry Andric #define STRINGIFY_(A) #A
23*b5893f02SDimitry Andric #define STRINGIFY(A) STRINGIFY_(A)
24*b5893f02SDimitry Andric 
25*b5893f02SDimitry Andric #if LIBFUZZER_MSVC
26*b5893f02SDimitry Andric // Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
27*b5893f02SDimitry Andric #if defined(_M_IX86) || defined(__i386__)
28*b5893f02SDimitry Andric #define WIN_SYM_PREFIX "_"
29*b5893f02SDimitry Andric #else
30*b5893f02SDimitry Andric #define WIN_SYM_PREFIX
31*b5893f02SDimitry Andric #endif
32*b5893f02SDimitry Andric 
33*b5893f02SDimitry Andric // Declare external functions as having alternativenames, so that we can
34*b5893f02SDimitry Andric // determine if they are not defined.
35*b5893f02SDimitry Andric #define EXTERNAL_FUNC(Name, Default)                                   \
36*b5893f02SDimitry Andric   __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
37*b5893f02SDimitry Andric                                Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
38*b5893f02SDimitry Andric #else
39*b5893f02SDimitry Andric // Declare external functions as weak to allow them to default to a specified
40*b5893f02SDimitry Andric // function if not defined explicitly. We must use weak symbols because clang's
41*b5893f02SDimitry Andric // support for alternatename is not 100%, see
42*b5893f02SDimitry Andric // https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
43*b5893f02SDimitry Andric #define EXTERNAL_FUNC(Name, Default) \
44*b5893f02SDimitry Andric   __attribute__((weak, alias(STRINGIFY(Default))))
45*b5893f02SDimitry Andric #endif  // LIBFUZZER_MSVC
46*b5893f02SDimitry Andric 
47*b5893f02SDimitry Andric extern "C" {
48*b5893f02SDimitry Andric #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)         \
49*b5893f02SDimitry Andric   RETURN_TYPE NAME##Def FUNC_SIG {                          \
50*b5893f02SDimitry Andric     Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
51*b5893f02SDimitry Andric     exit(1);                                                \
52*b5893f02SDimitry Andric   }                                                         \
53*b5893f02SDimitry Andric   EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG;
54*b5893f02SDimitry Andric 
55*b5893f02SDimitry Andric #include "FuzzerExtFunctions.def"
56*b5893f02SDimitry Andric 
57*b5893f02SDimitry Andric #undef EXT_FUNC
58*b5893f02SDimitry Andric }
59*b5893f02SDimitry Andric 
60*b5893f02SDimitry Andric template <typename T>
GetFnPtr(T * Fun,T * FunDef,const char * FnName,bool WarnIfMissing)61*b5893f02SDimitry Andric static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
62*b5893f02SDimitry Andric   if (Fun == FunDef) {
63*b5893f02SDimitry Andric     if (WarnIfMissing)
64*b5893f02SDimitry Andric       Printf("WARNING: Failed to find function \"%s\".\n", FnName);
65*b5893f02SDimitry Andric     return nullptr;
66*b5893f02SDimitry Andric   }
67*b5893f02SDimitry Andric   return Fun;
68*b5893f02SDimitry Andric }
69*b5893f02SDimitry Andric 
70*b5893f02SDimitry Andric namespace fuzzer {
71*b5893f02SDimitry Andric 
ExternalFunctions()72*b5893f02SDimitry Andric ExternalFunctions::ExternalFunctions() {
73*b5893f02SDimitry Andric #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
74*b5893f02SDimitry Andric   this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
75*b5893f02SDimitry Andric 
76*b5893f02SDimitry Andric #include "FuzzerExtFunctions.def"
77*b5893f02SDimitry Andric 
78*b5893f02SDimitry Andric #undef EXT_FUNC
79*b5893f02SDimitry Andric }
80*b5893f02SDimitry Andric 
81*b5893f02SDimitry Andric }  // namespace fuzzer
82*b5893f02SDimitry Andric 
83*b5893f02SDimitry Andric #endif // LIBFUZZER_WINDOWS
84