Move mkdir_recursive to common/filestuff.c
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.dwarf2 / dw2-ranges-func.exp
CommitLineData
450d1e88
KB
1# Copyright 2018 Free Software Foundation, Inc.
2
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.
7#
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.
12#
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/>.
15load_lib dwarf.exp
16
17# Test DW_AT_ranges in the context of a subprogram scope.
18
19# This test can only be run on targets which support DWARF-2 and use gas.
20if {![dwarf2_support]} {
21 unsupported "dwarf2 support required for this test"
22 return 0
23}
24
25if [get_compiler_info] {
26 return -1
27}
28if !$gcc_compiled {
29 unsupported "gcc required for this test"
30 return 0
31}
32
33standard_testfile dw2-ranges-func.c dw2-ranges-func-dw.S
34
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.
41
42if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
43 return -1
44}
45
46set asm_file [standard_output_file $srcfile2]
47Dwarf::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]
51
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_low [list ${srcdir}/${subdir}/$srcfile]] \
60 foo_low_start foo_low_len
61 set foo_low_end "$foo_low_start + $foo_low_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"
68
69 set e_var [gdb_target_symbol e]
70
71 cu {} {
72 compile_unit {
73 {language @DW_LANG_C}
74 {name dw-ranges-func.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 }
119
120 lines {version 2} L {
121 include_dir "${srcdir}/${subdir}"
122 file_name "$srcfile" 1
123
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 {DW_LNS_advance_line [expr [gdb_get_line_number "main prologue"] - 1]}
129 {DW_LNS_copy}
130 {DW_LNE_set_address main_label}
131 {DW_LNS_advance_line [expr [gdb_get_line_number "main foo call"] - [gdb_get_line_number "main prologue"]]}
132 {DW_LNS_copy}
133 {DW_LNE_set_address main_label2}
134 {DW_LNS_advance_line [expr [gdb_get_line_number "main return"] - [gdb_get_line_number "main foo call"]]}
135 {DW_LNS_copy}
136 {DW_LNE_set_address $main_end}
137 {DW_LNS_advance_line [expr [gdb_get_line_number "main end"] - [gdb_get_line_number "main return"] + 1]}
138 {DW_LNS_copy}
139 {DW_LNE_end_sequence}
140
141 {DW_LNE_set_address $foo_start}
142 {DW_LNS_advance_line [expr [gdb_get_line_number "foo prologue"] - 1] }
143 {DW_LNS_copy}
144 {DW_LNE_set_address foo_label}
145 {DW_LNS_advance_line [expr [gdb_get_line_number "foo bar call"] - [gdb_get_line_number "foo prologue"]]}
146 {DW_LNS_copy}
147 {DW_LNE_set_address foo_label2}
148 {DW_LNS_advance_line [expr [gdb_get_line_number "foo foo_low call"] - [gdb_get_line_number "foo bar call"]]}
149 {DW_LNS_copy}
150 {DW_LNE_set_address foo_label3}
151 {DW_LNS_advance_line [expr [gdb_get_line_number "foo end"] - [gdb_get_line_number "foo foo_low call"]]}
152 {DW_LNS_copy}
153 {DW_LNE_set_address $foo_end}
154 {DW_LNS_advance_line 1}
155 {DW_LNS_copy}
156 {DW_LNE_end_sequence}
157
158 {DW_LNE_set_address $bar_start}
159 {DW_LNS_advance_line [expr [gdb_get_line_number "bar end"] - 1]}
160 {DW_LNS_copy}
161 {DW_LNS_advance_pc $bar_len}
162 {DW_LNS_advance_line 1}
163 {DW_LNS_copy}
164 {DW_LNE_end_sequence}
165
166 {DW_LNE_set_address $baz_start}
167 {DW_LNS_advance_line [expr [gdb_get_line_number "baz end"] - 1]}
168 {DW_LNS_copy}
169 {DW_LNS_advance_pc $baz_len}
170 {DW_LNS_advance_line 1}
171 {DW_LNS_copy}
172 {DW_LNE_end_sequence}
173
174 {DW_LNE_set_address $foo_low_start}
175 {DW_LNS_advance_line [expr [gdb_get_line_number "foo_low prologue"] - 1]}
176 {DW_LNS_copy}
177 {DW_LNE_set_address foo_low_label}
178 {DW_LNS_advance_line [expr [gdb_get_line_number "foo_low baz call"] - [gdb_get_line_number "foo_low prologue"]]}
179 {DW_LNS_copy}
180 {DW_LNE_set_address foo_low_label2}
181 {DW_LNS_advance_line [expr [gdb_get_line_number "foo_low end"] - [gdb_get_line_number "foo_low baz call"]]}
182 {DW_LNS_copy}
183 {DW_LNE_set_address $foo_low_end}
184 {DW_LNS_advance_line 1}
185 {DW_LNS_copy}
186 {DW_LNE_end_sequence}
187 }
188 }
189
190 # Generate ranges data.
191 ranges {is_64 [is_64_target]} {
192 func_ranges_label: sequence {
193 {range {$foo_start } $foo_end}
194 {range {$foo_low_start} $foo_low_end}
195 }
196 cu_ranges_label: sequence {
197 {range {$foo_start } $foo_end}
198 {range {$foo_low_start} $foo_low_end}
199 {range {$main_start} $main_end}
200 {range {$bar_start} $bar_end}
201 {range {$baz_start} $baz_end}
202 }
203 }
204}
205
206if { [prepare_for_testing "failed to prepare" ${testfile} \
207 [list $srcfile $asm_file] {nodebug}] } {
208 return -1
209}
210
211if ![runto_main] {
212 return -1
213}
214
215set main_prologue_line_num [gdb_get_line_number "main prologue"]
216# Do a sanity check to make sure that line number info is available.
217gdb_test "info line main" \
218 "Line ${main_prologue_line_num} of .* starts at address .* and ends at .*"
219
220with_test_prefix "step-test-1" {
221 set bp_foo_bar [gdb_get_line_number "foo bar call"]
222
223 gdb_test "break $bp_foo_bar" \
224 "Breakpoint.*at.* file .*$srcfile, line $bp_foo_bar\\." \
225 "break at call to bar"
226
227 gdb_test "continue" \
228 "Continuing\\..*Breakpoint \[0-9\]+, foo \\(\\).*$bp_foo_bar\\s+bar\\s\\(\\);.*foo bar call.*" \
229 "continue to call of bar"
230
231 gdb_test "step" \
232 "bar \\(\\).*bar end.*" \
233 "step into bar"
234
235 gdb_test "step" \
236 "foo \\(\\).*foo foo_low call.*" \
237 "step out of bar, back into foo"
238}
239
240with_test_prefix "step-test-2" {
241 clean_restart ${testfile}
242 if ![runto_main] {
243 return -1
244 }
245
246 # Note that the RE used for the following test will fail when the
247 # breakpoint has been set on multiple locations. E.g. "(2 locations)".
248 # This is intentional since that behavior is one of the bugs that
249 # this test case tests for.
250 gdb_test "break foo" \
251 "Breakpoint.*at.* file .*$srcfile, line \\d+\\." \
252 "break foo"
253
254 # Continue to foo. Allow execution to stop either on the prologue
255 # or on the call to bar since either behavior is acceptable though
256 # the latter is preferred.
257 set test "continue to foo"
258 gdb_test_multiple "continue" $test {
259 -re "Breakpoint \\d+, foo \\(\\).*foo prologue.*${gdb_prompt}" {
260 pass $test
261 gdb_test "step" \
262 "foo bar call .*" \
263 "step to call of bar after landing on prologue"
264 }
265 -re "Breakpoint \\d+, foo \\(\\).*foo bar call.*${gdb_prompt}" {
266 pass $test
267 }
268 }
269
270 gdb_test "step" \
271 "bar \\(\\).*bar end.*" \
272 "step into bar"
273
274 gdb_test "step" \
275 "foo \\(\\).*foo foo_low call.*" \
276 "step out of bar, back into foo"
277}
278
279clean_restart ${testfile}
280if ![runto_main] {
281 return -1
282}
283
284# Disassembly of foo should have multiple address ranges.
285gdb_test_sequence "disassemble foo" "" [list \
286 "Dump of assembler code for function foo:" \
287 "Address range $hex to $hex:" \
288 " $hex <\\+0>:" \
289 "Address range $hex to $hex:" \
290 " $hex <(.+?)>:" \
291 "End of assembler dump\\." \
292]
293
294set foo_low_addr -1
295set test "x/i foo_low"
296gdb_test_multiple $test $test {
297 -re " ($hex) <foo.*?>.*${gdb_prompt}" {
298 set foo_low_addr $expect_out(1,string)
299 pass $test
300 }
301}
302
303set foo_addr -1
304set test "x/i foo"
305gdb_test_multiple $test $test {
306 -re " ($hex) <foo.*?>.*${gdb_prompt}" {
307 set foo_addr $expect_out(1,string)
308 pass $test
309 }
310}
311
312gdb_assert {$foo_low_addr != $foo_addr} "foo and foo_low are at different addresses"
313
314# This more permissive RE for "break foo" will allow a breakpoint on
315# multiple locations to PASS. */
316gdb_test "break foo" \
317 "Breakpoint.*at.*" \
318 "break foo"
319
320gdb_test "break baz" \
321 "Breakpoint.*at.* file .*$srcfile, line \\d+\\."
322
323gdb_test "continue" \
324 "Breakpoint \\d+, foo \\(\\).*" \
325 "continue to foo"
326
327gdb_test_no_output "set variable e=1"
328
329# If GDB incorrectly places the foo breakpoint on multiple locations,
330# then GDB will (incorrectly) stop in foo_low instead of in baz.
331gdb_test "continue" \
332 "Breakpoint \\d+, (?:$hex in )?baz \\(\\).*" \
333 "continue to baz"
334
335with_test_prefix "step-test-3" {
336 clean_restart ${testfile}
337 if ![runto_main] {
338 return -1
339 }
340
341 gdb_test "step" \
342 "foo \\(\\).*bar \\(\\);.*foo bar call.*" \
343 "step into foo from main"
344
345 gdb_test "step" \
346 "bar \\(\\).*\}.* bar end.*" \
347 "step into bar from foo"
348
349 gdb_test "step" \
350 "foo(_label2)? \\(\\).*foo_low \\(\\);.*foo foo_low call.*" \
351 "step out of bar to foo"
352
353 # The tests in the "enable_foo_low_stepping" section, below, work
354 # with some versions of gcc, though it's not clear that they
355 # should. This test case causes foo_low, originally a separate
356 # function invoked via a subroutine call, to be considered as part
357 # of foo via use of DW_AT_ranges. Real code that I've looked at
358 # uses a branch instruction to cause code in the "cold" range to
359 # be executed.
360 #
361 # For the moment though, these tests have been left in place, but
362 # disabled, in case we decide that making such a subroutine call
363 # is a reasonable thing to do that should also be supported by
364 # GDB.
365
366 set enable_foo_low_stepping false
367
368 if { $enable_foo_low_stepping } {
369 gdb_test_no_output "set variable e=1"
370
371 set test "step into foo_low from foo"
372 gdb_test_multiple "step" $test {
373 -re "foo(_low)? \\(\\).*\{.*foo_low prologue.*${gdb_prompt}" {
374 pass $test
375 gdb_test "step" \
376 "foo \\(\\).*baz \\(\\);.*foo_low baz call.*" \
377 "step to baz call in foo_low"
378
379 }
380 -re "foo(_low)? \\(\\).*baz \\(\\);.*foo_low baz call.*${gdb_prompt}" {
381 pass $test
382 }
383 }
384
385 gdb_test "step" \
386 "baz \\(\\).*\}.*baz end.*" \
387 "step into baz from foo_low"
388
389 gdb_test "step" \
390 "foo(?:_low(?:_label2)?)? \\(\\).*\}.*foo_low end.*" \
391 "step out of baz to foo_low"
392
393 gdb_test "step" \
394 "foo(?:_label3)? \\(\\).*\}.*foo end.*" \
395 "step out of foo_low to foo"
396 } else {
397 gdb_test "next" \
398 ".*foo end.*" \
399 "next over foo_low call"
400 }
401
402 gdb_test "step" \
403 "main(?:_label2)? \\(\\).*" \
404 "step out of foo to main"
405}
This page took 0.060118 seconds and 4 git commands to generate.