xref: /aosp_15_r20/external/mesa3d/src/util/tests/u_debug_stack_test.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2020 Google, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include <stdio.h>
25 #include <gtest/gtest.h>
26 
27 #include "util/macros.h"
28 #include "util/u_debug_stack.h"
29 
30 static void ATTRIBUTE_NOINLINE
func_a(void)31 func_a(void)
32 {
33    struct debug_stack_frame backtrace[16];
34 
35    fprintf(stderr, "--- backtrace from func_a:\n");
36    debug_backtrace_capture(backtrace, 0, 16);
37    debug_backtrace_dump(backtrace, 16);
38 }
39 
40 static void ATTRIBUTE_NOINLINE
func_b(void)41 func_b(void)
42 {
43    struct debug_stack_frame backtrace[16];
44 
45    func_a();
46 
47    fprintf(stderr, "--- backtrace from func_b:\n");
48    debug_backtrace_capture(backtrace, 0, 16);
49    debug_backtrace_dump(backtrace, 16);
50 }
51 
52 /* This function must emit a stack frame for the unit test to work */
53 static void ATTRIBUTE_NOINLINE ATTRIBUTE_OPTIMIZE("no-omit-frame-pointer")
func_c(struct debug_stack_frame * frames)54 func_c(struct debug_stack_frame *frames)
55 {
56    debug_backtrace_capture(frames, 0, 16);
57 }
58 
TEST(u_debug_stack_test,basics)59 TEST(u_debug_stack_test, basics)
60 {
61    struct debug_stack_frame backtrace[16];
62    struct debug_stack_frame stored_backtrace[16];
63 
64    func_c(stored_backtrace);
65 
66    fprintf(stderr, "--- backtrace from main to stderr:\n");
67    debug_backtrace_capture(backtrace, 0, 16);
68    debug_backtrace_print(stderr, backtrace, 16);
69 
70    fprintf(stderr, "--- backtrace from main again to debug_printf:\n");
71    debug_backtrace_capture(backtrace, 0, 16);
72    debug_backtrace_dump(backtrace, 16);
73 
74    func_a();
75 
76    func_b();
77 
78    fprintf(stderr, "--- stored backtrace from start of main:\n");
79    debug_backtrace_dump(stored_backtrace, 16);
80 }
81 
82 #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
83 
TEST(u_debug_stack_test,capture_not_overwritten)84 TEST(u_debug_stack_test, capture_not_overwritten)
85 {
86    struct debug_stack_frame backtrace1[16], backtrace2[16];
87 
88    FILE *fp;
89    char *bt1, *bt2;
90    size_t size;
91 
92    /* Old android implementation uses one global capture per thread. Test that
93     * we can store multiple captures and that they decode to different
94     * backtraces.
95     */
96 
97    func_c(backtrace1);
98    debug_backtrace_capture(backtrace2, 0, 16);
99 
100    fp = open_memstream(&bt1, &size);
101    debug_backtrace_print(fp, backtrace1, 16);
102    fclose(fp);
103 
104    fp = open_memstream(&bt2, &size);
105    debug_backtrace_print(fp, backtrace2, 16);
106    fclose(fp);
107 
108    if (size > 0) {
109       EXPECT_STRNE(bt1, bt2);
110    }
111 
112    free(bt1);
113    free(bt2);
114 }
115 
116 #endif
117