10646903fSDimitry Andric //=== FuzzerExtWindows.cpp - Interface to external functions --------------===//
20646903fSDimitry Andric //
38f3cadc2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48f3cadc2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58f3cadc2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60646903fSDimitry Andric //
70646903fSDimitry Andric //===----------------------------------------------------------------------===//
80646903fSDimitry Andric // Implementation of FuzzerExtFunctions for Windows. Uses alternatename when
90646903fSDimitry Andric // compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately
100646903fSDimitry Andric // the method each compiler supports is not supported by the other.
110646903fSDimitry Andric //===----------------------------------------------------------------------===//
12cfca06d7SDimitry Andric #include "FuzzerPlatform.h"
130646903fSDimitry Andric #if LIBFUZZER_WINDOWS
140646903fSDimitry Andric
150646903fSDimitry Andric #include "FuzzerExtFunctions.h"
160646903fSDimitry Andric #include "FuzzerIO.h"
170646903fSDimitry Andric
180646903fSDimitry Andric using namespace fuzzer;
190646903fSDimitry Andric
200646903fSDimitry Andric // Intermediate macro to ensure the parameter is expanded before stringified.
210646903fSDimitry Andric #define STRINGIFY_(A) #A
220646903fSDimitry Andric #define STRINGIFY(A) STRINGIFY_(A)
230646903fSDimitry Andric
240646903fSDimitry Andric #if LIBFUZZER_MSVC
250646903fSDimitry Andric // Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
260646903fSDimitry Andric #if defined(_M_IX86) || defined(__i386__)
270646903fSDimitry Andric #define WIN_SYM_PREFIX "_"
280646903fSDimitry Andric #else
290646903fSDimitry Andric #define WIN_SYM_PREFIX
300646903fSDimitry Andric #endif
310646903fSDimitry Andric
320646903fSDimitry Andric // Declare external functions as having alternativenames, so that we can
330646903fSDimitry Andric // determine if they are not defined.
340646903fSDimitry Andric #define EXTERNAL_FUNC(Name, Default) \
350646903fSDimitry Andric __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
360646903fSDimitry Andric Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
370646903fSDimitry Andric #else
380646903fSDimitry Andric // Declare external functions as weak to allow them to default to a specified
390646903fSDimitry Andric // function if not defined explicitly. We must use weak symbols because clang's
400646903fSDimitry Andric // support for alternatename is not 100%, see
410646903fSDimitry Andric // https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
420646903fSDimitry Andric #define EXTERNAL_FUNC(Name, Default) \
430646903fSDimitry Andric __attribute__((weak, alias(STRINGIFY(Default))))
440646903fSDimitry Andric #endif // LIBFUZZER_MSVC
450646903fSDimitry Andric
460646903fSDimitry Andric extern "C" {
470646903fSDimitry Andric #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
480646903fSDimitry Andric RETURN_TYPE NAME##Def FUNC_SIG { \
490646903fSDimitry Andric Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
500646903fSDimitry Andric exit(1); \
510646903fSDimitry Andric } \
528f3cadc2SDimitry Andric EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
530646903fSDimitry Andric
540646903fSDimitry Andric #include "FuzzerExtFunctions.def"
550646903fSDimitry Andric
560646903fSDimitry Andric #undef EXT_FUNC
570646903fSDimitry Andric }
580646903fSDimitry Andric
590646903fSDimitry Andric template <typename T>
GetFnPtr(T * Fun,T * FunDef,const char * FnName,bool WarnIfMissing)600646903fSDimitry Andric static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
610646903fSDimitry Andric if (Fun == FunDef) {
620646903fSDimitry Andric if (WarnIfMissing)
630646903fSDimitry Andric Printf("WARNING: Failed to find function \"%s\".\n", FnName);
640646903fSDimitry Andric return nullptr;
650646903fSDimitry Andric }
660646903fSDimitry Andric return Fun;
670646903fSDimitry Andric }
680646903fSDimitry Andric
690646903fSDimitry Andric namespace fuzzer {
700646903fSDimitry Andric
ExternalFunctions()710646903fSDimitry Andric ExternalFunctions::ExternalFunctions() {
720646903fSDimitry Andric #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
730646903fSDimitry Andric this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
740646903fSDimitry Andric
750646903fSDimitry Andric #include "FuzzerExtFunctions.def"
760646903fSDimitry Andric
770646903fSDimitry Andric #undef EXT_FUNC
780646903fSDimitry Andric }
790646903fSDimitry Andric
800646903fSDimitry Andric } // namespace fuzzer
810646903fSDimitry Andric
820646903fSDimitry Andric #endif // LIBFUZZER_WINDOWS
83