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