// Check that MemProf correctly handles malloc and free hooks. // RUN: %clangxx_memprof -O2 %s -o %t && %run %t 2>&1 | FileCheck %s #include #include #include extern "C" { const volatile void *global_ptr; #define WRITE(s) write(1, s, sizeof(s)) // Note: avoid calling functions that allocate memory in malloc/free // to avoid infinite recursion. void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) { if (__sanitizer_get_ownership(ptr) && sz == 4) { WRITE("MallocHook\n"); global_ptr = ptr; } } void __sanitizer_free_hook(const volatile void *ptr) { if (__sanitizer_get_ownership(ptr) && ptr == global_ptr) WRITE("FreeHook\n"); } } // extern "C" volatile int *x; void MallocHook1(const volatile void *ptr, size_t sz) { WRITE("MH1\n"); } void MallocHook2(const volatile void *ptr, size_t sz) { WRITE("MH2\n"); } void FreeHook1(const volatile void *ptr) { WRITE("FH1\n"); } void FreeHook2(const volatile void *ptr) { WRITE("FH2\n"); } // Call this function with uninitialized arguments to poison // TLS shadow for function parameters before calling operator // new and, eventually, user-provided hook. __attribute__((noinline)) void allocate(int *unused1, int *unused2) { x = new int; } int main() { __sanitizer_install_malloc_and_free_hooks(MallocHook1, FreeHook1); __sanitizer_install_malloc_and_free_hooks(MallocHook2, FreeHook2); int *undef1, *undef2; allocate(undef1, undef2); // CHECK: MallocHook // CHECK: MH1 // CHECK: MH2 // Check that malloc hook was called with correct argument. if (global_ptr != (void *)x) { _exit(1); } *x = 0; delete x; // CHECK: FreeHook // CHECK: FH1 // CHECK: FH2 return 0; }