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