xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
168d75effSDimitry Andric //===-- asan_interceptors.cpp ---------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // Intercept various libc functions.
1268d75effSDimitry Andric //===----------------------------------------------------------------------===//
1368d75effSDimitry Andric 
1468d75effSDimitry Andric #include "asan_interceptors.h"
1568d75effSDimitry Andric #include "asan_allocator.h"
1668d75effSDimitry Andric #include "asan_internal.h"
1768d75effSDimitry Andric #include "asan_mapping.h"
1868d75effSDimitry Andric #include "asan_poisoning.h"
1968d75effSDimitry Andric #include "asan_report.h"
2068d75effSDimitry Andric #include "asan_stack.h"
2168d75effSDimitry Andric #include "asan_stats.h"
2268d75effSDimitry Andric #include "asan_suppressions.h"
2368d75effSDimitry Andric #include "lsan/lsan_common.h"
2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h"
2568d75effSDimitry Andric 
2668d75effSDimitry Andric // There is no general interception at all on Fuchsia and RTEMS.
2768d75effSDimitry Andric // Only the functions in asan_interceptors_memintrinsics.cpp are
2868d75effSDimitry Andric // really defined to replace libc functions.
2968d75effSDimitry Andric #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
3068d75effSDimitry Andric 
3168d75effSDimitry Andric #if SANITIZER_POSIX
3268d75effSDimitry Andric #include "sanitizer_common/sanitizer_posix.h"
3368d75effSDimitry Andric #endif
3468d75effSDimitry Andric 
3568d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
3668d75effSDimitry Andric     ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
3768d75effSDimitry Andric #include <unwind.h>
3868d75effSDimitry Andric #endif
3968d75effSDimitry Andric 
4068d75effSDimitry Andric #if defined(__i386) && SANITIZER_LINUX
4168d75effSDimitry Andric #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
4268d75effSDimitry Andric #elif defined(__mips__) && SANITIZER_LINUX
4368d75effSDimitry Andric #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
4468d75effSDimitry Andric #endif
4568d75effSDimitry Andric 
4668d75effSDimitry Andric namespace __asan {
4768d75effSDimitry Andric 
4868d75effSDimitry Andric #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n)                 \
4968d75effSDimitry Andric   ASAN_READ_RANGE((ctx), (s),                                   \
5068d75effSDimitry Andric     common_flags()->strict_string_checks ? (len) + 1 : (n))
5168d75effSDimitry Andric 
5268d75effSDimitry Andric #define ASAN_READ_STRING(ctx, s, n)                             \
5368d75effSDimitry Andric   ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
5468d75effSDimitry Andric 
5568d75effSDimitry Andric static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
5668d75effSDimitry Andric #if SANITIZER_INTERCEPT_STRNLEN
5768d75effSDimitry Andric   if (REAL(strnlen)) {
5868d75effSDimitry Andric     return REAL(strnlen)(s, maxlen);
5968d75effSDimitry Andric   }
6068d75effSDimitry Andric #endif
6168d75effSDimitry Andric   return internal_strnlen(s, maxlen);
6268d75effSDimitry Andric }
6368d75effSDimitry Andric 
6468d75effSDimitry Andric void SetThreadName(const char *name) {
6568d75effSDimitry Andric   AsanThread *t = GetCurrentThread();
6668d75effSDimitry Andric   if (t)
6768d75effSDimitry Andric     asanThreadRegistry().SetThreadName(t->tid(), name);
6868d75effSDimitry Andric }
6968d75effSDimitry Andric 
7068d75effSDimitry Andric int OnExit() {
7168d75effSDimitry Andric   if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
7268d75effSDimitry Andric       __lsan::HasReportedLeaks()) {
7368d75effSDimitry Andric     return common_flags()->exitcode;
7468d75effSDimitry Andric   }
7568d75effSDimitry Andric   // FIXME: ask frontend whether we need to return failure.
7668d75effSDimitry Andric   return 0;
7768d75effSDimitry Andric }
7868d75effSDimitry Andric 
7968d75effSDimitry Andric } // namespace __asan
8068d75effSDimitry Andric 
8168d75effSDimitry Andric // ---------------------- Wrappers ---------------- {{{1
8268d75effSDimitry Andric using namespace __asan;
8368d75effSDimitry Andric 
8468d75effSDimitry Andric DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
8568d75effSDimitry Andric DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
8668d75effSDimitry Andric 
8768d75effSDimitry Andric #define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \
8868d75effSDimitry Andric   AsanInterceptorContext _ctx = {#func};                                       \
8968d75effSDimitry Andric   ctx = (void *)&_ctx;                                                         \
9068d75effSDimitry Andric   (void) ctx;                                                                  \
9168d75effSDimitry Andric 
9268d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
9368d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
9468d75effSDimitry Andric   ASAN_INTERCEPT_FUNC_VER(name, ver)
9568d75effSDimitry Andric #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
9668d75effSDimitry Andric   ASAN_WRITE_RANGE(ctx, ptr, size)
9768d75effSDimitry Andric #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
9868d75effSDimitry Andric   ASAN_READ_RANGE(ctx, ptr, size)
9968d75effSDimitry Andric #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
10068d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, func);                                           \
10168d75effSDimitry Andric   do {                                                                         \
10268d75effSDimitry Andric     if (asan_init_is_running)                                                  \
10368d75effSDimitry Andric       return REAL(func)(__VA_ARGS__);                                          \
10468d75effSDimitry Andric     if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
10568d75effSDimitry Andric       return REAL(func)(__VA_ARGS__);                                          \
10668d75effSDimitry Andric     ENSURE_ASAN_INITED();                                                      \
10768d75effSDimitry Andric   } while (false)
10868d75effSDimitry Andric #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
10968d75effSDimitry Andric   do {                                            \
11068d75effSDimitry Andric   } while (false)
11168d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
11268d75effSDimitry Andric   do {                                         \
11368d75effSDimitry Andric   } while (false)
11468d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
11568d75effSDimitry Andric   do {                                         \
11668d75effSDimitry Andric   } while (false)
11768d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
11868d75effSDimitry Andric   do {                                                      \
11968d75effSDimitry Andric   } while (false)
12068d75effSDimitry Andric #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
12168d75effSDimitry Andric // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
12268d75effSDimitry Andric // But asan does not remember UserId's for threads (pthread_t);
12368d75effSDimitry Andric // and remembers all ever existed threads, so the linear search by UserId
12468d75effSDimitry Andric // can be slow.
12568d75effSDimitry Andric #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
12668d75effSDimitry Andric   do {                                                         \
12768d75effSDimitry Andric   } while (false)
12868d75effSDimitry Andric #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
12968d75effSDimitry Andric // Strict init-order checking is dlopen-hostile:
13068d75effSDimitry Andric // https://github.com/google/sanitizers/issues/178
13168d75effSDimitry Andric #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \
13268d75effSDimitry Andric   do {                                                                         \
13368d75effSDimitry Andric     if (flags()->strict_init_order)                                            \
13468d75effSDimitry Andric       StopInitOrderChecking();                                                 \
13568d75effSDimitry Andric     CheckNoDeepBind(filename, flag);                                           \
13668d75effSDimitry Andric   } while (false)
13768d75effSDimitry Andric #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
13868d75effSDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
13968d75effSDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
14068d75effSDimitry Andric #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
14168d75effSDimitry Andric #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
14268d75effSDimitry Andric   if (AsanThread *t = GetCurrentThread()) {                                    \
14368d75effSDimitry Andric     *begin = t->tls_begin();                                                   \
14468d75effSDimitry Andric     *end = t->tls_end();                                                       \
14568d75effSDimitry Andric   } else {                                                                     \
14668d75effSDimitry Andric     *begin = *end = 0;                                                         \
14768d75effSDimitry Andric   }
14868d75effSDimitry Andric 
14968d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
15068d75effSDimitry Andric   do {                                                       \
15168d75effSDimitry Andric     ASAN_INTERCEPTOR_ENTER(ctx, memmove);                    \
15268d75effSDimitry Andric     ASAN_MEMMOVE_IMPL(ctx, to, from, size);                  \
15368d75effSDimitry Andric   } while (false)
15468d75effSDimitry Andric 
15568d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
15668d75effSDimitry Andric   do {                                                      \
15768d75effSDimitry Andric     ASAN_INTERCEPTOR_ENTER(ctx, memcpy);                    \
15868d75effSDimitry Andric     ASAN_MEMCPY_IMPL(ctx, to, from, size);                  \
15968d75effSDimitry Andric   } while (false)
16068d75effSDimitry Andric 
16168d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
16268d75effSDimitry Andric   do {                                                      \
16368d75effSDimitry Andric     ASAN_INTERCEPTOR_ENTER(ctx, memset);                    \
16468d75effSDimitry Andric     ASAN_MEMSET_IMPL(ctx, block, c, size);                  \
16568d75effSDimitry Andric   } while (false)
16668d75effSDimitry Andric 
16768d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
16868d75effSDimitry Andric #define COMMON_INTERCEPTOR_STRERROR()                       \
16968d75effSDimitry Andric   __lsan::ScopedInterceptorDisabler disabler
17068d75effSDimitry Andric #endif
17168d75effSDimitry Andric 
17268d75effSDimitry Andric #include "sanitizer_common/sanitizer_common_interceptors.inc"
17368d75effSDimitry Andric #include "sanitizer_common/sanitizer_signal_interceptors.inc"
17468d75effSDimitry Andric 
17568d75effSDimitry Andric // Syscall interceptors don't have contexts, we don't support suppressions
17668d75effSDimitry Andric // for them.
17768d75effSDimitry Andric #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
17868d75effSDimitry Andric #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
17968d75effSDimitry Andric #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
18068d75effSDimitry Andric   do {                                       \
18168d75effSDimitry Andric     (void)(p);                               \
18268d75effSDimitry Andric     (void)(s);                               \
18368d75effSDimitry Andric   } while (false)
18468d75effSDimitry Andric #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
18568d75effSDimitry Andric   do {                                        \
18668d75effSDimitry Andric     (void)(p);                                \
18768d75effSDimitry Andric     (void)(s);                                \
18868d75effSDimitry Andric   } while (false)
18968d75effSDimitry Andric #include "sanitizer_common/sanitizer_common_syscalls.inc"
19068d75effSDimitry Andric #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
19168d75effSDimitry Andric 
19268d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_CREATE
19368d75effSDimitry Andric static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
194*e8d8bef9SDimitry Andric   AsanThread *t = (AsanThread *)arg;
19568d75effSDimitry Andric   SetCurrentThread(t);
196*e8d8bef9SDimitry Andric   return t->ThreadStart(GetTid());
19768d75effSDimitry Andric }
19868d75effSDimitry Andric 
19968d75effSDimitry Andric INTERCEPTOR(int, pthread_create, void *thread,
20068d75effSDimitry Andric     void *attr, void *(*start_routine)(void*), void *arg) {
20168d75effSDimitry Andric   EnsureMainThreadIDIsCorrect();
20268d75effSDimitry Andric   // Strict init-order checking is thread-hostile.
20368d75effSDimitry Andric   if (flags()->strict_init_order)
20468d75effSDimitry Andric     StopInitOrderChecking();
20568d75effSDimitry Andric   GET_STACK_TRACE_THREAD;
20668d75effSDimitry Andric   int detached = 0;
20768d75effSDimitry Andric   if (attr)
20868d75effSDimitry Andric     REAL(pthread_attr_getdetachstate)(attr, &detached);
209*e8d8bef9SDimitry Andric 
210*e8d8bef9SDimitry Andric   u32 current_tid = GetCurrentTidOrInvalid();
211*e8d8bef9SDimitry Andric   AsanThread *t =
212*e8d8bef9SDimitry Andric       AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
213*e8d8bef9SDimitry Andric 
21468d75effSDimitry Andric   int result;
21568d75effSDimitry Andric   {
21668d75effSDimitry Andric     // Ignore all allocations made by pthread_create: thread stack/TLS may be
21768d75effSDimitry Andric     // stored by pthread for future reuse even after thread destruction, and
21868d75effSDimitry Andric     // the linked list it's stored in doesn't even hold valid pointers to the
21968d75effSDimitry Andric     // objects, the latter are calculated by obscure pointer arithmetic.
22068d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
22168d75effSDimitry Andric     __lsan::ScopedInterceptorDisabler disabler;
22268d75effSDimitry Andric #endif
223*e8d8bef9SDimitry Andric     result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
22468d75effSDimitry Andric   }
225*e8d8bef9SDimitry Andric   if (result != 0) {
226*e8d8bef9SDimitry Andric     // If the thread didn't start delete the AsanThread to avoid leaking it.
227*e8d8bef9SDimitry Andric     // Note AsanThreadContexts never get destroyed so the AsanThreadContext
228*e8d8bef9SDimitry Andric     // that was just created for the AsanThread is wasted.
229*e8d8bef9SDimitry Andric     t->Destroy();
23068d75effSDimitry Andric   }
23168d75effSDimitry Andric   return result;
23268d75effSDimitry Andric }
23368d75effSDimitry Andric 
23468d75effSDimitry Andric INTERCEPTOR(int, pthread_join, void *t, void **arg) {
23568d75effSDimitry Andric   return real_pthread_join(t, arg);
23668d75effSDimitry Andric }
23768d75effSDimitry Andric 
23868d75effSDimitry Andric DEFINE_REAL_PTHREAD_FUNCTIONS
23968d75effSDimitry Andric #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
24068d75effSDimitry Andric 
24168d75effSDimitry Andric #if ASAN_INTERCEPT_SWAPCONTEXT
24268d75effSDimitry Andric static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
24368d75effSDimitry Andric   // Align to page size.
24468d75effSDimitry Andric   uptr PageSize = GetPageSizeCached();
24568d75effSDimitry Andric   uptr bottom = stack & ~(PageSize - 1);
24668d75effSDimitry Andric   ssize += stack - bottom;
24768d75effSDimitry Andric   ssize = RoundUpTo(ssize, PageSize);
24868d75effSDimitry Andric   static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
24968d75effSDimitry Andric   if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
25068d75effSDimitry Andric     PoisonShadow(bottom, ssize, 0);
25168d75effSDimitry Andric   }
25268d75effSDimitry Andric }
25368d75effSDimitry Andric 
25468d75effSDimitry Andric INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
25568d75effSDimitry Andric             struct ucontext_t *ucp) {
25668d75effSDimitry Andric   static bool reported_warning = false;
25768d75effSDimitry Andric   if (!reported_warning) {
25868d75effSDimitry Andric     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
25968d75effSDimitry Andric            "functions and may produce false positives in some cases!\n");
26068d75effSDimitry Andric     reported_warning = true;
26168d75effSDimitry Andric   }
26268d75effSDimitry Andric   // Clear shadow memory for new context (it may share stack
26368d75effSDimitry Andric   // with current context).
26468d75effSDimitry Andric   uptr stack, ssize;
26568d75effSDimitry Andric   ReadContextStack(ucp, &stack, &ssize);
26668d75effSDimitry Andric   ClearShadowMemoryForContextStack(stack, ssize);
26768d75effSDimitry Andric #if __has_attribute(__indirect_return__) && \
26868d75effSDimitry Andric     (defined(__x86_64__) || defined(__i386__))
26968d75effSDimitry Andric   int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
27068d75effSDimitry Andric     __attribute__((__indirect_return__))
27168d75effSDimitry Andric     = REAL(swapcontext);
27268d75effSDimitry Andric   int res = real_swapcontext(oucp, ucp);
27368d75effSDimitry Andric #else
27468d75effSDimitry Andric   int res = REAL(swapcontext)(oucp, ucp);
27568d75effSDimitry Andric #endif
27668d75effSDimitry Andric   // swapcontext technically does not return, but program may swap context to
27768d75effSDimitry Andric   // "oucp" later, that would look as if swapcontext() returned 0.
27868d75effSDimitry Andric   // We need to clear shadow for ucp once again, as it may be in arbitrary
27968d75effSDimitry Andric   // state.
28068d75effSDimitry Andric   ClearShadowMemoryForContextStack(stack, ssize);
28168d75effSDimitry Andric   return res;
28268d75effSDimitry Andric }
28368d75effSDimitry Andric #endif  // ASAN_INTERCEPT_SWAPCONTEXT
28468d75effSDimitry Andric 
28568d75effSDimitry Andric #if SANITIZER_NETBSD
28668d75effSDimitry Andric #define longjmp __longjmp14
28768d75effSDimitry Andric #define siglongjmp __siglongjmp14
28868d75effSDimitry Andric #endif
28968d75effSDimitry Andric 
29068d75effSDimitry Andric INTERCEPTOR(void, longjmp, void *env, int val) {
29168d75effSDimitry Andric   __asan_handle_no_return();
29268d75effSDimitry Andric   REAL(longjmp)(env, val);
29368d75effSDimitry Andric }
29468d75effSDimitry Andric 
29568d75effSDimitry Andric #if ASAN_INTERCEPT__LONGJMP
29668d75effSDimitry Andric INTERCEPTOR(void, _longjmp, void *env, int val) {
29768d75effSDimitry Andric   __asan_handle_no_return();
29868d75effSDimitry Andric   REAL(_longjmp)(env, val);
29968d75effSDimitry Andric }
30068d75effSDimitry Andric #endif
30168d75effSDimitry Andric 
30268d75effSDimitry Andric #if ASAN_INTERCEPT___LONGJMP_CHK
30368d75effSDimitry Andric INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
30468d75effSDimitry Andric   __asan_handle_no_return();
30568d75effSDimitry Andric   REAL(__longjmp_chk)(env, val);
30668d75effSDimitry Andric }
30768d75effSDimitry Andric #endif
30868d75effSDimitry Andric 
30968d75effSDimitry Andric #if ASAN_INTERCEPT_SIGLONGJMP
31068d75effSDimitry Andric INTERCEPTOR(void, siglongjmp, void *env, int val) {
31168d75effSDimitry Andric   __asan_handle_no_return();
31268d75effSDimitry Andric   REAL(siglongjmp)(env, val);
31368d75effSDimitry Andric }
31468d75effSDimitry Andric #endif
31568d75effSDimitry Andric 
31668d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_THROW
31768d75effSDimitry Andric INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
31868d75effSDimitry Andric   CHECK(REAL(__cxa_throw));
31968d75effSDimitry Andric   __asan_handle_no_return();
32068d75effSDimitry Andric   REAL(__cxa_throw)(a, b, c);
32168d75effSDimitry Andric }
32268d75effSDimitry Andric #endif
32368d75effSDimitry Andric 
32468d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
32568d75effSDimitry Andric INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
32668d75effSDimitry Andric   CHECK(REAL(__cxa_rethrow_primary_exception));
32768d75effSDimitry Andric   __asan_handle_no_return();
32868d75effSDimitry Andric   REAL(__cxa_rethrow_primary_exception)(a);
32968d75effSDimitry Andric }
33068d75effSDimitry Andric #endif
33168d75effSDimitry Andric 
33268d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
33368d75effSDimitry Andric INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
33468d75effSDimitry Andric             _Unwind_Exception *object) {
33568d75effSDimitry Andric   CHECK(REAL(_Unwind_RaiseException));
33668d75effSDimitry Andric   __asan_handle_no_return();
33768d75effSDimitry Andric   return REAL(_Unwind_RaiseException)(object);
33868d75effSDimitry Andric }
33968d75effSDimitry Andric #endif
34068d75effSDimitry Andric 
34168d75effSDimitry Andric #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
34268d75effSDimitry Andric INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
34368d75effSDimitry Andric             _Unwind_Exception *object) {
34468d75effSDimitry Andric   CHECK(REAL(_Unwind_SjLj_RaiseException));
34568d75effSDimitry Andric   __asan_handle_no_return();
34668d75effSDimitry Andric   return REAL(_Unwind_SjLj_RaiseException)(object);
34768d75effSDimitry Andric }
34868d75effSDimitry Andric #endif
34968d75effSDimitry Andric 
35068d75effSDimitry Andric #if ASAN_INTERCEPT_INDEX
35168d75effSDimitry Andric # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
35268d75effSDimitry Andric INTERCEPTOR(char*, index, const char *string, int c)
35368d75effSDimitry Andric   ALIAS(WRAPPER_NAME(strchr));
35468d75effSDimitry Andric # else
35568d75effSDimitry Andric #  if SANITIZER_MAC
35668d75effSDimitry Andric DECLARE_REAL(char*, index, const char *string, int c)
35768d75effSDimitry Andric OVERRIDE_FUNCTION(index, strchr);
35868d75effSDimitry Andric #  else
35968d75effSDimitry Andric DEFINE_REAL(char*, index, const char *string, int c)
36068d75effSDimitry Andric #  endif
36168d75effSDimitry Andric # endif
36268d75effSDimitry Andric #endif  // ASAN_INTERCEPT_INDEX
36368d75effSDimitry Andric 
36468d75effSDimitry Andric // For both strcat() and strncat() we need to check the validity of |to|
36568d75effSDimitry Andric // argument irrespective of the |from| length.
36668d75effSDimitry Andric   INTERCEPTOR(char *, strcat, char *to, const char *from) {
36768d75effSDimitry Andric     void *ctx;
36868d75effSDimitry Andric     ASAN_INTERCEPTOR_ENTER(ctx, strcat);
36968d75effSDimitry Andric     ENSURE_ASAN_INITED();
37068d75effSDimitry Andric     if (flags()->replace_str) {
37168d75effSDimitry Andric       uptr from_length = REAL(strlen)(from);
37268d75effSDimitry Andric       ASAN_READ_RANGE(ctx, from, from_length + 1);
37368d75effSDimitry Andric       uptr to_length = REAL(strlen)(to);
37468d75effSDimitry Andric       ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
37568d75effSDimitry Andric       ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
37668d75effSDimitry Andric       // If the copying actually happens, the |from| string should not overlap
37768d75effSDimitry Andric       // with the resulting string starting at |to|, which has a length of
37868d75effSDimitry Andric       // to_length + from_length + 1.
37968d75effSDimitry Andric       if (from_length > 0) {
38068d75effSDimitry Andric         CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
38168d75effSDimitry Andric                              from_length + 1);
38268d75effSDimitry Andric       }
38368d75effSDimitry Andric     }
38468d75effSDimitry Andric     return REAL(strcat)(to, from);
38568d75effSDimitry Andric   }
38668d75effSDimitry Andric 
38768d75effSDimitry Andric INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
38868d75effSDimitry Andric   void *ctx;
38968d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
39068d75effSDimitry Andric   ENSURE_ASAN_INITED();
39168d75effSDimitry Andric   if (flags()->replace_str) {
39268d75effSDimitry Andric     uptr from_length = MaybeRealStrnlen(from, size);
39368d75effSDimitry Andric     uptr copy_length = Min(size, from_length + 1);
39468d75effSDimitry Andric     ASAN_READ_RANGE(ctx, from, copy_length);
39568d75effSDimitry Andric     uptr to_length = REAL(strlen)(to);
39668d75effSDimitry Andric     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
39768d75effSDimitry Andric     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
39868d75effSDimitry Andric     if (from_length > 0) {
39968d75effSDimitry Andric       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
40068d75effSDimitry Andric                            from, copy_length);
40168d75effSDimitry Andric     }
40268d75effSDimitry Andric   }
40368d75effSDimitry Andric   return REAL(strncat)(to, from, size);
40468d75effSDimitry Andric }
40568d75effSDimitry Andric 
40668d75effSDimitry Andric INTERCEPTOR(char *, strcpy, char *to, const char *from) {
40768d75effSDimitry Andric   void *ctx;
40868d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
40968d75effSDimitry Andric #if SANITIZER_MAC
41068d75effSDimitry Andric   if (UNLIKELY(!asan_inited))
41168d75effSDimitry Andric     return REAL(strcpy)(to, from);
41268d75effSDimitry Andric #endif
41368d75effSDimitry Andric   // strcpy is called from malloc_default_purgeable_zone()
41468d75effSDimitry Andric   // in __asan::ReplaceSystemAlloc() on Mac.
41568d75effSDimitry Andric   if (asan_init_is_running) {
41668d75effSDimitry Andric     return REAL(strcpy)(to, from);
41768d75effSDimitry Andric   }
41868d75effSDimitry Andric   ENSURE_ASAN_INITED();
41968d75effSDimitry Andric   if (flags()->replace_str) {
42068d75effSDimitry Andric     uptr from_size = REAL(strlen)(from) + 1;
42168d75effSDimitry Andric     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
42268d75effSDimitry Andric     ASAN_READ_RANGE(ctx, from, from_size);
42368d75effSDimitry Andric     ASAN_WRITE_RANGE(ctx, to, from_size);
42468d75effSDimitry Andric   }
42568d75effSDimitry Andric   return REAL(strcpy)(to, from);
42668d75effSDimitry Andric }
42768d75effSDimitry Andric 
42868d75effSDimitry Andric INTERCEPTOR(char*, strdup, const char *s) {
42968d75effSDimitry Andric   void *ctx;
43068d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
43168d75effSDimitry Andric   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
43268d75effSDimitry Andric   ENSURE_ASAN_INITED();
43368d75effSDimitry Andric   uptr length = REAL(strlen)(s);
43468d75effSDimitry Andric   if (flags()->replace_str) {
43568d75effSDimitry Andric     ASAN_READ_RANGE(ctx, s, length + 1);
43668d75effSDimitry Andric   }
43768d75effSDimitry Andric   GET_STACK_TRACE_MALLOC;
43868d75effSDimitry Andric   void *new_mem = asan_malloc(length + 1, &stack);
43968d75effSDimitry Andric   REAL(memcpy)(new_mem, s, length + 1);
44068d75effSDimitry Andric   return reinterpret_cast<char*>(new_mem);
44168d75effSDimitry Andric }
44268d75effSDimitry Andric 
44368d75effSDimitry Andric #if ASAN_INTERCEPT___STRDUP
44468d75effSDimitry Andric INTERCEPTOR(char*, __strdup, const char *s) {
44568d75effSDimitry Andric   void *ctx;
44668d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
44768d75effSDimitry Andric   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
44868d75effSDimitry Andric   ENSURE_ASAN_INITED();
44968d75effSDimitry Andric   uptr length = REAL(strlen)(s);
45068d75effSDimitry Andric   if (flags()->replace_str) {
45168d75effSDimitry Andric     ASAN_READ_RANGE(ctx, s, length + 1);
45268d75effSDimitry Andric   }
45368d75effSDimitry Andric   GET_STACK_TRACE_MALLOC;
45468d75effSDimitry Andric   void *new_mem = asan_malloc(length + 1, &stack);
45568d75effSDimitry Andric   REAL(memcpy)(new_mem, s, length + 1);
45668d75effSDimitry Andric   return reinterpret_cast<char*>(new_mem);
45768d75effSDimitry Andric }
45868d75effSDimitry Andric #endif // ASAN_INTERCEPT___STRDUP
45968d75effSDimitry Andric 
46068d75effSDimitry Andric INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
46168d75effSDimitry Andric   void *ctx;
46268d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
46368d75effSDimitry Andric   ENSURE_ASAN_INITED();
46468d75effSDimitry Andric   if (flags()->replace_str) {
46568d75effSDimitry Andric     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
46668d75effSDimitry Andric     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
46768d75effSDimitry Andric     ASAN_READ_RANGE(ctx, from, from_size);
46868d75effSDimitry Andric     ASAN_WRITE_RANGE(ctx, to, size);
46968d75effSDimitry Andric   }
47068d75effSDimitry Andric   return REAL(strncpy)(to, from, size);
47168d75effSDimitry Andric }
47268d75effSDimitry Andric 
47368d75effSDimitry Andric INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
47468d75effSDimitry Andric   void *ctx;
47568d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strtol);
47668d75effSDimitry Andric   ENSURE_ASAN_INITED();
47768d75effSDimitry Andric   if (!flags()->replace_str) {
47868d75effSDimitry Andric     return REAL(strtol)(nptr, endptr, base);
47968d75effSDimitry Andric   }
48068d75effSDimitry Andric   char *real_endptr;
48168d75effSDimitry Andric   long result = REAL(strtol)(nptr, &real_endptr, base);
48268d75effSDimitry Andric   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
48368d75effSDimitry Andric   return result;
48468d75effSDimitry Andric }
48568d75effSDimitry Andric 
48668d75effSDimitry Andric INTERCEPTOR(int, atoi, const char *nptr) {
48768d75effSDimitry Andric   void *ctx;
48868d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
48968d75effSDimitry Andric #if SANITIZER_MAC
49068d75effSDimitry Andric   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
49168d75effSDimitry Andric #endif
49268d75effSDimitry Andric   ENSURE_ASAN_INITED();
49368d75effSDimitry Andric   if (!flags()->replace_str) {
49468d75effSDimitry Andric     return REAL(atoi)(nptr);
49568d75effSDimitry Andric   }
49668d75effSDimitry Andric   char *real_endptr;
49768d75effSDimitry Andric   // "man atoi" tells that behavior of atoi(nptr) is the same as
49868d75effSDimitry Andric   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
49968d75effSDimitry Andric   // parsed integer can't be stored in *long* type (even if it's
50068d75effSDimitry Andric   // different from int). So, we just imitate this behavior.
50168d75effSDimitry Andric   int result = REAL(strtol)(nptr, &real_endptr, 10);
50268d75effSDimitry Andric   FixRealStrtolEndptr(nptr, &real_endptr);
50368d75effSDimitry Andric   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
50468d75effSDimitry Andric   return result;
50568d75effSDimitry Andric }
50668d75effSDimitry Andric 
50768d75effSDimitry Andric INTERCEPTOR(long, atol, const char *nptr) {
50868d75effSDimitry Andric   void *ctx;
50968d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, atol);
51068d75effSDimitry Andric #if SANITIZER_MAC
51168d75effSDimitry Andric   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
51268d75effSDimitry Andric #endif
51368d75effSDimitry Andric   ENSURE_ASAN_INITED();
51468d75effSDimitry Andric   if (!flags()->replace_str) {
51568d75effSDimitry Andric     return REAL(atol)(nptr);
51668d75effSDimitry Andric   }
51768d75effSDimitry Andric   char *real_endptr;
51868d75effSDimitry Andric   long result = REAL(strtol)(nptr, &real_endptr, 10);
51968d75effSDimitry Andric   FixRealStrtolEndptr(nptr, &real_endptr);
52068d75effSDimitry Andric   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
52168d75effSDimitry Andric   return result;
52268d75effSDimitry Andric }
52368d75effSDimitry Andric 
52468d75effSDimitry Andric #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
52568d75effSDimitry Andric INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
52668d75effSDimitry Andric   void *ctx;
52768d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
52868d75effSDimitry Andric   ENSURE_ASAN_INITED();
52968d75effSDimitry Andric   if (!flags()->replace_str) {
53068d75effSDimitry Andric     return REAL(strtoll)(nptr, endptr, base);
53168d75effSDimitry Andric   }
53268d75effSDimitry Andric   char *real_endptr;
53368d75effSDimitry Andric   long long result = REAL(strtoll)(nptr, &real_endptr, base);
53468d75effSDimitry Andric   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
53568d75effSDimitry Andric   return result;
53668d75effSDimitry Andric }
53768d75effSDimitry Andric 
53868d75effSDimitry Andric INTERCEPTOR(long long, atoll, const char *nptr) {
53968d75effSDimitry Andric   void *ctx;
54068d75effSDimitry Andric   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
54168d75effSDimitry Andric   ENSURE_ASAN_INITED();
54268d75effSDimitry Andric   if (!flags()->replace_str) {
54368d75effSDimitry Andric     return REAL(atoll)(nptr);
54468d75effSDimitry Andric   }
54568d75effSDimitry Andric   char *real_endptr;
54668d75effSDimitry Andric   long long result = REAL(strtoll)(nptr, &real_endptr, 10);
54768d75effSDimitry Andric   FixRealStrtolEndptr(nptr, &real_endptr);
54868d75effSDimitry Andric   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
54968d75effSDimitry Andric   return result;
55068d75effSDimitry Andric }
55168d75effSDimitry Andric #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
55268d75effSDimitry Andric 
55368d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
55468d75effSDimitry Andric static void AtCxaAtexit(void *unused) {
55568d75effSDimitry Andric   (void)unused;
55668d75effSDimitry Andric   StopInitOrderChecking();
55768d75effSDimitry Andric }
55868d75effSDimitry Andric #endif
55968d75effSDimitry Andric 
56068d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_ATEXIT
56168d75effSDimitry Andric INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
56268d75effSDimitry Andric             void *dso_handle) {
56368d75effSDimitry Andric #if SANITIZER_MAC
56468d75effSDimitry Andric   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
56568d75effSDimitry Andric #endif
56668d75effSDimitry Andric   ENSURE_ASAN_INITED();
56768d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
56868d75effSDimitry Andric   __lsan::ScopedInterceptorDisabler disabler;
56968d75effSDimitry Andric #endif
57068d75effSDimitry Andric   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
57168d75effSDimitry Andric   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
57268d75effSDimitry Andric   return res;
57368d75effSDimitry Andric }
57468d75effSDimitry Andric #endif  // ASAN_INTERCEPT___CXA_ATEXIT
57568d75effSDimitry Andric 
57668d75effSDimitry Andric #if ASAN_INTERCEPT_ATEXIT
57768d75effSDimitry Andric INTERCEPTOR(int, atexit, void (*func)()) {
57868d75effSDimitry Andric   ENSURE_ASAN_INITED();
57968d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
58068d75effSDimitry Andric   __lsan::ScopedInterceptorDisabler disabler;
58168d75effSDimitry Andric #endif
58268d75effSDimitry Andric   // Avoid calling real atexit as it is unrechable on at least on Linux.
58368d75effSDimitry Andric   int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
58468d75effSDimitry Andric   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
58568d75effSDimitry Andric   return res;
58668d75effSDimitry Andric }
58768d75effSDimitry Andric #endif
58868d75effSDimitry Andric 
58968d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_ATFORK
59068d75effSDimitry Andric extern "C" {
59168d75effSDimitry Andric extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
59268d75effSDimitry Andric                            void (*child)());
59368d75effSDimitry Andric };
59468d75effSDimitry Andric 
59568d75effSDimitry Andric INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
59668d75effSDimitry Andric             void (*child)()) {
59768d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
59868d75effSDimitry Andric   __lsan::ScopedInterceptorDisabler disabler;
59968d75effSDimitry Andric #endif
60068d75effSDimitry Andric   // REAL(pthread_atfork) cannot be called due to symbol indirections at least
60168d75effSDimitry Andric   // on NetBSD
60268d75effSDimitry Andric   return _pthread_atfork(prepare, parent, child);
60368d75effSDimitry Andric }
60468d75effSDimitry Andric #endif
60568d75effSDimitry Andric 
60668d75effSDimitry Andric #if ASAN_INTERCEPT_VFORK
60768d75effSDimitry Andric DEFINE_REAL(int, vfork)
60868d75effSDimitry Andric DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
60968d75effSDimitry Andric #endif
61068d75effSDimitry Andric 
61168d75effSDimitry Andric // ---------------------- InitializeAsanInterceptors ---------------- {{{1
61268d75effSDimitry Andric namespace __asan {
61368d75effSDimitry Andric void InitializeAsanInterceptors() {
61468d75effSDimitry Andric   static bool was_called_once;
61568d75effSDimitry Andric   CHECK(!was_called_once);
61668d75effSDimitry Andric   was_called_once = true;
61768d75effSDimitry Andric   InitializeCommonInterceptors();
61868d75effSDimitry Andric   InitializeSignalInterceptors();
61968d75effSDimitry Andric 
62068d75effSDimitry Andric   // Intercept str* functions.
62168d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strcat);
62268d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strcpy);
62368d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strncat);
62468d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strncpy);
62568d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strdup);
62668d75effSDimitry Andric #if ASAN_INTERCEPT___STRDUP
62768d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(__strdup);
62868d75effSDimitry Andric #endif
62968d75effSDimitry Andric #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
63068d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(index);
63168d75effSDimitry Andric #endif
63268d75effSDimitry Andric 
63368d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(atoi);
63468d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(atol);
63568d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strtol);
63668d75effSDimitry Andric #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
63768d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(atoll);
63868d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(strtoll);
63968d75effSDimitry Andric #endif
64068d75effSDimitry Andric 
64168d75effSDimitry Andric   // Intecept jump-related functions.
64268d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(longjmp);
64368d75effSDimitry Andric 
64468d75effSDimitry Andric #if ASAN_INTERCEPT_SWAPCONTEXT
64568d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(swapcontext);
64668d75effSDimitry Andric #endif
64768d75effSDimitry Andric #if ASAN_INTERCEPT__LONGJMP
64868d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(_longjmp);
64968d75effSDimitry Andric #endif
65068d75effSDimitry Andric #if ASAN_INTERCEPT___LONGJMP_CHK
65168d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(__longjmp_chk);
65268d75effSDimitry Andric #endif
65368d75effSDimitry Andric #if ASAN_INTERCEPT_SIGLONGJMP
65468d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(siglongjmp);
65568d75effSDimitry Andric #endif
65668d75effSDimitry Andric 
65768d75effSDimitry Andric   // Intercept exception handling functions.
65868d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_THROW
65968d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(__cxa_throw);
66068d75effSDimitry Andric #endif
66168d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
66268d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
66368d75effSDimitry Andric #endif
66468d75effSDimitry Andric   // Indirectly intercept std::rethrow_exception.
66568d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
66668d75effSDimitry Andric   INTERCEPT_FUNCTION(_Unwind_RaiseException);
66768d75effSDimitry Andric #endif
66868d75effSDimitry Andric   // Indirectly intercept std::rethrow_exception.
66968d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
67068d75effSDimitry Andric   INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException);
67168d75effSDimitry Andric #endif
67268d75effSDimitry Andric 
67368d75effSDimitry Andric   // Intercept threading-related functions
67468d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_CREATE
67568d75effSDimitry Andric #if defined(ASAN_PTHREAD_CREATE_VERSION)
67668d75effSDimitry Andric   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
67768d75effSDimitry Andric #else
67868d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(pthread_create);
67968d75effSDimitry Andric #endif
68068d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(pthread_join);
68168d75effSDimitry Andric #endif
68268d75effSDimitry Andric 
68368d75effSDimitry Andric   // Intercept atexit function.
68468d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_ATEXIT
68568d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(__cxa_atexit);
68668d75effSDimitry Andric #endif
68768d75effSDimitry Andric 
68868d75effSDimitry Andric #if ASAN_INTERCEPT_ATEXIT
68968d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(atexit);
69068d75effSDimitry Andric #endif
69168d75effSDimitry Andric 
69268d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_ATFORK
69368d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(pthread_atfork);
69468d75effSDimitry Andric #endif
69568d75effSDimitry Andric 
69668d75effSDimitry Andric #if ASAN_INTERCEPT_VFORK
69768d75effSDimitry Andric   ASAN_INTERCEPT_FUNC(vfork);
69868d75effSDimitry Andric #endif
69968d75effSDimitry Andric 
70068d75effSDimitry Andric   InitializePlatformInterceptors();
70168d75effSDimitry Andric 
70268d75effSDimitry Andric   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
70368d75effSDimitry Andric }
70468d75effSDimitry Andric 
70568d75effSDimitry Andric } // namespace __asan
70668d75effSDimitry Andric 
70768d75effSDimitry Andric #endif  // !SANITIZER_FUCHSIA
708