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