1343175Sdim//=== FuzzerExtWindows.cpp - Interface to external functions --------------===//
2343175Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343175Sdim//
7343175Sdim//===----------------------------------------------------------------------===//
8343175Sdim// Implementation of FuzzerExtFunctions for Windows. Uses alternatename when
9343175Sdim// compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately
10343175Sdim// the method each compiler supports is not supported by the other.
11343175Sdim//===----------------------------------------------------------------------===//
12343175Sdim#include "FuzzerDefs.h"
13343175Sdim#if LIBFUZZER_WINDOWS
14343175Sdim
15343175Sdim#include "FuzzerExtFunctions.h"
16343175Sdim#include "FuzzerIO.h"
17343175Sdim
18343175Sdimusing namespace fuzzer;
19343175Sdim
20343175Sdim// Intermediate macro to ensure the parameter is expanded before stringified.
21343175Sdim#define STRINGIFY_(A) #A
22343175Sdim#define STRINGIFY(A) STRINGIFY_(A)
23343175Sdim
24343175Sdim#if LIBFUZZER_MSVC
25343175Sdim// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
26343175Sdim#if defined(_M_IX86) || defined(__i386__)
27343175Sdim#define WIN_SYM_PREFIX "_"
28343175Sdim#else
29343175Sdim#define WIN_SYM_PREFIX
30343175Sdim#endif
31343175Sdim
32343175Sdim// Declare external functions as having alternativenames, so that we can
33343175Sdim// determine if they are not defined.
34343175Sdim#define EXTERNAL_FUNC(Name, Default)                                   \
35343175Sdim  __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
36343175Sdim                               Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
37343175Sdim#else
38343175Sdim// Declare external functions as weak to allow them to default to a specified
39343175Sdim// function if not defined explicitly. We must use weak symbols because clang's
40343175Sdim// support for alternatename is not 100%, see
41343175Sdim// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
42343175Sdim#define EXTERNAL_FUNC(Name, Default) \
43343175Sdim  __attribute__((weak, alias(STRINGIFY(Default))))
44343175Sdim#endif  // LIBFUZZER_MSVC
45343175Sdim
46343175Sdimextern "C" {
47343175Sdim#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)         \
48343175Sdim  RETURN_TYPE NAME##Def FUNC_SIG {                          \
49343175Sdim    Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
50343175Sdim    exit(1);                                                \
51343175Sdim  }                                                         \
52353358Sdim  EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
53343175Sdim
54343175Sdim#include "FuzzerExtFunctions.def"
55343175Sdim
56343175Sdim#undef EXT_FUNC
57343175Sdim}
58343175Sdim
59343175Sdimtemplate <typename T>
60343175Sdimstatic T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
61343175Sdim  if (Fun == FunDef) {
62343175Sdim    if (WarnIfMissing)
63343175Sdim      Printf("WARNING: Failed to find function \"%s\".\n", FnName);
64343175Sdim    return nullptr;
65343175Sdim  }
66343175Sdim  return Fun;
67343175Sdim}
68343175Sdim
69343175Sdimnamespace fuzzer {
70343175Sdim
71343175SdimExternalFunctions::ExternalFunctions() {
72343175Sdim#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
73343175Sdim  this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
74343175Sdim
75343175Sdim#include "FuzzerExtFunctions.def"
76343175Sdim
77343175Sdim#undef EXT_FUNC
78343175Sdim}
79343175Sdim
80343175Sdim}  // namespace fuzzer
81343175Sdim
82343175Sdim#endif // LIBFUZZER_WINDOWS
83