]>
Commit | Line | Data |
---|---|---|
5a03b7c3 MT |
1 | http://sourceware.org/ml/gdb-patches/2011-09/msg00451.html |
2 | Subject: [patch 2/2] Fix DW_OP_GNU_implicit_pointer for DWARF32 v3+ on 64-bit arches | |
3 | ||
4 | Hi, | |
5 | ||
6 | on 64-bit targets DWARF-3+ is used DW_OP_GNU_implicit_pointer does not work. | |
7 | ||
8 | DWARF-2 says: | |
9 | This type of reference (DW_FORM_ref_addr) is the size of an address on | |
10 | the target architecture; | |
11 | DWARF-3 says: | |
12 | 1.5.1 Upward Compatibility | |
13 | References that use the attribute form DW_FORM_ref_addr are specified | |
14 | to be four bytes in the DWARF 32-bit format and eight bytes in the | |
15 | DWARF 64-bit format, while DWARF Version 2 specifies that such | |
16 | references have the same size as an address on the target system (see | |
17 | Sections 7.4 and 7.5.4). | |
18 | ||
19 | (DW_FORM_ref_addr) | |
20 | In the 32-bit DWARF format, this offset is a 4-byte unsigned value; in | |
21 | the 64-bit DWARF format, it is an 8-byte unsigned value (see Section | |
22 | 7.4). | |
23 | ||
24 | GDB currently parsed DW_OP_GNU_implicit_pointer the DWARF-2 way, being | |
25 | incompatible with DWARF-3+. | |
26 | ||
27 | I think DW_OP_GNU_implicit_pointer does not make sense to be used from | |
28 | .debug_frame (DWARF-5 is not yet released to say more) so for .debug_frame its | |
29 | use is just not permitted (the code would be more complicated otherwise). | |
30 | ||
31 | No regressions on {x86_64,x86_64-m32,i686}-fedora16pre-linux-gnu. | |
32 | ||
33 | ||
34 | Thanks, | |
35 | Jan | |
36 | ||
37 | ||
38 | gdb/ | |
39 | 2011-09-26 Jan Kratochvil <jan.kratochvil@redhat.com> | |
40 | ||
41 | Fix DW_OP_GNU_implicit_pointer for DWARF32 v3+ on 64-bit arches. | |
42 | * dwarf2-frame.c (execute_stack_op): Initialize ctx->ref_addr_size. | |
43 | * dwarf2expr.c (execute_stack_op) <DW_OP_GNU_implicit_pointer>: Use | |
44 | ctx->ref_addr_size. Handle its invalid value. | |
45 | * dwarf2expr.h (struct dwarf_expr_context): New field ref_addr_size. | |
46 | * dwarf2loc.c (dwarf2_evaluate_loc_desc_full) | |
47 | (dwarf2_loc_desc_needs_frame): Initialize ctx->ref_addr_size. | |
48 | * dwarf2loc.h (dwarf2_per_cu_ref_addr_size): New declaration. | |
49 | * dwarf2read.c (decode_locdesc): Initialize ctx->ref_addr_size. | |
50 | (dwarf2_per_cu_ref_addr_size): New function. | |
51 | ||
52 | gdb/testsuite/ | |
53 | 2011-09-26 Jan Kratochvil <jan.kratochvil@redhat.com> | |
54 | ||
55 | Fix DW_OP_GNU_implicit_pointer for DWARF32 v3+ on 64-bit arches. | |
56 | * gdb.dwarf2/implptr-64bit.S: New file. | |
57 | * gdb.dwarf2/implptr-64bit.exp: New file. | |
58 | ||
59 | --- a/gdb/dwarf2-frame.c | |
60 | +++ b/gdb/dwarf2-frame.c | |
61 | @@ -371,6 +371,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, | |
62 | ||
63 | ctx->gdbarch = get_frame_arch (this_frame); | |
64 | ctx->addr_size = addr_size; | |
65 | + ctx->ref_addr_size = -1; | |
66 | ctx->offset = offset; | |
67 | ctx->baton = this_frame; | |
68 | ctx->funcs = &dwarf2_frame_ctx_funcs; | |
69 | --- a/gdb/dwarf2expr.c | |
70 | +++ b/gdb/dwarf2expr.c | |
71 | @@ -709,10 +709,14 @@ execute_stack_op (struct dwarf_expr_context *ctx, | |
72 | ULONGEST die; | |
73 | LONGEST len; | |
74 | ||
75 | + if (ctx->ref_addr_size == -1) | |
76 | + error (_("DWARF-2 expression error: DW_OP_GNU_implicit_pointer " | |
77 | + "is not allowed in frame context")); | |
78 | + | |
79 | /* The referred-to DIE. */ | |
80 | - ctx->len = extract_unsigned_integer (op_ptr, ctx->addr_size, | |
81 | + ctx->len = extract_unsigned_integer (op_ptr, ctx->ref_addr_size, | |
82 | byte_order); | |
83 | - op_ptr += ctx->addr_size; | |
84 | + op_ptr += ctx->ref_addr_size; | |
85 | ||
86 | /* The byte offset into the data. */ | |
87 | op_ptr = read_sleb128 (op_ptr, op_end, &len); | |
88 | --- a/gdb/dwarf2expr.h | |
89 | +++ b/gdb/dwarf2expr.h | |
90 | @@ -125,6 +125,10 @@ struct dwarf_expr_context | |
91 | /* Target address size in bytes. */ | |
92 | int addr_size; | |
93 | ||
94 | + /* DW_FORM_ref_addr size in bytes. If -1 DWARF is executed from a frame | |
95 | + context and operations depending on DW_FORM_ref_addr are not allowed. */ | |
96 | + int ref_addr_size; | |
97 | + | |
98 | /* Offset used to relocate DW_OP_addr argument. */ | |
99 | CORE_ADDR offset; | |
100 | ||
101 | --- a/gdb/dwarf2loc.c | |
102 | +++ b/gdb/dwarf2loc.c | |
103 | @@ -1118,6 +1118,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, | |
104 | ||
105 | ctx->gdbarch = get_objfile_arch (objfile); | |
106 | ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); | |
107 | + ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu); | |
108 | ctx->offset = dwarf2_per_cu_text_offset (per_cu); | |
109 | ctx->baton = &baton; | |
110 | ctx->funcs = &dwarf_expr_ctx_funcs; | |
111 | @@ -1398,6 +1399,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size, | |
112 | ||
113 | ctx->gdbarch = get_objfile_arch (objfile); | |
114 | ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); | |
115 | + ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu); | |
116 | ctx->offset = dwarf2_per_cu_text_offset (per_cu); | |
117 | ctx->baton = &baton; | |
118 | ctx->funcs = &needs_frame_ctx_funcs; | |
119 | --- a/gdb/dwarf2loc.h | |
120 | +++ b/gdb/dwarf2loc.h | |
121 | @@ -39,6 +39,10 @@ struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu); | |
122 | /* Return the address size given in the compilation unit header for CU. */ | |
123 | CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu); | |
124 | ||
125 | +/* Return the DW_FORM_ref_addr size given in the compilation unit header for | |
126 | + CU. */ | |
127 | +int dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *cu); | |
128 | + | |
129 | /* Return the offset size given in the compilation unit header for CU. */ | |
130 | int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu); | |
131 | ||
132 | --- a/gdb/dwarf2read.c | |
133 | +++ b/gdb/dwarf2read.c | |
134 | @@ -15238,6 +15239,22 @@ dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) | |
135 | return cu_headerp->offset_size; | |
136 | } | |
137 | ||
138 | +/* See its dwarf2loc.h declaration. */ | |
139 | + | |
140 | +int | |
141 | +dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *per_cu) | |
142 | +{ | |
143 | + struct comp_unit_head cu_header_local; | |
144 | + const struct comp_unit_head *cu_headerp; | |
145 | + | |
146 | + cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu); | |
147 | + | |
148 | + if (cu_headerp->version == 2) | |
149 | + return cu_headerp->addr_size; | |
150 | + else | |
151 | + return cu_headerp->offset_size; | |
152 | +} | |
153 | + | |
154 | /* Return the text offset of the CU. The returned offset comes from | |
155 | this CU's objfile. If this objfile came from a separate debuginfo | |
156 | file, then the offset may be different from the corresponding | |
157 | --- /dev/null | |
158 | +++ b/gdb/testsuite/gdb.dwarf2/implptr-64bit.S | |
159 | @@ -0,0 +1,197 @@ | |
160 | +/* Copyright 2010, 2011 Free Software Foundation, Inc. | |
161 | + | |
162 | + This program is free software; you can redistribute it and/or modify | |
163 | + it under the terms of the GNU General Public License as published by | |
164 | + the Free Software Foundation; either version 3 of the License, or | |
165 | + (at your option) any later version. | |
166 | + | |
167 | + This program is distributed in the hope that it will be useful, | |
168 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
169 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
170 | + GNU General Public License for more details. | |
171 | + | |
172 | + You should have received a copy of the GNU General Public License | |
173 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
174 | + | |
175 | + .section .debug_info | |
176 | +d: | |
177 | + /* Length of Compilation Unit Info */ | |
178 | +#if OFFSET_SIZE == 4 | |
179 | +# define OFFSET .4byte | |
180 | + .4byte debug_end - 1f | |
181 | +#elif OFFSET_SIZE == 8 | |
182 | +# define OFFSET .8byte | |
183 | + .4byte 0xffffffff | |
184 | + .8byte debug_end - 1f | |
185 | +#else | |
186 | +# error | |
187 | +#endif | |
188 | +#if ADDR_SIZE == 4 | |
189 | +# define ADDR .4byte | |
190 | +#elif ADDR_SIZE == 8 | |
191 | +# define ADDR .8byte | |
192 | +#else | |
193 | +# error | |
194 | +#endif | |
195 | +#if REF_ADDR_SIZE == 4 | |
196 | +# define REF_ADDR .4byte | |
197 | +#elif REF_ADDR_SIZE == 8 | |
198 | +# define REF_ADDR .8byte | |
199 | +#else | |
200 | +# error | |
201 | +#endif | |
202 | +1: | |
203 | + .2byte DWARF_VERSION /* DWARF version number */ | |
204 | + OFFSET .Ldebug_abbrev0 /* Offset Into Abbrev. Section */ | |
205 | + .byte ADDR_SIZE /* Pointer Size (in bytes) */ | |
206 | + | |
207 | + .uleb128 0x1 /* (DIE (0xb) DW_TAG_compile_unit) */ | |
208 | + .ascii "GNU C 4.4.3\0" /* DW_AT_producer */ | |
209 | + .byte 0x1 /* DW_AT_language */ | |
210 | + .ascii "1.c\0" /* DW_AT_name */ | |
211 | + | |
212 | +.Ltype_int: | |
213 | + .uleb128 0x7 /* DW_TAG_base_type */ | |
214 | + .byte 0x4 /* DW_AT_byte_size */ | |
215 | + .byte 0x5 /* DW_AT_encoding */ | |
216 | + .ascii "int\0" /* DW_AT_name */ | |
217 | + | |
218 | +.Ltype_struct: | |
219 | + .uleb128 0x2 /* DW_TAG_structure_type */ | |
220 | + .ascii "s\0" /* DW_AT_name */ | |
221 | + .byte 4 /* DW_AT_byte_size */ | |
222 | + | |
223 | + .uleb128 0x3 /* DW_TAG_member */ | |
224 | + .ascii "f\0" /* DW_AT_name */ | |
225 | + .4byte .Ltype_int - d /* DW_AT_type */ | |
226 | + .byte 0 /* DW_AT_data_member_location */ | |
227 | + | |
228 | + .byte 0x0 /* end of children of DW_TAG_structure_type */ | |
229 | + | |
230 | + .uleb128 6 /* Abbrev: DW_TAG_subprogram */ | |
231 | + .ascii "main\0" /* DW_AT_name */ | |
232 | + ADDR main /* DW_AT_low_pc */ | |
233 | + ADDR main + 0x100 /* DW_AT_high_pc */ | |
234 | + .4byte .Ltype_int - d /* DW_AT_type */ | |
235 | + .byte 1 /* DW_AT_external */ | |
236 | + | |
237 | +.Ltype_structptr: | |
238 | + .uleb128 0x5 /* DW_TAG_pointer_type */ | |
239 | + .byte ADDR_SIZE /* DW_AT_byte_size */ | |
240 | + .4byte .Ltype_struct - d /* DW_AT_type */ | |
241 | + | |
242 | +.Lvar_out: | |
243 | + .uleb128 0x4 /* (DW_TAG_variable) */ | |
244 | + .ascii "v\0" /* DW_AT_name */ | |
245 | + .byte 2f - 1f /* DW_AT_location: DW_FORM_block1 */ | |
246 | +1: | |
247 | + .byte 0x9e /* DW_OP_implicit_value */ | |
248 | + .uleb128 2f - 3f | |
249 | +3: | |
250 | + .byte 1, 1, 1, 1 | |
251 | +2: | |
252 | + .4byte .Ltype_struct - d /* DW_AT_type */ | |
253 | + | |
254 | + .uleb128 0x4 /* (DW_TAG_variable) */ | |
255 | + .ascii "p\0" /* DW_AT_name */ | |
256 | + .byte 2f - 1f /* DW_AT_location: DW_FORM_block1 */ | |
257 | +1: | |
258 | + .byte 0xf2 /* DW_OP_GNU_implicit_pointer */ | |
259 | + REF_ADDR .Lvar_out - d /* referenced DIE */ | |
260 | + .sleb128 0 /* offset */ | |
261 | +2: | |
262 | + .4byte .Ltype_structptr - d /* DW_AT_type */ | |
263 | + | |
264 | + .byte 0x0 /* end of children of main */ | |
265 | + | |
266 | + .byte 0x0 /* end of children of CU */ | |
267 | +debug_end: | |
268 | + | |
269 | + .section .debug_abbrev | |
270 | +.Ldebug_abbrev0: | |
271 | + | |
272 | + .uleb128 0x1 /* (abbrev code) */ | |
273 | + .uleb128 0x11 /* (TAG: DW_TAG_compile_unit) */ | |
274 | + .byte 0x1 /* DW_children_yes */ | |
275 | + .uleb128 0x25 /* (DW_AT_producer) */ | |
276 | + .uleb128 0x8 /* (DW_FORM_string) */ | |
277 | + .uleb128 0x13 /* (DW_AT_language) */ | |
278 | + .uleb128 0xb /* (DW_FORM_data1) */ | |
279 | + .uleb128 0x3 /* (DW_AT_name) */ | |
280 | + .uleb128 0x8 /* (DW_FORM_string) */ | |
281 | + .byte 0x0 | |
282 | + .byte 0x0 | |
283 | + | |
284 | + .uleb128 0x2 /* (abbrev code) */ | |
285 | + .uleb128 0x13 /* (TAG: DW_TAG_structure_type) */ | |
286 | + .byte 0x1 /* DW_children_yes */ | |
287 | + .uleb128 0x3 /* (DW_AT_name) */ | |
288 | + .uleb128 0x8 /* (DW_FORM_string) */ | |
289 | + .uleb128 0xb /* (DW_AT_byte_size) */ | |
290 | + .uleb128 0xb /* (DW_FORM_data1) */ | |
291 | + .byte 0 | |
292 | + .byte 0 | |
293 | + | |
294 | + .uleb128 0x3 /* (abbrev code) */ | |
295 | + .uleb128 0xd /* (TAG: DW_TAG_member) */ | |
296 | + .byte 0 /* DW_children_no */ | |
297 | + .uleb128 0x3 /* (DW_AT_name) */ | |
298 | + .uleb128 0x8 /* (DW_FORM_string) */ | |
299 | + .uleb128 0x49 /* (DW_AT_type) */ | |
300 | + .uleb128 0x13 /* (DW_FORM_ref4) */ | |
301 | + .uleb128 0x38 /* (DW_AT_data_member_location) */ | |
302 | + .uleb128 0xb /* (DW_FORM_data1) */ | |
303 | + .byte 0 | |
304 | + .byte 0 | |
305 | + | |
306 | + .uleb128 0x4 /* (abbrev code) */ | |
307 | + .uleb128 0x34 /* (TAG: DW_TAG_variable) */ | |
308 | + .byte 0x0 /* DW_children_yes */ | |
309 | + .uleb128 0x3 /* (DW_AT_name) */ | |
310 | + .uleb128 0x8 /* (DW_FORM_string) */ | |
311 | + .uleb128 0x02 /* (DW_AT_location) */ | |
312 | + .uleb128 0xa /* (DW_FORM_block1) */ | |
313 | + .uleb128 0x49 /* (DW_AT_type) */ | |
314 | + .uleb128 0x13 /* (DW_FORM_ref4) */ | |
315 | + .byte 0x0 | |
316 | + .byte 0x0 | |
317 | + | |
318 | + .uleb128 0x5 /* (abbrev code) */ | |
319 | + .uleb128 0xf /* (TAG: DW_TAG_pointer_type) */ | |
320 | + .byte 0x0 /* DW_children_no */ | |
321 | + .uleb128 0xb /* (DW_AT_byte_size) */ | |
322 | + .uleb128 0xb /* (DW_FORM_data1) */ | |
323 | + .uleb128 0x49 /* (DW_AT_type) */ | |
324 | + .uleb128 0x13 /* (DW_FORM_ref4) */ | |
325 | + .byte 0x0 | |
326 | + .byte 0x0 | |
327 | + | |
328 | + .uleb128 6 /* Abbrev code */ | |
329 | + .uleb128 0x2e /* DW_TAG_subprogram */ | |
330 | + .byte 1 /* has_children */ | |
331 | + .uleb128 0x3 /* DW_AT_name */ | |
332 | + .uleb128 0x8 /* DW_FORM_string */ | |
333 | + .uleb128 0x11 /* DW_AT_low_pc */ | |
334 | + .uleb128 0x1 /* DW_FORM_addr */ | |
335 | + .uleb128 0x12 /* DW_AT_high_pc */ | |
336 | + .uleb128 0x1 /* DW_FORM_addr */ | |
337 | + .uleb128 0x49 /* DW_AT_type */ | |
338 | + .uleb128 0x13 /* DW_FORM_ref4 */ | |
339 | + .uleb128 0x3f /* DW_AT_external */ | |
340 | + .uleb128 0xc /* DW_FORM_flag */ | |
341 | + .byte 0x0 /* Terminator */ | |
342 | + .byte 0x0 /* Terminator */ | |
343 | + | |
344 | + .uleb128 0x7 /* (abbrev code) */ | |
345 | + .uleb128 0x24 /* (TAG: DW_TAG_base_type) */ | |
346 | + .byte 0 /* DW_children_no */ | |
347 | + .uleb128 0xb /* (DW_AT_byte_size) */ | |
348 | + .uleb128 0xb /* (DW_FORM_data1) */ | |
349 | + .uleb128 0x3e /* (DW_AT_encoding) */ | |
350 | + .uleb128 0xb /* (DW_FORM_data1) */ | |
351 | + .uleb128 0x3 /* (DW_AT_name) */ | |
352 | + .uleb128 0x8 /* (DW_FORM_string) */ | |
353 | + .byte 0 | |
354 | + .byte 0 | |
355 | + | |
356 | + .byte 0x0 | |
357 | --- /dev/null | |
358 | +++ b/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp | |
359 | @@ -0,0 +1,51 @@ | |
360 | +# Copyright 2011 Free Software Foundation, Inc. | |
361 | + | |
362 | +# This program is free software; you can redistribute it and/or modify | |
363 | +# it under the terms of the GNU General Public License as published by | |
364 | +# the Free Software Foundation; either version 3 of the License, or | |
365 | +# (at your option) any later version. | |
366 | +# | |
367 | +# This program is distributed in the hope that it will be useful, | |
368 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
369 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
370 | +# GNU General Public License for more details. | |
371 | +# | |
372 | +# You should have received a copy of the GNU General Public License | |
373 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
374 | +load_lib dwarf.exp | |
375 | + | |
376 | +# This test can only be run on targets which support DWARF-2 and use gas. | |
377 | +if {![dwarf2_support]} { | |
378 | + return 0 | |
379 | +} | |
380 | + | |
381 | +set testfile "implptr-64bit" | |
382 | +set srcfile ${testfile}.S | |
383 | +set mainfile main.c | |
384 | + | |
385 | +proc test { dwarf_version offset_size addr_size ref_addr_size } { | |
386 | + global testfile srcfile mainfile | |
387 | + | |
388 | + set opts {} | |
389 | + foreach n { dwarf_version offset_size addr_size ref_addr_size } { | |
390 | + lappend opts "additional_flags=-D[string toupper $n]=[expr "\$$n"]" | |
391 | + } | |
392 | + | |
393 | + set name "d${dwarf_version}o${offset_size}a${addr_size}r${ref_addr_size}" | |
394 | + set executable ${testfile}-${name} | |
395 | + if [prepare_for_testing ${testfile}.exp $executable "${srcfile} ${mainfile}" $opts] { | |
396 | + return -1 | |
397 | + } | |
398 | + | |
399 | + if ![runto_main] { | |
400 | + return -1 | |
401 | + } | |
402 | + | |
403 | + gdb_test "p/x p->f" " = 0x1010101" $name | |
404 | +} | |
405 | + | |
406 | +# DWARF_VERSION OFFSET_SIZE ADDR_SIZE REF_ADDR_SIZE | |
407 | +test 2 8 4 4 | |
408 | +test 2 4 8 8 | |
409 | +test 3 8 4 8 | |
410 | +test 3 4 8 4 | |
411 |