]>
Commit | Line | Data |
---|---|---|
8c95582d AB |
1 | # Copyright 2020 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/>. | |
15 | ||
16 | # This test shows the importance of not corrupting the order of line | |
17 | # table information. When multiple lines are given for the same | |
18 | # address the compiler usually lists these in the order in which we | |
19 | # would expect to encounter them. When stepping through nested inline | |
20 | # frames the last line given for an address is assumed by GDB to be | |
21 | # the most inner frame, and this is what GDB displays. | |
22 | # | |
23 | # If we corrupt the order of the line table entries then GDB will | |
24 | # display the wrong line as being the inner most frame. | |
25 | ||
26 | load_lib dwarf.exp | |
27 | ||
28 | # This test can only be run on targets which support DWARF-2 and use gas. | |
29 | if {![dwarf2_support]} { | |
30 | return 0 | |
31 | } | |
32 | ||
33 | # The .c files use __attribute__. | |
34 | if [get_compiler_info] { | |
35 | return -1 | |
36 | } | |
37 | if !$gcc_compiled { | |
38 | return 0 | |
39 | } | |
40 | ||
41 | standard_testfile dw2-is-stmt.c dw2-is-stmt.S | |
42 | ||
8c95582d AB |
43 | set asm_file [standard_output_file $srcfile2] |
44 | Dwarf::assemble $asm_file { | |
45 | global srcdir subdir srcfile | |
46 | declare_labels lines_label | |
47 | ||
48 | get_func_info main | |
49 | ||
50 | cu {} { | |
51 | compile_unit { | |
52 | {language @DW_LANG_C} | |
53 | {name dw2-is-stmt.c} | |
54 | {low_pc 0 addr} | |
55 | {stmt_list ${lines_label} DW_FORM_sec_offset} | |
56 | } { | |
57 | subprogram { | |
58 | {external 1 flag} | |
59 | {name main} | |
60 | {low_pc $main_start addr} | |
61 | {high_pc "$main_start + $main_len" addr} | |
62 | } {} | |
63 | } | |
64 | } | |
65 | ||
66 | lines {version 2 default_is_stmt 0} lines_label { | |
67 | include_dir "${srcdir}/${subdir}" | |
68 | file_name "$srcfile" 1 | |
69 | ||
70 | program { | |
71 | {DW_LNE_set_address main} | |
72 | {DW_LNS_advance_line \ | |
73 | [expr [gdb_get_line_number "main prologue"] - 1]} | |
74 | {DW_LNS_negate_stmt} | |
75 | {DW_LNS_copy} | |
76 | ||
77 | {DW_LNE_set_address line_label_1} | |
78 | {DW_LNS_advance_line \ | |
79 | [expr [gdb_get_line_number "main, set var to 99"] \ | |
80 | - [gdb_get_line_number "main prologue"]]} | |
81 | {DW_LNS_copy} | |
82 | ||
83 | {DW_LNE_set_address line_label_2} | |
84 | {DW_LNS_advance_line \ | |
85 | [expr [gdb_get_line_number "main, set var to 0"] \ | |
86 | - [gdb_get_line_number "main, set var to 99"]]} | |
87 | {DW_LNS_negate_stmt} | |
88 | {DW_LNS_copy} | |
89 | ||
90 | {DW_LNE_set_address line_label_3} | |
91 | {DW_LNS_negate_stmt} | |
92 | {DW_LNS_copy} | |
93 | ||
94 | {DW_LNE_set_address line_label_4} | |
95 | {DW_LNS_negate_stmt} | |
96 | {DW_LNS_copy} | |
97 | ||
98 | {DW_LNE_set_address line_label_5} | |
99 | {DW_LNS_advance_line \ | |
100 | [expr [gdb_get_line_number "main end"] \ | |
101 | - [gdb_get_line_number "main, set var to 0"]]} | |
102 | {DW_LNS_negate_stmt} | |
103 | {DW_LNS_copy} | |
104 | ||
105 | {DW_LNE_set_address ${main_end}} | |
106 | {DW_LNE_end_sequence} | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | if { [prepare_for_testing "failed to prepare" ${testfile} \ | |
112 | [list $srcfile $asm_file] {nodebug}] } { | |
113 | return -1 | |
114 | } | |
115 | ||
116 | if ![runto_main] { | |
117 | return -1 | |
118 | } | |
119 | ||
120 | # First, break by address at a location we know is marked as not a | |
121 | # statement. GDB should still correctly report the file and line | |
122 | # number. | |
123 | gdb_breakpoint "*line_label_2" | |
124 | gdb_continue_to_breakpoint "*line_label_2" | |
125 | ||
126 | # Now step by instruction. We should skip over the is-stmt location | |
127 | # for this line, and land on the next source line. | |
128 | gdb_test "step" "/\\* main end \\*/" \ | |
129 | "step to end from line_label_2" | |
130 | ||
131 | # Restart the test. This time, stop at a location we know is marked | |
132 | # as a statement. | |
133 | clean_restart ${binfile} | |
134 | runto_main | |
135 | ||
136 | gdb_breakpoint "*line_label_3" | |
137 | gdb_continue_to_breakpoint "*line_label_3" | |
138 | ||
139 | # Now step by instruction. As you would expect we should leave this | |
140 | # line and stop at the next source line. | |
141 | gdb_test "step" "/\\* main end \\*/" \ | |
142 | "step to end from line_label_3" | |
143 | ||
144 | # Restart the test, this time, step through line by line, ensure we | |
145 | # only stop at the places where is-stmt is true. | |
146 | clean_restart ${binfile} | |
147 | runto_main | |
148 | ||
149 | # Get the values of the labels where we expect to stop. | |
150 | set ll1 [get_hexadecimal_valueof "&line_label_1" "INVALID"] | |
151 | set ll2 [get_hexadecimal_valueof "&line_label_2" "INVALID"] | |
152 | set ll3 [get_hexadecimal_valueof "&line_label_3" "INVALID"] | |
153 | set ll5 [get_hexadecimal_valueof "&line_label_5" "INVALID"] | |
154 | ||
155 | # The first stop should be at line_label_1 | |
156 | with_test_prefix "check we're at line_label_1" { | |
157 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC"] | |
158 | gdb_assert { $ll1 == $pc } "check initial \$pc is line_label_1" | |
159 | } | |
160 | ||
161 | # Now step, this should take us to line_label_3 which is the next | |
162 | # location marked as is-stmt. | |
163 | with_test_prefix "step to line_label_3" { | |
164 | gdb_test "step" "/\\* main, set var to 0 \\*/" | |
165 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC"] | |
166 | gdb_assert { $ll3 == $pc } "check initial \$pc is line_label_3" | |
167 | } | |
168 | ||
169 | # A final step should take us to line_label_5. | |
170 | with_test_prefix "step to line_label_5" { | |
171 | gdb_test "step" "/\\* main end \\*/" | |
172 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC"] | |
173 | gdb_assert { $ll5 == $pc } "check initial \$pc" | |
174 | } | |
175 | ||
176 | # Now restart the test, and place a breakpoint by line number. GDB | |
177 | # should select the location that is marked as is-stmt. | |
178 | clean_restart ${binfile} | |
179 | runto_main | |
180 | set linum [gdb_get_line_number "main, set var to 0"] | |
181 | gdb_breakpoint "$srcfile:$linum" | |
182 | gdb_continue_to_breakpoint "Breakpoint on line, set var to 0" | |
183 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC"] | |
184 | gdb_assert { $ll3 == $pc } "check initial \$pc" | |
185 | ||
186 | # Restart the test again, this time we will test stepping by | |
187 | # instruction. | |
188 | clean_restart ${binfile} | |
189 | runto_main | |
190 | ||
191 | # We will be at line_label_1 at this point - we already tested this | |
192 | # above. Now single instruction step forward until we get to | |
193 | # line_label_2. Every instruction before line_label_2 should be | |
194 | # attributed to the 'var = 99' line. For most targets there will only | |
195 | # be a single instruction between line_label_1 and line_label_2, but | |
196 | # we allow for up to 25 (just a random number). | |
197 | ||
198 | set $i 0 | |
199 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC" \ | |
200 | "get pc before stepi loop at line_label_1"] | |
201 | while { $pc < $ll2 } { | |
202 | incr i | |
203 | set line_changed -1 | |
204 | gdb_test_multiple "stepi" "stepi until line_label_2, $i" { | |
205 | -re "main, set var to 99.*$gdb_prompt" { | |
206 | set line_changed 0 | |
207 | } | |
208 | -re "main, set var to 0.*$gdb_prompt " { | |
209 | set line_changed 1 | |
210 | } | |
211 | } | |
212 | gdb_assert { $line_changed != -1 } \ | |
213 | "ensure we saw a valid line pattern, $i" | |
214 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC" \ | |
215 | "get pc inside stepi loop from line_label_1, $i"] | |
216 | if { $ll2 == $pc } { | |
217 | gdb_assert { $line_changed } \ | |
218 | "line must change at line_label_2" | |
219 | } else { | |
220 | gdb_assert { !$line_changed } \ | |
221 | "line should not change until line_label_2, $i" | |
222 | } | |
223 | } | |
224 | ||
225 | # Now single instruction step forward until GDB reports a new source | |
226 | # line, at which point we should be at line_label_5. | |
227 | ||
228 | set $i 0 | |
229 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC" \ | |
230 | "get pc before stepi loop at line_label_2"] | |
231 | while { $pc < $ll5 } { | |
232 | incr i | |
233 | set line_changed -1 | |
234 | gdb_test_multiple "stepi" "stepi until line_label_5, $i" { | |
235 | -re "main, set var to 0.*$gdb_prompt" { | |
236 | set line_changed 0 | |
237 | } | |
238 | -re "main end.*$gdb_prompt " { | |
239 | set line_changed 1 | |
240 | } | |
241 | } | |
242 | gdb_assert { $line_changed != -1 } \ | |
243 | "ensure we saw a valid line pattern, $i" | |
244 | set pc [get_hexadecimal_valueof "\$pc" "NO-PC" \ | |
245 | "get pc inside stepi loop from line_label_2, $i"] | |
246 | if { $ll5 == $pc } { | |
247 | gdb_assert { $line_changed } \ | |
248 | "line must change at line_label_5" | |
249 | } else { | |
250 | gdb_assert { !$line_changed } \ | |
251 | "line should not change until line_label_5, $i" | |
252 | } | |
253 | } |