Add translations for various sub-directories
[binutils-gdb.git] / gdb / testsuite / gdb.dwarf2 / dw2-ranges-func.exp
blobc952e82b335ec9078e77733146c36aea47d30edb
1 # Copyright 2018-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/>.
15 load_lib dwarf.exp
17 # Test DW_AT_ranges in the context of a subprogram scope.
19 # This test can only be run on targets which support DWARF-2 and use gas.
20 require dwarf2_support
22 require is_c_compiler_gcc
24 proc do_test {suffix} {
25     global gdb_test_file_name
26     global testfile binfile srcfile srcfile2 gdb_prompt hex
28     # Don't use standard_testfile; we want different binaries for
29     # each suffix.
30     set testfile $gdb_test_file_name-$suffix
31     set binfile [standard_output_file ${testfile}]
32     set srcfile $testfile.c
33     set srcfile2 $testfile-dw2.S
35     # We need to know the size of integer and address types in order to
36     # write some of the debugging info we'd like to generate.
37     #
38     # For that, we ask GDB by debugging our test program.  Any program
39     # would do, but since we already have it specifically for this
40     # testcase, might as well use that.
42     if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
43         return -1
44     }
46     set asm_file [standard_output_file $srcfile2]
47     Dwarf::assemble $asm_file {
48         global srcdir subdir srcfile srcfile2
49         declare_labels integer_label volatile_label func_ranges_label cu_ranges_label L
50         set int_size [get_sizeof "int" 4]
52         # Find start address and length for our functions.
53         lassign [function_range main [list ${srcdir}/${subdir}/$srcfile]] \
54             main_start main_len
55         set main_end "$main_start + $main_len"
56         lassign [function_range foo [list ${srcdir}/${subdir}/$srcfile]] \
57             foo_start foo_len
58         set foo_end "$foo_start + $foo_len"
59         lassign [function_range foo_cold [list ${srcdir}/${subdir}/$srcfile]] \
60             foo_cold_start foo_cold_len
61         set foo_cold_end "$foo_cold_start + $foo_cold_len"
62         lassign [function_range bar [list ${srcdir}/${subdir}/$srcfile]] \
63             bar_start bar_len
64         set bar_end "$bar_start + $bar_len"
65         lassign [function_range baz [list ${srcdir}/${subdir}/$srcfile]] \
66             baz_start baz_len
67         set baz_end "$baz_start + $baz_len"
69         set e_var [gdb_target_symbol e]
71         cu {} {
72             compile_unit {
73                 {language @DW_LANG_C}
74                 {name dw-ranges-func2.c}
75                 {stmt_list $L DW_FORM_sec_offset}
76                 {low_pc 0 addr}
77                 {ranges ${cu_ranges_label} DW_FORM_sec_offset}
78             } {
79                 integer_label: DW_TAG_base_type {
80                     {DW_AT_byte_size $int_size DW_FORM_sdata}
81                     {DW_AT_encoding  @DW_ATE_signed}
82                     {DW_AT_name      integer}
83                 }
84                 volatile_label: DW_TAG_volatile_type {
85                     {type :$integer_label}
86                 }
87                 DW_TAG_variable {
88                     {name e}
89                     {external 1 flag}
90                     {type :$volatile_label}
91                     {location {addr $e_var} SPECIAL_expr}
92                 }
93                 subprogram {
94                     {external 1 flag}
95                     {name main}
96                     {DW_AT_type :$integer_label}
97                     {low_pc $main_start addr}
98                     {high_pc $main_len DW_FORM_data4}
99                 }
100                 subprogram {
101                     {external 1 flag}
102                     {name foo}
103                     {ranges ${func_ranges_label} DW_FORM_sec_offset}
104                 }
105                 subprogram {
106                     {external 1 flag}
107                     {name bar}
108                     {low_pc $bar_start addr}
109                     {high_pc $bar_len DW_FORM_data4}
110                 }
111                 subprogram {
112                     {external 1 flag}
113                     {name baz}
114                     {low_pc $baz_start addr}
115                     {high_pc $baz_len DW_FORM_data4}
116                 }
117             }
118         }
120         lines {version 2} L {
121             include_dir "${srcdir}/${subdir}"
122             file_name "$srcfile" 1
124             # Generate a line table program.  An attempt was made to make it
125             # reasonably accurate as it made debugging the test case easier.
126             program {
127                 DW_LNE_set_address $main_start
128                 line [gdb_get_line_number "main prologue"]
129                 DW_LNS_copy
130                 DW_LNE_set_address main_label
131                 line [gdb_get_line_number "main foo call"]
132                 DW_LNS_copy
133                 DW_LNE_set_address main_label2
134                 line [gdb_get_line_number "main return"]
135                 DW_LNS_copy
137                 DW_LNE_set_address $main_end
138                 DW_LNE_end_sequence
140                 DW_LNE_set_address $foo_start
141                 line [gdb_get_line_number "foo prologue"]
142                 DW_LNS_copy
143                 DW_LNE_set_address foo_label
144                 line [gdb_get_line_number "foo bar call"]
145                 DW_LNS_copy
146                 DW_LNE_set_address foo_label2
147                 line [gdb_get_line_number "foo foo_cold call"]
148                 DW_LNS_copy
149                 DW_LNE_set_address foo_label3
150                 line [gdb_get_line_number "foo end"]
151                 DW_LNS_copy
153                 DW_LNE_set_address $foo_end
154                 DW_LNE_end_sequence
156                 DW_LNE_set_address $bar_start
157                 line [gdb_get_line_number "bar end"]
158                 DW_LNS_copy
160                 DW_LNS_advance_pc $bar_len
161                 DW_LNE_end_sequence
163                 DW_LNE_set_address $baz_start
164                 line [gdb_get_line_number "baz end"]
165                 DW_LNS_copy
167                 DW_LNS_advance_pc $baz_len
168                 DW_LNE_end_sequence
170                 DW_LNE_set_address $foo_cold_start
171                 line [gdb_get_line_number "foo_cold prologue"]
172                 DW_LNS_copy
173                 DW_LNE_set_address foo_cold_label
174                 line [gdb_get_line_number "foo_cold baz call"]
175                 DW_LNS_copy
176                 DW_LNE_set_address foo_cold_label2
177                 line [gdb_get_line_number "foo_cold end"]
178                 DW_LNS_copy
180                 DW_LNE_set_address $foo_cold_end
181                 DW_LNE_end_sequence
182             }
183         }
185         # Generate ranges data.
186         ranges {is_64 [is_64_target]} {
187             func_ranges_label: sequence {
188                 range $foo_start $foo_end
189                 range $foo_cold_start $foo_cold_end
190             }
191             cu_ranges_label: sequence {
192                 range $foo_start $foo_end
193                 range $foo_cold_start $foo_cold_end
194                 range $main_start $main_end
195                 range $bar_start $bar_end
196                 range $baz_start $baz_end
197             }
198         }
199     }
201     if { [prepare_for_testing "failed to prepare" ${testfile} \
202               [list $srcfile $asm_file] {nodebug}] } {
203         return -1
204     }
206     if ![runto_main] {
207         return -1
208     }
210     set main_prologue_line_num [gdb_get_line_number "main prologue"]
211     # Do a sanity check to make sure that line number info is available.
212     gdb_test "info line main" \
213         "Line ${main_prologue_line_num} of .* starts at address .* and ends at .*"
215     with_test_prefix "step-test-1" {
216         set bp_foo_bar [gdb_get_line_number "foo bar call"]
218         gdb_test "break $bp_foo_bar" \
219             "Breakpoint.*at.* file .*$srcfile, line $bp_foo_bar\\." \
220             "break at call to bar"
222         gdb_test "continue" \
223             "Continuing\\..*Breakpoint \[0-9\]+, foo \\(\\).*$bp_foo_bar\\s+bar\\s\\(\\);.*foo bar call.*" \
224             "continue to call of bar"
226         gdb_test "step" \
227             "bar \\(\\).*bar end.*" \
228             "step into bar"
230         gdb_test "step" \
231             "foo \\(\\).*foo foo_cold call.*" \
232             "step out of bar, back into foo"
233     }
235     with_test_prefix "step-test-2" {
236         clean_restart ${testfile}
237         if ![runto_main] {
238             return -1
239         }
241         # Note that the RE used for the following test will fail when the
242         # breakpoint has been set on multiple locations. E.g. "(2 locations)". 
243         # This is intentional since that behavior is one of the bugs that
244         # this test case tests for.
245         gdb_test "break foo" \
246             "Breakpoint.*at.* file .*$srcfile, line \\d+\\."
248         # Continue to foo.  Allow execution to stop either on the prologue
249         # or on the call to bar since either behavior is acceptable though
250         # the latter is preferred.
251         set test "continue to foo"
252         gdb_test_multiple "continue" $test {
253             -re "Breakpoint \\d+, foo \\(\\).*foo prologue.*${gdb_prompt}" {
254                 pass $test
255                 gdb_test "step" \
256                          "foo bar call .*" \
257                          "step to call of bar after landing on prologue"
258             }
259             -re "Breakpoint \\d+, foo \\(\\).*foo bar call.*${gdb_prompt}" {
260                 pass $test
261             }
262         }
264         gdb_test "step" \
265             "bar \\(\\).*bar end.*" \
266             "step into bar"
268         gdb_test "step" \
269             "foo \\(\\).*foo foo_cold call.*" \
270             "step out of bar, back into foo"
271     }
273     clean_restart ${testfile}
274     if ![runto_main] {
275         return -1
276     }
278     # Disassembly of foo should have multiple address ranges.
279     gdb_test_sequence "disassemble foo" "" [list \
280         "Dump of assembler code for function foo:" \
281         "Address range $hex to $hex:" \
282         "   $hex <\\+0>:" \
283         "Address range $hex to $hex:" \
284         "   $hex <(.+?)>:" \
285         "End of assembler dump\\." \
286     ]
288     set foo_cold_addr -1
289     set test "x/i foo_cold"
290     gdb_test_multiple $test $test {
291         -re "   ($hex) <foo.*?>.*${gdb_prompt}" {
292             set foo_cold_addr $expect_out(1,string)
293             pass $test
294         }
295     }
297     set foo_addr -1
298     set test "x/i foo"
299     gdb_test_multiple $test $test {
300         -re "   ($hex) <foo.*?>.*${gdb_prompt}" {
301             set foo_addr $expect_out(1,string)
302             pass $test
303         }
304     }
306     gdb_assert {$foo_cold_addr != $foo_addr} "foo and foo_cold are at different addresses"
308     # This more permissive RE for "break foo" will allow a breakpoint on
309     # multiple locations to PASS.  */
310     gdb_test "break foo" \
311         "Breakpoint.*at.*"
313     gdb_test "break baz" \
314         "Breakpoint.*at.* file .*$srcfile, line \\d+\\."
316     gdb_test "continue" \
317         "Breakpoint \\d+, foo \\(\\).*" \
318         "continue to foo"
320     gdb_test_no_output "set variable e=1"
322     # If GDB incorrectly places the foo breakpoint on multiple locations,
323     # then GDB will (incorrectly) stop in foo_cold instead of in baz.
324     gdb_test "continue" \
325         "Breakpoint \\d+, (?:$hex in )?baz \\(\\).*" \
326         "continue to baz"
328     with_test_prefix "no-cold-names" {
330         # Due to the calling sequence, this backtrace would normally
331         # show function foo_cold for frame #1.  However, we don't want
332         # this to be the case due to placing it in the same block
333         # (albeit at a different range) as foo.  Thus it is correct to
334         # see foo for frames #1 and #2.  It is incorrect to see
335         # foo_cold at frame #1.
336         gdb_test_sequence "bt" "backtrace from baz" {
337             "\[\r\n\]#0 .*? baz \\(\\) "
338             "\[\r\n\]#1 .*? foo \\(\\) "
339             "\[\r\n\]#2 .*? foo \\(\\) "
340             "\[\r\n\]#3 .*? main \\(\\) "
341         }
343         # Doing x/2i foo_cold should show foo_cold as the first symbolic
344         # address and an offset from foo for the second.  We also check to
345         # make sure that the offset is not too large - we don't GDB to
346         # display really large offsets that would (try to) wrap around the
347         # address space.
348         set foo_cold_offset 0
349         set test "x/2i foo_cold"
350         gdb_test_multiple $test $test {
351             -re "   (?:$hex) <foo_cold>.*?\n   (?:$hex) <foo\[+-\](\[0-9\]+)>.*${gdb_prompt}" {
352                 set foo_cold_offset $expect_out(1,string)
353                 pass $test
354             }
355         }
356         gdb_assert {$foo_cold_offset <= 10000} "offset to foo_cold is not too large"
358         # Likewise, verify that second address shown by "info line" is at
359         # and offset from foo instead of foo_cold.
360         gdb_test "info line *foo_cold" "starts at address $hex <foo_cold> and ends at $hex <foo\[+-\].*?>.*"
362     }
364     with_test_prefix "step-test-3" {
365         clean_restart ${testfile}
366         if ![runto_main] {
367             return -1
368         }
370         gdb_test "step" \
371                  "foo \\(\\).*bar \\(\\);.*foo bar call.*" \
372                  "step into foo from main"
374         gdb_test "step" \
375                  "bar \\(\\).*\}.* bar end.*" \
376                  "step into bar from foo"
378         gdb_test "step" \
379                  "foo(_label2)? \\(\\).*foo_cold \\(\\);.*foo foo_cold call.*" \
380                  "step out of bar to foo"
382         # Tests in the "enable_foo_cold_stepping" section, below, did
383         # not work prior to July, 2019.  They had been disabled via
384         # use of the "enable_foo_cold_stepping" flag.
385         # 
386         # As noted elsewhere, this test case causes foo_cold,
387         # originally a separate function invoked via a subroutine
388         # call, to be considered as part of foo via use of
389         # DW_AT_ranges.  Real code that I've looked at uses a branch
390         # instruction to cause code in the "cold" range to be
391         # executed.  These tests used to fail which is why they were
392         # disabled.
393         #
394         # After adding a "hi" cold test, I found that we were able to
395         # step into foo_cold from foo for the "hi" version, but for
396         # the "lo" version, GDB would run to either the next
397         # breakpoint or until the inferior exited when there were no
398         # breakpoints.  Not being able to step is definitely a bug
399         # even if it's unlikely that this problem would ever be hit in
400         # a real program.  Therefore, the bug was fixed in GDB and
401         # these tests are now enabled.
402         #
403         # I've left in place the flag (and test) which may be used to
404         # disable these tests.
406         set enable_foo_cold_stepping true
408         if { $enable_foo_cold_stepping } {
409             gdb_test_no_output "set variable e=1"
411             set test "step into foo_cold from foo"
412             gdb_test_multiple "step" $test {
413                 -re "foo(_low)? \\(\\).*\{.*foo_cold prologue.*${gdb_prompt}" {
414                     pass $test
415                     gdb_test "step" \
416                              "foo \\(\\).*baz \\(\\);.*foo_cold baz call.*" \
417                              "step to baz call in foo_cold"
419                 }
420                 -re "foo(_cold)? \\(\\).*baz \\(\\);.*foo_cold baz call.*${gdb_prompt}" {
421                     pass $test
422                 }
423             }
425             gdb_test "step" \
426                      "baz \\(\\).*\}.*baz end.*" \
427                      "step into baz from foo_cold"
429             gdb_test "step" \
430                      "foo(?:_low(?:_label2)?)? \\(\\).*\}.*foo_cold end.*" \
431                      "step out of baz to foo_cold"
433             gdb_test "step" \
434                      "foo(?:_label3)? \\(\\).*\}.*foo end.*" \
435                      "step out of foo_cold to foo"
436         } else {
437             gdb_test "next" \
438                      ".*foo end.*" \
439                      "next over foo_cold call"
440         }
442         gdb_test "step" \
443                  "main(?:_label2)? \\(\\).*" \
444                  "step out of foo to main"
445     }
448 # foreach_with_prefix could be used here, but the log file output is somewhat
449 # less verbose when using an explicit "with_test_prefix".
451 foreach test_suffix { "lo-cold" "hi-cold" } {
452     with_test_prefix $test_suffix {
453         do_test $test_suffix
454     }