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
87INTERCEPTOR(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
98INTERCEPTOR(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
109INTERCEPTOR(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
138INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, usize size) {
139 void *ctx;
140 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
141}
142
143INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, usize size) {
144 void *ctx;
145 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
146}
147
148INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, usize size) {
149 void *ctx;
150 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
151}
152
153INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, usize size) {
154 void *ctx;
155 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
156}
157
158INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, usize size) {
159 void *ctx;
160 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
161}
162
163INTERCEPTOR(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.
169INTERCEPTOR(void *, __aeabi_memset, void *block, usize size, int c) {
170 void *ctx;
171 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
172}
173
174INTERCEPTOR(void *, __aeabi_memset4, void *block, usize size, int c) {
175 void *ctx;
176 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
177}
178
179INTERCEPTOR(void *, __aeabi_memset8, void *block, usize size, int c) {
180 void *ctx;
181 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
182}
183
184INTERCEPTOR(void *, __aeabi_memclr, void *block, usize size) {
185 void *ctx;
186 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
187}
188
189INTERCEPTOR(void *, __aeabi_memclr4, void *block, usize size) {
190 void *ctx;
191 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
192}
193
194INTERCEPTOR(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
217INTERCEPTOR(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
227INTERCEPTOR(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
236namespace __sanitizer {
237// This does not need to be called if InitializeCommonInterceptors() is called.
238void 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