]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/testsuite/gdb.dwarf2/locexpr-data-member-location.exp
[gdb/testsuite] Fix gdb.dwarf2/locexpr-data-member-location.exp with nopie
[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
2899c914 69# We're generating DWARF assembly for the shared object;
a640adf7
KB
70# The output of Dwarf::assemble will be placed in $lib_basename.S
71# which will be ${srcfile3} after the execution of standard_testfile.
72
2899c914 73standard_testfile $main_basename.c $lib_basename.c $lib_basename.S
a640adf7 74
2899c914 75set libsrc "${::srcdir}/${::subdir}/${::srcfile2}"
a640adf7
KB
76set lib_so [standard_output_file ${lib_basename}.so]
77set asm_file [standard_output_file ${::srcfile3}]
78
2899c914
TV
79# Compile the shared library for the first GDB session. Note that debugging
80# symbols will be present for this compilation, because we want to print some
81# type information.
a640adf7 82if {[gdb_compile_shlib $libsrc $lib_so \
2899c914 83 {debug}] != ""} {
a640adf7
KB
84 untested "failed to compile shared library"
85 return
86}
87
2899c914
TV
88# Compile the main program for use with the shared object. Note we're using
89# debug, such that "finish out of foo" prints:
90# Value returned is $1 = (class B *) $hex <g_>
91# instead of:
92# Value returned is $1 = (B *) $hex <g_>
93# Note that this compilation is used for all GDB sessions.
94set exec_options [list debug shlib=$lib_so]
95if [prepare_for_testing "failed to prepare" ${testfile} \
96 ${::srcfile} $exec_options] {
97 return -1
98}
99
100# Do whatever is necessary to make sure that the shared library is
101# loaded for remote targets.
102gdb_load_shlib ${lib_so}
103
a640adf7 104
2899c914 105### First GDB session.
a640adf7 106
2899c914
TV
107# Run to foo to make sure foo refers to the function, and not foo@PLT.
108if ![runto foo qualified] then {
a640adf7
KB
109 return
110}
111
2899c914
TV
112with_shared_gdb {
113
114 set session_options $exec_options
115
116 # Rather than start a new session, declare the current session the
117 # shared one. Otherwise, get_func_info would compile an executable
118 # in a temp dir, which means -Wl,-rpath,\\\$ORIGIN no longer finds
119 # the shared lib.
120 share_gdb ${srcdir}/${subdir}/$srcfile $session_options
121
122 get_func_info foo $session_options
123 get_func_info bar $session_options
124
125 # Using our running GDB session, determine sizes of several types.
126 set long_size [get_sizeof "long" -1]
127 set addr_size [get_sizeof "void *" -1]
128 set struct_A_size [get_sizeof "g_A" -1]
129 set struct_B_size [get_sizeof "g_B" -1]
130
131 # Retrieve struct offset of MBR in struct TP
132 proc get_offsetof { tp mbr } {
133 return [get_integer_valueof "&((${tp} *) 0)->${mbr}" -1]
134 }
135
136 # Use running GDB session to get struct offsets
137 set A_a [get_offsetof A a]
138 set A_x [get_offsetof A x]
139 set B_a [get_offsetof B a]
140 set B_b [get_offsetof B b]
141 set B_x2 [get_offsetof B x2]
a640adf7
KB
142}
143
2899c914
TV
144if { $long_size == -1 || $addr_size == -1 \
145 || $struct_A_size == -1 || $struct_B_size == -1} {
146 perror "Can't determine type sizes"
147 return
148}
a640adf7
KB
149
150# Create the DWARF.
151Dwarf::assemble ${asm_file} {
152 declare_labels L
2899c914
TV
153 global foo_start foo_end
154 global bar_start bar_end
155 global libsrc
a640adf7 156
3859e65e 157 cu { label cu_label } {
a640adf7
KB
158 DW_TAG_compile_unit {
159 {DW_AT_language @DW_LANG_C_plus_plus}
160 {name ${::srcfile}}
161 {stmt_list $L DW_FORM_sec_offset}
162 } {
163 declare_labels int_label class_A_label class_B_label \
164 B_ptr_label
165
166 int_label: DW_TAG_base_type {
167 {DW_AT_byte_size ${::long_size} DW_FORM_udata}
168 {DW_AT_encoding @DW_ATE_signed}
169 {DW_AT_name "int"}
170 }
171
172 class_A_label: DW_TAG_class_type {
173 {DW_AT_name "A"}
174 {DW_AT_byte_size ${::struct_A_size} DW_FORM_sdata}
175 } {
176 DW_TAG_member {
177 {DW_AT_name "a"}
178 {DW_AT_type :$int_label}
179 {DW_AT_data_member_location ${::A_a} DW_FORM_udata}
180 }
181 DW_TAG_member {
182 {DW_AT_name "x"}
183 {DW_AT_type :$int_label}
184 {DW_AT_data_member_location ${::A_x} DW_FORM_udata}
185 }
186 }
187
188 class_B_label: DW_TAG_class_type {
189 {DW_AT_name "B"}
190 {DW_AT_byte_size ${::struct_B_size} DW_FORM_sdata}
191 } {
192 # While there are easier / better ways to specify an
193 # offset used by DW_AT_data_member_location than that
194 # used below, we need a location expression here in
195 # order to reproduce the bug. Moreover, this location
196 # expression needs to use opcodes that aren't handled
197 # by decode_locdesc() in dwarf2/read.c; if we use
198 # opcodes that _are_ handled by that function, the
199 # location expression will be converted into a simple
200 # offset - which will then (again) not reproduce the
201 # bug. At the time that this test was written,
202 # neither DW_OP_pick nor DW_OP_drop were being handled
203 # by decode_locdesc(); this is why those opcodes were
204 # chosen.
205 DW_TAG_inheritance {
206 {DW_AT_type :$class_A_label}
207 {DW_AT_data_member_location {
208 DW_OP_constu ${::B_a}
209 DW_OP_plus
210 DW_OP_pick 0
211 DW_OP_drop} SPECIAL_expr}
212 {DW_AT_accessibility 1 DW_FORM_data1}
213 }
214 DW_TAG_member {
215 {DW_AT_name "b"}
216 {DW_AT_type :$int_label}
217 {DW_AT_data_member_location ${::B_b} DW_FORM_udata}
218 }
219 DW_TAG_member {
220 {DW_AT_name "x2"}
221 {DW_AT_type :$int_label}
222 {DW_AT_data_member_location ${::B_x2} DW_FORM_udata}
223 }
224 }
225
226 B_ptr_label: DW_TAG_pointer_type {
227 {DW_AT_type :$class_B_label}
228 {DW_AT_byte_size ${::addr_size} DW_FORM_sdata}
229 }
230
231 DW_TAG_variable {
232 {DW_AT_name "g_A"}
233 {DW_AT_type :$class_A_label}
234 {DW_AT_external 1 flag}
235 {DW_AT_location {DW_OP_addr [gdb_target_symbol "g_A"]} \
236 SPECIAL_expr}
237 }
238
239 DW_TAG_variable {
240 {DW_AT_name "g_B"}
241 {DW_AT_type :$class_B_label}
242 {DW_AT_external 1 flag}
243 {DW_AT_location {DW_OP_addr [gdb_target_symbol "g_B"]} \
244 SPECIAL_expr}
245 }
246
247 # We can't use MACRO_AT for the definitions of foo and bar
248 # because it doesn't provide a way to pass the appropriate
249 # flags. Therefore, we list the name, low_pc, and high_pc
250 # explicitly.
251 DW_TAG_subprogram {
252 {DW_AT_name foo}
253 {DW_AT_low_pc $foo_start DW_FORM_addr}
254 {DW_AT_high_pc $foo_end DW_FORM_addr}
255 {DW_AT_type :${B_ptr_label}}
256 {DW_AT_external 1 flag}
257 }
258
259 DW_TAG_subprogram {
260 {DW_AT_name bar}
261 {DW_AT_low_pc $bar_start DW_FORM_addr}
262 {DW_AT_high_pc $bar_end DW_FORM_addr}
263 {DW_AT_type :${B_ptr_label}}
264 {DW_AT_external 1 flag}
265 } {
266 DW_TAG_formal_parameter {
267 {DW_AT_name v}
268 {DW_AT_type :${B_ptr_label}}
269 }
270 }
271 }
272 }
273
274 lines {version 2} L {
275 include_dir "${::srcdir}/${::subdir}"
2899c914 276 file_name "${::srcfile2}" 1
a640adf7
KB
277
278 # Generate a line table program.
279 program {
d4c4a229 280 DW_LNE_set_address $foo_start
2899c914 281 line [gdb_get_line_number "foo prologue" $libsrc]
d4c4a229
SM
282 DW_LNS_copy
283 DW_LNE_set_address foo_label
2899c914 284 line [gdb_get_line_number "foo return" $libsrc]
d4c4a229 285 DW_LNS_copy
2899c914 286 line [gdb_get_line_number "foo end" $libsrc]
d4c4a229
SM
287 DW_LNS_copy
288 DW_LNE_set_address $foo_end
289 DW_LNS_advance_line 1
290 DW_LNS_copy
291 DW_LNE_end_sequence
a640adf7 292
d4c4a229 293 DW_LNE_set_address $bar_start
2899c914 294 line [gdb_get_line_number "bar prologue" $libsrc]
d4c4a229
SM
295 DW_LNS_copy
296 DW_LNE_set_address bar_label
2899c914 297 line [gdb_get_line_number "bar return" $libsrc]
d4c4a229 298 DW_LNS_copy
2899c914 299 line [gdb_get_line_number "bar end" $libsrc]
d4c4a229
SM
300 DW_LNS_copy
301 DW_LNE_set_address $bar_end
302 DW_LNS_advance_line 1
303 DW_LNS_copy
304 DW_LNE_end_sequence
a640adf7
KB
305 }
306 }
3859e65e
TV
307
308 aranges {} cu_label {
1a7c41d5
TT
309 # This 0,0 entry tests that the .debug_aranges reader can
310 # handle an apparent terminator before the end of the ranges.
311 arange {} 0 0
3859e65e
TV
312 arange {} $foo_start $foo_end
313 arange {} $bar_start $bar_end
314 }
a640adf7
KB
315}
316
317# Compile the shared object again, but this time include / use the
2899c914
TV
318# DWARF info that we've created above. Note the use of the "nodebug" option.
319# Any debugging information that we need will be provided by the DWARF info
320# created above.
a640adf7 321if {[gdb_compile_shlib [list $libsrc $asm_file] $lib_so \
2899c914 322 {nodebug}] != ""} {
a640adf7
KB
323 untested "failed to compile shared library"
324 return
325}
326
2899c914 327### Second GDB session.
a640adf7 328
2899c914
TV
329clean_restart $binfile
330
331# Again, do whatever is necessary to make sure that the shared library is
a640adf7
KB
332# loaded for remote targets.
333gdb_load_shlib ${lib_so}
334
335if ![runto_main] then {
a640adf7
KB
336 return
337}
338
339# Step into foo so that we can finish out of it.
340gdb_test "step" "foo .. at .* foo end.*" "step into foo"
341
342# Finishing out of foo will create a value that will later need to
343# be preserved when restarting the program.
344gdb_test "finish" "= \\(class B \\*\\) ${::hex} .*" "finish out of foo"
345
346# Dereferencing and printing the return value isn't necessary
347# for reproducing the bug, but we should make sure that the
348# return value is what we expect it to be.
349gdb_test "p *$" { = {<A> = {a = 8, x = 9}, b = 10, x2 = 11}} \
350 "dereference return value"
351
352# The original PR28030 reproducer stepped back into the shared object,
353# so we'll do the same here:
354gdb_test "step" "bar \\(.*" "step into bar"
355
2899c914
TV
356
357### Third GDB session.
358
a640adf7
KB
359# We don't want a clean restart here since that will be too clean.
360# The original reproducer for PR28030 set a breakpoint in the shared
361# library and then restarted via "run". The command below does roughly
362# the same thing. It's at this step that an internal error would
363# occur for PR28030. The "message" argument tells runto to turn on
364# the printing of PASSes while runto is doing its job.
365runto "bar" message