1//===-- asan_interceptors.h -------------------------------------*- 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// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// ASan-private header for asan_interceptors.cpp
12//===----------------------------------------------------------------------===//
13#ifndef ASAN_INTERCEPTORS_H
14#define ASAN_INTERCEPTORS_H
15
16#include "asan_interceptors_memintrinsics.h"
17#include "asan_internal.h"
18#include "interception/interception.h"
19#include "sanitizer_common/sanitizer_platform.h"
20#include "sanitizer_common/sanitizer_platform_interceptors.h"
21
22namespace __asan {
23
24void InitializeAsanInterceptors();
25void InitializePlatformInterceptors();
26
27} // namespace __asan
28
29// There is no general interception at all on Fuchsia.
30// Only the functions in asan_interceptors_memintrinsics.h are
31// really defined to replace libc functions.
32#if !SANITIZER_FUCHSIA
33
34// Sanitizer on AIX is currently unable to retrieve the address
35// of the real longjump (or an alternative thereto).
36// TODO: Consider intercepting longjmpx on AIX.
37# if !SANITIZER_AIX
38# define ASAN_INTERCEPT_LONGJMP 1
39# else
40# define ASAN_INTERCEPT_LONGJMP 0
41# endif
42
43// Use macro to describe if specific function should be
44// intercepted on a given platform.
45# if !SANITIZER_WINDOWS
46 // Sanitizer on AIX is currently unable to retrieve the address
47 // of the real _longjump (or an alternative thereto).
48 // TODO: Consider intercepting _longjmpx on AIX.
49# if !SANITIZER_AIX
50# define ASAN_INTERCEPT__LONGJMP 1
51# else
52# define ASAN_INTERCEPT__LONGJMP 0
53# endif
54# define ASAN_INTERCEPT_INDEX 1
55# define ASAN_INTERCEPT_PTHREAD_CREATE 1
56# else
57# define ASAN_INTERCEPT__LONGJMP 0
58# define ASAN_INTERCEPT_INDEX 0
59# define ASAN_INTERCEPT_PTHREAD_CREATE 0
60# endif
61
62# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
63 SANITIZER_SOLARIS
64# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
65# else
66# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
67# endif
68
69# if SANITIZER_GLIBC || SANITIZER_SOLARIS
70# define ASAN_INTERCEPT_SWAPCONTEXT 1
71# else
72# define ASAN_INTERCEPT_SWAPCONTEXT 0
73# endif
74
75// Sanitizer on AIX is currently unable to retrieve the address
76// of the real siglongjump (or an alternative thereto).
77// TODO: Consider intercepting sigsetjmpx on AIX.
78# if !SANITIZER_WINDOWS && !SANITIZER_AIX
79# define ASAN_INTERCEPT_SIGLONGJMP 1
80# else
81# define ASAN_INTERCEPT_SIGLONGJMP 0
82# endif
83
84# if SANITIZER_GLIBC
85# define ASAN_INTERCEPT___LONGJMP_CHK 1
86# else
87# define ASAN_INTERCEPT___LONGJMP_CHK 0
88# endif
89
90# if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
91 (!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
92# define ASAN_INTERCEPT___CXA_THROW 1
93# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
94# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
95# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
96# else
97# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
98# endif
99# else
100# define ASAN_INTERCEPT___CXA_THROW 0
101# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
102# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
103# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
104# endif
105
106// Clang on AIX neither uses `__cxa_atexit` nor links against a library with
107// such.
108// TODO: Consider intercepting `atexit` and `unatexit` on AIX.
109# if !SANITIZER_WINDOWS && !SANITIZER_AIX
110# define ASAN_INTERCEPT___CXA_ATEXIT 1
111# else
112# define ASAN_INTERCEPT___CXA_ATEXIT 0
113# endif
114
115# if SANITIZER_NETBSD
116# define ASAN_INTERCEPT_ATEXIT 1
117# else
118# define ASAN_INTERCEPT_ATEXIT 0
119# endif
120
121# if SANITIZER_GLIBC
122# define ASAN_INTERCEPT___STRDUP 1
123# else
124# define ASAN_INTERCEPT___STRDUP 0
125# endif
126
127# if SANITIZER_GLIBC && ASAN_INTERCEPT_PTHREAD_CREATE
128# define ASAN_INTERCEPT_TIMEDJOIN 1
129# define ASAN_INTERCEPT_TRYJOIN 1
130# else
131# define ASAN_INTERCEPT_TIMEDJOIN 0
132# define ASAN_INTERCEPT_TRYJOIN 0
133# endif
134
135# if SANITIZER_LINUX && \
136 (defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
137 defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
138# define ASAN_INTERCEPT_VFORK 1
139# else
140# define ASAN_INTERCEPT_VFORK 0
141# endif
142
143# if SANITIZER_NETBSD
144# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
145# else
146# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
147# endif
148
149DECLARE_REAL(int, memcmp, const void* a1, const void* a2, SIZE_T size)
150DECLARE_REAL(char*, strchr, const char* str, int c)
151DECLARE_REAL(SIZE_T, strlen, const char* s)
152DECLARE_REAL(char*, strncpy, char* to, const char* from, SIZE_T size)
153DECLARE_REAL(SIZE_T, strnlen, const char* s, SIZE_T maxlen)
154DECLARE_REAL(SIZE_T, wcsnlen, const wchar_t* s, SIZE_T maxlen)
155DECLARE_REAL(char*, strstr, const char* s1, const char* s2)
156
157# if !SANITIZER_APPLE
158# define ASAN_INTERCEPT_FUNC(name) \
159 do { \
160 if (!INTERCEPT_FUNCTION(name)) \
161 VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
162 } while (0)
163# define ASAN_INTERCEPT_FUNC_VER(name, ver) \
164 do { \
165 if (!INTERCEPT_FUNCTION_VER(name, ver)) \
166 VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", \
167 #name, ver); \
168 } while (0)
169# define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
170 do { \
171 if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
172 VReport(1, \
173 "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
174 #name, ver, #name); \
175 } while (0)
176
177# else
178// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
179# define ASAN_INTERCEPT_FUNC(name)
180# endif // SANITIZER_APPLE
181
182# define ASAN_INTERCEPTOR_ENTER(ctx, func) \
183 AsanInterceptorContext _ctx = {#func}; \
184 ctx = (void*)&_ctx; \
185 (void)ctx;
186# define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
187
188#endif // !SANITIZER_FUCHSIA
189
190#endif // ASAN_INTERCEPTORS_H
191