]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_interceptors.cc
Merge compiler-rt trunk r321017 to contrib/compiler-rt.
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / asan / asan_interceptors.cc
1 //===-- asan_interceptors.cc ----------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Intercept various libc functions.
13 //===----------------------------------------------------------------------===//
14
15 #include "asan_interceptors.h"
16 #include "asan_allocator.h"
17 #include "asan_internal.h"
18 #include "asan_mapping.h"
19 #include "asan_poisoning.h"
20 #include "asan_report.h"
21 #include "asan_stack.h"
22 #include "asan_stats.h"
23 #include "asan_suppressions.h"
24 #include "lsan/lsan_common.h"
25 #include "sanitizer_common/sanitizer_libc.h"
26
27 // There is no general interception at all on Fuchsia.
28 // Only the functions in asan_interceptors_memintrinsics.cc are
29 // really defined to replace libc functions.
30 #if !SANITIZER_FUCHSIA
31
32 #if SANITIZER_POSIX
33 #include "sanitizer_common/sanitizer_posix.h"
34 #endif
35
36 #if defined(__i386) && SANITIZER_LINUX
37 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
38 #elif defined(__mips__) && SANITIZER_LINUX
39 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
40 #endif
41
42 namespace __asan {
43
44 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n)                 \
45   ASAN_READ_RANGE((ctx), (s),                                   \
46     common_flags()->strict_string_checks ? (len) + 1 : (n))
47
48 #define ASAN_READ_STRING(ctx, s, n)                             \
49   ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
50
51 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
52 #if SANITIZER_INTERCEPT_STRNLEN
53   if (REAL(strnlen)) {
54     return REAL(strnlen)(s, maxlen);
55   }
56 #endif
57   return internal_strnlen(s, maxlen);
58 }
59
60 void SetThreadName(const char *name) {
61   AsanThread *t = GetCurrentThread();
62   if (t)
63     asanThreadRegistry().SetThreadName(t->tid(), name);
64 }
65
66 int OnExit() {
67   if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
68       __lsan::HasReportedLeaks()) {
69     return common_flags()->exitcode;
70   }
71   // FIXME: ask frontend whether we need to return failure.
72   return 0;
73 }
74
75 } // namespace __asan
76
77 // ---------------------- Wrappers ---------------- {{{1
78 using namespace __asan;  // NOLINT
79
80 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
81 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
82
83 #define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \
84   AsanInterceptorContext _ctx = {#func};                                       \
85   ctx = (void *)&_ctx;                                                         \
86   (void) ctx;                                                                  \
87
88 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
89 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
90   ASAN_INTERCEPT_FUNC_VER(name, ver)
91 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
92   ASAN_WRITE_RANGE(ctx, ptr, size)
93 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
94   ASAN_READ_RANGE(ctx, ptr, size)
95 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
96   ASAN_INTERCEPTOR_ENTER(ctx, func);                                           \
97   do {                                                                         \
98     if (asan_init_is_running)                                                  \
99       return REAL(func)(__VA_ARGS__);                                          \
100     if (SANITIZER_MAC && UNLIKELY(!asan_inited))                               \
101       return REAL(func)(__VA_ARGS__);                                          \
102     ENSURE_ASAN_INITED();                                                      \
103   } while (false)
104 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
105   do {                                            \
106   } while (false)
107 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
108   do {                                         \
109   } while (false)
110 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
111   do {                                         \
112   } while (false)
113 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
114   do {                                                      \
115   } while (false)
116 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
117 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
118 // But asan does not remember UserId's for threads (pthread_t);
119 // and remembers all ever existed threads, so the linear search by UserId
120 // can be slow.
121 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
122   do {                                                         \
123   } while (false)
124 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
125 // Strict init-order checking is dlopen-hostile:
126 // https://github.com/google/sanitizers/issues/178
127 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \
128   do {                                                                         \
129     if (flags()->strict_init_order)                                            \
130       StopInitOrderChecking();                                                 \
131     CheckNoDeepBind(filename, flag);                                           \
132   } while (false)
133 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
134 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
135 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
136 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
137 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
138   if (AsanThread *t = GetCurrentThread()) {                                    \
139     *begin = t->tls_begin();                                                   \
140     *end = t->tls_end();                                                       \
141   } else {                                                                     \
142     *begin = *end = 0;                                                         \
143   }
144
145 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
146   do {                                                       \
147     ASAN_INTERCEPTOR_ENTER(ctx, memmove);                    \
148     ASAN_MEMMOVE_IMPL(ctx, to, from, size);                  \
149   } while (false)
150
151 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
152   do {                                                      \
153     ASAN_INTERCEPTOR_ENTER(ctx, memcpy);                    \
154     ASAN_MEMCPY_IMPL(ctx, to, from, size);                  \
155   } while (false)
156
157 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
158   do {                                                      \
159     ASAN_INTERCEPTOR_ENTER(ctx, memset);                    \
160     ASAN_MEMSET_IMPL(ctx, block, c, size);                  \
161   } while (false)
162
163 #include "sanitizer_common/sanitizer_common_interceptors.inc"
164 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
165
166 // Syscall interceptors don't have contexts, we don't support suppressions
167 // for them.
168 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
169 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
170 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
171   do {                                       \
172     (void)(p);                               \
173     (void)(s);                               \
174   } while (false)
175 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
176   do {                                        \
177     (void)(p);                                \
178     (void)(s);                                \
179   } while (false)
180 #include "sanitizer_common/sanitizer_common_syscalls.inc"
181
182 struct ThreadStartParam {
183   atomic_uintptr_t t;
184   atomic_uintptr_t is_registered;
185 };
186
187 #if ASAN_INTERCEPT_PTHREAD_CREATE
188 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
189   ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
190   AsanThread *t = nullptr;
191   while ((t = reinterpret_cast<AsanThread *>(
192               atomic_load(&param->t, memory_order_acquire))) == nullptr)
193     internal_sched_yield();
194   SetCurrentThread(t);
195   return t->ThreadStart(GetTid(), &param->is_registered);
196 }
197
198 INTERCEPTOR(int, pthread_create, void *thread,
199     void *attr, void *(*start_routine)(void*), void *arg) {
200   EnsureMainThreadIDIsCorrect();
201   // Strict init-order checking is thread-hostile.
202   if (flags()->strict_init_order)
203     StopInitOrderChecking();
204   GET_STACK_TRACE_THREAD;
205   int detached = 0;
206   if (attr)
207     REAL(pthread_attr_getdetachstate)(attr, &detached);
208   ThreadStartParam param;
209   atomic_store(&param.t, 0, memory_order_relaxed);
210   atomic_store(&param.is_registered, 0, memory_order_relaxed);
211   int result;
212   {
213     // Ignore all allocations made by pthread_create: thread stack/TLS may be
214     // stored by pthread for future reuse even after thread destruction, and
215     // the linked list it's stored in doesn't even hold valid pointers to the
216     // objects, the latter are calculated by obscure pointer arithmetic.
217 #if CAN_SANITIZE_LEAKS
218     __lsan::ScopedInterceptorDisabler disabler;
219 #endif
220     result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
221   }
222   if (result == 0) {
223     u32 current_tid = GetCurrentTidOrInvalid();
224     AsanThread *t =
225         AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
226     atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
227     // Wait until the AsanThread object is initialized and the ThreadRegistry
228     // entry is in "started" state. One reason for this is that after this
229     // interceptor exits, the child thread's stack may be the only thing holding
230     // the |arg| pointer. This may cause LSan to report a leak if leak checking
231     // happens at a point when the interceptor has already exited, but the stack
232     // range for the child thread is not yet known.
233     while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
234       internal_sched_yield();
235   }
236   return result;
237 }
238
239 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
240   return real_pthread_join(t, arg);
241 }
242
243 DEFINE_REAL_PTHREAD_FUNCTIONS
244 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE
245
246 #if ASAN_INTERCEPT_SWAPCONTEXT
247 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
248   // Align to page size.
249   uptr PageSize = GetPageSizeCached();
250   uptr bottom = stack & ~(PageSize - 1);
251   ssize += stack - bottom;
252   ssize = RoundUpTo(ssize, PageSize);
253   static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb
254   if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
255     PoisonShadow(bottom, ssize, 0);
256   }
257 }
258
259 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
260             struct ucontext_t *ucp) {
261   static bool reported_warning = false;
262   if (!reported_warning) {
263     Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
264            "functions and may produce false positives in some cases!\n");
265     reported_warning = true;
266   }
267   // Clear shadow memory for new context (it may share stack
268   // with current context).
269   uptr stack, ssize;
270   ReadContextStack(ucp, &stack, &ssize);
271   ClearShadowMemoryForContextStack(stack, ssize);
272   int res = REAL(swapcontext)(oucp, ucp);
273   // swapcontext technically does not return, but program may swap context to
274   // "oucp" later, that would look as if swapcontext() returned 0.
275   // We need to clear shadow for ucp once again, as it may be in arbitrary
276   // state.
277   ClearShadowMemoryForContextStack(stack, ssize);
278   return res;
279 }
280 #endif  // ASAN_INTERCEPT_SWAPCONTEXT
281
282 #if SANITIZER_NETBSD
283 #define longjmp __longjmp14
284 #define siglongjmp __siglongjmp14
285 #endif
286
287 INTERCEPTOR(void, longjmp, void *env, int val) {
288   __asan_handle_no_return();
289   REAL(longjmp)(env, val);
290 }
291
292 #if ASAN_INTERCEPT__LONGJMP
293 INTERCEPTOR(void, _longjmp, void *env, int val) {
294   __asan_handle_no_return();
295   REAL(_longjmp)(env, val);
296 }
297 #endif
298
299 #if ASAN_INTERCEPT___LONGJMP_CHK
300 INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
301   __asan_handle_no_return();
302   REAL(__longjmp_chk)(env, val);
303 }
304 #endif
305
306 #if ASAN_INTERCEPT_SIGLONGJMP
307 INTERCEPTOR(void, siglongjmp, void *env, int val) {
308   __asan_handle_no_return();
309   REAL(siglongjmp)(env, val);
310 }
311 #endif
312
313 #if ASAN_INTERCEPT___CXA_THROW
314 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
315   CHECK(REAL(__cxa_throw));
316   __asan_handle_no_return();
317   REAL(__cxa_throw)(a, b, c);
318 }
319 #endif
320
321 #if ASAN_INTERCEPT_INDEX
322 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
323 INTERCEPTOR(char*, index, const char *string, int c)
324   ALIAS(WRAPPER_NAME(strchr));
325 # else
326 #  if SANITIZER_MAC
327 DECLARE_REAL(char*, index, const char *string, int c)
328 OVERRIDE_FUNCTION(index, strchr);
329 #  else
330 DEFINE_REAL(char*, index, const char *string, int c)
331 #  endif
332 # endif
333 #endif  // ASAN_INTERCEPT_INDEX
334
335 // For both strcat() and strncat() we need to check the validity of |to|
336 // argument irrespective of the |from| length.
337 INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
338   void *ctx;
339   ASAN_INTERCEPTOR_ENTER(ctx, strcat);  // NOLINT
340   ENSURE_ASAN_INITED();
341   if (flags()->replace_str) {
342     uptr from_length = REAL(strlen)(from);
343     ASAN_READ_RANGE(ctx, from, from_length + 1);
344     uptr to_length = REAL(strlen)(to);
345     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
346     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
347     // If the copying actually happens, the |from| string should not overlap
348     // with the resulting string starting at |to|, which has a length of
349     // to_length + from_length + 1.
350     if (from_length > 0) {
351       CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
352                            from, from_length + 1);
353     }
354   }
355   return REAL(strcat)(to, from);  // NOLINT
356 }
357
358 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
359   void *ctx;
360   ASAN_INTERCEPTOR_ENTER(ctx, strncat);
361   ENSURE_ASAN_INITED();
362   if (flags()->replace_str) {
363     uptr from_length = MaybeRealStrnlen(from, size);
364     uptr copy_length = Min(size, from_length + 1);
365     ASAN_READ_RANGE(ctx, from, copy_length);
366     uptr to_length = REAL(strlen)(to);
367     ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
368     ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
369     if (from_length > 0) {
370       CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
371                            from, copy_length);
372     }
373   }
374   return REAL(strncat)(to, from, size);
375 }
376
377 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
378   void *ctx;
379   ASAN_INTERCEPTOR_ENTER(ctx, strcpy);  // NOLINT
380 #if SANITIZER_MAC
381   if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
382 #endif
383   // strcpy is called from malloc_default_purgeable_zone()
384   // in __asan::ReplaceSystemAlloc() on Mac.
385   if (asan_init_is_running) {
386     return REAL(strcpy)(to, from);  // NOLINT
387   }
388   ENSURE_ASAN_INITED();
389   if (flags()->replace_str) {
390     uptr from_size = REAL(strlen)(from) + 1;
391     CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
392     ASAN_READ_RANGE(ctx, from, from_size);
393     ASAN_WRITE_RANGE(ctx, to, from_size);
394   }
395   return REAL(strcpy)(to, from);  // NOLINT
396 }
397
398 INTERCEPTOR(char*, strdup, const char *s) {
399   void *ctx;
400   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
401   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
402   ENSURE_ASAN_INITED();
403   uptr length = REAL(strlen)(s);
404   if (flags()->replace_str) {
405     ASAN_READ_RANGE(ctx, s, length + 1);
406   }
407   GET_STACK_TRACE_MALLOC;
408   void *new_mem = asan_malloc(length + 1, &stack);
409   REAL(memcpy)(new_mem, s, length + 1);
410   return reinterpret_cast<char*>(new_mem);
411 }
412
413 #if ASAN_INTERCEPT___STRDUP
414 INTERCEPTOR(char*, __strdup, const char *s) {
415   void *ctx;
416   ASAN_INTERCEPTOR_ENTER(ctx, strdup);
417   if (UNLIKELY(!asan_inited)) return internal_strdup(s);
418   ENSURE_ASAN_INITED();
419   uptr length = REAL(strlen)(s);
420   if (flags()->replace_str) {
421     ASAN_READ_RANGE(ctx, s, length + 1);
422   }
423   GET_STACK_TRACE_MALLOC;
424   void *new_mem = asan_malloc(length + 1, &stack);
425   REAL(memcpy)(new_mem, s, length + 1);
426   return reinterpret_cast<char*>(new_mem);
427 }
428 #endif // ASAN_INTERCEPT___STRDUP
429
430 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
431   void *ctx;
432   ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
433   ENSURE_ASAN_INITED();
434   if (flags()->replace_str) {
435     uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
436     CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
437     ASAN_READ_RANGE(ctx, from, from_size);
438     ASAN_WRITE_RANGE(ctx, to, size);
439   }
440   return REAL(strncpy)(to, from, size);
441 }
442
443 INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
444             char **endptr, int base) {
445   void *ctx;
446   ASAN_INTERCEPTOR_ENTER(ctx, strtol);
447   ENSURE_ASAN_INITED();
448   if (!flags()->replace_str) {
449     return REAL(strtol)(nptr, endptr, base);
450   }
451   char *real_endptr;
452   long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
453   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
454   return result;
455 }
456
457 INTERCEPTOR(int, atoi, const char *nptr) {
458   void *ctx;
459   ASAN_INTERCEPTOR_ENTER(ctx, atoi);
460 #if SANITIZER_MAC
461   if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
462 #endif
463   ENSURE_ASAN_INITED();
464   if (!flags()->replace_str) {
465     return REAL(atoi)(nptr);
466   }
467   char *real_endptr;
468   // "man atoi" tells that behavior of atoi(nptr) is the same as
469   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
470   // parsed integer can't be stored in *long* type (even if it's
471   // different from int). So, we just imitate this behavior.
472   int result = REAL(strtol)(nptr, &real_endptr, 10);
473   FixRealStrtolEndptr(nptr, &real_endptr);
474   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
475   return result;
476 }
477
478 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
479   void *ctx;
480   ASAN_INTERCEPTOR_ENTER(ctx, atol);
481 #if SANITIZER_MAC
482   if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
483 #endif
484   ENSURE_ASAN_INITED();
485   if (!flags()->replace_str) {
486     return REAL(atol)(nptr);
487   }
488   char *real_endptr;
489   long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
490   FixRealStrtolEndptr(nptr, &real_endptr);
491   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
492   return result;
493 }
494
495 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
496 INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
497             char **endptr, int base) {
498   void *ctx;
499   ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
500   ENSURE_ASAN_INITED();
501   if (!flags()->replace_str) {
502     return REAL(strtoll)(nptr, endptr, base);
503   }
504   char *real_endptr;
505   long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
506   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
507   return result;
508 }
509
510 INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
511   void *ctx;
512   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
513   ENSURE_ASAN_INITED();
514   if (!flags()->replace_str) {
515     return REAL(atoll)(nptr);
516   }
517   char *real_endptr;
518   long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
519   FixRealStrtolEndptr(nptr, &real_endptr);
520   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
521   return result;
522 }
523 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
524
525 #if ASAN_INTERCEPT___CXA_ATEXIT
526 static void AtCxaAtexit(void *unused) {
527   (void)unused;
528   StopInitOrderChecking();
529 }
530
531 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
532             void *dso_handle) {
533 #if SANITIZER_MAC
534   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
535 #endif
536   ENSURE_ASAN_INITED();
537   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
538   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
539   return res;
540 }
541 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
542
543 #if ASAN_INTERCEPT_FORK
544 INTERCEPTOR(int, fork, void) {
545   ENSURE_ASAN_INITED();
546   int pid = REAL(fork)();
547   return pid;
548 }
549 #endif  // ASAN_INTERCEPT_FORK
550
551 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
552 namespace __asan {
553 void InitializeAsanInterceptors() {
554   static bool was_called_once;
555   CHECK(!was_called_once);
556   was_called_once = true;
557   InitializeCommonInterceptors();
558   InitializeSignalInterceptors();
559
560   // Intercept str* functions.
561   ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
562   ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
563   ASAN_INTERCEPT_FUNC(strncat);
564   ASAN_INTERCEPT_FUNC(strncpy);
565   ASAN_INTERCEPT_FUNC(strdup);
566 #if ASAN_INTERCEPT___STRDUP
567   ASAN_INTERCEPT_FUNC(__strdup);
568 #endif
569 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
570   ASAN_INTERCEPT_FUNC(index);
571 #endif
572
573   ASAN_INTERCEPT_FUNC(atoi);
574   ASAN_INTERCEPT_FUNC(atol);
575   ASAN_INTERCEPT_FUNC(strtol);
576 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
577   ASAN_INTERCEPT_FUNC(atoll);
578   ASAN_INTERCEPT_FUNC(strtoll);
579 #endif
580
581   // Intecept jump-related functions.
582   ASAN_INTERCEPT_FUNC(longjmp);
583
584 #if ASAN_INTERCEPT_SWAPCONTEXT
585   ASAN_INTERCEPT_FUNC(swapcontext);
586 #endif
587 #if ASAN_INTERCEPT__LONGJMP
588   ASAN_INTERCEPT_FUNC(_longjmp);
589 #endif
590 #if ASAN_INTERCEPT___LONGJMP_CHK
591   ASAN_INTERCEPT_FUNC(__longjmp_chk);
592 #endif
593 #if ASAN_INTERCEPT_SIGLONGJMP
594   ASAN_INTERCEPT_FUNC(siglongjmp);
595 #endif
596
597   // Intercept exception handling functions.
598 #if ASAN_INTERCEPT___CXA_THROW
599   ASAN_INTERCEPT_FUNC(__cxa_throw);
600 #endif
601
602   // Intercept threading-related functions
603 #if ASAN_INTERCEPT_PTHREAD_CREATE
604 #if defined(ASAN_PTHREAD_CREATE_VERSION)
605   ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
606 #else
607   ASAN_INTERCEPT_FUNC(pthread_create);
608 #endif
609   ASAN_INTERCEPT_FUNC(pthread_join);
610 #endif
611
612   // Intercept atexit function.
613 #if ASAN_INTERCEPT___CXA_ATEXIT
614   ASAN_INTERCEPT_FUNC(__cxa_atexit);
615 #endif
616
617 #if ASAN_INTERCEPT_FORK
618   ASAN_INTERCEPT_FUNC(fork);
619 #endif
620
621   InitializePlatformInterceptors();
622
623   VReport(1, "AddressSanitizer: libc interceptors initialized\n");
624 }
625
626 } // namespace __asan
627
628 #endif  // !SANITIZER_FUCHSIA