1*673dc3d4SNico Weber // Check that the stack trace debugging API works and returns correct
2*673dc3d4SNico Weber // malloc and free stacks.
3*673dc3d4SNico Weber // RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
4*673dc3d4SNico Weber
5*673dc3d4SNico Weber // FIXME: Figure out why allocation/free stack traces may be too short on ARM.
6*673dc3d4SNico Weber // REQUIRES: stable-runtime
7*673dc3d4SNico Weber
8*673dc3d4SNico Weber #if _WIN64
9*673dc3d4SNico Weber #define PTR "%llx"
10*673dc3d4SNico Weber #else
11*673dc3d4SNico Weber #define PTR "%lx"
12*673dc3d4SNico Weber #endif
13*673dc3d4SNico Weber
14*673dc3d4SNico Weber #include <sanitizer/asan_interface.h>
15*673dc3d4SNico Weber #include <stdio.h>
16*673dc3d4SNico Weber #include <stdlib.h>
17*673dc3d4SNico Weber
18*673dc3d4SNico Weber char *mem;
func1()19*673dc3d4SNico Weber void func1() {
20*673dc3d4SNico Weber mem = (char *)malloc(10);
21*673dc3d4SNico Weber }
22*673dc3d4SNico Weber
func2()23*673dc3d4SNico Weber void func2() {
24*673dc3d4SNico Weber free(mem);
25*673dc3d4SNico Weber }
26*673dc3d4SNico Weber
main()27*673dc3d4SNico Weber int main() {
28*673dc3d4SNico Weber // Disable stderr buffering. Needed on Windows.
29*673dc3d4SNico Weber setvbuf(stderr, NULL, _IONBF, 0);
30*673dc3d4SNico Weber
31*673dc3d4SNico Weber func1();
32*673dc3d4SNico Weber func2();
33*673dc3d4SNico Weber
34*673dc3d4SNico Weber void *trace[100];
35*673dc3d4SNico Weber size_t num_frames = 100;
36*673dc3d4SNico Weber int thread_id;
37*673dc3d4SNico Weber num_frames = __asan_get_alloc_stack(mem, trace, num_frames, &thread_id);
38*673dc3d4SNico Weber
39*673dc3d4SNico Weber fprintf(stderr, "alloc stack retval %s\n", (num_frames > 0 && num_frames < 10)
40*673dc3d4SNico Weber ? "ok" : "");
41*673dc3d4SNico Weber // CHECK: alloc stack retval ok
42*673dc3d4SNico Weber fprintf(stderr, "thread id = %d\n", thread_id);
43*673dc3d4SNico Weber // CHECK: thread id = 0
44*673dc3d4SNico Weber fprintf(stderr, "0x" PTR "\n", trace[0]);
45*673dc3d4SNico Weber // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
46*673dc3d4SNico Weber fprintf(stderr, "0x" PTR "\n", trace[1]);
47*673dc3d4SNico Weber // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]
48*673dc3d4SNico Weber
49*673dc3d4SNico Weber num_frames = 100;
50*673dc3d4SNico Weber num_frames = __asan_get_free_stack(mem, trace, num_frames, &thread_id);
51*673dc3d4SNico Weber
52*673dc3d4SNico Weber fprintf(stderr, "free stack retval %s\n", (num_frames > 0 && num_frames < 10)
53*673dc3d4SNico Weber ? "ok" : "");
54*673dc3d4SNico Weber // CHECK: free stack retval ok
55*673dc3d4SNico Weber fprintf(stderr, "thread id = %d\n", thread_id);
56*673dc3d4SNico Weber // CHECK: thread id = 0
57*673dc3d4SNico Weber fprintf(stderr, "0x" PTR "\n", trace[0]);
58*673dc3d4SNico Weber // CHECK: [[FREE_FRAME_0:0x[0-9a-f]+]]
59*673dc3d4SNico Weber fprintf(stderr, "0x" PTR "\n", trace[1]);
60*673dc3d4SNico Weber // CHECK: [[FREE_FRAME_1:0x[0-9a-f]+]]
61*673dc3d4SNico Weber
62*673dc3d4SNico Weber mem[0] = 'A'; // BOOM
63*673dc3d4SNico Weber
64*673dc3d4SNico Weber // CHECK: ERROR: AddressSanitizer: heap-use-after-free
65*673dc3d4SNico Weber // CHECK: WRITE of size 1 at 0x{{.*}}
66*673dc3d4SNico Weber // CHECK: freed by thread T0 here:
67*673dc3d4SNico Weber // CHECK: #0 [[FREE_FRAME_0]]
68*673dc3d4SNico Weber // CHECK: #1 [[FREE_FRAME_1]]
69*673dc3d4SNico Weber // CHECK: previously allocated by thread T0 here:
70*673dc3d4SNico Weber // CHECK: #0 [[ALLOC_FRAME_0]]
71*673dc3d4SNico Weber // CHECK: #1 [[ALLOC_FRAME_1]]
72*673dc3d4SNico Weber
73*673dc3d4SNico Weber return 0;
74*673dc3d4SNico Weber }
75