1 //===-- asan_interceptors.cc ----------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Intercept various libc functions.
11 //===----------------------------------------------------------------------===//
13 #include "asan_interceptors.h"
14 #include "asan_allocator.h"
15 #include "asan_internal.h"
16 #include "asan_mapping.h"
17 #include "asan_poisoning.h"
18 #include "asan_report.h"
19 #include "asan_stack.h"
20 #include "asan_stats.h"
21 #include "asan_suppressions.h"
22 #include "lsan/lsan_common.h"
23 #include "sanitizer_common/sanitizer_libc.h"
25 // There is no general interception at all on Fuchsia.
26 // Only the functions in asan_interceptors_memintrinsics.cc are
27 // really defined to replace libc functions.
28 #if !SANITIZER_FUCHSIA
31 #include "sanitizer_common/sanitizer_posix.h"
34 #if defined(__i386) && SANITIZER_LINUX
35 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
36 #elif defined(__mips__) && SANITIZER_LINUX
37 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
42 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
43 ASAN_READ_RANGE((ctx), (s), \
44 common_flags()->strict_string_checks ? (len) + 1 : (n))
46 #define ASAN_READ_STRING(ctx, s, n) \
47 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
49 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
50 #if SANITIZER_INTERCEPT_STRNLEN
52 return REAL(strnlen
)(s
, maxlen
);
55 return internal_strnlen(s
, maxlen
);
58 void SetThreadName(const char *name
) {
59 AsanThread
*t
= GetCurrentThread();
61 asanThreadRegistry().SetThreadName(t
->tid(), name
);
65 if (CAN_SANITIZE_LEAKS
&& common_flags()->detect_leaks
&&
66 __lsan::HasReportedLeaks()) {
67 return common_flags()->exitcode
;
69 // FIXME: ask frontend whether we need to return failure.
75 // ---------------------- Wrappers ---------------- {{{1
76 using namespace __asan
; // NOLINT
78 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc
, uptr
)
79 DECLARE_REAL_AND_INTERCEPTOR(void, free
, void *)
81 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \
82 AsanInterceptorContext _ctx = {#func}; \
83 ctx = (void *)&_ctx; \
86 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
87 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
88 ASAN_INTERCEPT_FUNC_VER(name, ver)
89 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
90 ASAN_WRITE_RANGE(ctx, ptr, size)
91 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
92 ASAN_READ_RANGE(ctx, ptr, size)
93 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
94 ASAN_INTERCEPTOR_ENTER(ctx, func); \
96 if (asan_init_is_running) \
97 return REAL(func)(__VA_ARGS__); \
98 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
99 return REAL(func)(__VA_ARGS__); \
100 ENSURE_ASAN_INITED(); \
102 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
105 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
108 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
111 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
114 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
115 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
116 // But asan does not remember UserId's for threads (pthread_t);
117 // and remembers all ever existed threads, so the linear search by UserId
119 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
122 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
123 // Strict init-order checking is dlopen-hostile:
124 // https://github.com/google/sanitizers/issues/178
125 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
127 if (flags()->strict_init_order) \
128 StopInitOrderChecking(); \
129 CheckNoDeepBind(filename, flag); \
131 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
132 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
133 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
134 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
135 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
136 if (AsanThread *t = GetCurrentThread()) { \
137 *begin = t->tls_begin(); \
138 *end = t->tls_end(); \
143 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
145 ASAN_INTERCEPTOR_ENTER(ctx, memmove); \
146 ASAN_MEMMOVE_IMPL(ctx, to, from, size); \
149 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
151 ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \
152 ASAN_MEMCPY_IMPL(ctx, to, from, size); \
155 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
157 ASAN_INTERCEPTOR_ENTER(ctx, memset); \
158 ASAN_MEMSET_IMPL(ctx, block, c, size); \
161 #include "sanitizer_common/sanitizer_common_interceptors.inc"
162 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
164 // Syscall interceptors don't have contexts, we don't support suppressions
166 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
167 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
168 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
173 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
178 #include "sanitizer_common/sanitizer_common_syscalls.inc"
180 struct ThreadStartParam
{
182 atomic_uintptr_t is_registered
;
185 #if ASAN_INTERCEPT_PTHREAD_CREATE
186 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
187 ThreadStartParam
*param
= reinterpret_cast<ThreadStartParam
*>(arg
);
188 AsanThread
*t
= nullptr;
189 while ((t
= reinterpret_cast<AsanThread
*>(
190 atomic_load(¶m
->t
, memory_order_acquire
))) == nullptr)
191 internal_sched_yield();
193 return t
->ThreadStart(GetTid(), ¶m
->is_registered
);
196 INTERCEPTOR(int, pthread_create
, void *thread
,
197 void *attr
, void *(*start_routine
)(void*), void *arg
) {
198 EnsureMainThreadIDIsCorrect();
199 // Strict init-order checking is thread-hostile.
200 if (flags()->strict_init_order
)
201 StopInitOrderChecking();
202 GET_STACK_TRACE_THREAD
;
205 REAL(pthread_attr_getdetachstate
)(attr
, &detached
);
206 ThreadStartParam param
;
207 atomic_store(¶m
.t
, 0, memory_order_relaxed
);
208 atomic_store(¶m
.is_registered
, 0, memory_order_relaxed
);
211 // Ignore all allocations made by pthread_create: thread stack/TLS may be
212 // stored by pthread for future reuse even after thread destruction, and
213 // the linked list it's stored in doesn't even hold valid pointers to the
214 // objects, the latter are calculated by obscure pointer arithmetic.
215 #if CAN_SANITIZE_LEAKS
216 __lsan::ScopedInterceptorDisabler disabler
;
218 result
= REAL(pthread_create
)(thread
, attr
, asan_thread_start
, ¶m
);
221 u32 current_tid
= GetCurrentTidOrInvalid();
223 AsanThread::Create(start_routine
, arg
, current_tid
, &stack
, detached
);
224 atomic_store(¶m
.t
, reinterpret_cast<uptr
>(t
), memory_order_release
);
225 // Wait until the AsanThread object is initialized and the ThreadRegistry
226 // entry is in "started" state. One reason for this is that after this
227 // interceptor exits, the child thread's stack may be the only thing holding
228 // the |arg| pointer. This may cause LSan to report a leak if leak checking
229 // happens at a point when the interceptor has already exited, but the stack
230 // range for the child thread is not yet known.
231 while (atomic_load(¶m
.is_registered
, memory_order_acquire
) == 0)
232 internal_sched_yield();
237 INTERCEPTOR(int, pthread_join
, void *t
, void **arg
) {
238 return real_pthread_join(t
, arg
);
241 DEFINE_REAL_PTHREAD_FUNCTIONS
242 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
244 #if ASAN_INTERCEPT_SWAPCONTEXT
245 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
246 // Align to page size.
247 uptr PageSize
= GetPageSizeCached();
248 uptr bottom
= stack
& ~(PageSize
- 1);
249 ssize
+= stack
- bottom
;
250 ssize
= RoundUpTo(ssize
, PageSize
);
251 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
252 if (AddrIsInMem(bottom
) && ssize
&& ssize
<= kMaxSaneContextStackSize
) {
253 PoisonShadow(bottom
, ssize
, 0);
257 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
258 struct ucontext_t
*ucp
) {
259 static bool reported_warning
= false;
260 if (!reported_warning
) {
261 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
262 "functions and may produce false positives in some cases!\n");
263 reported_warning
= true;
265 // Clear shadow memory for new context (it may share stack
266 // with current context).
268 ReadContextStack(ucp
, &stack
, &ssize
);
269 ClearShadowMemoryForContextStack(stack
, ssize
);
270 int res
= REAL(swapcontext
)(oucp
, ucp
);
271 // swapcontext technically does not return, but program may swap context to
272 // "oucp" later, that would look as if swapcontext() returned 0.
273 // We need to clear shadow for ucp once again, as it may be in arbitrary
275 ClearShadowMemoryForContextStack(stack
, ssize
);
278 #endif // ASAN_INTERCEPT_SWAPCONTEXT
281 #define longjmp __longjmp14
282 #define siglongjmp __siglongjmp14
285 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
286 __asan_handle_no_return();
287 REAL(longjmp
)(env
, val
);
290 #if ASAN_INTERCEPT__LONGJMP
291 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
292 __asan_handle_no_return();
293 REAL(_longjmp
)(env
, val
);
297 #if ASAN_INTERCEPT___LONGJMP_CHK
298 INTERCEPTOR(void, __longjmp_chk
, void *env
, int val
) {
299 __asan_handle_no_return();
300 REAL(__longjmp_chk
)(env
, val
);
304 #if ASAN_INTERCEPT_SIGLONGJMP
305 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
306 __asan_handle_no_return();
307 REAL(siglongjmp
)(env
, val
);
311 #if ASAN_INTERCEPT___CXA_THROW
312 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
313 CHECK(REAL(__cxa_throw
));
314 __asan_handle_no_return();
315 REAL(__cxa_throw
)(a
, b
, c
);
319 #if ASAN_INTERCEPT_INDEX
320 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
321 INTERCEPTOR(char*, index
, const char *string
, int c
)
322 ALIAS(WRAPPER_NAME(strchr
));
325 DECLARE_REAL(char*, index
, const char *string
, int c
)
326 OVERRIDE_FUNCTION(index
, strchr
);
328 DEFINE_REAL(char*, index
, const char *string
, int c
)
331 #endif // ASAN_INTERCEPT_INDEX
333 // For both strcat() and strncat() we need to check the validity of |to|
334 // argument irrespective of the |from| length.
335 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
337 ASAN_INTERCEPTOR_ENTER(ctx
, strcat
); // NOLINT
338 ENSURE_ASAN_INITED();
339 if (flags()->replace_str
) {
340 uptr from_length
= REAL(strlen
)(from
);
341 ASAN_READ_RANGE(ctx
, from
, from_length
+ 1);
342 uptr to_length
= REAL(strlen
)(to
);
343 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
344 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
345 // If the copying actually happens, the |from| string should not overlap
346 // with the resulting string starting at |to|, which has a length of
347 // to_length + from_length + 1.
348 if (from_length
> 0) {
349 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
350 from
, from_length
+ 1);
353 return REAL(strcat
)(to
, from
); // NOLINT
356 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
358 ASAN_INTERCEPTOR_ENTER(ctx
, strncat
);
359 ENSURE_ASAN_INITED();
360 if (flags()->replace_str
) {
361 uptr from_length
= MaybeRealStrnlen(from
, size
);
362 uptr copy_length
= Min(size
, from_length
+ 1);
363 ASAN_READ_RANGE(ctx
, from
, copy_length
);
364 uptr to_length
= REAL(strlen
)(to
);
365 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
366 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
367 if (from_length
> 0) {
368 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
372 return REAL(strncat
)(to
, from
, size
);
375 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
377 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
); // NOLINT
379 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
381 // strcpy is called from malloc_default_purgeable_zone()
382 // in __asan::ReplaceSystemAlloc() on Mac.
383 if (asan_init_is_running
) {
384 return REAL(strcpy
)(to
, from
); // NOLINT
386 ENSURE_ASAN_INITED();
387 if (flags()->replace_str
) {
388 uptr from_size
= REAL(strlen
)(from
) + 1;
389 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
390 ASAN_READ_RANGE(ctx
, from
, from_size
);
391 ASAN_WRITE_RANGE(ctx
, to
, from_size
);
393 return REAL(strcpy
)(to
, from
); // NOLINT
396 INTERCEPTOR(char*, strdup
, const char *s
) {
398 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
399 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
400 ENSURE_ASAN_INITED();
401 uptr length
= REAL(strlen
)(s
);
402 if (flags()->replace_str
) {
403 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
405 GET_STACK_TRACE_MALLOC
;
406 void *new_mem
= asan_malloc(length
+ 1, &stack
);
407 REAL(memcpy
)(new_mem
, s
, length
+ 1);
408 return reinterpret_cast<char*>(new_mem
);
411 #if ASAN_INTERCEPT___STRDUP
412 INTERCEPTOR(char*, __strdup
, const char *s
) {
414 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
415 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
416 ENSURE_ASAN_INITED();
417 uptr length
= REAL(strlen
)(s
);
418 if (flags()->replace_str
) {
419 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
421 GET_STACK_TRACE_MALLOC
;
422 void *new_mem
= asan_malloc(length
+ 1, &stack
);
423 REAL(memcpy
)(new_mem
, s
, length
+ 1);
424 return reinterpret_cast<char*>(new_mem
);
426 #endif // ASAN_INTERCEPT___STRDUP
428 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
430 ASAN_INTERCEPTOR_ENTER(ctx
, strncpy
);
431 ENSURE_ASAN_INITED();
432 if (flags()->replace_str
) {
433 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
434 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
435 ASAN_READ_RANGE(ctx
, from
, from_size
);
436 ASAN_WRITE_RANGE(ctx
, to
, size
);
438 return REAL(strncpy
)(to
, from
, size
);
441 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
442 char **endptr
, int base
) {
444 ASAN_INTERCEPTOR_ENTER(ctx
, strtol
);
445 ENSURE_ASAN_INITED();
446 if (!flags()->replace_str
) {
447 return REAL(strtol
)(nptr
, endptr
, base
);
450 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
451 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
455 INTERCEPTOR(int, atoi
, const char *nptr
) {
457 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
459 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
461 ENSURE_ASAN_INITED();
462 if (!flags()->replace_str
) {
463 return REAL(atoi
)(nptr
);
466 // "man atoi" tells that behavior of atoi(nptr) is the same as
467 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
468 // parsed integer can't be stored in *long* type (even if it's
469 // different from int). So, we just imitate this behavior.
470 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
471 FixRealStrtolEndptr(nptr
, &real_endptr
);
472 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
476 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
478 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
480 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
482 ENSURE_ASAN_INITED();
483 if (!flags()->replace_str
) {
484 return REAL(atol
)(nptr
);
487 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
488 FixRealStrtolEndptr(nptr
, &real_endptr
);
489 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
493 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
494 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
495 char **endptr
, int base
) {
497 ASAN_INTERCEPTOR_ENTER(ctx
, strtoll
);
498 ENSURE_ASAN_INITED();
499 if (!flags()->replace_str
) {
500 return REAL(strtoll
)(nptr
, endptr
, base
);
503 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
504 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
508 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
510 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
511 ENSURE_ASAN_INITED();
512 if (!flags()->replace_str
) {
513 return REAL(atoll
)(nptr
);
516 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
517 FixRealStrtolEndptr(nptr
, &real_endptr
);
518 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
521 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
523 #if ASAN_INTERCEPT___CXA_ATEXIT
524 static void AtCxaAtexit(void *unused
) {
526 StopInitOrderChecking();
529 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
532 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
534 ENSURE_ASAN_INITED();
535 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
536 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
539 #endif // ASAN_INTERCEPT___CXA_ATEXIT
541 #if ASAN_INTERCEPT_FORK
542 INTERCEPTOR(int, fork
, void) {
543 ENSURE_ASAN_INITED();
544 int pid
= REAL(fork
)();
547 #endif // ASAN_INTERCEPT_FORK
549 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
551 void InitializeAsanInterceptors() {
552 static bool was_called_once
;
553 CHECK(!was_called_once
);
554 was_called_once
= true;
555 InitializeCommonInterceptors();
556 InitializeSignalInterceptors();
558 // Intercept str* functions.
559 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
560 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
561 ASAN_INTERCEPT_FUNC(strncat
);
562 ASAN_INTERCEPT_FUNC(strncpy
);
563 ASAN_INTERCEPT_FUNC(strdup
);
564 #if ASAN_INTERCEPT___STRDUP
565 ASAN_INTERCEPT_FUNC(__strdup
);
567 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
568 ASAN_INTERCEPT_FUNC(index
);
571 ASAN_INTERCEPT_FUNC(atoi
);
572 ASAN_INTERCEPT_FUNC(atol
);
573 ASAN_INTERCEPT_FUNC(strtol
);
574 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
575 ASAN_INTERCEPT_FUNC(atoll
);
576 ASAN_INTERCEPT_FUNC(strtoll
);
579 // Intecept jump-related functions.
580 ASAN_INTERCEPT_FUNC(longjmp
);
582 #if ASAN_INTERCEPT_SWAPCONTEXT
583 ASAN_INTERCEPT_FUNC(swapcontext
);
585 #if ASAN_INTERCEPT__LONGJMP
586 ASAN_INTERCEPT_FUNC(_longjmp
);
588 #if ASAN_INTERCEPT___LONGJMP_CHK
589 ASAN_INTERCEPT_FUNC(__longjmp_chk
);
591 #if ASAN_INTERCEPT_SIGLONGJMP
592 ASAN_INTERCEPT_FUNC(siglongjmp
);
595 // Intercept exception handling functions.
596 #if ASAN_INTERCEPT___CXA_THROW
597 ASAN_INTERCEPT_FUNC(__cxa_throw
);
600 // Intercept threading-related functions
601 #if ASAN_INTERCEPT_PTHREAD_CREATE
602 #if defined(ASAN_PTHREAD_CREATE_VERSION)
603 ASAN_INTERCEPT_FUNC_VER(pthread_create
, ASAN_PTHREAD_CREATE_VERSION
);
605 ASAN_INTERCEPT_FUNC(pthread_create
);
607 ASAN_INTERCEPT_FUNC(pthread_join
);
610 // Intercept atexit function.
611 #if ASAN_INTERCEPT___CXA_ATEXIT
612 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
615 #if ASAN_INTERCEPT_FORK
616 ASAN_INTERCEPT_FUNC(fork
);
619 InitializePlatformInterceptors();
621 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
624 } // namespace __asan
626 #endif // !SANITIZER_FUCHSIA