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