xref: /llvm-project/compiler-rt/lib/asan/asan_malloc_win_thunk.cpp (revision 0265981b6ec0f46fc372897fef7f945d8f4625c2)
1 //===-- asan_malloc_win_thunk.cpp
2 //-----------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Windows-specific malloc interception.
13 // This is included statically for projects statically linking
14 // with the C Runtime (/MT, /MTd) in order to provide ASAN-aware
15 // versions of the C allocation functions.
16 //===----------------------------------------------------------------------===//
17 
18 #ifdef SANITIZER_STATIC_RUNTIME_THUNK
19 #  include "..\sanitizer_common\sanitizer_allocator_interface.h"
20 // #include "asan_win_thunk_common.h"
21 
22 // Preserve stack traces with noinline.
23 #  define STATIC_MALLOC_INTERFACE __declspec(noinline)
24 
25 extern "C" {
26 __declspec(dllimport) size_t __cdecl __asan_msize(void *ptr);
27 __declspec(dllimport) void __cdecl __asan_free(void *const ptr);
28 __declspec(dllimport) void *__cdecl __asan_malloc(const size_t size);
29 __declspec(dllimport) void *__cdecl __asan_calloc(const size_t nmemb,
30                                                   const size_t size);
31 __declspec(dllimport) void *__cdecl __asan_realloc(void *const ptr,
32                                                    const size_t size);
33 __declspec(dllimport) void *__cdecl __asan_recalloc(void *const ptr,
34                                                     const size_t nmemb,
35                                                     const size_t size);
36 
37 // Avoid tailcall optimization to preserve stack frames.
38 #  pragma optimize("", off)
39 
40 // _msize
41 STATIC_MALLOC_INTERFACE size_t _msize(void *ptr) { return __asan_msize(ptr); }
42 
43 STATIC_MALLOC_INTERFACE size_t _msize_base(void *ptr) {
44   return __asan_msize(ptr);
45 }
46 
47 STATIC_MALLOC_INTERFACE size_t _msize_dbg(void *ptr) {
48   return __asan_msize(ptr);
49 }
50 
51 // free
52 STATIC_MALLOC_INTERFACE void free(void *const ptr) { return __asan_free(ptr); }
53 
54 STATIC_MALLOC_INTERFACE void _free_base(void *const ptr) {
55   return __asan_free(ptr);
56 }
57 
58 STATIC_MALLOC_INTERFACE void _free_dbg(void *const ptr) {
59   return __asan_free(ptr);
60 }
61 
62 // malloc
63 STATIC_MALLOC_INTERFACE void *malloc(const size_t size) {
64   return __asan_malloc(size);
65 }
66 
67 STATIC_MALLOC_INTERFACE void *_malloc_base(const size_t size) {
68   return __asan_malloc(size);
69 }
70 
71 STATIC_MALLOC_INTERFACE void *_malloc_dbg(const size_t size) {
72   return __asan_malloc(size);
73 }
74 
75 // calloc
76 STATIC_MALLOC_INTERFACE void *calloc(const size_t nmemb, const size_t size) {
77   return __asan_calloc(nmemb, size);
78 }
79 
80 STATIC_MALLOC_INTERFACE void *_calloc_base(const size_t nmemb,
81                                            const size_t size) {
82   return __asan_calloc(nmemb, size);
83 }
84 
85 STATIC_MALLOC_INTERFACE void *_calloc_impl(const size_t nmemb,
86                                            const size_t size,
87                                            int *const errno_tmp) {
88   // Provided by legacy msvcrt.
89   (void)errno_tmp;
90 
91   return __asan_calloc(nmemb, size);
92 }
93 
94 STATIC_MALLOC_INTERFACE void *_calloc_dbg(const size_t nmemb, const size_t size,
95                                           int, const char *, int) {
96   return __asan_calloc(nmemb, size);
97 }
98 
99 // realloc
100 STATIC_MALLOC_INTERFACE void *realloc(void *const ptr, const size_t size) {
101   return __asan_realloc(ptr, size);
102 }
103 
104 STATIC_MALLOC_INTERFACE void *_realloc_base(void *const ptr,
105                                             const size_t size) {
106   return __asan_realloc(ptr, size);
107 }
108 
109 STATIC_MALLOC_INTERFACE void *_realloc_dbg(void *const ptr, const size_t size,
110                                            int, const char *, int) {
111   return __asan_realloc(ptr, size);
112 }
113 
114 // recalloc
115 STATIC_MALLOC_INTERFACE void *_recalloc(void *const ptr, const size_t nmemb,
116                                         const size_t size) {
117   return __asan_recalloc(ptr, nmemb, size);
118 }
119 
120 STATIC_MALLOC_INTERFACE void *_recalloc_base(void *const ptr,
121                                              const size_t nmemb,
122                                              const size_t size) {
123   return __asan_recalloc(ptr, nmemb, size);
124 }
125 
126 STATIC_MALLOC_INTERFACE void *_recalloc_dbg(void *const ptr, const size_t nmemb,
127                                             const size_t size, int,
128                                             const char *, int) {
129   return __asan_recalloc(ptr, nmemb, size);
130 }
131 
132 // expand
133 STATIC_MALLOC_INTERFACE void *_expand(void *, size_t) {
134   // _expand is used in realloc-like functions to resize the buffer if possible.
135   // We don't want memory to stand still while resizing buffers, so return 0.
136   return nullptr;
137 }
138 
139 STATIC_MALLOC_INTERFACE void *_expand_dbg(void *, size_t, int, const char *,
140                                           int) {
141   return nullptr;
142 }
143 
144 // We need to provide symbols for all the debug CRT functions if we decide to
145 // provide any. Most of these functions make no sense under ASan and so we
146 // make them no-ops.
147 long _CrtSetBreakAlloc(long const) { return ~0; }
148 
149 void _CrtSetDbgBlockType(void *const, int const) { return; }
150 
151 typedef int(__cdecl *CRT_ALLOC_HOOK)(int, void *, size_t, int, long,
152                                      const unsigned char *, int);
153 
154 CRT_ALLOC_HOOK _CrtGetAllocHook() { return nullptr; }
155 
156 CRT_ALLOC_HOOK _CrtSetAllocHook(CRT_ALLOC_HOOK const hook) { return hook; }
157 
158 int _CrtCheckMemory() { return 1; }
159 
160 int _CrtSetDbgFlag(int const new_bits) { return new_bits; }
161 
162 typedef void (*CrtDoForAllClientObjectsCallback)(void *, void *);
163 
164 void _CrtDoForAllClientObjects(CrtDoForAllClientObjectsCallback const,
165                                void *const) {
166   return;
167 }
168 
169 int _CrtIsValidPointer(void const *const p, unsigned int const, int const) {
170   return p != nullptr;
171 }
172 
173 int _CrtIsValidHeapPointer(void const *const block) {
174   if (!block) {
175     return 0;
176   }
177 
178   return __sanitizer_get_ownership(block);
179 }
180 
181 int _CrtIsMemoryBlock(void const *const, unsigned const, long *const,
182                       char **const, int *const) {
183   return 0;
184 }
185 
186 int _CrtReportBlockType(void const *const) { return -1; }
187 
188 typedef void(__cdecl *CRT_DUMP_CLIENT)(void *, size_t);
189 
190 CRT_DUMP_CLIENT _CrtGetDumpClient() { return nullptr; }
191 
192 CRT_DUMP_CLIENT _CrtSetDumpClient(CRT_DUMP_CLIENT new_client) {
193   return new_client;
194 }
195 
196 void _CrtMemCheckpoint(void *const) { return; }
197 
198 int _CrtMemDifference(void *const, void const *const, void const *const) {
199   return 0;
200 }
201 
202 void _CrtMemDumpAllObjectsSince(void const *const) { return; }
203 
204 int _CrtDumpMemoryLeaks() { return 0; }
205 
206 void _CrtMemDumpStatistics(void const *const) { return; }
207 
208 int _crtDbgFlag{0};
209 long _crtBreakAlloc{-1};
210 CRT_DUMP_CLIENT _pfnDumpClient{nullptr};
211 
212 int *__p__crtDbgFlag() { return &_crtDbgFlag; }
213 
214 long *__p__crtBreakAlloc() { return &_crtBreakAlloc; }
215 
216 // TODO: These were added upstream but conflict with definitions in ucrtbased.
217 // int _CrtDbgReport(int, const char *, int, const char *, const char *, ...) {
218 //   ShowStatsAndAbort();
219 // }
220 //
221 // int _CrtDbgReportW(int reportType, const wchar_t *, int, const wchar_t *,
222 //                    const wchar_t *, ...) {
223 //   ShowStatsAndAbort();
224 // }
225 //
226 // int _CrtSetReportMode(int, int) { return 0; }
227 
228 }  // extern "C"
229 #endif  // SANITIZER_STATIC_RUNTIME_THUNK
230