1 //===-- sanitizer_win_interception.cpp -------------------- --*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Windows-specific export surface to provide interception for parts of the
10 // runtime that are always statically linked, both for overriding user-defined
11 // functions as well as registering weak functions that the ASAN runtime should
14 //===----------------------------------------------------------------------===//
16 #include "sanitizer_platform.h"
20 # include "interception/interception.h"
21 # include "sanitizer_addrhashmap.h"
22 # include "sanitizer_common.h"
23 # include "sanitizer_internal_defs.h"
24 # include "sanitizer_placement_new.h"
25 # include "sanitizer_win_immortalize.h"
26 # include "sanitizer_win_interception.h"
28 using namespace __sanitizer
;
30 extern "C" void *__ImageBase
;
32 namespace __sanitizer
{
34 static uptr
GetSanitizerDllExport(const char *export_name
) {
35 const uptr function_address
=
36 __interception::InternalGetProcAddress(&__ImageBase
, export_name
);
37 if (function_address
== 0) {
38 Report("ERROR: Failed to find sanitizer DLL export '%s'\n", export_name
);
39 CHECK("Failed to find sanitizer DLL export" && 0);
41 return function_address
;
44 struct WeakCallbackList
{
45 explicit constexpr WeakCallbackList(RegisterWeakFunctionCallback cb
)
46 : callback(cb
), next(nullptr) {}
48 static void *operator new(size_t size
) { return InternalAlloc(size
); }
50 static void operator delete(void *p
) { InternalFree(p
); }
52 RegisterWeakFunctionCallback callback
;
53 WeakCallbackList
*next
;
55 using WeakCallbackMap
= AddrHashMap
<WeakCallbackList
*, 11>;
57 static WeakCallbackMap
*GetWeakCallbackMap() {
58 return &immortalize
<WeakCallbackMap
>();
61 void AddRegisterWeakFunctionCallback(uptr export_address
,
62 RegisterWeakFunctionCallback cb
) {
63 WeakCallbackMap::Handle
h_find_or_create(GetWeakCallbackMap(), export_address
,
65 CHECK(h_find_or_create
.exists());
66 if (h_find_or_create
.created()) {
67 *h_find_or_create
= new WeakCallbackList(cb
);
69 (*h_find_or_create
)->next
= new WeakCallbackList(cb
);
73 static void RunWeakFunctionCallbacks(uptr export_address
) {
74 WeakCallbackMap::Handle
h_find(GetWeakCallbackMap(), export_address
, false,
76 if (!h_find
.exists()) {
80 WeakCallbackList
*list
= *h_find
;
83 } while ((list
= list
->next
));
86 } // namespace __sanitizer
88 extern "C" __declspec(dllexport
) bool __cdecl
__sanitizer_override_function(
89 const char *export_name
, const uptr user_function
,
90 uptr
*const old_user_function
) {
94 const uptr sanitizer_function
= GetSanitizerDllExport(export_name
);
96 const bool function_overridden
= __interception::OverrideFunction(
97 user_function
, sanitizer_function
, old_user_function
);
98 if (!function_overridden
) {
100 "ERROR: Failed to override local function at '%p' with sanitizer "
102 user_function
, export_name
);
103 CHECK("Failed to replace local function with sanitizer version." && 0);
106 return function_overridden
;
110 __declspec(dllexport
) bool __cdecl
__sanitizer_override_function_by_addr(
111 const uptr source_function
, const uptr target_function
,
112 uptr
*const old_target_function
) {
113 CHECK(source_function
);
114 CHECK(target_function
);
116 const bool function_overridden
= __interception::OverrideFunction(
117 target_function
, source_function
, old_target_function
);
118 if (!function_overridden
) {
120 "ERROR: Failed to override function at '%p' with function at "
122 target_function
, source_function
);
123 CHECK("Failed to apply function override." && 0);
126 return function_overridden
;
130 __declspec(dllexport
) bool __cdecl
__sanitizer_register_weak_function(
131 const char *export_name
, const uptr user_function
,
132 uptr
*const old_user_function
) {
134 CHECK(user_function
);
136 const uptr sanitizer_function
= GetSanitizerDllExport(export_name
);
138 const bool function_overridden
= __interception::OverrideFunction(
139 sanitizer_function
, user_function
, old_user_function
);
140 if (!function_overridden
) {
142 "ERROR: Failed to register local function at '%p' to be used in "
143 "place of sanitizer function '%s'\n.",
144 user_function
, export_name
);
145 CHECK("Failed to register weak function." && 0);
148 // Note that thread-safety of RunWeakFunctionCallbacks in InitializeFlags
149 // depends on __sanitizer_register_weak_functions being called during the
151 RunWeakFunctionCallbacks(sanitizer_function
);
153 return function_overridden
;
156 #endif // SANITIZER_WINDOWS