Index: lib/asan/CMakeLists.txt =================================================================== --- lib/asan/CMakeLists.txt +++ lib/asan/CMakeLists.txt @@ -65,6 +65,19 @@ CFLAGS ${ASAN_CFLAGS} DEFS ${ASAN_COMMON_DEFINITIONS}) list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan_osx) + + add_compiler_rt_osx_dynamic_runtime(clang_rt.asan_osx_dynamic + ARCH ${ASAN_SUPPORTED_ARCH} + SOURCES ${ASAN_DYLIB_SOURCES} + $ + $ + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_DYLIB_DEFINITIONS} + # Dynamic lookup is needed because shadow scale and offset are + # provided by the instrumented modules. + LINKFLAGS "-framework Foundation" + "-undefined dynamic_lookup") + list(APPEND ASAN_RUNTIME_LIBRARIES clang_rt.asan_osx_dynamic) elseif(ANDROID) add_library(clang_rt.asan-arm-android SHARED ${ASAN_SOURCES} @@ -90,23 +103,6 @@ endforeach() endif() -set(ASAN_DYNAMIC_RUNTIME_LIBRARIES) -if(APPLE) - # Build universal binary on APPLE. - add_compiler_rt_osx_dynamic_runtime(clang_rt.asan_osx_dynamic - ARCH ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_DYLIB_SOURCES} - $ - $ - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_DYLIB_DEFINITIONS} - # Dynamic lookup is needed because shadow scale and offset are - # provided by the instrumented modules. - LINKFLAGS "-framework Foundation" - "-undefined dynamic_lookup") - list(APPEND ASAN_DYNAMIC_RUNTIME_LIBRARIES clang_rt.asan_osx_dynamic) -endif() - if(LLVM_INCLUDE_TESTS) add_subdirectory(tests) endif() Index: lib/asan/asan_intercepted_functions.h =================================================================== --- lib/asan/asan_intercepted_functions.h +++ lib/asan/asan_intercepted_functions.h @@ -216,8 +216,6 @@ typedef u64 dispatch_time_t; typedef void (*dispatch_function_t)(void *block); typedef void* (*worker_t)(void *block); -typedef void* CFStringRef; -typedef void* CFAllocatorRef; DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async_f, dispatch_queue_t dq, @@ -235,11 +233,6 @@ dispatch_group_t group, dispatch_queue_t dq, void *ctxt, dispatch_function_t func); -DECLARE_FUNCTION_AND_WRAPPER(void, __CFInitialize, void); -DECLARE_FUNCTION_AND_WRAPPER(CFStringRef, CFStringCreateCopy, - CFAllocatorRef alloc, CFStringRef str); -DECLARE_FUNCTION_AND_WRAPPER(void, free, void* ptr); - # if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT) DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async, dispatch_group_t dg, @@ -253,6 +246,32 @@ DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_cancel_handler, dispatch_source_t ds, void (^work)(void)); # endif // MAC_INTERPOSE_FUNCTIONS + +typedef void malloc_zone_t; +typedef size_t vm_size_t; +DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_create_zone, + vm_size_t start_size, unsigned flags); +DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_default_zone, void); +DECLARE_FUNCTION_AND_WRAPPER( + malloc_zone_t *, malloc_default_purgeable_zone, void); +DECLARE_FUNCTION_AND_WRAPPER(void, malloc_make_purgeable, void *ptr); +DECLARE_FUNCTION_AND_WRAPPER(int, malloc_make_nonpurgeable, void *ptr); +DECLARE_FUNCTION_AND_WRAPPER(void, malloc_set_zone_name, + malloc_zone_t *zone, const char *name); +DECLARE_FUNCTION_AND_WRAPPER(void *, malloc, size_t size); +DECLARE_FUNCTION_AND_WRAPPER(void, free, void *ptr); +DECLARE_FUNCTION_AND_WRAPPER(void *, realloc, void *ptr, size_t size); +DECLARE_FUNCTION_AND_WRAPPER(void *, calloc, size_t nmemb, size_t size); +DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size); +DECLARE_FUNCTION_AND_WRAPPER(size_t, malloc_good_size, size_t size); +DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign, + void **memptr, size_t alignment, size_t size); +DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_prepare, void); +DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void); +DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void); + + + # endif // __APPLE__ } // extern "C" #endif // defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL)) Index: lib/asan/asan_mac.cc =================================================================== --- lib/asan/asan_mac.cc +++ lib/asan/asan_mac.cc @@ -36,7 +36,6 @@ #include // for free() #include #include -#include namespace __asan { @@ -131,14 +130,6 @@ } void AsanPlatformThreadInit() { - // For the first program thread, we can't replace the allocator before - // __CFInitialize() has been called. If it hasn't, we'll call - // MaybeReplaceCFAllocator() later on this thread. - // For other threads __CFInitialize() has been called before their creation. - // See also asan_malloc_mac.cc. - if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) { - MaybeReplaceCFAllocator(); - } } void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) { @@ -424,29 +415,6 @@ } #endif -// See http://opensource.apple.com/source/CF/CF-635.15/CFString.c -int __CFStrIsConstant(CFStringRef str) { - CFRuntimeBase *base = (CFRuntimeBase*)str; -#if __LP64__ - return base->_rc == 0; -#else - return (base->_cfinfo[CF_RC_BITS]) == 0; -#endif -} - -INTERCEPTOR(CFStringRef, CFStringCreateCopy, CFAllocatorRef alloc, - CFStringRef str) { - if (__CFStrIsConstant(str)) { - return str; - } else { - return REAL(CFStringCreateCopy)(alloc, str); - } -} - -DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) - -DECLARE_REAL_AND_INTERCEPTOR(void, __CFInitialize, void) - namespace __asan { void InitializeMacInterceptors() { @@ -455,20 +423,6 @@ CHECK(INTERCEPT_FUNCTION(dispatch_after_f)); CHECK(INTERCEPT_FUNCTION(dispatch_barrier_async_f)); CHECK(INTERCEPT_FUNCTION(dispatch_group_async_f)); - // Normally CFStringCreateCopy should not copy constant CF strings. - // Replacing the default CFAllocator causes constant strings to be copied - // rather than just returned, which leads to bugs in big applications like - // Chromium and WebKit, see - // http://code.google.com/p/address-sanitizer/issues/detail?id=10 - // Until this problem is fixed we need to check that the string is - // non-constant before calling CFStringCreateCopy. - CHECK(INTERCEPT_FUNCTION(CFStringCreateCopy)); - // Some of the library functions call free() directly, so we have to - // intercept it. - CHECK(INTERCEPT_FUNCTION(free)); - if (flags()->replace_cfallocator) { - CHECK(INTERCEPT_FUNCTION(__CFInitialize)); - } } } // namespace __asan Index: lib/asan/asan_malloc_mac.cc =================================================================== --- lib/asan/asan_malloc_mac.cc +++ lib/asan/asan_malloc_mac.cc @@ -36,85 +36,108 @@ // TODO(glider): do we need both zones? static malloc_zone_t *system_malloc_zone = 0; -static malloc_zone_t *system_purgeable_zone = 0; static malloc_zone_t asan_zone; -CFAllocatorRef cf_asan = 0; -// _CFRuntimeCreateInstance() checks whether the supplied allocator is -// kCFAllocatorSystemDefault and, if it is not, stores the allocator reference -// at the beginning of the allocated memory and returns the pointer to the -// allocated memory plus sizeof(CFAllocatorRef). See -// http://www.opensource.apple.com/source/CF/CF-635.21/CFRuntime.c -// Pointers returned by _CFRuntimeCreateInstance() can then be passed directly -// to free() or CFAllocatorDeallocate(), which leads to false invalid free -// reports. -// The corresponding rdar bug is http://openradar.appspot.com/radar?id=1796404. -void* ALWAYS_INLINE get_saved_cfallocator_ref(void *ptr) { - if (flags()->replace_cfallocator) { - // Make sure we're not hitting the previous page. This may be incorrect - // if ASan's malloc returns an address ending with 0xFF8, which will be - // then padded to a page boundary with a CFAllocatorRef. - uptr arith_ptr = (uptr)ptr; - if ((arith_ptr & 0xFFF) > sizeof(CFAllocatorRef)) { - CFAllocatorRef *saved = - (CFAllocatorRef*)(arith_ptr - sizeof(CFAllocatorRef)); - if ((*saved == cf_asan) && asan_mz_size(saved)) ptr = (void*)saved; - } +INTERCEPTOR(malloc_zone_t *, malloc_create_zone, + vm_size_t start_size, unsigned zone_flags) { + if (!asan_inited) __asan_init(); + GET_STACK_TRACE_MALLOC; + malloc_zone_t *new_zone = + (malloc_zone_t*)asan_malloc(sizeof(asan_zone), &stack); + internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone)); + new_zone->zone_name = NULL; // The name will be changed anyway. + return new_zone; +} + +INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { + if (!asan_inited) __asan_init(); + return &asan_zone; +} + +INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { + // FIXME: ASan should support purgeable allocations. + // https://code.google.com/p/address-sanitizer/issues/detail?id=139 + if (!asan_inited) __asan_init(); + return &asan_zone; +} + +INTERCEPTOR(void, malloc_make_purgeable, void *ptr) { + // FIXME: ASan should support purgeable allocations. Ignoring them is fine + // for now. + if (!asan_inited) __asan_init(); +} + +INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { + // FIXME: ASan should support purgeable allocations. Ignoring them is fine + // for now. + if (!asan_inited) __asan_init(); + // Must return 0 if the contents were not purged since the last call to + // malloc_make_purgeable(). + return 0; +} + +INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { + if (!asan_inited) __asan_init(); + // Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes. + size_t buflen = 6 + (name ? internal_strlen(name) : 0); + InternalScopedBuffer new_name(buflen); + if (name && zone->introspect == asan_zone.introspect) { + internal_snprintf(new_name.data(), buflen, "asan-%s", name); + name = new_name.data(); } - return ptr; + + // Call the system malloc's implementation for both external and our zones, + // since that appropriately changes VM region protections on the zone. + REAL(malloc_set_zone_name)(zone, name); +} + +INTERCEPTOR(void *, malloc, size_t size) { + if (!asan_inited) __asan_init(); + GET_STACK_TRACE_MALLOC; + void *res = asan_malloc(size, &stack); + return res; } -// The free() implementation provided by OS X calls malloc_zone_from_ptr() -// to find the owner of |ptr|. If the result is 0, an invalid free() is -// reported. Our implementation falls back to asan_free() in this case -// in order to print an ASan-style report. -// -// For the objects created by _CFRuntimeCreateInstance a CFAllocatorRef is -// placed at the beginning of the allocated chunk and the pointer returned by -// our allocator is off by sizeof(CFAllocatorRef). This pointer can be then -// passed directly to free(), which will lead to errors. -// To overcome this we're checking whether |ptr-sizeof(CFAllocatorRef)| -// contains a pointer to our CFAllocator (assuming no other allocator is used). -// See http://code.google.com/p/address-sanitizer/issues/detail?id=70 for more -// info. INTERCEPTOR(void, free, void *ptr) { - malloc_zone_t *zone = malloc_zone_from_ptr(ptr); - if (zone) { -#if defined(MAC_OS_X_VERSION_10_6) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - if ((zone->version >= 6) && (zone->free_definite_size)) { - zone->free_definite_size(zone, ptr, malloc_size(ptr)); - } else { - malloc_zone_free(zone, ptr); - } -#else - malloc_zone_free(zone, ptr); -#endif - } else { - if (!asan_mz_size(ptr)) ptr = get_saved_cfallocator_ref(ptr); - GET_STACK_TRACE_FREE; - asan_free(ptr, &stack, FROM_MALLOC); - } + if (!asan_inited) __asan_init(); + if (!ptr) return; + GET_STACK_TRACE_FREE; + asan_free(ptr, &stack, FROM_MALLOC); } -// We can't always replace the default CFAllocator with cf_asan right in -// ReplaceSystemMalloc(), because it is sometimes called before -// __CFInitialize(), when the default allocator is invalid and replacing it may -// crash the program. Instead we wait for the allocator to initialize and jump -// in just after __CFInitialize(). Nobody is going to allocate memory using -// CFAllocators before that, so we won't miss anything. -// -// See http://code.google.com/p/address-sanitizer/issues/detail?id=87 -// and http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c -INTERCEPTOR(void, __CFInitialize, void) { - // If the runtime is built as dynamic library, __CFInitialize wrapper may be - // called before __asan_init. -#if !MAC_INTERPOSE_FUNCTIONS - CHECK(flags()->replace_cfallocator); - CHECK(asan_inited); -#endif - REAL(__CFInitialize)(); - if (!cf_asan && asan_inited) MaybeReplaceCFAllocator(); +INTERCEPTOR(void *, realloc, void *ptr, size_t size) { + if (!asan_inited) __asan_init(); + GET_STACK_TRACE_MALLOC; + return asan_realloc(ptr, size, &stack); +} + +INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { + if (!asan_inited) __asan_init(); + GET_STACK_TRACE_MALLOC; + return asan_calloc(nmemb, size, &stack); +} + +INTERCEPTOR(void *, valloc, size_t size) { + if (!asan_inited) __asan_init(); + GET_STACK_TRACE_MALLOC; + return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); +} + +INTERCEPTOR(size_t, malloc_good_size, size_t size) { + if (!asan_inited) __asan_init(); + return asan_zone.introspect->good_size(&asan_zone, size); +} + +INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { + if (!asan_inited) __asan_init(); + CHECK(memptr); + GET_STACK_TRACE_MALLOC; + void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC); + if (result) { + *memptr = result; + return 0; + } + return -1; } namespace { @@ -134,15 +157,6 @@ return asan_malloc(size, &stack); } -void *cf_malloc(CFIndex size, CFOptionFlags hint, void *info) { - if (!asan_inited) { - CHECK(system_malloc_zone); - return malloc_zone_malloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); -} - void *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { if (!asan_inited) { // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. @@ -174,31 +188,14 @@ void ALWAYS_INLINE free_common(void *context, void *ptr) { if (!ptr) return; - if (asan_mz_size(ptr)) { - GET_STACK_TRACE_FREE; + GET_STACK_TRACE_FREE; + // FIXME: need to retire this flag. + if (!flags()->mac_ignore_invalid_free) { asan_free(ptr, &stack, FROM_MALLOC); } else { - // If the pointer does not belong to any of the zones, use one of the - // fallback methods to free memory. - malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); - if (zone_ptr == system_purgeable_zone) { - // allocations from malloc_default_purgeable_zone() done before - // __asan_init() may be occasionally freed via free_common(). - // see http://code.google.com/p/address-sanitizer/issues/detail?id=99. - malloc_zone_free(zone_ptr, ptr); - } else { - // If the memory chunk pointer was moved to store additional - // CFAllocatorRef, fix it back. - ptr = get_saved_cfallocator_ref(ptr); - GET_STACK_TRACE_FREE; - if (!flags()->mac_ignore_invalid_free) { - asan_free(ptr, &stack, FROM_MALLOC); - } else { - GET_ZONE_FOR_PTR(ptr); - WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - return; - } - } + GET_ZONE_FOR_PTR(ptr); + WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); + return; } } @@ -207,10 +204,6 @@ free_common(zone, ptr); } -void cf_free(void *ptr, void *info) { - free_common(info, ptr); -} - void *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { if (!ptr) { GET_STACK_TRACE_MALLOC; @@ -230,29 +223,11 @@ } } -void *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) { - if (!ptr) { - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); - } else { - if (asan_mz_size(ptr)) { - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); - } else { - // We can't recover from reallocating an unknown address, because - // this would require reading at most |size| bytes from - // potentially unaccessible memory. - GET_STACK_TRACE_FREE; - GET_ZONE_FOR_PTR(ptr); - ReportMacCfReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - } - } -} - void mz_destroy(malloc_zone_t* zone) { // A no-op -- we will not be destroyed! - Printf("mz_destroy() called -- ignoring\n"); + Report("mz_destroy() called -- ignoring\n"); } + // from AvailabilityMacros.h #if defined(MAC_OS_X_VERSION_10_6) && \ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 @@ -324,23 +299,7 @@ } // unnamed namespace -extern int __CFRuntimeClassTableSize; - namespace __asan { -void MaybeReplaceCFAllocator() { - static CFAllocatorContext asan_context = { - /*version*/ 0, /*info*/ &asan_zone, - /*retain*/ 0, /*release*/ 0, - /*copyDescription*/0, - /*allocate*/ &cf_malloc, - /*reallocate*/ &cf_realloc, - /*deallocate*/ &cf_free, - /*preferredSize*/ 0 }; - if (!cf_asan) - cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context); - if (flags()->replace_cfallocator && CFAllocatorGetDefault() != cf_asan) - CFAllocatorSetDefault(cf_asan); -} void ReplaceSystemMalloc() { static malloc_introspection_t asan_introspection; @@ -380,41 +339,10 @@ asan_zone.free_definite_size = 0; asan_zone.memalign = &mz_memalign; asan_introspection.zone_locked = &mi_zone_locked; - - // Request the default purgable zone to force its creation. The - // current default zone is registered with the purgable zone for - // doing tiny and small allocs. Sadly, it assumes that the default - // zone is the szone implementation from OS X and will crash if it - // isn't. By creating the zone now, this will be true and changing - // the default zone won't cause a problem. (OS X 10.6 and higher.) - system_purgeable_zone = malloc_default_purgeable_zone(); #endif - // Register the ASan zone. At this point, it will not be the - // default zone. + // Register the ASan zone. malloc_zone_register(&asan_zone); - - // Unregister and reregister the default zone. Unregistering swaps - // the specified zone with the last one registered which for the - // default zone makes the more recently registered zone the default - // zone. The default zone is then re-registered to ensure that - // allocations made from it earlier will be handled correctly. - // Things are not guaranteed to work that way, but it's how they work now. - system_malloc_zone = malloc_default_zone(); - malloc_zone_unregister(system_malloc_zone); - malloc_zone_register(system_malloc_zone); - // Make sure the default allocator was replaced. - CHECK(malloc_default_zone() == &asan_zone); - - // If __CFInitialize() hasn't been called yet, cf_asan will be created and - // installed as the default allocator after __CFInitialize() finishes (see - // the interceptor for __CFInitialize() above). Otherwise install cf_asan - // right now. On both Snow Leopard and Lion __CFInitialize() calls - // __CFAllocatorInitialize(), which initializes the _base._cfisa field of - // the default allocators we check here. - if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) { - MaybeReplaceCFAllocator(); - } } } // namespace __asan Index: lib/asan/dynamic/asan_interceptors_dynamic.cc =================================================================== --- lib/asan/dynamic/asan_interceptors_dynamic.cc +++ lib/asan/dynamic/asan_interceptors_dynamic.cc @@ -101,9 +101,19 @@ INTERPOSE_FUNCTION(signal), INTERPOSE_FUNCTION(sigaction), - INTERPOSE_FUNCTION(__CFInitialize), - INTERPOSE_FUNCTION(CFStringCreateCopy), + INTERPOSE_FUNCTION(malloc_create_zone), + INTERPOSE_FUNCTION(malloc_default_zone), + INTERPOSE_FUNCTION(malloc_default_purgeable_zone), + INTERPOSE_FUNCTION(malloc_make_purgeable), + INTERPOSE_FUNCTION(malloc_make_nonpurgeable), + INTERPOSE_FUNCTION(malloc_set_zone_name), + INTERPOSE_FUNCTION(malloc), INTERPOSE_FUNCTION(free), + INTERPOSE_FUNCTION(realloc), + INTERPOSE_FUNCTION(calloc), + INTERPOSE_FUNCTION(valloc), + INTERPOSE_FUNCTION(malloc_good_size), + INTERPOSE_FUNCTION(posix_memalign), }; } // namespace __asan Index: lib/asan/lit_tests/Darwin/interface_symbols_darwin.c =================================================================== --- /dev/null +++ lib/asan/lit_tests/Darwin/interface_symbols_darwin.c @@ -0,0 +1,37 @@ +// Check the presense of interface symbols in the ASan runtime dylib. +// If you're changing this file, please also change +// ../Linux/interface_symbols.c + +// RUN: %clang -fsanitize=address -dead_strip -O2 %s -o %t.exe +// RUN: rm -f %t.symbols %t.interface + +// RUN: nm `otool -L %t.exe | grep "asan_osx_dynamic.dylib" | \ +// RUN: tr -d '\011' | \ +// RUN: sed "s/.dylib.*/.dylib/"` \ +// RUN: | grep " T " | sed "s/.* T //" \ +// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \ +// RUN: | grep -v "__asan_malloc_hook" \ +// RUN: | grep -v "__asan_free_hook" \ +// RUN: | grep -v "__asan_symbolize" \ +// RUN: | grep -v "__asan_default_options" \ +// RUN: | grep -v "__asan_on_error" > %t.symbols + +// RUN: cat %p/../../../../include/sanitizer/asan_interface.h \ +// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \ +// RUN: | grep -v "OPTIONAL" \ +// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \ +// RUN: > %t.interface +// RUN: echo __asan_report_load1 >> %t.interface +// RUN: echo __asan_report_load2 >> %t.interface +// RUN: echo __asan_report_load4 >> %t.interface +// RUN: echo __asan_report_load8 >> %t.interface +// RUN: echo __asan_report_load16 >> %t.interface +// RUN: echo __asan_report_store1 >> %t.interface +// RUN: echo __asan_report_store2 >> %t.interface +// RUN: echo __asan_report_store4 >> %t.interface +// RUN: echo __asan_report_store8 >> %t.interface +// RUN: echo __asan_report_store16 >> %t.interface + +// RUN: cat %t.interface | sort -u | diff %t.symbols - + +int main() { return 0; } Index: lib/asan/lit_tests/Darwin/lit.local.cfg =================================================================== --- /dev/null +++ lib/asan/lit_tests/Darwin/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['Darwin']: + config.unsupported = True Index: lib/asan/lit_tests/heap-overflow.cc =================================================================== --- lib/asan/lit_tests/heap-overflow.cc +++ lib/asan/lit_tests/heap-overflow.cc @@ -29,10 +29,8 @@ // CHECK-Linux: {{ #0 0x.* in .*malloc}} // CHECK-Linux: {{ #1 0x.* in main .*heap-overflow.cc:21}} - // CHECK-Darwin: {{ #0 0x.* in .*mz_malloc.*}} - // CHECK-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}} - // CHECK-Darwin: {{ #2 0x.* in malloc.*}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*heap-overflow.cc:21}} + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*heap-overflow.cc:21}} free(x); return res; } Index: lib/asan/lit_tests/large_func_test.cc =================================================================== --- lib/asan/lit_tests/large_func_test.cc +++ lib/asan/lit_tests/large_func_test.cc @@ -56,7 +56,12 @@ // CHECK: {{ #1 0x.* in _?main .*large_func_test.cc:}}[[@LINE-1]] // CHECK: {{0x.* is located 44 bytes to the right of 400-byte region}} // CHECK: {{allocated by thread T0 here:}} - // CHECK: {{ #0 0x.* in operator new.*}} - // CHECK: {{ #1 0x.* in _?main .*large_func_test.cc:}}[[@LINE-6]] + // CHECK-Linux: {{ #0 0x.* in operator new.*}} + // CHECK-Linux: {{ #1 0x.* in _?main .*large_func_test.cc:}}[[@LINE-6]] + + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in operator new.*}} + // CHECK-Darwin: {{ #2 0x.* in operator new\[\].*}} + // CHECK-Darwin: {{ #3 0x.* in _?main .*large_func_test.cc:}}[[@LINE-11]] delete x; } Index: lib/asan/lit_tests/malloc_delete_mismatch.cc =================================================================== --- lib/asan/lit_tests/malloc_delete_mismatch.cc +++ lib/asan/lit_tests/malloc_delete_mismatch.cc @@ -1,26 +0,0 @@ -// Check that we detect malloc/delete mismatch only if the approptiate flag -// is set. - -// RUN: %clangxx_asan -g %s -o %t 2>&1 -// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1 %t 2>&1 | \ -// RUN: %symbolize | FileCheck %s - -// No error here. -// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=0 %t -#include - -static volatile char *x; - -int main() { - x = (char*)malloc(10); - x[0] = 0; - delete x; -} -// CHECK: ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x -// CHECK-NEXT: #0{{.*}}operator delete -// CHECK: #{{.*}}main -// CHECK: is located 0 bytes inside of 10-byte region -// CHECK-NEXT: allocated by thread T0 here: -// CHECK-NEXT: #0{{.*}}malloc -// CHECK: #{{.*}}main -// CHECK: HINT: {{.*}} you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0 Index: lib/asan/lit_tests/strncpy-overflow.cc =================================================================== --- lib/asan/lit_tests/strncpy-overflow.cc +++ lib/asan/lit_tests/strncpy-overflow.cc @@ -32,9 +32,7 @@ // CHECK-Linux: {{ #0 0x.* in .*malloc}} // CHECK-Linux: {{ #1 0x.* in main .*strncpy-overflow.cc:}}[[@LINE-10]] - // CHECK-Darwin: {{ #0 0x.* in .*mz_malloc.*}} - // CHECK-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}} - // CHECK-Darwin: {{ #2 0x.* in malloc.*}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*strncpy-overflow.cc:}}[[@LINE-15]] + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*strncpy-overflow.cc:}}[[@LINE-13]] return short_buffer[8]; } Index: lib/asan/lit_tests/use-after-free.cc =================================================================== --- lib/asan/lit_tests/use-after-free.cc +++ lib/asan/lit_tests/use-after-free.cc @@ -30,19 +30,14 @@ // CHECK-Linux: {{ #0 0x.* in .*free}} // CHECK-Linux: {{ #1 0x.* in main .*use-after-free.cc:21}} - // CHECK-Darwin: {{ #0 0x.* in .*free_common.*}} - // CHECK-Darwin: {{ #1 0x.* in .*mz_free.*}} - // We override free() on Darwin, thus no malloc_zone_free - // CHECK-Darwin: {{ #2 0x.* in _?wrap_free}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*use-after-free.cc:21}} + // CHECK-Darwin: {{ #0 0x.* in _?wrap_free}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*use-after-free.cc:21}} // CHECK: {{previously allocated by thread T0 here:}} // CHECK-Linux: {{ #0 0x.* in .*malloc}} // CHECK-Linux: {{ #1 0x.* in main .*use-after-free.cc:20}} - // CHECK-Darwin: {{ #0 0x.* in .*mz_malloc.*}} - // CHECK-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}} - // CHECK-Darwin: {{ #2 0x.* in malloc.*}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*use-after-free.cc:20}} + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*use-after-free.cc:20}} }