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 | #elif SANITIZER_AIX |
40 | # define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 |
41 | #else |
42 | # define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 |
43 | #endif // SANITIZER_APPLE |
44 | |
45 | #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL |
46 | #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ |
47 | { \ |
48 | if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ |
49 | return internal_memset(dst, v, size); \ |
50 | COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ |
51 | if (common_flags()->intercept_intrin) \ |
52 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ |
53 | return REAL(memset)(dst, v, size); \ |
54 | } |
55 | #endif |
56 | |
57 | #ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL |
58 | #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \ |
59 | { \ |
60 | if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ |
61 | return internal_memmove(dst, src, size); \ |
62 | COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \ |
63 | if (common_flags()->intercept_intrin) { \ |
64 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ |
65 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \ |
66 | } \ |
67 | return REAL(memmove)(dst, src, size); \ |
68 | } |
69 | #endif |
70 | |
71 | #ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL |
72 | #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \ |
73 | { \ |
74 | if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \ |
75 | return internal_memmove(dst, src, size); \ |
76 | } \ |
77 | COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \ |
78 | if (common_flags()->intercept_intrin) { \ |
79 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ |
80 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \ |
81 | } \ |
82 | return REAL(memcpy)(dst, src, size); \ |
83 | } |
84 | #endif |
85 | |
86 | #if SANITIZER_INTERCEPT_MEMSET |
87 | INTERCEPTOR(void *, memset, void *dst, int v, usize size) { |
88 | void *ctx; |
89 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size); |
90 | } |
91 | |
92 | #define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset) |
93 | #else |
94 | #define INIT_MEMSET |
95 | #endif |
96 | |
97 | #if SANITIZER_INTERCEPT_MEMMOVE |
98 | INTERCEPTOR(void *, memmove, void *dst, const void *src, usize size) { |
99 | void *ctx; |
100 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); |
101 | } |
102 | |
103 | #define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove) |
104 | #else |
105 | #define INIT_MEMMOVE |
106 | #endif |
107 | |
108 | #if SANITIZER_INTERCEPT_MEMCPY |
109 | INTERCEPTOR(void *, memcpy, void *dst, const void *src, usize size) { |
110 | // On OS X, calling internal_memcpy here will cause memory corruptions, |
111 | // because memcpy and memmove are actually aliases of the same |
112 | // implementation. We need to use internal_memmove here. |
113 | // N.B.: If we switch this to internal_ we'll have to use internal_memmove |
114 | // due to memcpy being an alias of memmove on OS X. |
115 | void *ctx; |
116 | #if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE |
117 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); |
118 | #else |
119 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); |
120 | #endif |
121 | } |
122 | |
123 | #define INIT_MEMCPY \ |
124 | do { \ |
125 | if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \ |
126 | COMMON_INTERCEPT_FUNCTION(memcpy); \ |
127 | } else { \ |
128 | ASSIGN_REAL(memcpy, memmove); \ |
129 | } \ |
130 | CHECK(REAL(memcpy)); \ |
131 | } while (false) |
132 | |
133 | #else |
134 | #define INIT_MEMCPY |
135 | #endif |
136 | |
137 | #if SANITIZER_INTERCEPT_AEABI_MEM |
138 | INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, usize size) { |
139 | void *ctx; |
140 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); |
141 | } |
142 | |
143 | INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, usize size) { |
144 | void *ctx; |
145 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); |
146 | } |
147 | |
148 | INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, usize size) { |
149 | void *ctx; |
150 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size); |
151 | } |
152 | |
153 | INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, usize size) { |
154 | void *ctx; |
155 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); |
156 | } |
157 | |
158 | INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, usize size) { |
159 | void *ctx; |
160 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); |
161 | } |
162 | |
163 | INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, usize size) { |
164 | void *ctx; |
165 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size); |
166 | } |
167 | |
168 | // Note the argument order. |
169 | INTERCEPTOR(void *, __aeabi_memset, void *block, usize size, int c) { |
170 | void *ctx; |
171 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); |
172 | } |
173 | |
174 | INTERCEPTOR(void *, __aeabi_memset4, void *block, usize size, int c) { |
175 | void *ctx; |
176 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); |
177 | } |
178 | |
179 | INTERCEPTOR(void *, __aeabi_memset8, void *block, usize size, int c) { |
180 | void *ctx; |
181 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size); |
182 | } |
183 | |
184 | INTERCEPTOR(void *, __aeabi_memclr, void *block, usize size) { |
185 | void *ctx; |
186 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
187 | } |
188 | |
189 | INTERCEPTOR(void *, __aeabi_memclr4, void *block, usize size) { |
190 | void *ctx; |
191 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
192 | } |
193 | |
194 | INTERCEPTOR(void *, __aeabi_memclr8, void *block, usize size) { |
195 | void *ctx; |
196 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
197 | } |
198 | |
199 | #define INIT_AEABI_MEM \ |
200 | COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \ |
201 | COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \ |
202 | COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \ |
203 | COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \ |
204 | COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \ |
205 | COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \ |
206 | COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \ |
207 | COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \ |
208 | COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \ |
209 | COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \ |
210 | COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \ |
211 | COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8); |
212 | #else |
213 | #define INIT_AEABI_MEM |
214 | #endif // SANITIZER_INTERCEPT_AEABI_MEM |
215 | |
216 | #if SANITIZER_INTERCEPT___BZERO |
217 | INTERCEPTOR(void *, __bzero, void *block, usize size) { |
218 | void *ctx; |
219 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
220 | } |
221 | #define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero); |
222 | #else |
223 | #define INIT___BZERO |
224 | #endif // SANITIZER_INTERCEPT___BZERO |
225 | |
226 | #if SANITIZER_INTERCEPT_BZERO |
227 | INTERCEPTOR(void *, bzero, void *block, usize size) { |
228 | void *ctx; |
229 | COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size); |
230 | } |
231 | #define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero); |
232 | #else |
233 | #define INIT_BZERO |
234 | #endif // SANITIZER_INTERCEPT_BZERO |
235 | |
236 | namespace __sanitizer { |
237 | // This does not need to be called if InitializeCommonInterceptors() is called. |
238 | void InitializeMemintrinsicInterceptors() { |
239 | INIT_MEMSET; |
240 | INIT_MEMMOVE; |
241 | INIT_MEMCPY; |
242 | INIT_AEABI_MEM; |
243 | INIT___BZERO; |
244 | INIT_BZERO; |
245 | } |
246 | } // namespace __sanitizer |
247 | |