diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cc b/compiler-rt/lib/asan/asan_malloc_linux.cc index 077a50c8519f..1f510f5a357c 100644 --- a/compiler-rt/lib/asan/asan_malloc_linux.cc +++ b/compiler-rt/lib/asan/asan_malloc_linux.cc @@ -23,45 +23,6 @@ #include "asan_internal.h" #include "asan_stack.h" -#if SANITIZER_ANDROID -DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) -DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) -DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) -DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) -DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) -DECLARE_REAL_AND_INTERCEPTOR(uptr, malloc_usable_size, void *mem) - -struct MallocDebug { - void *(*malloc)(uptr bytes); - void (*free)(void *mem); - void *(*calloc)(uptr n_elements, uptr elem_size); - void *(*realloc)(void *oldMem, uptr bytes); - void *(*memalign)(uptr alignment, uptr bytes); - uptr (*malloc_usable_size)(void *mem); -}; - -ALIGNED(32) const MallocDebug asan_malloc_dispatch = { - WRAP(malloc), WRAP(free), WRAP(calloc), - WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; - -namespace __asan { -void ReplaceSystemMalloc() { - const MallocDebug** __libc_malloc_dispatch_p; - __libc_malloc_dispatch_p = - (const MallocDebug **)AsanDlSymNext("__libc_malloc_dispatch"); - if (__libc_malloc_dispatch_p) - *__libc_malloc_dispatch_p = &asan_malloc_dispatch; -} -} // namespace __asan - -#else // SANITIZER_ANDROID - -namespace __asan { -void ReplaceSystemMalloc() { -} -} // namespace __asan -#endif // SANITIZER_ANDROID - // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT @@ -162,4 +123,65 @@ INTERCEPTOR(void, malloc_stats, void) { __asan_print_accumulated_stats(); } +#if SANITIZER_ANDROID +// Format of __libc_malloc_dispatch has changed in Android L. +// While we are moving towards a solution that does not depend on bionic +// internals, here is something to support both K* and L releases. +struct MallocDebugK { + void *(*malloc)(uptr bytes); + void (*free)(void *mem); + void *(*calloc)(uptr n_elements, uptr elem_size); + void *(*realloc)(void *oldMem, uptr bytes); + void *(*memalign)(uptr alignment, uptr bytes); + uptr (*malloc_usable_size)(void *mem); +}; + +struct MallocDebugL { + void *(*calloc)(uptr n_elements, uptr elem_size); + void (*free)(void *mem); + fake_mallinfo (*mallinfo)(void); + void *(*malloc)(uptr bytes); + uptr (*malloc_usable_size)(void *mem); + void *(*memalign)(uptr alignment, uptr bytes); + int (*posix_memalign)(void **memptr, uptr alignment, uptr size); + void* (*pvalloc)(uptr size); + void *(*realloc)(void *oldMem, uptr bytes); + void* (*valloc)(uptr size); +}; + +ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = { + WRAP(malloc), WRAP(free), WRAP(calloc), + WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; + +ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = { + WRAP(calloc), WRAP(free), WRAP(mallinfo), + WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign), + WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc), + WRAP(valloc)}; + +namespace __asan { +void ReplaceSystemMalloc() { + void **__libc_malloc_dispatch_p = + (void **)AsanDlSymNext("__libc_malloc_dispatch"); + if (__libc_malloc_dispatch_p) { + // Decide on K vs L dispatch format by the presence of + // __libc_malloc_default_dispatch export in libc. + void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch"); + Printf("default dispatch: %p\n", default_dispatch_p); + if (default_dispatch_p) + *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k; + else + *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l; + } +} +} // namespace __asan + +#else // SANITIZER_ANDROID + +namespace __asan { +void ReplaceSystemMalloc() { +} +} // namespace __asan +#endif // SANITIZER_ANDROID + #endif // SANITIZER_FREEBSD || SANITIZER_LINUX