asan_interceptors.cc revision c8365231004cb1d956aba4164c89ea1398eadd6b
1//===-- asan_interceptors.cc ------------------------------------*- C++ -*-===//
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#include "asan_interceptors.h"
15
16#include "asan_allocator.h"
17#include "asan_interface.h"
18#include "asan_internal.h"
19#include "asan_mac.h"
20#include "asan_mapping.h"
21#include "asan_stack.h"
22#include "asan_stats.h"
23#include "asan_thread_registry.h"
24
25#include <new>
26#include <ctype.h>
27#include <dlfcn.h>
28
29#include <pthread.h>
30
31// To replace weak system functions on Linux we just need to declare functions
32// with same names in our library and then obtain the real function pointers
33// using dlsym(). This is not so on Mac OS, where the two-level namespace makes
34// our replacement functions invisible to other libraries. This may be overcomed
35// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
36// libraries in Chromium were noticed when doing so.
37// Instead we use mach_override, a handy framework for patching functions at
38// runtime. To avoid possible name clashes, our replacement functions have
39// the "wrap_" prefix on Mac.
40//
41// After interception, the calls to system functions will be substituted by
42// calls to our interceptors. We store pointers to system function f()
43// in __asan::real_f().
44#ifdef __APPLE__
45// Include the declarations of the original functions.
46#include <string.h>
47#include <strings.h>
48
49#include "mach_override/mach_override.h"
50#define WRAPPER_NAME(x) "wrap_"#x
51
52#define OVERRIDE_FUNCTION(oldfunc, newfunc)                                   \
53  do {CHECK(0 == __asan_mach_override_ptr_custom((void*)(oldfunc),            \
54                                                 (void*)(newfunc),            \
55                                                 (void**)&real_##oldfunc,     \
56                                                 __asan_allocate_island,      \
57                                                 __asan_deallocate_island));  \
58  CHECK(real_##oldfunc != NULL);   } while (0)
59
60#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc)               \
61  do { __asan_mach_override_ptr_custom((void*)(oldfunc),            \
62                                       (void*)(newfunc),            \
63                                       (void**)&real_##oldfunc,     \
64                                       __asan_allocate_island,      \
65                                       __asan_deallocate_island);   \
66  } while (0)
67
68#define INTERCEPT_FUNCTION(func)                                        \
69  OVERRIDE_FUNCTION(func, WRAP(func))
70
71#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
72  OVERRIDE_FUNCTION_IF_EXISTS(func, WRAP(func))
73
74#else  // __linux__
75#define WRAPPER_NAME(x) #x
76
77#define INTERCEPT_FUNCTION(func)                                        \
78  CHECK((real_##func = (func##_f)dlsym(RTLD_NEXT, #func)));
79
80#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
81  do { real_##func = (func##_f)dlsym(RTLD_NEXT, #func); } while (0)
82#endif
83
84namespace __asan {
85
86typedef void (*longjmp_f)(void *env, int val);
87typedef longjmp_f _longjmp_f;
88typedef longjmp_f siglongjmp_f;
89typedef void (*__cxa_throw_f)(void *, void *, void *);
90typedef int (*pthread_create_f)(void *thread, const void *attr,
91                                void *(*start_routine) (void *), void *arg);
92#ifdef __APPLE__
93dispatch_async_f_f real_dispatch_async_f;
94dispatch_sync_f_f real_dispatch_sync_f;
95dispatch_after_f_f real_dispatch_after_f;
96dispatch_barrier_async_f_f real_dispatch_barrier_async_f;
97dispatch_group_async_f_f real_dispatch_group_async_f;
98pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np;
99CFStringCreateCopy_f real_CFStringCreateCopy;
100#endif
101
102sigaction_f             real_sigaction;
103signal_f                real_signal;
104longjmp_f               real_longjmp;
105_longjmp_f              real__longjmp;
106siglongjmp_f            real_siglongjmp;
107__cxa_throw_f           real___cxa_throw;
108pthread_create_f        real_pthread_create;
109
110index_f       real_index;
111memcmp_f      real_memcmp;
112memcpy_f      real_memcpy;
113memmove_f     real_memmove;
114memset_f      real_memset;
115strcasecmp_f  real_strcasecmp;
116strcat_f      real_strcat;
117strchr_f      real_strchr;
118strcmp_f      real_strcmp;
119strcpy_f      real_strcpy;
120strdup_f      real_strdup;
121strlen_f      real_strlen;
122strncasecmp_f real_strncasecmp;
123strncmp_f     real_strncmp;
124strncpy_f     real_strncpy;
125strnlen_f     real_strnlen;
126
127// Instruments read/write access to a single byte in memory.
128// On error calls __asan_report_error, which aborts the program.
129__attribute__((noinline))
130static void AccessAddress(uintptr_t address, bool isWrite) {
131  if (__asan_address_is_poisoned((void*)address)) {
132    GET_BP_PC_SP;
133    __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1);
134  }
135}
136
137// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
138// and ASAN_WRITE_RANGE as macro instead of function so
139// that no extra frames are created, and stack trace contains
140// relevant information only.
141
142// Instruments read/write access to a memory range.
143// More complex implementation is possible, for now just
144// checking the first and the last byte of a range.
145#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
146  if (size > 0) { \
147    uintptr_t ptr = (uintptr_t)(offset); \
148    AccessAddress(ptr, isWrite); \
149    AccessAddress(ptr + (size) - 1, isWrite); \
150  } \
151} while (0)
152
153#define ASAN_READ_RANGE(offset, size) do { \
154  ACCESS_MEMORY_RANGE(offset, size, false); \
155} while (0)
156
157#define ASAN_WRITE_RANGE(offset, size) do { \
158  ACCESS_MEMORY_RANGE(offset, size, true); \
159} while (0)
160
161// Behavior of functions like "memcpy" or "strcpy" is undefined
162// if memory intervals overlap. We report error in this case.
163// Macro is used to avoid creation of new frames.
164static inline bool RangesOverlap(const char *offset1, size_t length1,
165                                 const char *offset2, size_t length2) {
166  return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
167}
168#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
169  const char *offset1 = (const char*)_offset1; \
170  const char *offset2 = (const char*)_offset2; \
171  if (RangesOverlap(offset1, length1, offset2, length2)) { \
172    Report("ERROR: AddressSanitizer %s-param-overlap: " \
173           "memory ranges [%p,%p) and [%p, %p) overlap\n", \
174           name, offset1, offset1 + length1, offset2, offset2 + length2); \
175    PRINT_CURRENT_STACK(); \
176    ShowStatsAndAbort(); \
177  } \
178} while (0)
179
180#define ENSURE_ASAN_INITED() do { \
181  CHECK(!asan_init_is_running); \
182  if (!asan_inited) { \
183    __asan_init(); \
184  } \
185} while (0)
186
187size_t internal_strlen(const char *s) {
188  size_t i = 0;
189  while (s[i]) i++;
190  return i;
191}
192
193size_t internal_strnlen(const char *s, size_t maxlen) {
194  if (real_strnlen != NULL) {
195    return real_strnlen(s, maxlen);
196  }
197  size_t i = 0;
198  while (i < maxlen && s[i]) i++;
199  return i;
200}
201
202void* internal_memchr(const void* s, int c, size_t n) {
203  const char* t = (char*)s;
204  for (size_t i = 0; i < n; ++i, ++t)
205    if (*t == c)
206      return (void*)t;
207  return NULL;
208}
209
210int internal_memcmp(const void* s1, const void* s2, size_t n) {
211  const char* t1 = (char*)s1;
212  const char* t2 = (char*)s2;
213  for (size_t i = 0; i < n; ++i, ++t1, ++t2)
214    if (*t1 != *t2)
215      return *t1 < *t2 ? -1 : 1;
216  return 0;
217}
218
219char *internal_strstr(const char *haystack, const char *needle) {
220  // This is O(N^2), but we are not using it in hot places.
221  size_t len1 = internal_strlen(haystack);
222  size_t len2 = internal_strlen(needle);
223  if (len1 < len2) return 0;
224  for (size_t pos = 0; pos <= len1 - len2; pos++) {
225    if (internal_memcmp(haystack + pos, needle, len2) == 0)
226      return (char*)haystack + pos;
227  }
228  return 0;
229}
230
231char *internal_strncat(char *dst, const char *src, size_t n) {
232  size_t len = internal_strlen(dst);
233  size_t i;
234  for (i = 0; i < n && src[i]; i++)
235    dst[len + i] = src[i];
236  dst[len + i] = 0;
237  return dst;
238}
239
240int internal_strcmp(const char *s1, const char *s2) {
241  while (true) {
242    unsigned c1 = *s1;
243    unsigned c2 = *s2;
244    if (c1 != c2) return (c1 < c2) ? -1 : 1;
245    if (c1 == 0) break;
246    s1++;
247    s2++;
248  }
249  return 0;
250}
251
252}  // namespace __asan
253
254// ---------------------- Wrappers ---------------- {{{1
255using namespace __asan;  // NOLINT
256
257#define OPERATOR_NEW_BODY \
258  GET_STACK_TRACE_HERE_FOR_MALLOC;\
259  return asan_memalign(0, size, &stack);
260
261#ifdef ANDROID
262void *operator new(size_t size) { OPERATOR_NEW_BODY; }
263void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
264#else
265void *operator new(size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
266void *operator new[](size_t size) throw(std::bad_alloc) { OPERATOR_NEW_BODY; }
267void *operator new(size_t size, std::nothrow_t const&) throw()
268{ OPERATOR_NEW_BODY; }
269void *operator new[](size_t size, std::nothrow_t const&) throw()
270{ OPERATOR_NEW_BODY; }
271#endif
272
273#define OPERATOR_DELETE_BODY \
274  GET_STACK_TRACE_HERE_FOR_FREE(ptr);\
275  asan_free(ptr, &stack);
276
277void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
278void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
279void operator delete(void *ptr, std::nothrow_t const&) throw()
280{ OPERATOR_DELETE_BODY; }
281void operator delete[](void *ptr, std::nothrow_t const&) throw()
282{ OPERATOR_DELETE_BODY;}
283
284static void *asan_thread_start(void *arg) {
285  AsanThread *t = (AsanThread*)arg;
286  asanThreadRegistry().SetCurrent(t);
287  return t->ThreadStart();
288}
289
290extern "C"
291#ifndef __APPLE__
292__attribute__((visibility("default")))
293#endif
294int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
295                         void *(*start_routine) (void *), void *arg) {
296  GET_STACK_TRACE_HERE(kStackTraceMax);
297  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
298  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
299  asanThreadRegistry().RegisterThread(t);
300  return real_pthread_create(thread, attr, asan_thread_start, t);
301}
302
303extern "C"
304void *WRAP(signal)(int signum, void *handler) {
305  if (!AsanInterceptsSignal(signum)) {
306    return real_signal(signum, handler);
307  }
308  return NULL;
309}
310
311extern "C"
312int (sigaction)(int signum, const void *act, void *oldact);
313
314extern "C"
315int WRAP(sigaction)(int signum, const void *act, void *oldact) {
316  if (!AsanInterceptsSignal(signum)) {
317    return real_sigaction(signum, act, oldact);
318  }
319  return 0;
320}
321
322
323static void UnpoisonStackFromHereToTop() {
324  int local_stack;
325  AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
326  CHECK(curr_thread);
327  uintptr_t top = curr_thread->stack_top();
328  uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1);
329  PoisonShadow(bottom, top - bottom, 0);
330}
331
332extern "C" void WRAP(longjmp)(void *env, int val) {
333  UnpoisonStackFromHereToTop();
334  real_longjmp(env, val);
335}
336
337extern "C" void WRAP(_longjmp)(void *env, int val) {
338  UnpoisonStackFromHereToTop();
339  real__longjmp(env, val);
340}
341
342extern "C" void WRAP(siglongjmp)(void *env, int val) {
343  UnpoisonStackFromHereToTop();
344  real_siglongjmp(env, val);
345}
346
347extern "C" void __cxa_throw(void *a, void *b, void *c);
348
349#if ASAN_HAS_EXCEPTIONS == 1
350extern "C" void WRAP(__cxa_throw)(void *a, void *b, void *c) {
351  CHECK(&real___cxa_throw);
352  UnpoisonStackFromHereToTop();
353  real___cxa_throw(a, b, c);
354}
355#endif
356
357extern "C" {
358// intercept mlock and friends.
359// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
360// All functions return 0 (success).
361static void MlockIsUnsupported() {
362  static bool printed = 0;
363  if (printed) return;
364  printed = true;
365  Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
366}
367int mlock(const void *addr, size_t len) {
368  MlockIsUnsupported();
369  return 0;
370}
371int munlock(const void *addr, size_t len) {
372  MlockIsUnsupported();
373  return 0;
374}
375int mlockall(int flags) {
376  MlockIsUnsupported();
377  return 0;
378}
379int munlockall(void) {
380  MlockIsUnsupported();
381  return 0;
382}
383}  // extern "C"
384
385
386
387static inline int CharCmp(unsigned char c1, unsigned char c2) {
388  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
389}
390
391static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
392  int c1_low = tolower(c1);
393  int c2_low = tolower(c2);
394  return c1_low - c2_low;
395}
396
397extern "C"
398int WRAP(memcmp)(const void *a1, const void *a2, size_t size) {
399  ENSURE_ASAN_INITED();
400  unsigned char c1 = 0, c2 = 0;
401  const unsigned char *s1 = (const unsigned char*)a1;
402  const unsigned char *s2 = (const unsigned char*)a2;
403  size_t i;
404  for (i = 0; i < size; i++) {
405    c1 = s1[i];
406    c2 = s2[i];
407    if (c1 != c2) break;
408  }
409  ASAN_READ_RANGE(s1, Min(i + 1, size));
410  ASAN_READ_RANGE(s2, Min(i + 1, size));
411  return CharCmp(c1, c2);
412}
413
414extern "C"
415void *WRAP(memcpy)(void *to, const void *from, size_t size) {
416  // memcpy is called during __asan_init() from the internals
417  // of printf(...).
418  if (asan_init_is_running) {
419    return real_memcpy(to, from, size);
420  }
421  ENSURE_ASAN_INITED();
422  if (FLAG_replace_intrin) {
423    if (to != from) {
424      // We do not treat memcpy with to==from as a bug.
425      // See http://llvm.org/bugs/show_bug.cgi?id=11763.
426      CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
427    }
428    ASAN_WRITE_RANGE(from, size);
429    ASAN_READ_RANGE(to, size);
430  }
431  return real_memcpy(to, from, size);
432}
433
434extern "C"
435void *WRAP(memmove)(void *to, const void *from, size_t size) {
436  ENSURE_ASAN_INITED();
437  if (FLAG_replace_intrin) {
438    ASAN_WRITE_RANGE(from, size);
439    ASAN_READ_RANGE(to, size);
440  }
441  return real_memmove(to, from, size);
442}
443
444extern "C"
445void *WRAP(memset)(void *block, int c, size_t size) {
446  // memset is called inside INTERCEPT_FUNCTION on Mac.
447  if (asan_init_is_running) {
448    return real_memset(block, c, size);
449  }
450  ENSURE_ASAN_INITED();
451  if (FLAG_replace_intrin) {
452    ASAN_WRITE_RANGE(block, size);
453  }
454  return real_memset(block, c, size);
455}
456
457#ifndef __APPLE__
458extern "C"
459char *WRAP(index)(const char *str, int c)
460  __attribute__((alias(WRAPPER_NAME(strchr))));
461#endif
462
463extern "C"
464char *WRAP(strchr)(const char *str, int c) {
465  ENSURE_ASAN_INITED();
466  char *result = real_strchr(str, c);
467  if (FLAG_replace_str) {
468    size_t bytes_read = (result ? result - str : real_strlen(str)) + 1;
469    ASAN_READ_RANGE(str, bytes_read);
470  }
471  return result;
472}
473
474extern "C"
475int WRAP(strcasecmp)(const char *s1, const char *s2) {
476  ENSURE_ASAN_INITED();
477  unsigned char c1, c2;
478  size_t i;
479  for (i = 0; ; i++) {
480    c1 = (unsigned char)s1[i];
481    c2 = (unsigned char)s2[i];
482    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
483  }
484  ASAN_READ_RANGE(s1, i + 1);
485  ASAN_READ_RANGE(s2, i + 1);
486  return CharCaseCmp(c1, c2);
487}
488
489extern "C"
490char *WRAP(strcat)(char *to, const char *from) {  // NOLINT
491  ENSURE_ASAN_INITED();
492  if (FLAG_replace_str) {
493    size_t from_length = real_strlen(from);
494    ASAN_READ_RANGE(from, from_length + 1);
495    if (from_length > 0) {
496      size_t to_length = real_strlen(to);
497      ASAN_READ_RANGE(to, to_length);
498      ASAN_WRITE_RANGE(to + to_length, from_length + 1);
499      CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1);
500    }
501  }
502  return real_strcat(to, from);
503}
504
505extern "C"
506int WRAP(strcmp)(const char *s1, const char *s2) {
507  if (!asan_inited) {
508    return internal_strcmp(s1, s2);
509  }
510  unsigned char c1, c2;
511  size_t i;
512  for (i = 0; ; i++) {
513    c1 = (unsigned char)s1[i];
514    c2 = (unsigned char)s2[i];
515    if (c1 != c2 || c1 == '\0') break;
516  }
517  ASAN_READ_RANGE(s1, i + 1);
518  ASAN_READ_RANGE(s2, i + 1);
519  return CharCmp(c1, c2);
520}
521
522extern "C"
523char *WRAP(strcpy)(char *to, const char *from) {  // NOLINT
524  // strcpy is called from malloc_default_purgeable_zone()
525  // in __asan::ReplaceSystemAlloc() on Mac.
526  if (asan_init_is_running) {
527    return real_strcpy(to, from);
528  }
529  ENSURE_ASAN_INITED();
530  if (FLAG_replace_str) {
531    size_t from_size = real_strlen(from) + 1;
532    CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
533    ASAN_READ_RANGE(from, from_size);
534    ASAN_WRITE_RANGE(to, from_size);
535  }
536  return real_strcpy(to, from);
537}
538
539extern "C"
540char *WRAP(strdup)(const char *s) {
541  ENSURE_ASAN_INITED();
542  if (FLAG_replace_str) {
543    size_t length = real_strlen(s);
544    ASAN_READ_RANGE(s, length + 1);
545  }
546  return real_strdup(s);
547}
548
549extern "C"
550size_t WRAP(strlen)(const char *s) {
551  // strlen is called from malloc_default_purgeable_zone()
552  // in __asan::ReplaceSystemAlloc() on Mac.
553  if (asan_init_is_running) {
554    return real_strlen(s);
555  }
556  ENSURE_ASAN_INITED();
557  size_t length = real_strlen(s);
558  if (FLAG_replace_str) {
559    ASAN_READ_RANGE(s, length + 1);
560  }
561  return length;
562}
563
564extern "C"
565int WRAP(strncasecmp)(const char *s1, const char *s2, size_t size) {
566  ENSURE_ASAN_INITED();
567  unsigned char c1 = 0, c2 = 0;
568  size_t i;
569  for (i = 0; i < size; i++) {
570    c1 = (unsigned char)s1[i];
571    c2 = (unsigned char)s2[i];
572    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
573  }
574  ASAN_READ_RANGE(s1, Min(i + 1, size));
575  ASAN_READ_RANGE(s2, Min(i + 1, size));
576  return CharCaseCmp(c1, c2);
577}
578
579extern "C"
580int WRAP(strncmp)(const char *s1, const char *s2, size_t size) {
581  // strncmp is called from malloc_default_purgeable_zone()
582  // in __asan::ReplaceSystemAlloc() on Mac.
583  if (asan_init_is_running) {
584    return real_strncmp(s1, s2, size);
585  }
586  unsigned char c1 = 0, c2 = 0;
587  size_t i;
588  for (i = 0; i < size; i++) {
589    c1 = (unsigned char)s1[i];
590    c2 = (unsigned char)s2[i];
591    if (c1 != c2 || c1 == '\0') break;
592  }
593  ASAN_READ_RANGE(s1, Min(i + 1, size));
594  ASAN_READ_RANGE(s2, Min(i + 1, size));
595  return CharCmp(c1, c2);
596}
597
598extern "C"
599char *WRAP(strncpy)(char *to, const char *from, size_t size) {
600  ENSURE_ASAN_INITED();
601  if (FLAG_replace_str) {
602    size_t from_size = Min(size, internal_strnlen(from, size) + 1);
603    CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
604    ASAN_READ_RANGE(from, from_size);
605    ASAN_WRITE_RANGE(to, size);
606  }
607  return real_strncpy(to, from, size);
608}
609
610#ifndef __APPLE__
611extern "C"
612size_t WRAP(strnlen)(const char *s, size_t maxlen) {
613  ENSURE_ASAN_INITED();
614  size_t length = real_strnlen(s, maxlen);
615  if (FLAG_replace_str) {
616    ASAN_READ_RANGE(s, Min(length + 1, maxlen));
617  }
618  return length;
619}
620#endif
621
622// ---------------------- InitializeAsanInterceptors ---------------- {{{1
623namespace __asan {
624void InitializeAsanInterceptors() {
625#ifndef __APPLE__
626  INTERCEPT_FUNCTION(index);
627#else
628  OVERRIDE_FUNCTION(index, WRAP(strchr));
629#endif
630  INTERCEPT_FUNCTION(memcmp);
631  INTERCEPT_FUNCTION(memcpy);
632  INTERCEPT_FUNCTION(memmove);
633  INTERCEPT_FUNCTION(memset);
634  INTERCEPT_FUNCTION(strcasecmp);
635  INTERCEPT_FUNCTION(strcat);  // NOLINT
636  INTERCEPT_FUNCTION(strchr);
637  INTERCEPT_FUNCTION(strcmp);
638  INTERCEPT_FUNCTION(strcpy);  // NOLINT
639  INTERCEPT_FUNCTION(strdup);
640  INTERCEPT_FUNCTION(strlen);
641  INTERCEPT_FUNCTION(strncasecmp);
642  INTERCEPT_FUNCTION(strncmp);
643  INTERCEPT_FUNCTION(strncpy);
644
645  INTERCEPT_FUNCTION(sigaction);
646  INTERCEPT_FUNCTION(signal);
647  INTERCEPT_FUNCTION(longjmp);
648  INTERCEPT_FUNCTION(_longjmp);
649  INTERCEPT_FUNCTION_IF_EXISTS(__cxa_throw);
650  INTERCEPT_FUNCTION(pthread_create);
651
652#ifdef __APPLE__
653  INTERCEPT_FUNCTION(dispatch_async_f);
654  INTERCEPT_FUNCTION(dispatch_sync_f);
655  INTERCEPT_FUNCTION(dispatch_after_f);
656  INTERCEPT_FUNCTION(dispatch_barrier_async_f);
657  INTERCEPT_FUNCTION(dispatch_group_async_f);
658  // We don't need to intercept pthread_workqueue_additem_np() to support the
659  // libdispatch API, but it helps us to debug the unsupported functions. Let's
660  // intercept it only during verbose runs.
661  if (FLAG_v >= 2) {
662    INTERCEPT_FUNCTION(pthread_workqueue_additem_np);
663  }
664  // Normally CFStringCreateCopy should not copy constant CF strings.
665  // Replacing the default CFAllocator causes constant strings to be copied
666  // rather than just returned, which leads to bugs in big applications like
667  // Chromium and WebKit, see
668  // http://code.google.com/p/address-sanitizer/issues/detail?id=10
669  // Until this problem is fixed we need to check that the string is
670  // non-constant before calling CFStringCreateCopy.
671  INTERCEPT_FUNCTION(CFStringCreateCopy);
672#else
673  // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
674  // there.
675  INTERCEPT_FUNCTION(siglongjmp);
676#endif
677
678#ifndef __APPLE__
679  INTERCEPT_FUNCTION(strnlen);
680#endif
681  if (FLAG_v > 0) {
682    Printf("AddressSanitizer: libc interceptors initialized\n");
683  }
684}
685
686}  // namespace __asan
687