Fix C++ template function matching in cooked index
[binutils-gdb.git] / gdb / testsuite / gdb.base / inline-frame-cycle-unwind.exp
blob45086f69a39d3d78152adc083b24b311af7af680
1 # Copyright (C) 2021-2024 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 # This test checks for an edge case when unwinding inline frames which
17 # occur towards the older end of the stack when the stack ends with a
18 # cycle.  Consider this well formed stack:
20 #   main -> normal_frame -> inline_frame
22 # Now consider that, for whatever reason, the stack unwinding of
23 # "normal_frame" becomes corrupted, such that the stack appears to be
24 # this:
26 #   .-> normal_frame -> inline_frame
27 #   |      |
28 #   '------'
30 # When confronted with such a situation we would expect GDB to detect
31 # the stack frame cycle and terminate the backtrace at the first
32 # instance of "normal_frame" with a message:
34 #   Backtrace stopped: previous frame identical to this frame (corrupt stack?)
36 # However, at one point there was a bug in GDB's inline frame
37 # mechanism such that the fact that "inline_frame" was inlined into
38 # "normal_frame" would cause GDB to trigger an assertion.
40 # This test makes use of a Python unwinder which can fake the cyclic
41 # stack cycle, further the test sets up multiple levels of normal and
42 # inline frames.  At the point of testing the stack looks like this:
44 #   main -> normal_func -> inline_func -> normal_func -> inline_func -> normal_func -> inline_func
46 # Where "normal_func" is a normal frame, and "inline_func" is an inline frame.
48 # The python unwinder is then used to force a stack cycle at each
49 # "normal_func" frame in turn, we then check that GDB can successfully unwind
50 # the stack.
52 standard_testfile
54 require allow_python_tests
56 if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
57     return -1
60 if {![runto_main]} {
61     return 0
64 set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
66 # Run to the breakpoint where we will carry out the test.
67 gdb_breakpoint [gdb_get_line_number "Break here"]
68 gdb_continue_to_breakpoint "stop at test breakpoint"
70 # Load the script containing the unwinder, this must be done at the
71 # testing point as the script will examine the stack as it is loaded.
72 gdb_test_no_output "source ${pyfile}"\
73     "import python scripts"
75 # Check the unbroken stack.
76 gdb_test_sequence "bt" "backtrace when the unwind is left unbroken" {
77     "\\r\\n#0 \[^\r\n\]* inline_func \\(\\) at "
78     "\\r\\n#1 \[^\r\n\]* normal_func \\(\\) at "
79     "\\r\\n#2 \[^\r\n\]* inline_func \\(\\) at "
80     "\\r\\n#3 \[^\r\n\]* normal_func \\(\\) at "
81     "\\r\\n#4 \[^\r\n\]* inline_func \\(\\) at "
82     "\\r\\n#5 \[^\r\n\]* normal_func \\(\\) at "
83     "\\r\\n#6 \[^\r\n\]* main \\(\\) at "
86 with_test_prefix "cycle at level 5" {
87     # Arrange to introduce a stack cycle at frame 5.
88     gdb_test_no_output "python stop_at_level=5"
89     gdb_test "maint flush register-cache" \
90         "Register cache flushed\\."
91     gdb_test_lines "bt" "backtrace when the unwind is broken at frame 5" \
92         [multi_line \
93              "#0 \[^\r\n\]* inline_func \\(\\) at \[^\r\n\]+" \
94              "#1 \[^\r\n\]* normal_func \\(\\) at \[^\r\n\]+" \
95              "#2 \[^\r\n\]* inline_func \\(\\) at \[^\r\n\]+" \
96              "#3 \[^\r\n\]* normal_func \\(\\) at \[^\r\n\]+" \
97              "#4 \[^\r\n\]* inline_func \\(\\) at \[^\r\n\]+" \
98              "#5 \[^\r\n\]* normal_func \\(\\) at \[^\r\n\]+" \
99              "Backtrace stopped: previous frame identical to this frame \\(corrupt stack\\?\\)"]
102 with_test_prefix "cycle at level 3" {
103     # Arrange to introduce a stack cycle at frame 3.
104     gdb_test_no_output "python stop_at_level=3"
105     gdb_test "maint flush register-cache" \
106         "Register cache flushed\\."
107     gdb_test_lines "bt" "backtrace when the unwind is broken at frame 3" \
108         [multi_line \
109              "#0 \[^\r\n\]* inline_func \\(\\) at \[^\r\n\]+" \
110              "#1 \[^\r\n\]* normal_func \\(\\) at \[^\r\n\]+" \
111              "#2 \[^\r\n\]* inline_func \\(\\) at \[^\r\n\]+" \
112              "#3 \[^\r\n\]* normal_func \\(\\) at \[^\r\n\]+" \
113              "Backtrace stopped: previous frame identical to this frame \\(corrupt stack\\?\\)"]
116 with_test_prefix "cycle at level 1" {
117     # Arrange to introduce a stack cycle at frame 1.
118     gdb_test_no_output "python stop_at_level=1"
119     gdb_test "maint flush register-cache" \
120         "Register cache flushed\\."
121     gdb_test_lines "bt" "backtrace when the unwind is broken at frame 1" \
122         [multi_line \
123              "#0 \[^\r\n\]* inline_func \\(\\) at \[^\r\n\]+" \
124              "#1 \[^\r\n\]* normal_func \\(\\) at \[^\r\n\]+" \
125              "Backtrace stopped: previous frame identical to this frame \\(corrupt stack\\?\\)"]
128 # Flush the register cache (which also flushes the frame cache) so we
129 # get a full backtrace again, then switch on frame debugging and try
130 # to back trace.  At one point this triggered an assertion.
131 gdb_test "maint flush register-cache" \
132     "Register cache flushed\\." ""
133 gdb_test_no_output "set debug frame 1"
134 set ok 1
135 gdb_test_multiple "bt" "backtrace with debugging on" {
136     -re "^$gdb_prompt $" {
137         gdb_assert { $ok } $gdb_test_name
138     }
139     -re "Python Exception <class 'gdb.error'>: \[^\r\n\]*\r\n" {
140         set ok 0
141         exp_continue
142     }
143     -re "\[^\r\n\]+\r\n" {
144         exp_continue
145     }
147 gdb_test "p 1 + 2 + 3" " = 6" \
148     "ensure GDB is still alive"