]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp
gdb/testsuite/dwarf: simplify line number program syntax
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.dwarf2 / locexpr-data-member-location.exp
CommitLineData
4a94e368 1# Copyright 2021-2022 Free Software Foundation, Inc.
a640adf7
KB
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 case uses the DWARF assembler to reproduce the problem
17# described by PR28030. The bug turned out to be that
18# FIELD_LOC_KIND_DWARF_BLOCK was not handled when recursively copying
19# a value's type when preserving the value history during the freeing
20# up of objfiles associated with a shared object. (Yes, figuring out
21# how to make this happen in a concise test case turned out to be
22# challenging.)
23#
24# The following elements proved to be necessary for reproducing the
25# problem:
26#
27# 1) A location expression needed to be used with
28# DW_AT_data_member_location rather than a simple offset.
29# Moreover, this location expression needed to use opcodes
30# which GDB's DWARF reader could not convert to a simple
31# offset. (Note, however, that GDB could probably be improved
32# to handle the opcodes chosen for this test; if decode_locdesc()
33# in dwarf2/read.c is ever updated to handle both DW_OP_pick and
34# DW_OP_drop, then this test could end up passing even if
35# the bug it's intended to test has not been fixed.)
36#
37# 2) The debug info containing the above DWARF info needed
38# to be associated with a shared object since the problem
39# occurred while GDB was preserving values during the
40# purging of shared objects.
41#
42# 3) After performing some simple gdb commands, the program is
43# run again. In the course of running the objfile destructor
44# associated with the shared object, values are preserved
45# along with their types. As noted earlier, it was during
46# the recursive type copy that the bug was observed.
47#
48# Therefore, due to #2 above, this test case creates debug info
49# which is then used by a shared object.
50
51# This test can't be run on targets lacking shared library support.
52if [skip_shlib_tests] {
53 return 0
54}
55
56load_lib dwarf.exp
57
58# This test can only be run on targets which support DWARF-2 and use gas.
59if ![dwarf2_support] {
60 return 0
61}
62
63# gdb_test_file_name is the name of this file without the .exp
64# extension. Use it to form basenames for the main program
65# and shared object.
66set main_basename ${::gdb_test_file_name}-main
67set lib_basename ${::gdb_test_file_name}-lib
68
69# We're generating DWARF assembly for the shared object; therefore,
70# the source file for the library / shared object must be listed first
71# (in the standard_testfile invocation) since ${srcfile} is used by
72# get_func_info (for determining the start, end, and length of a
73# function).
74#
75# The output of Dwarf::assemble will be placed in $lib_basename.S
76# which will be ${srcfile3} after the execution of standard_testfile.
77
78standard_testfile $lib_basename.c $main_basename.c $lib_basename.S
79
80set libsrc "${::srcdir}/${::subdir}/${::srcfile}"
81set lib_so [standard_output_file ${lib_basename}.so]
82set asm_file [standard_output_file ${::srcfile3}]
83
84# We need to know the size of some types in order to write some of the
85# debugging info that we're about to generate. For that, we ask GDB
86# by debugging the shared object associated with this test case.
87
88# Compile the shared library: -DIS_SHAREDLIB prevents main() from
89# being defined. Note that debugging symbols will be present for
90# this compilation.
91if {[gdb_compile_shlib $libsrc $lib_so \
92 {additional_flags=-DIS_SHAREDLIB debug}] != ""} {
93 untested "failed to compile shared library"
94 return
95}
96
97# Start a fresh GDB and load the shared library.
98clean_restart $lib_so
99
100# Using our running GDB session, determine sizes of several types.
101set long_size [get_sizeof "long" -1]
102set addr_size [get_sizeof "void *" -1]
103set struct_A_size [get_sizeof "g_A" -1]
104set struct_B_size [get_sizeof "g_B" -1]
105
106if { $long_size == -1 || $addr_size == -1 \
107 || $struct_A_size == -1 || $struct_B_size == -1} {
108 perror "Can't determine type sizes"
109 return
110}
111
112# Retrieve struct offset of MBR in struct TP
113proc get_offsetof { tp mbr } {
114 return [get_integer_valueof "&((${tp} *) 0)->${mbr}" -1]
115}
116
117# Use running GDB session to get struct offsets
118set A_a [get_offsetof A a]
119set A_x [get_offsetof A x]
120set B_a [get_offsetof B a]
121set B_b [get_offsetof B b]
122set B_x2 [get_offsetof B x2]
123
124# Create the DWARF.
125Dwarf::assemble ${asm_file} {
126 declare_labels L
127
128 # Find start, end, and length of functions foo and bar.
129 # These calls to get_func_info will create and set variables
130 # foo_start, bar_start, foo_end, bar_end, foo_len, and
131 # bar_len.
132 #
133 # In order to get the right answers, get_func_info (and,
134 # underneath, function_range) should use the same compiler flags
135 # as those used to make a shared object. For any targets that get
136 # this far, -fpic is probably correct.
137 #
138 # Also, it should be noted that IS_SHAREDLIB is NOT defined as one
139 # of the additional flags. Not defining IS_SHAREDLIB will cause a
140 # main() to be defined for the compilation of the shared library
141 # source file which happens as a result of using get_func_info;
142 # this is currently required in order to this facility.
143 set flags {additional_flags=-fpic debug}
144 get_func_info foo $flags
145 get_func_info bar $flags
146
3859e65e 147 cu { label cu_label } {
a640adf7
KB
148 DW_TAG_compile_unit {
149 {DW_AT_language @DW_LANG_C_plus_plus}
150 {name ${::srcfile}}
151 {stmt_list $L DW_FORM_sec_offset}
152 } {
153 declare_labels int_label class_A_label class_B_label \
154 B_ptr_label
155
156 int_label: DW_TAG_base_type {
157 {DW_AT_byte_size ${::long_size} DW_FORM_udata}
158 {DW_AT_encoding @DW_ATE_signed}
159 {DW_AT_name "int"}
160 }
161
162 class_A_label: DW_TAG_class_type {
163 {DW_AT_name "A"}
164 {DW_AT_byte_size ${::struct_A_size} DW_FORM_sdata}
165 } {
166 DW_TAG_member {
167 {DW_AT_name "a"}
168 {DW_AT_type :$int_label}
169 {DW_AT_data_member_location ${::A_a} DW_FORM_udata}
170 }
171 DW_TAG_member {
172 {DW_AT_name "x"}
173 {DW_AT_type :$int_label}
174 {DW_AT_data_member_location ${::A_x} DW_FORM_udata}
175 }
176 }
177
178 class_B_label: DW_TAG_class_type {
179 {DW_AT_name "B"}
180 {DW_AT_byte_size ${::struct_B_size} DW_FORM_sdata}
181 } {
182 # While there are easier / better ways to specify an
183 # offset used by DW_AT_data_member_location than that
184 # used below, we need a location expression here in
185 # order to reproduce the bug. Moreover, this location
186 # expression needs to use opcodes that aren't handled
187 # by decode_locdesc() in dwarf2/read.c; if we use
188 # opcodes that _are_ handled by that function, the
189 # location expression will be converted into a simple
190 # offset - which will then (again) not reproduce the
191 # bug. At the time that this test was written,
192 # neither DW_OP_pick nor DW_OP_drop were being handled
193 # by decode_locdesc(); this is why those opcodes were
194 # chosen.
195 DW_TAG_inheritance {
196 {DW_AT_type :$class_A_label}
197 {DW_AT_data_member_location {
198 DW_OP_constu ${::B_a}
199 DW_OP_plus
200 DW_OP_pick 0
201 DW_OP_drop} SPECIAL_expr}
202 {DW_AT_accessibility 1 DW_FORM_data1}
203 }
204 DW_TAG_member {
205 {DW_AT_name "b"}
206 {DW_AT_type :$int_label}
207 {DW_AT_data_member_location ${::B_b} DW_FORM_udata}
208 }
209 DW_TAG_member {
210 {DW_AT_name "x2"}
211 {DW_AT_type :$int_label}
212 {DW_AT_data_member_location ${::B_x2} DW_FORM_udata}
213 }
214 }
215
216 B_ptr_label: DW_TAG_pointer_type {
217 {DW_AT_type :$class_B_label}
218 {DW_AT_byte_size ${::addr_size} DW_FORM_sdata}
219 }
220
221 DW_TAG_variable {
222 {DW_AT_name "g_A"}
223 {DW_AT_type :$class_A_label}
224 {DW_AT_external 1 flag}
225 {DW_AT_location {DW_OP_addr [gdb_target_symbol "g_A"]} \
226 SPECIAL_expr}
227 }
228
229 DW_TAG_variable {
230 {DW_AT_name "g_B"}
231 {DW_AT_type :$class_B_label}
232 {DW_AT_external 1 flag}
233 {DW_AT_location {DW_OP_addr [gdb_target_symbol "g_B"]} \
234 SPECIAL_expr}
235 }
236
237 # We can't use MACRO_AT for the definitions of foo and bar
238 # because it doesn't provide a way to pass the appropriate
239 # flags. Therefore, we list the name, low_pc, and high_pc
240 # explicitly.
241 DW_TAG_subprogram {
242 {DW_AT_name foo}
243 {DW_AT_low_pc $foo_start DW_FORM_addr}
244 {DW_AT_high_pc $foo_end DW_FORM_addr}
245 {DW_AT_type :${B_ptr_label}}
246 {DW_AT_external 1 flag}
247 }
248
249 DW_TAG_subprogram {
250 {DW_AT_name bar}
251 {DW_AT_low_pc $bar_start DW_FORM_addr}
252 {DW_AT_high_pc $bar_end DW_FORM_addr}
253 {DW_AT_type :${B_ptr_label}}
254 {DW_AT_external 1 flag}
255 } {
256 DW_TAG_formal_parameter {
257 {DW_AT_name v}
258 {DW_AT_type :${B_ptr_label}}
259 }
260 }
261 }
262 }
263
264 lines {version 2} L {
265 include_dir "${::srcdir}/${::subdir}"
266 file_name "${::srcfile}" 1
267
268 # Generate a line table program.
269 program {
d4c4a229
SM
270 DW_LNE_set_address $foo_start
271 line [gdb_get_line_number "foo prologue"]
272 DW_LNS_copy
273 DW_LNE_set_address foo_label
274 line [gdb_get_line_number "foo return"]
275 DW_LNS_copy
276 line [gdb_get_line_number "foo end"]
277 DW_LNS_copy
278 DW_LNE_set_address $foo_end
279 DW_LNS_advance_line 1
280 DW_LNS_copy
281 DW_LNE_end_sequence
a640adf7 282
d4c4a229
SM
283 DW_LNE_set_address $bar_start
284 line [gdb_get_line_number "bar prologue"]
285 DW_LNS_copy
286 DW_LNE_set_address bar_label
287 line [gdb_get_line_number "bar return"]
288 DW_LNS_copy
289 line [gdb_get_line_number "bar end"]
290 DW_LNS_copy
291 DW_LNE_set_address $bar_end
292 DW_LNS_advance_line 1
293 DW_LNS_copy
294 DW_LNE_end_sequence
a640adf7
KB
295 }
296 }
3859e65e
TV
297
298 aranges {} cu_label {
299 arange {} $foo_start $foo_end
300 arange {} $bar_start $bar_end
301 }
a640adf7
KB
302}
303
304# Compile the shared object again, but this time include / use the
305# DWARF info that we've created above. Note that (again)
306# -DIS_SHAREDLIB is used to prevent inclusion of main() in the shared
307# object. Also note the use of the "nodebug" option. Any debugging
308# information that we need will be provided by the DWARF info created
309# above.
310if {[gdb_compile_shlib [list $libsrc $asm_file] $lib_so \
311 {additional_flags=-DIS_SHAREDLIB nodebug}] != ""} {
312 untested "failed to compile shared library"
313 return
314}
315
316# Compile the main program for use with the shared object.
317if [prepare_for_testing "failed to prepare" ${testfile} \
318 ${::srcfile2} [list debug shlib=$lib_so]] {
319 return -1
320}
321
322# Do whatever is necessary to make sure that the shared library is
323# loaded for remote targets.
324gdb_load_shlib ${lib_so}
325
326if ![runto_main] then {
a640adf7
KB
327 return
328}
329
330# Step into foo so that we can finish out of it.
331gdb_test "step" "foo .. at .* foo end.*" "step into foo"
332
333# Finishing out of foo will create a value that will later need to
334# be preserved when restarting the program.
335gdb_test "finish" "= \\(class B \\*\\) ${::hex} .*" "finish out of foo"
336
337# Dereferencing and printing the return value isn't necessary
338# for reproducing the bug, but we should make sure that the
339# return value is what we expect it to be.
340gdb_test "p *$" { = {<A> = {a = 8, x = 9}, b = 10, x2 = 11}} \
341 "dereference return value"
342
343# The original PR28030 reproducer stepped back into the shared object,
344# so we'll do the same here:
345gdb_test "step" "bar \\(.*" "step into bar"
346
347# We don't want a clean restart here since that will be too clean.
348# The original reproducer for PR28030 set a breakpoint in the shared
349# library and then restarted via "run". The command below does roughly
350# the same thing. It's at this step that an internal error would
351# occur for PR28030. The "message" argument tells runto to turn on
352# the printing of PASSes while runto is doing its job.
353runto "bar" message