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 #if __has_attribute(__indirect_return__) && \
271 (defined(__x86_64__) || defined(__i386__))
272 int (*real_swapcontext
)(struct ucontext_t
*, struct ucontext_t
*)
273 __attribute__((__indirect_return__
))
275 int res
= real_swapcontext(oucp
, ucp
);
277 int res
= REAL(swapcontext
)(oucp
, ucp
);
279 // swapcontext technically does not return, but program may swap context to
280 // "oucp" later, that would look as if swapcontext() returned 0.
281 // We need to clear shadow for ucp once again, as it may be in arbitrary
283 ClearShadowMemoryForContextStack(stack
, ssize
);
286 #endif // ASAN_INTERCEPT_SWAPCONTEXT
289 #define longjmp __longjmp14
290 #define siglongjmp __siglongjmp14
293 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
294 __asan_handle_no_return();
295 REAL(longjmp
)(env
, val
);
298 #if ASAN_INTERCEPT__LONGJMP
299 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
300 __asan_handle_no_return();
301 REAL(_longjmp
)(env
, val
);
305 #if ASAN_INTERCEPT___LONGJMP_CHK
306 INTERCEPTOR(void, __longjmp_chk
, void *env
, int val
) {
307 __asan_handle_no_return();
308 REAL(__longjmp_chk
)(env
, val
);
312 #if ASAN_INTERCEPT_SIGLONGJMP
313 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
314 __asan_handle_no_return();
315 REAL(siglongjmp
)(env
, val
);
319 #if ASAN_INTERCEPT___CXA_THROW
320 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
321 CHECK(REAL(__cxa_throw
));
322 __asan_handle_no_return();
323 REAL(__cxa_throw
)(a
, b
, c
);
327 #if ASAN_INTERCEPT_INDEX
328 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
329 INTERCEPTOR(char*, index
, const char *string
, int c
)
330 ALIAS(WRAPPER_NAME(strchr
));
333 DECLARE_REAL(char*, index
, const char *string
, int c
)
334 OVERRIDE_FUNCTION(index
, strchr
);
336 DEFINE_REAL(char*, index
, const char *string
, int c
)
339 #endif // ASAN_INTERCEPT_INDEX
341 // For both strcat() and strncat() we need to check the validity of |to|
342 // argument irrespective of the |from| length.
343 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
345 ASAN_INTERCEPTOR_ENTER(ctx
, strcat
); // NOLINT
346 ENSURE_ASAN_INITED();
347 if (flags()->replace_str
) {
348 uptr from_length
= REAL(strlen
)(from
);
349 ASAN_READ_RANGE(ctx
, from
, from_length
+ 1);
350 uptr to_length
= REAL(strlen
)(to
);
351 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
352 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
353 // If the copying actually happens, the |from| string should not overlap
354 // with the resulting string starting at |to|, which has a length of
355 // to_length + from_length + 1.
356 if (from_length
> 0) {
357 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
358 from
, from_length
+ 1);
361 return REAL(strcat
)(to
, from
); // NOLINT
364 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
366 ASAN_INTERCEPTOR_ENTER(ctx
, strncat
);
367 ENSURE_ASAN_INITED();
368 if (flags()->replace_str
) {
369 uptr from_length
= MaybeRealStrnlen(from
, size
);
370 uptr copy_length
= Min(size
, from_length
+ 1);
371 ASAN_READ_RANGE(ctx
, from
, copy_length
);
372 uptr to_length
= REAL(strlen
)(to
);
373 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
374 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
375 if (from_length
> 0) {
376 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
380 return REAL(strncat
)(to
, from
, size
);
383 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
385 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
); // NOLINT
387 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
389 // strcpy is called from malloc_default_purgeable_zone()
390 // in __asan::ReplaceSystemAlloc() on Mac.
391 if (asan_init_is_running
) {
392 return REAL(strcpy
)(to
, from
); // NOLINT
394 ENSURE_ASAN_INITED();
395 if (flags()->replace_str
) {
396 uptr from_size
= REAL(strlen
)(from
) + 1;
397 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
398 ASAN_READ_RANGE(ctx
, from
, from_size
);
399 ASAN_WRITE_RANGE(ctx
, to
, from_size
);
401 return REAL(strcpy
)(to
, from
); // NOLINT
404 INTERCEPTOR(char*, strdup
, const char *s
) {
406 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
407 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
408 ENSURE_ASAN_INITED();
409 uptr length
= REAL(strlen
)(s
);
410 if (flags()->replace_str
) {
411 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
413 GET_STACK_TRACE_MALLOC
;
414 void *new_mem
= asan_malloc(length
+ 1, &stack
);
415 REAL(memcpy
)(new_mem
, s
, length
+ 1);
416 return reinterpret_cast<char*>(new_mem
);
419 #if ASAN_INTERCEPT___STRDUP
420 INTERCEPTOR(char*, __strdup
, const char *s
) {
422 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
423 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
424 ENSURE_ASAN_INITED();
425 uptr length
= REAL(strlen
)(s
);
426 if (flags()->replace_str
) {
427 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
429 GET_STACK_TRACE_MALLOC
;
430 void *new_mem
= asan_malloc(length
+ 1, &stack
);
431 REAL(memcpy
)(new_mem
, s
, length
+ 1);
432 return reinterpret_cast<char*>(new_mem
);
434 #endif // ASAN_INTERCEPT___STRDUP
436 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
438 ASAN_INTERCEPTOR_ENTER(ctx
, strncpy
);
439 ENSURE_ASAN_INITED();
440 if (flags()->replace_str
) {
441 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
442 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
443 ASAN_READ_RANGE(ctx
, from
, from_size
);
444 ASAN_WRITE_RANGE(ctx
, to
, size
);
446 return REAL(strncpy
)(to
, from
, size
);
449 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
450 char **endptr
, int base
) {
452 ASAN_INTERCEPTOR_ENTER(ctx
, strtol
);
453 ENSURE_ASAN_INITED();
454 if (!flags()->replace_str
) {
455 return REAL(strtol
)(nptr
, endptr
, base
);
458 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
459 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
463 INTERCEPTOR(int, atoi
, const char *nptr
) {
465 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
467 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
469 ENSURE_ASAN_INITED();
470 if (!flags()->replace_str
) {
471 return REAL(atoi
)(nptr
);
474 // "man atoi" tells that behavior of atoi(nptr) is the same as
475 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
476 // parsed integer can't be stored in *long* type (even if it's
477 // different from int). So, we just imitate this behavior.
478 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
479 FixRealStrtolEndptr(nptr
, &real_endptr
);
480 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
484 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
486 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
488 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
490 ENSURE_ASAN_INITED();
491 if (!flags()->replace_str
) {
492 return REAL(atol
)(nptr
);
495 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
496 FixRealStrtolEndptr(nptr
, &real_endptr
);
497 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
501 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
502 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
503 char **endptr
, int base
) {
505 ASAN_INTERCEPTOR_ENTER(ctx
, strtoll
);
506 ENSURE_ASAN_INITED();
507 if (!flags()->replace_str
) {
508 return REAL(strtoll
)(nptr
, endptr
, base
);
511 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
512 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
516 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
518 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
519 ENSURE_ASAN_INITED();
520 if (!flags()->replace_str
) {
521 return REAL(atoll
)(nptr
);
524 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
525 FixRealStrtolEndptr(nptr
, &real_endptr
);
526 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
529 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
531 #if ASAN_INTERCEPT___CXA_ATEXIT
532 static void AtCxaAtexit(void *unused
) {
534 StopInitOrderChecking();
537 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
540 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
542 ENSURE_ASAN_INITED();
543 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
544 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
547 #endif // ASAN_INTERCEPT___CXA_ATEXIT
549 #if ASAN_INTERCEPT_FORK
550 INTERCEPTOR(int, fork
, void) {
551 ENSURE_ASAN_INITED();
552 int pid
= REAL(fork
)();
555 #endif // ASAN_INTERCEPT_FORK
557 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
559 void InitializeAsanInterceptors() {
560 static bool was_called_once
;
561 CHECK(!was_called_once
);
562 was_called_once
= true;
563 InitializeCommonInterceptors();
564 InitializeSignalInterceptors();
566 // Intercept str* functions.
567 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
568 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
569 ASAN_INTERCEPT_FUNC(strncat
);
570 ASAN_INTERCEPT_FUNC(strncpy
);
571 ASAN_INTERCEPT_FUNC(strdup
);
572 #if ASAN_INTERCEPT___STRDUP
573 ASAN_INTERCEPT_FUNC(__strdup
);
575 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
576 ASAN_INTERCEPT_FUNC(index
);
579 ASAN_INTERCEPT_FUNC(atoi
);
580 ASAN_INTERCEPT_FUNC(atol
);
581 ASAN_INTERCEPT_FUNC(strtol
);
582 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
583 ASAN_INTERCEPT_FUNC(atoll
);
584 ASAN_INTERCEPT_FUNC(strtoll
);
587 // Intecept jump-related functions.
588 ASAN_INTERCEPT_FUNC(longjmp
);
590 #if ASAN_INTERCEPT_SWAPCONTEXT
591 ASAN_INTERCEPT_FUNC(swapcontext
);
593 #if ASAN_INTERCEPT__LONGJMP
594 ASAN_INTERCEPT_FUNC(_longjmp
);
596 #if ASAN_INTERCEPT___LONGJMP_CHK
597 ASAN_INTERCEPT_FUNC(__longjmp_chk
);
599 #if ASAN_INTERCEPT_SIGLONGJMP
600 ASAN_INTERCEPT_FUNC(siglongjmp
);
603 // Intercept exception handling functions.
604 #if ASAN_INTERCEPT___CXA_THROW
605 ASAN_INTERCEPT_FUNC(__cxa_throw
);
608 // Intercept threading-related functions
609 #if ASAN_INTERCEPT_PTHREAD_CREATE
610 #if defined(ASAN_PTHREAD_CREATE_VERSION)
611 ASAN_INTERCEPT_FUNC_VER(pthread_create
, ASAN_PTHREAD_CREATE_VERSION
);
613 ASAN_INTERCEPT_FUNC(pthread_create
);
615 ASAN_INTERCEPT_FUNC(pthread_join
);
618 // Intercept atexit function.
619 #if ASAN_INTERCEPT___CXA_ATEXIT
620 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
623 #if ASAN_INTERCEPT_FORK
624 ASAN_INTERCEPT_FUNC(fork
);
627 InitializePlatformInterceptors();
629 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
632 } // namespace __asan
634 #endif // !SANITIZER_FUCHSIA