1 | //===-- sanitizer_win_weak_interception.cpp -------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // This module should be included in the sanitizer when it is implemented as a |
9 | // shared library on Windows (dll), in order to delegate the calls of weak |
10 | // functions to the implementation in the main executable when a strong |
11 | // definition is provided. |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "sanitizer_platform.h" |
15 | #if SANITIZER_WINDOWS && SANITIZER_DYNAMIC |
16 | #include "sanitizer_win_weak_interception.h" |
17 | #include "sanitizer_allocator_interface.h" |
18 | #include "sanitizer_interface_internal.h" |
19 | #include "sanitizer_win_defs.h" |
20 | #include "interception/interception.h" |
21 | |
22 | extern "C" { |
23 | void *WINAPI GetModuleHandleA(const char *module_name); |
24 | void abort(); |
25 | } |
26 | |
27 | namespace __sanitizer { |
28 | // Try to get a pointer to real_function in the main module and override |
29 | // dll_function with that pointer. If the function isn't found, nothing changes. |
30 | int interceptWhenPossible(uptr dll_function, const char *real_function) { |
31 | uptr real = __interception::InternalGetProcAddress( |
32 | (void *)GetModuleHandleA(0), real_function); |
33 | if (real && !__interception::OverrideFunction((uptr)dll_function, real, 0)) |
34 | abort(); |
35 | return 0; |
36 | } |
37 | } // namespace __sanitizer |
38 | |
39 | // Declare weak hooks. |
40 | extern "C" { |
41 | void __sanitizer_on_print(const char *str); |
42 | void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1, |
43 | const void *s2, uptr n, int result); |
44 | void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1, |
45 | const char *s2, int result); |
46 | void __sanitizer_weak_hook_strncmp(uptr called_pc, const char *s1, |
47 | const char *s2, uptr n, int result); |
48 | void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1, |
49 | const char *s2, char *result); |
50 | } |
51 | |
52 | // Include Sanitizer Common interface. |
53 | #define INTERFACE_FUNCTION(Name) |
54 | #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) |
55 | #include "sanitizer_common_interface.inc" |
56 | |
57 | #pragma section(".WEAK$A", read) |
58 | #pragma section(".WEAK$Z", read) |
59 | |
60 | typedef void (*InterceptCB)(); |
61 | extern "C" { |
62 | __declspec(allocate(".WEAK$A" )) InterceptCB __start_weak_list; |
63 | __declspec(allocate(".WEAK$Z" )) InterceptCB __stop_weak_list; |
64 | } |
65 | |
66 | static int weak_intercept_init() { |
67 | static bool flag = false; |
68 | // weak_interception_init is expected to be called by only one thread. |
69 | if (flag) return 0; |
70 | flag = true; |
71 | |
72 | for (InterceptCB *it = &__start_weak_list; it < &__stop_weak_list; ++it) |
73 | if (*it) |
74 | (*it)(); |
75 | |
76 | // In DLLs, the callbacks are expected to return 0, |
77 | // otherwise CRT initialization fails. |
78 | return 0; |
79 | } |
80 | |
81 | #pragma section(".CRT$XIB", long, read) |
82 | __declspec(allocate(".CRT$XIB" )) int (*__weak_intercept_preinit)() = |
83 | weak_intercept_init; |
84 | |
85 | static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason, |
86 | void *reserved) { |
87 | if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init(); |
88 | } |
89 | |
90 | #pragma section(".CRT$XLAB", long, read) |
91 | __declspec(allocate(".CRT$XLAB" )) void(WINAPI *__weak_intercept_tls_init)( |
92 | void *, unsigned long, void *) = weak_intercept_thread_init; |
93 | |
94 | #endif // SANITIZER_WINDOWS && SANITIZER_DYNAMIC |
95 | |