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