1*3d4bba30STeresa Johnson // Check that MemProf correctly handles malloc and free hooks.
2*3d4bba30STeresa Johnson // RUN: %clangxx_memprof -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
3*3d4bba30STeresa Johnson
4*3d4bba30STeresa Johnson #include <sanitizer/allocator_interface.h>
5*3d4bba30STeresa Johnson #include <stdlib.h>
6*3d4bba30STeresa Johnson #include <unistd.h>
7*3d4bba30STeresa Johnson
8*3d4bba30STeresa Johnson extern "C" {
9*3d4bba30STeresa Johnson const volatile void *global_ptr;
10*3d4bba30STeresa Johnson
11*3d4bba30STeresa Johnson #define WRITE(s) write(1, s, sizeof(s))
12*3d4bba30STeresa Johnson
13*3d4bba30STeresa Johnson // Note: avoid calling functions that allocate memory in malloc/free
14*3d4bba30STeresa Johnson // to avoid infinite recursion.
__sanitizer_malloc_hook(const volatile void * ptr,size_t sz)15*3d4bba30STeresa Johnson void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
16*3d4bba30STeresa Johnson if (__sanitizer_get_ownership(ptr) && sz == 4) {
17*3d4bba30STeresa Johnson WRITE("MallocHook\n");
18*3d4bba30STeresa Johnson global_ptr = ptr;
19*3d4bba30STeresa Johnson }
20*3d4bba30STeresa Johnson }
__sanitizer_free_hook(const volatile void * ptr)21*3d4bba30STeresa Johnson void __sanitizer_free_hook(const volatile void *ptr) {
22*3d4bba30STeresa Johnson if (__sanitizer_get_ownership(ptr) && ptr == global_ptr)
23*3d4bba30STeresa Johnson WRITE("FreeHook\n");
24*3d4bba30STeresa Johnson }
25*3d4bba30STeresa Johnson } // extern "C"
26*3d4bba30STeresa Johnson
27*3d4bba30STeresa Johnson volatile int *x;
28*3d4bba30STeresa Johnson
MallocHook1(const volatile void * ptr,size_t sz)29*3d4bba30STeresa Johnson void MallocHook1(const volatile void *ptr, size_t sz) { WRITE("MH1\n"); }
MallocHook2(const volatile void * ptr,size_t sz)30*3d4bba30STeresa Johnson void MallocHook2(const volatile void *ptr, size_t sz) { WRITE("MH2\n"); }
FreeHook1(const volatile void * ptr)31*3d4bba30STeresa Johnson void FreeHook1(const volatile void *ptr) { WRITE("FH1\n"); }
FreeHook2(const volatile void * ptr)32*3d4bba30STeresa Johnson void FreeHook2(const volatile void *ptr) { WRITE("FH2\n"); }
33*3d4bba30STeresa Johnson // Call this function with uninitialized arguments to poison
34*3d4bba30STeresa Johnson // TLS shadow for function parameters before calling operator
35*3d4bba30STeresa Johnson // new and, eventually, user-provided hook.
allocate(int * unused1,int * unused2)36*3d4bba30STeresa Johnson __attribute__((noinline)) void allocate(int *unused1, int *unused2) {
37*3d4bba30STeresa Johnson x = new int;
38*3d4bba30STeresa Johnson }
39*3d4bba30STeresa Johnson
main()40*3d4bba30STeresa Johnson int main() {
41*3d4bba30STeresa Johnson __sanitizer_install_malloc_and_free_hooks(MallocHook1, FreeHook1);
42*3d4bba30STeresa Johnson __sanitizer_install_malloc_and_free_hooks(MallocHook2, FreeHook2);
43*3d4bba30STeresa Johnson int *undef1, *undef2;
44*3d4bba30STeresa Johnson allocate(undef1, undef2);
45*3d4bba30STeresa Johnson // CHECK: MallocHook
46*3d4bba30STeresa Johnson // CHECK: MH1
47*3d4bba30STeresa Johnson // CHECK: MH2
48*3d4bba30STeresa Johnson // Check that malloc hook was called with correct argument.
49*3d4bba30STeresa Johnson if (global_ptr != (void *)x) {
50*3d4bba30STeresa Johnson _exit(1);
51*3d4bba30STeresa Johnson }
52*3d4bba30STeresa Johnson *x = 0;
53*3d4bba30STeresa Johnson delete x;
54*3d4bba30STeresa Johnson // CHECK: FreeHook
55*3d4bba30STeresa Johnson // CHECK: FH1
56*3d4bba30STeresa Johnson // CHECK: FH2
57*3d4bba30STeresa Johnson return 0;
58*3d4bba30STeresa Johnson }
59