forked from OSchip/llvm-project
[ASan] make ASan malloc/free hooks weak interface functions, overridable by user. Now the user can control malloc/free hooks without recompiling ASan runtime
llvm-svn: 162355
This commit is contained in:
parent
99120e04be
commit
de17f86655
|
@ -788,45 +788,38 @@ static u8 *Reallocate(u8 *old_ptr, uptr new_size,
|
|||
|
||||
} // namespace __asan
|
||||
|
||||
// Malloc hooks declaration.
|
||||
// ASAN_NEW_HOOK(ptr, size) is called immediately after
|
||||
// allocation of "size" bytes, which returned "ptr".
|
||||
// ASAN_DELETE_HOOK(ptr) is called immediately before
|
||||
// deallocation of "ptr".
|
||||
// If ASAN_NEW_HOOK or ASAN_DELETE_HOOK is defined, user
|
||||
// program must provide implementation of this hook.
|
||||
// If macro is undefined, the hook is no-op.
|
||||
#ifdef ASAN_NEW_HOOK
|
||||
extern "C" void ASAN_NEW_HOOK(void *ptr, uptr size);
|
||||
#else
|
||||
static inline void ASAN_NEW_HOOK(void *ptr, uptr size) { }
|
||||
#endif
|
||||
|
||||
#ifdef ASAN_DELETE_HOOK
|
||||
extern "C" void ASAN_DELETE_HOOK(void *ptr);
|
||||
#else
|
||||
static inline void ASAN_DELETE_HOOK(void *ptr) { }
|
||||
#endif
|
||||
// Default (no-op) implementation of malloc hooks.
|
||||
extern "C" {
|
||||
SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_malloc_hook(void *ptr, uptr size) {
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
}
|
||||
SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_free_hook(void *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *asan_memalign(uptr alignment, uptr size, AsanStackTrace *stack) {
|
||||
void *ptr = (void*)Allocate(alignment, size, stack);
|
||||
ASAN_NEW_HOOK(ptr, size);
|
||||
__asan_malloc_hook(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void asan_free(void *ptr, AsanStackTrace *stack) {
|
||||
ASAN_DELETE_HOOK(ptr);
|
||||
__asan_free_hook(ptr);
|
||||
Deallocate((u8*)ptr, stack);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *asan_malloc(uptr size, AsanStackTrace *stack) {
|
||||
void *ptr = (void*)Allocate(0, size, stack);
|
||||
ASAN_NEW_HOOK(ptr, size);
|
||||
__asan_malloc_hook(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -834,17 +827,17 @@ void *asan_calloc(uptr nmemb, uptr size, AsanStackTrace *stack) {
|
|||
void *ptr = (void*)Allocate(0, nmemb * size, stack);
|
||||
if (ptr)
|
||||
REAL(memset)(ptr, 0, nmemb * size);
|
||||
ASAN_NEW_HOOK(ptr, nmemb * size);
|
||||
__asan_malloc_hook(ptr, nmemb * size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *asan_realloc(void *p, uptr size, AsanStackTrace *stack) {
|
||||
if (p == 0) {
|
||||
void *ptr = (void*)Allocate(0, size, stack);
|
||||
ASAN_NEW_HOOK(ptr, size);
|
||||
__asan_malloc_hook(ptr, size);
|
||||
return ptr;
|
||||
} else if (size == 0) {
|
||||
ASAN_DELETE_HOOK(p);
|
||||
__asan_free_hook(p);
|
||||
Deallocate((u8*)p, stack);
|
||||
return 0;
|
||||
}
|
||||
|
@ -853,7 +846,7 @@ void *asan_realloc(void *p, uptr size, AsanStackTrace *stack) {
|
|||
|
||||
void *asan_valloc(uptr size, AsanStackTrace *stack) {
|
||||
void *ptr = (void*)Allocate(kPageSize, size, stack);
|
||||
ASAN_NEW_HOOK(ptr, size);
|
||||
__asan_malloc_hook(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -864,7 +857,7 @@ void *asan_pvalloc(uptr size, AsanStackTrace *stack) {
|
|||
size = kPageSize;
|
||||
}
|
||||
void *ptr = (void*)Allocate(kPageSize, size, stack);
|
||||
ASAN_NEW_HOOK(ptr, size);
|
||||
__asan_malloc_hook(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -872,7 +865,7 @@ int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
|
|||
AsanStackTrace *stack) {
|
||||
void *ptr = Allocate(alignment, size, stack);
|
||||
CHECK(IsAligned((uptr)ptr, alignment));
|
||||
ASAN_NEW_HOOK(ptr, size);
|
||||
__asan_malloc_hook(ptr, size);
|
||||
*memptr = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -175,6 +175,17 @@ extern "C" {
|
|||
// ASan runtime options. See asan_flags.h for details.
|
||||
const char* __asan_default_options()
|
||||
SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
|
||||
|
||||
// Malloc hooks that may be overriden by user.
|
||||
// __asan_malloc_hook(ptr, size) is called immediately after
|
||||
// allocation of "size" bytes, which returned "ptr".
|
||||
// __asan_free_hook(ptr) is called immediately before
|
||||
// deallocation of "ptr".
|
||||
// If user doesn't provide implementations of these hooks, they are no-op.
|
||||
void __asan_malloc_hook(void *ptr, uptr size)
|
||||
SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
|
||||
void __asan_free_hook(void *ptr)
|
||||
SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
|
||||
} // extern "C"
|
||||
|
||||
#endif // ASAN_INTERFACE_H
|
||||
|
|
|
@ -250,6 +250,8 @@ static NOINLINE void force_interface_symbols() {
|
|||
case 31: __asan_default_options(); break;
|
||||
case 32: __asan_before_dynamic_init(0, 0); break;
|
||||
case 33: __asan_after_dynamic_init(); break;
|
||||
case 34: __asan_malloc_hook(0, 0); break;
|
||||
case 35: __asan_free_hook(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: %clangxx_asan -O2 %s -o %t
|
||||
// RUN: %t 2>&1 | FileCheck %s
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern "C" {
|
||||
// Note: avoid calling functions that allocate memory in malloc/free
|
||||
// to avoid infinite recursion.
|
||||
void __asan_malloc_hook(void *ptr, size_t sz) { puts("MallocHook"); }
|
||||
void __asan_free_hook(void *ptr) { puts("FreeHook"); }
|
||||
} // extern "C"
|
||||
|
||||
int main() {
|
||||
volatile int *x = new int;
|
||||
// CHECK: MallocHook
|
||||
*x = 0;
|
||||
delete x;
|
||||
// CHECK: FreeHook
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue