reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
//===-- sanitizer_win_defs.h ------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Common definitions for Windows-specific code.
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_WIN_DEFS_H
#define SANITIZER_WIN_DEFS_H

#include "sanitizer_platform.h"
#if SANITIZER_WINDOWS

#ifndef WINAPI
#if defined(_M_IX86) || defined(__i386__)
#define WINAPI __stdcall
#else
#define WINAPI
#endif
#endif

#if defined(_M_IX86) || defined(__i386__)
#define WIN_SYM_PREFIX "_"
#else
#define WIN_SYM_PREFIX
#endif

// For MinGW, the /export: directives contain undecorated symbols, contrary to
// link/lld-link. The GNU linker doesn't support /alternatename and /include
// though, thus lld-link in MinGW mode interprets them in the same way as
// in the default mode.
#ifdef __MINGW32__
#define WIN_EXPORT_PREFIX
#else
#define WIN_EXPORT_PREFIX WIN_SYM_PREFIX
#endif

// Intermediate macro to ensure the parameter is expanded before stringified.
#define STRINGIFY_(A) #A
#define STRINGIFY(A) STRINGIFY_(A)

#if !SANITIZER_GO

// ----------------- A workaround for the absence of weak symbols --------------
// We don't have a direct equivalent of weak symbols when using MSVC, but we can
// use the /alternatename directive to tell the linker to default a specific
// symbol to a specific value.
// Take into account that this is a pragma directive for the linker, so it will
// be ignored by the compiler and the function will be marked as UNDEF in the
// symbol table of the resulting object file. The linker won't find the default
// implementation until it links with that object file.
// So, suppose we provide a default implementation "fundef" for "fun", and this
// is compiled into the object file "test.obj" including the pragma directive.
// If we have some code with references to "fun" and we link that code with
// "test.obj", it will work because the linker always link object files.
// But, if "test.obj" is included in a static library, like "test.lib", then the
// liker will only link to "test.obj" if necessary. If we only included the
// definition of "fun", it won't link to "test.obj" (from test.lib) because
// "fun" appears as UNDEF, so it doesn't resolve the symbol "fun", and will
// result in a link error (the linker doesn't find the pragma directive).
// So, a workaround is to force linkage with the modules that include weak
// definitions, with the following macro: WIN_FORCE_LINK()

#define WIN_WEAK_ALIAS(Name, Default)                                          \
  __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY(Name) "="\
                                             WIN_SYM_PREFIX STRINGIFY(Default)))

#define WIN_FORCE_LINK(Name)                                                   \
  __pragma(comment(linker, "/include:" WIN_SYM_PREFIX STRINGIFY(Name)))

#define WIN_EXPORT(ExportedName, Name)                                         \
  __pragma(comment(linker, "/export:" WIN_EXPORT_PREFIX STRINGIFY(ExportedName)\
                                  "=" WIN_EXPORT_PREFIX STRINGIFY(Name)))

// We cannot define weak functions on Windows, but we can use WIN_WEAK_ALIAS()
// which defines an alias to a default implementation, and only works when
// linking statically.
// So, to define a weak function "fun", we define a default implementation with
// a different name "fun__def" and we create a "weak alias" fun = fun__def.
// Then, users can override it just defining "fun".
// We impose "extern "C"" because otherwise WIN_WEAK_ALIAS() will fail because
// of name mangling.

// Dummy name for default implementation of weak function.
# define WEAK_DEFAULT_NAME(Name) Name##__def
// Name for exported implementation of weak function.
# define WEAK_EXPORT_NAME(Name) Name##__dll

// Use this macro when you need to define and export a weak function from a
// library. For example:
//   WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...)                            \
  WIN_WEAK_ALIAS(Name, WEAK_DEFAULT_NAME(Name))                                \
  WIN_EXPORT(WEAK_EXPORT_NAME(Name), Name)                                     \
  extern "C" ReturnType Name(__VA_ARGS__);                                     \
  extern "C" ReturnType WEAK_DEFAULT_NAME(Name)(__VA_ARGS__)

// Use this macro when you need to import a weak function from a library. It
// defines a weak alias to the imported function from the dll. For example:
//   WIN_WEAK_IMPORT_DEF(compare)
# define WIN_WEAK_IMPORT_DEF(Name)                                             \
  WIN_WEAK_ALIAS(Name, WEAK_EXPORT_NAME(Name))

// So, for Windows we provide something similar to weak symbols in Linux, with
// some differences:
// + A default implementation must always be provided.
//
// + When linking statically it works quite similarly. For example:
//
//   // libExample.cc
//   WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
//
//   // client.cc
//   // We can use the default implementation from the library:
//   compare(1, 2);
//   // Or we can override it:
//   extern "C" bool compare (int a, int b) { return a >= b; }
//
//  And it will work fine. If we don't override the function, we need to ensure
//  that the linker includes the object file with the default implementation.
//  We can do so with the linker option "-wholearchive:".
//
// + When linking dynamically with a library (dll), weak functions are exported
//  with "__dll" suffix. Clients can use the macro WIN_WEAK_IMPORT_DEF(fun)
//  which defines a "weak alias" fun = fun__dll.
//
//   // libExample.cc
//   WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
//
//   // client.cc
//   WIN_WEAK_IMPORT_DEF(compare)
//   // We can use the default implementation from the library:
//   compare(1, 2);
//   // Or we can override it:
//   extern "C" bool compare (int a, int b) { return a >= b; }
//
//  But if we override the function, the dlls don't have access to it (which
//  is different in linux). If that is desired, the strong definition must be
//  exported and interception can be used from the rest of the dlls.
//
//   // libExample.cc
//   WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
//   // When initialized, check if the main executable defined "compare".
//   int libExample_init() {
//     uptr fnptr = __interception::InternalGetProcAddress(
//         (void *)GetModuleHandleA(0), "compare");
//     if (fnptr && !__interception::OverrideFunction((uptr)compare, fnptr, 0))
//       abort();
//     return 0;
//   }
//
//   // client.cc
//   WIN_WEAK_IMPORT_DEF(compare)
//   // We override and export compare:
//   extern "C" __declspec(dllexport) bool compare (int a, int b) {
//     return a >= b;
//   }
//

#else // SANITIZER_GO

// Go neither needs nor wants weak references.
// The shenanigans above don't work for gcc.
# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...)                            \
  extern "C" ReturnType Name(__VA_ARGS__)

#endif // SANITIZER_GO

#endif // SANITIZER_WINDOWS
#endif // SANITIZER_WIN_DEFS_H