Fix C++ template function matching in cooked index
[binutils-gdb.git] / gdb / testsuite / gdb.gdb / python-helper.exp
blobd136d687dacae51b2b87c61f379bd69329b59f1e
1 # Copyright 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 exercises the gdb-gdb.py helper script that is generated
17 # into the GDB build directory.  This script is intended for use by
18 # developers to make debugging GDB easier.
20 load_lib selftest-support.exp
22 require {!target_info exists gdb,noinferiorio}
24 require allow_python_tests
26 standard_testfile .cc
28 if { [build_executable "failed to build" $testfile $srcfile {debug c++}] } {
29     return -1
32 # Find the helper script in the GDB build directory.
33 set py_helper_script [file dirname $GDB]/gdb-gdb.py
34 if { ![file readable $py_helper_script] \
35          || [file type $py_helper_script] != "file" } {
36     untested "failed to find gdb-gdb.py helper script"
37     return
40 # The main test.  This is called by the self-test framework once GDB
41 # has been started on a copy of itself.
42 proc test_python_helper {} {
43     global py_helper_script decimal hex gdb_prompt bkptno_numopt_re
44     global inferior_spawn_id
46     # Source the python helper script.  This script registers the
47     # pretty printer for the object file called 'gdb', however, in our
48     # selftests we rename 'gdb' to 'xgdb', so the pretty printer
49     # doesn't get registered by default.
50     #
51     # So, after sourcing the script we do our own objfile scan and
52     # register the pretty printer for the objfile called 'xgdb'.
53     gdb_test_no_output "source $py_helper_script" \
54         "source gdb-gdb.py helper script"
55     gdb_test [multi_line_input \
56                   "python" \
57                   "for objfile in gdb.objfiles():" \
58                   "  if os.path.basename(objfile.filename) == \"xgdb\":" \
59                   "    objfile.pretty_printers.append(type_lookup_function)" \
60                   "end"] ".*" \
61         "register the type pretty printer"
63     # Now place breakpoints somewhere useful.  These locations can be
64     # any function that:
65     #
66     # (a) is easy to reach by issuing a simple gdb command, and
67     # (b) is unlikely to be modified very often within gdb, and
68     # (c) has a parameter that is either a 'struct type *' or a 'struct value *'.
69     gdb_breakpoint value_print qualified
70     gdb_breakpoint c_print_type qualified
72     # With gdb build with -O2 -flto=auto and gcc 7.5.0, we can get the mangled
73     # names due to a problem in the debug info, so we work around this by less
74     # strict matching.
75     set fn_name_value_print "\[^\r\n\]*value_print\[^\r\n\]*"
76     set fn_name_c_print_type "\[^\r\n\]*c_print_type\[^\r\n\]*"
78     # Disable all breakpoints until after we have loaded the test
79     # binary into the inner GDB.
80     gdb_test_no_output "disable breakpoints"
82     set outer_prompt_re "\\(outer-gdb\\) $"
84     # Adjust the prompt on the outer gdb, this just makes things a
85     # little clearer when trying to unpick which GDB is active.
86     gdb_test_no_output -prompt $outer_prompt_re  "set prompt (outer-gdb) " "set outer gdb prompt"
88     # Send a command to the outer GDB to continue the inner GDB.  The
89     # stop is being detected from the inner GDB, hence the use of -i
90     # here.
91     gdb_test_multiple "continue" "start inner gdb" {
92         -re "received signal SIGSEGV.* in GC_.*$outer_prompt_re" {
93             # Some versions of the GC used by Guile cause a SEGV
94             # during stack probing.  Ignore this and carry on.
95             send_gdb "continue\n"
96             exp_continue
97         }
98         -i "$inferior_spawn_id"
99         -re "\r\n$gdb_prompt $" {
100             pass $gdb_test_name
101         }
102     }
104     # Load the test executable into the inner GDB.  The output here is
105     # being read from the inner GDB, hence the use of -i here.
106     send_inferior "file -readnow $::binfile\n"
107     gdb_test_multiple "" "loading test binary into inner GDB" {
108         -i "$inferior_spawn_id"
109         -re "Reading symbols from.*\r\n$gdb_prompt $" {
110             pass $gdb_test_name
111         }
112     }
114     # Add a second inferior, useful to the intrusive_list pretty-printer test
115     # below.
116     send_inferior "add-inferior\n"
117     gdb_test_multiple "" "add second inferior in inner GDB" {
118         -i "$inferior_spawn_id"
119         -re "Added inferior 2\r\n$gdb_prompt $" {
120             pass $gdb_test_name
121         }
122     }
124     # Send Ctrl-C to the inner GDB, this should kick us back to the
125     # prompt of the outer GDB.
126     send_inferior "\003"
127     gdb_test -prompt $outer_prompt_re "" "" "interrupted the inner"
129     # Now enable all breakpoints within the outer GDB.
130     gdb_test_no_output -prompt $outer_prompt_re "enable breakpoints"
132     # We need to resume the inner GDB after interrupting it, this is
133     # done by sending 'continue'.  However, GDB will not redisplay the
134     # prompt in this case, so we have nothing that we can detect in
135     # order to know this continue was successful.  Still, if this
136     # didn't work, then later tests should fail.
137     send_gdb "continue\n"
139     # Control is back with the inner GDB.  Send a command to the inner
140     # GDB, this should result in the outer GDB stopping at one of the
141     # breakpoints we created..
142     send_inferior "print 1\n"
143     gdb_test -prompt $outer_prompt_re "" \
144         "Breakpoint $bkptno_numopt_re, $fn_name_value_print.*" \
145         "hit breakpoint in outer gdb"
147     # Now inspect the type of parameter VAL, this should trigger the
148     # pretty printers.
149     set answer [multi_line \
150                     "${decimal} = " \
151                     "\{pointer_type = 0x0," \
152                     " reference_type = 0x0," \
153                     " chain = 0x0," \
154                     " instance_flags = 0," \
155                     " length = $decimal," \
156                     " main_type = $hex\}"]
157     gdb_test -prompt $outer_prompt_re "print *val->m_type" $answer "pretty print type"
159     set answer [multi_line \
160                     "$decimal = " \
161                     "\{name = $hex \"int\"," \
162                     " code = TYPE_CODE_INT," \
163                     " flags = \[^\r\n\]+," \
164                     " owner = $hex \\(gdbarch\\)," \
165                     " target_type = 0x0," \
166                     " int_stuff = \{ bit_size = $decimal, bit_offset = $decimal \}\}"]
167     gdb_test -prompt $outer_prompt_re "print *val->m_type->main_type" $answer "pretty print type->main_type"
169     # Send the continue to the outer GDB, which resumes the inner GDB,
170     # we then detect the prompt from the inner GDB, hence the use of
171     # -i here.
172     gdb_test_multiple "continue" "resume inner gdb" {
173         -i $inferior_spawn_id
174         -re "\r\n$gdb_prompt $" {
175             pass $gdb_test_name
176         }
177     }
179     # Now print an integer that was created from the DWARF
180     # information, this will include the TYPE_SPECIFIC_INT
181     # information.
182     send_inferior "print global_c.m_val\n"
183     gdb_test -prompt $outer_prompt_re "" \
184         "Breakpoint $bkptno_numopt_re, $fn_name_value_print.*" \
185         "print integer from DWARF info"
187     set answer [multi_line \
188                     "$decimal = " \
189                     "\{name = $hex \"int\"," \
190                     " code = TYPE_CODE_INT," \
191                     " flags = \[^\r\n\]+," \
192                     " owner = $hex \\(objfile\\)," \
193                     " target_type = 0x0," \
194                     " int_stuff = \{ bit_size = $decimal, bit_offset = $decimal \}\}"]
195     gdb_test -prompt $outer_prompt_re "print *val->m_type->main_type" $answer "pretty print type->main_type for DWARF type"
197     # Send the continue to the outer GDB, which resumes the inner GDB,
198     # we then detect the prompt from the inner GDB, hence the use of
199     # -i here.
200     gdb_test_multiple "continue" "resume inner gdb again" {
201         -i $inferior_spawn_id
202         -re "\r\n$gdb_prompt $" {
203             pass $gdb_test_name
204         }
205     }
207     # Send a command to the inner GDB, this should result in the outer
208     # GDB stopping at the value_print breakpoint again.
209     send_inferior "ptype global_c\n"
210     set test "hit breakpoint in outer gdb again"
211     set in_outer_gdb 0
212     gdb_test_multiple "" $test  -prompt $outer_prompt_re {
213         -re -wrap "Breakpoint $bkptno_numopt_re, $fn_name_c_print_type.*" {
214             pass $gdb_test_name
215             set in_outer_gdb 1
216         }
217         -re "\r\n$gdb_prompt $" {
218             unsupported $gdb_test_name
219         }
220     }
222     if { ! $in_outer_gdb } {
223         return 0
224     }
226     set cmd "print *type->main_type"
227     set cmd_supported 1
228     foreach sub_expr { type type->main_type } {
229         set ok 0
230         gdb_test_multiple "print $sub_expr" "" -prompt $outer_prompt_re {
231             -re -wrap " = \\(\[^\r\n\]+ \\*\\) $hex" {
232                 set ok 1
233             }
234             -re -wrap "" {
235             }
236         }
237         if { ! $ok } {
238             set cmd_supported 0
239             break
240         }
241     }
243     if { $cmd_supported } {
244         set answer [multi_line \
245                         "$decimal = " \
246                         "\{name = $hex \"CC\"," \
247                         " code = TYPE_CODE_STRUCT," \
248                         " flags = \[^\r\n\]+," \
249                         " owner = $hex \\(objfile\\)," \
250                         " target_type = 0x0," \
251                         " flds_bnds\\.fields\\\[0\\\]:" \
252                         "  \{m_name = $hex \"m_val\"," \
253                         "   m_type = $hex," \
254                         "   m_loc_kind = FIELD_LOC_KIND_BITPOS," \
255                         "   bitsize = 0," \
256                         "   bitpos = 0\}," \
257                         " cplus_stuff = $hex\}"]
258         gdb_test -prompt $outer_prompt_re $cmd $answer
259     } else {
260         unsupported $cmd
261     }
263     # Test the htab_t pretty-printer.
264     gdb_test -prompt $outer_prompt_re "print varobj_table" \
265         "htab_t with ${::decimal} elements"
267     # Test the intrusive_list pretty-printer.  A bug occurred in the
268     # pretty-printer for lists with more than one element.  Verify that
269     # we see both elements of the inferior_list list being printed.
270     gdb_test -prompt $outer_prompt_re "print inferior_list" "intrusive list of inferior = {.*, num = 1,.*, num = 2,.*}"
272     return 0
275 # Use the self-test framework to run the test.
276 do_self_tests captured_main test_python_helper