10b57cec5SDimitry Andric //=== FuzzerExtWindows.cpp - Interface to external functions --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric // Implementation of FuzzerExtFunctions for Windows. Uses alternatename when
90b57cec5SDimitry Andric // compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately
100b57cec5SDimitry Andric // the method each compiler supports is not supported by the other.
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*5ffd83dbSDimitry Andric #include "FuzzerPlatform.h"
130b57cec5SDimitry Andric #if LIBFUZZER_WINDOWS
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "FuzzerExtFunctions.h"
160b57cec5SDimitry Andric #include "FuzzerIO.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace fuzzer;
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric // Intermediate macro to ensure the parameter is expanded before stringified.
210b57cec5SDimitry Andric #define STRINGIFY_(A) #A
220b57cec5SDimitry Andric #define STRINGIFY(A) STRINGIFY_(A)
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric #if LIBFUZZER_MSVC
250b57cec5SDimitry Andric // Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
260b57cec5SDimitry Andric #if defined(_M_IX86) || defined(__i386__)
270b57cec5SDimitry Andric #define WIN_SYM_PREFIX "_"
280b57cec5SDimitry Andric #else
290b57cec5SDimitry Andric #define WIN_SYM_PREFIX
300b57cec5SDimitry Andric #endif
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric // Declare external functions as having alternativenames, so that we can
330b57cec5SDimitry Andric // determine if they are not defined.
340b57cec5SDimitry Andric #define EXTERNAL_FUNC(Name, Default) \
350b57cec5SDimitry Andric __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
360b57cec5SDimitry Andric Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
370b57cec5SDimitry Andric #else
380b57cec5SDimitry Andric // Declare external functions as weak to allow them to default to a specified
390b57cec5SDimitry Andric // function if not defined explicitly. We must use weak symbols because clang's
400b57cec5SDimitry Andric // support for alternatename is not 100%, see
410b57cec5SDimitry Andric // https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
420b57cec5SDimitry Andric #define EXTERNAL_FUNC(Name, Default) \
430b57cec5SDimitry Andric __attribute__((weak, alias(STRINGIFY(Default))))
440b57cec5SDimitry Andric #endif // LIBFUZZER_MSVC
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric extern "C" {
470b57cec5SDimitry Andric #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
480b57cec5SDimitry Andric RETURN_TYPE NAME##Def FUNC_SIG { \
490b57cec5SDimitry Andric Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
500b57cec5SDimitry Andric exit(1); \
510b57cec5SDimitry Andric } \
520b57cec5SDimitry Andric EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric #include "FuzzerExtFunctions.def"
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric #undef EXT_FUNC
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric template <typename T>
GetFnPtr(T * Fun,T * FunDef,const char * FnName,bool WarnIfMissing)600b57cec5SDimitry Andric static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
610b57cec5SDimitry Andric if (Fun == FunDef) {
620b57cec5SDimitry Andric if (WarnIfMissing)
630b57cec5SDimitry Andric Printf("WARNING: Failed to find function \"%s\".\n", FnName);
640b57cec5SDimitry Andric return nullptr;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric return Fun;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric namespace fuzzer {
700b57cec5SDimitry Andric
ExternalFunctions()710b57cec5SDimitry Andric ExternalFunctions::ExternalFunctions() {
720b57cec5SDimitry Andric #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
730b57cec5SDimitry Andric this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric #include "FuzzerExtFunctions.def"
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric #undef EXT_FUNC
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric } // namespace fuzzer
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric #endif // LIBFUZZER_WINDOWS
83