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