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