1 | //===-- sanitizer_common_interceptors_memintrinsics.inc ---------*- C++ -*-===// |
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 | // |
9 | // Memintrinsic function interceptors for tools like AddressSanitizer, |
10 | // ThreadSanitizer, MemorySanitizer, etc. |
11 | // |
12 | // These interceptors are part of the common interceptors, but separated out so |
13 | // that implementations may add them, if necessary, to a separate source file |
14 | // that should define SANITIZER_COMMON_NO_REDEFINE_BUILTINS at the top. |
15 | // |
16 | // This file should be included into the tool's memintrinsic interceptor file, |
17 | // which has to define its own macros: |
18 | // COMMON_INTERCEPTOR_ENTER |
19 | // COMMON_INTERCEPTOR_READ_RANGE |
20 | // COMMON_INTERCEPTOR_WRITE_RANGE |
21 | // COMMON_INTERCEPTOR_MEMSET_IMPL |
22 | // COMMON_INTERCEPTOR_MEMMOVE_IMPL |
23 | // COMMON_INTERCEPTOR_MEMCPY_IMPL |
24 | // COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED |
25 | //===----------------------------------------------------------------------===// |
26 | |
27 | #ifdef SANITIZER_REDEFINE_BUILTINS_H |
28 | #error "Define SANITIZER_COMMON_NO_REDEFINE_BUILTINS in .cpp file" |
29 | #endif |
30 | |
31 | #include "interception/interception.h" |
32 | #include "sanitizer_platform_interceptors.h" |
33 | |
34 | // Platform-specific options. |
35 | #if SANITIZER_APPLE |
36 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 |
37 | #elif SANITIZER_WINDOWS64 |
38 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 |
39 | #else |
40 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 |
41 | #endif // SANITIZER_APPLE |
42 | |
43 | #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL |
44 | #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ |
45 | { \ |
46 | if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ |
47 | return internal_memset(dst, v, size); \ |
48 | COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ |
49 | if (common_flags()->intercept_intrin) \ |
50 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ |
51 | return REAL(memset)(dst, v, size); \ |
52 | } |
53 | #endif |
54 | |
55 | #ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL |
56 | #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \ |
57 | { \ |
58 | if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ |
59 | return internal_memmove(dst, src, size); \ |
60 | COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \ |
61 | if (common_flags()->intercept_intrin) { \ |
62 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ |
63 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \ |
64 | } \ |
65 | return REAL(memmove)(dst, src, size); \ |
66 | } |
67 | #endif |
68 | |
69 | #ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL |
70 | #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \ |
71 | { \ |
72 | if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \ |
73 | return internal_memmove(dst, src, size); \ |
74 | } \ |
75 | COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \ |
76 | if (common_flags()->intercept_intrin) { \ |
77 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ |
78 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \ |
79 | } \ |
80 | return REAL(memcpy)(dst, src, size); \ |
81 | } |
82 | #endif |
83 | |
84 | #if SANITIZER_INTERCEPT_MEMSET |
85 | INTERCEPTOR(void *, memset, void *dst, int v, uptr size) { |
86 | void *ctx; |
87 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size); |
88 | } |
89 | |
90 | #define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset) |
91 | #else |
92 | #define INIT_MEMSET |
93 | #endif |
94 | |
95 | #if SANITIZER_INTERCEPT_MEMMOVE |
96 | INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) { |
97 | void *ctx; |
98 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); |
99 | } |
100 | |
101 | #define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove) |
102 | #else |
103 | #define INIT_MEMMOVE |
104 | #endif |
105 | |
106 | #if SANITIZER_INTERCEPT_MEMCPY |
107 | INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) { |
108 | // On OS X, calling internal_memcpy here will cause memory corruptions, |
109 | // because memcpy and memmove are actually aliases of the same |
110 | // implementation. We need to use internal_memmove here. |
111 | // N.B.: If we switch this to internal_ we'll have to use internal_memmove |
112 | // due to memcpy being an alias of memmove on OS X. |
113 | void *ctx; |
114 | #if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE |
115 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); |
116 | #else |
117 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); |
118 | #endif |
119 | } |
120 | |
121 | #define INIT_MEMCPY \ |
122 | do { \ |
123 | if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \ |
124 | COMMON_INTERCEPT_FUNCTION(memcpy); \ |
125 | } else { \ |
126 | ASSIGN_REAL(memcpy, memmove); \ |
127 | } \ |
128 | CHECK(REAL(memcpy)); \ |
129 | } while (false) |
130 | |
131 | #else |
132 | #define INIT_MEMCPY |
133 | #endif |
134 | |
135 | #if SANITIZER_INTERCEPT_AEABI_MEM |
136 | INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) { |
137 | void *ctx; |
138 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); |
139 | } |
140 | |
141 | INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) { |
142 | void *ctx; |
143 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); |
144 | } |
145 | |
146 | INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) { |
147 | void *ctx; |
148 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); |
149 | } |
150 | |
151 | INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) { |
152 | void *ctx; |
153 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); |
154 | } |
155 | |
156 | INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) { |
157 | void *ctx; |
158 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); |
159 | } |
160 | |
161 | INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) { |
162 | void *ctx; |
163 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); |
164 | } |
165 | |
166 | // Note the argument order. |
167 | INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) { |
168 | void *ctx; |
169 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); |
170 | } |
171 | |
172 | INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) { |
173 | void *ctx; |
174 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); |
175 | } |
176 | |
177 | INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) { |
178 | void *ctx; |
179 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); |
180 | } |
181 | |
182 | INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) { |
183 | void *ctx; |
184 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
185 | } |
186 | |
187 | INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) { |
188 | void *ctx; |
189 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
190 | } |
191 | |
192 | INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) { |
193 | void *ctx; |
194 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
195 | } |
196 | |
197 | #define INIT_AEABI_MEM \ |
198 | COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \ |
199 | COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \ |
200 | COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \ |
201 | COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \ |
202 | COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \ |
203 | COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \ |
204 | COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \ |
205 | COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \ |
206 | COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \ |
207 | COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \ |
208 | COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \ |
209 | COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8); |
210 | #else |
211 | #define INIT_AEABI_MEM |
212 | #endif // SANITIZER_INTERCEPT_AEABI_MEM |
213 | |
214 | #if SANITIZER_INTERCEPT___BZERO |
215 | INTERCEPTOR(void *, __bzero, void *block, uptr size) { |
216 | void *ctx; |
217 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
218 | } |
219 | #define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero); |
220 | #else |
221 | #define INIT___BZERO |
222 | #endif // SANITIZER_INTERCEPT___BZERO |
223 | |
224 | #if SANITIZER_INTERCEPT_BZERO |
225 | INTERCEPTOR(void *, bzero, void *block, uptr size) { |
226 | void *ctx; |
227 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
228 | } |
229 | #define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero); |
230 | #else |
231 | #define INIT_BZERO |
232 | #endif // SANITIZER_INTERCEPT_BZERO |
233 | |
234 | namespace __sanitizer { |
235 | // This does not need to be called if InitializeCommonInterceptors() is called. |
236 | void InitializeMemintrinsicInterceptors() { |
237 | INIT_MEMSET; |
238 | INIT_MEMMOVE; |
239 | INIT_MEMCPY; |
240 | INIT_AEABI_MEM; |
241 | INIT___BZERO; |
242 | INIT_BZERO; |
243 | } |
244 | } // namespace __sanitizer |
245 | |