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