412 lines
13 KiB
Diff
412 lines
13 KiB
Diff
|
http://sourceware.org/ml/gdb-patches/2011-09/msg00451.html
|
||
|
Subject: [patch 2/2] Fix DW_OP_GNU_implicit_pointer for DWARF32 v3+ on 64-bit arches
|
||
|
|
||
|
Hi,
|
||
|
|
||
|
on 64-bit targets DWARF-3+ is used DW_OP_GNU_implicit_pointer does not work.
|
||
|
|
||
|
DWARF-2 says:
|
||
|
This type of reference (DW_FORM_ref_addr) is the size of an address on
|
||
|
the target architecture;
|
||
|
DWARF-3 says:
|
||
|
1.5.1 Upward Compatibility
|
||
|
References that use the attribute form DW_FORM_ref_addr are specified
|
||
|
to be four bytes in the DWARF 32-bit format and eight bytes in the
|
||
|
DWARF 64-bit format, while DWARF Version 2 specifies that such
|
||
|
references have the same size as an address on the target system (see
|
||
|
Sections 7.4 and 7.5.4).
|
||
|
|
||
|
(DW_FORM_ref_addr)
|
||
|
In the 32-bit DWARF format, this offset is a 4-byte unsigned value; in
|
||
|
the 64-bit DWARF format, it is an 8-byte unsigned value (see Section
|
||
|
7.4).
|
||
|
|
||
|
GDB currently parsed DW_OP_GNU_implicit_pointer the DWARF-2 way, being
|
||
|
incompatible with DWARF-3+.
|
||
|
|
||
|
I think DW_OP_GNU_implicit_pointer does not make sense to be used from
|
||
|
.debug_frame (DWARF-5 is not yet released to say more) so for .debug_frame its
|
||
|
use is just not permitted (the code would be more complicated otherwise).
|
||
|
|
||
|
No regressions on {x86_64,x86_64-m32,i686}-fedora16pre-linux-gnu.
|
||
|
|
||
|
|
||
|
Thanks,
|
||
|
Jan
|
||
|
|
||
|
|
||
|
gdb/
|
||
|
2011-09-26 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
|
||
|
Fix DW_OP_GNU_implicit_pointer for DWARF32 v3+ on 64-bit arches.
|
||
|
* dwarf2-frame.c (execute_stack_op): Initialize ctx->ref_addr_size.
|
||
|
* dwarf2expr.c (execute_stack_op) <DW_OP_GNU_implicit_pointer>: Use
|
||
|
ctx->ref_addr_size. Handle its invalid value.
|
||
|
* dwarf2expr.h (struct dwarf_expr_context): New field ref_addr_size.
|
||
|
* dwarf2loc.c (dwarf2_evaluate_loc_desc_full)
|
||
|
(dwarf2_loc_desc_needs_frame): Initialize ctx->ref_addr_size.
|
||
|
* dwarf2loc.h (dwarf2_per_cu_ref_addr_size): New declaration.
|
||
|
* dwarf2read.c (decode_locdesc): Initialize ctx->ref_addr_size.
|
||
|
(dwarf2_per_cu_ref_addr_size): New function.
|
||
|
|
||
|
gdb/testsuite/
|
||
|
2011-09-26 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
|
||
|
Fix DW_OP_GNU_implicit_pointer for DWARF32 v3+ on 64-bit arches.
|
||
|
* gdb.dwarf2/implptr-64bit.S: New file.
|
||
|
* gdb.dwarf2/implptr-64bit.exp: New file.
|
||
|
|
||
|
--- a/gdb/dwarf2-frame.c
|
||
|
+++ b/gdb/dwarf2-frame.c
|
||
|
@@ -371,6 +371,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
|
||
|
|
||
|
ctx->gdbarch = get_frame_arch (this_frame);
|
||
|
ctx->addr_size = addr_size;
|
||
|
+ ctx->ref_addr_size = -1;
|
||
|
ctx->offset = offset;
|
||
|
ctx->baton = this_frame;
|
||
|
ctx->funcs = &dwarf2_frame_ctx_funcs;
|
||
|
--- a/gdb/dwarf2expr.c
|
||
|
+++ b/gdb/dwarf2expr.c
|
||
|
@@ -709,10 +709,14 @@ execute_stack_op (struct dwarf_expr_context *ctx,
|
||
|
ULONGEST die;
|
||
|
LONGEST len;
|
||
|
|
||
|
+ if (ctx->ref_addr_size == -1)
|
||
|
+ error (_("DWARF-2 expression error: DW_OP_GNU_implicit_pointer "
|
||
|
+ "is not allowed in frame context"));
|
||
|
+
|
||
|
/* The referred-to DIE. */
|
||
|
- ctx->len = extract_unsigned_integer (op_ptr, ctx->addr_size,
|
||
|
+ ctx->len = extract_unsigned_integer (op_ptr, ctx->ref_addr_size,
|
||
|
byte_order);
|
||
|
- op_ptr += ctx->addr_size;
|
||
|
+ op_ptr += ctx->ref_addr_size;
|
||
|
|
||
|
/* The byte offset into the data. */
|
||
|
op_ptr = read_sleb128 (op_ptr, op_end, &len);
|
||
|
--- a/gdb/dwarf2expr.h
|
||
|
+++ b/gdb/dwarf2expr.h
|
||
|
@@ -125,6 +125,10 @@ struct dwarf_expr_context
|
||
|
/* Target address size in bytes. */
|
||
|
int addr_size;
|
||
|
|
||
|
+ /* DW_FORM_ref_addr size in bytes. If -1 DWARF is executed from a frame
|
||
|
+ context and operations depending on DW_FORM_ref_addr are not allowed. */
|
||
|
+ int ref_addr_size;
|
||
|
+
|
||
|
/* Offset used to relocate DW_OP_addr argument. */
|
||
|
CORE_ADDR offset;
|
||
|
|
||
|
--- a/gdb/dwarf2loc.c
|
||
|
+++ b/gdb/dwarf2loc.c
|
||
|
@@ -1118,6 +1118,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
|
||
|
|
||
|
ctx->gdbarch = get_objfile_arch (objfile);
|
||
|
ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
|
||
|
+ ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
|
||
|
ctx->offset = dwarf2_per_cu_text_offset (per_cu);
|
||
|
ctx->baton = &baton;
|
||
|
ctx->funcs = &dwarf_expr_ctx_funcs;
|
||
|
@@ -1398,6 +1399,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size,
|
||
|
|
||
|
ctx->gdbarch = get_objfile_arch (objfile);
|
||
|
ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
|
||
|
+ ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
|
||
|
ctx->offset = dwarf2_per_cu_text_offset (per_cu);
|
||
|
ctx->baton = &baton;
|
||
|
ctx->funcs = &needs_frame_ctx_funcs;
|
||
|
--- a/gdb/dwarf2loc.h
|
||
|
+++ b/gdb/dwarf2loc.h
|
||
|
@@ -39,6 +39,10 @@ struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu);
|
||
|
/* Return the address size given in the compilation unit header for CU. */
|
||
|
CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu);
|
||
|
|
||
|
+/* Return the DW_FORM_ref_addr size given in the compilation unit header for
|
||
|
+ CU. */
|
||
|
+int dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *cu);
|
||
|
+
|
||
|
/* Return the offset size given in the compilation unit header for CU. */
|
||
|
int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu);
|
||
|
|
||
|
--- a/gdb/dwarf2read.c
|
||
|
+++ b/gdb/dwarf2read.c
|
||
|
@@ -15238,6 +15239,22 @@ dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu)
|
||
|
return cu_headerp->offset_size;
|
||
|
}
|
||
|
|
||
|
+/* See its dwarf2loc.h declaration. */
|
||
|
+
|
||
|
+int
|
||
|
+dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *per_cu)
|
||
|
+{
|
||
|
+ struct comp_unit_head cu_header_local;
|
||
|
+ const struct comp_unit_head *cu_headerp;
|
||
|
+
|
||
|
+ cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu);
|
||
|
+
|
||
|
+ if (cu_headerp->version == 2)
|
||
|
+ return cu_headerp->addr_size;
|
||
|
+ else
|
||
|
+ return cu_headerp->offset_size;
|
||
|
+}
|
||
|
+
|
||
|
/* Return the text offset of the CU. The returned offset comes from
|
||
|
this CU's objfile. If this objfile came from a separate debuginfo
|
||
|
file, then the offset may be different from the corresponding
|
||
|
--- /dev/null
|
||
|
+++ b/gdb/testsuite/gdb.dwarf2/implptr-64bit.S
|
||
|
@@ -0,0 +1,197 @@
|
||
|
+/* Copyright 2010, 2011 Free Software Foundation, Inc.
|
||
|
+
|
||
|
+ This program is free software; you can redistribute it and/or modify
|
||
|
+ it under the terms of the GNU General Public License as published by
|
||
|
+ the Free Software Foundation; either version 3 of the License, or
|
||
|
+ (at your option) any later version.
|
||
|
+
|
||
|
+ This program is distributed in the hope that it will be useful,
|
||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ GNU General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU General Public License
|
||
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
+
|
||
|
+ .section .debug_info
|
||
|
+d:
|
||
|
+ /* Length of Compilation Unit Info */
|
||
|
+#if OFFSET_SIZE == 4
|
||
|
+# define OFFSET .4byte
|
||
|
+ .4byte debug_end - 1f
|
||
|
+#elif OFFSET_SIZE == 8
|
||
|
+# define OFFSET .8byte
|
||
|
+ .4byte 0xffffffff
|
||
|
+ .8byte debug_end - 1f
|
||
|
+#else
|
||
|
+# error
|
||
|
+#endif
|
||
|
+#if ADDR_SIZE == 4
|
||
|
+# define ADDR .4byte
|
||
|
+#elif ADDR_SIZE == 8
|
||
|
+# define ADDR .8byte
|
||
|
+#else
|
||
|
+# error
|
||
|
+#endif
|
||
|
+#if REF_ADDR_SIZE == 4
|
||
|
+# define REF_ADDR .4byte
|
||
|
+#elif REF_ADDR_SIZE == 8
|
||
|
+# define REF_ADDR .8byte
|
||
|
+#else
|
||
|
+# error
|
||
|
+#endif
|
||
|
+1:
|
||
|
+ .2byte DWARF_VERSION /* DWARF version number */
|
||
|
+ OFFSET .Ldebug_abbrev0 /* Offset Into Abbrev. Section */
|
||
|
+ .byte ADDR_SIZE /* Pointer Size (in bytes) */
|
||
|
+
|
||
|
+ .uleb128 0x1 /* (DIE (0xb) DW_TAG_compile_unit) */
|
||
|
+ .ascii "GNU C 4.4.3\0" /* DW_AT_producer */
|
||
|
+ .byte 0x1 /* DW_AT_language */
|
||
|
+ .ascii "1.c\0" /* DW_AT_name */
|
||
|
+
|
||
|
+.Ltype_int:
|
||
|
+ .uleb128 0x7 /* DW_TAG_base_type */
|
||
|
+ .byte 0x4 /* DW_AT_byte_size */
|
||
|
+ .byte 0x5 /* DW_AT_encoding */
|
||
|
+ .ascii "int\0" /* DW_AT_name */
|
||
|
+
|
||
|
+.Ltype_struct:
|
||
|
+ .uleb128 0x2 /* DW_TAG_structure_type */
|
||
|
+ .ascii "s\0" /* DW_AT_name */
|
||
|
+ .byte 4 /* DW_AT_byte_size */
|
||
|
+
|
||
|
+ .uleb128 0x3 /* DW_TAG_member */
|
||
|
+ .ascii "f\0" /* DW_AT_name */
|
||
|
+ .4byte .Ltype_int - d /* DW_AT_type */
|
||
|
+ .byte 0 /* DW_AT_data_member_location */
|
||
|
+
|
||
|
+ .byte 0x0 /* end of children of DW_TAG_structure_type */
|
||
|
+
|
||
|
+ .uleb128 6 /* Abbrev: DW_TAG_subprogram */
|
||
|
+ .ascii "main\0" /* DW_AT_name */
|
||
|
+ ADDR main /* DW_AT_low_pc */
|
||
|
+ ADDR main + 0x100 /* DW_AT_high_pc */
|
||
|
+ .4byte .Ltype_int - d /* DW_AT_type */
|
||
|
+ .byte 1 /* DW_AT_external */
|
||
|
+
|
||
|
+.Ltype_structptr:
|
||
|
+ .uleb128 0x5 /* DW_TAG_pointer_type */
|
||
|
+ .byte ADDR_SIZE /* DW_AT_byte_size */
|
||
|
+ .4byte .Ltype_struct - d /* DW_AT_type */
|
||
|
+
|
||
|
+.Lvar_out:
|
||
|
+ .uleb128 0x4 /* (DW_TAG_variable) */
|
||
|
+ .ascii "v\0" /* DW_AT_name */
|
||
|
+ .byte 2f - 1f /* DW_AT_location: DW_FORM_block1 */
|
||
|
+1:
|
||
|
+ .byte 0x9e /* DW_OP_implicit_value */
|
||
|
+ .uleb128 2f - 3f
|
||
|
+3:
|
||
|
+ .byte 1, 1, 1, 1
|
||
|
+2:
|
||
|
+ .4byte .Ltype_struct - d /* DW_AT_type */
|
||
|
+
|
||
|
+ .uleb128 0x4 /* (DW_TAG_variable) */
|
||
|
+ .ascii "p\0" /* DW_AT_name */
|
||
|
+ .byte 2f - 1f /* DW_AT_location: DW_FORM_block1 */
|
||
|
+1:
|
||
|
+ .byte 0xf2 /* DW_OP_GNU_implicit_pointer */
|
||
|
+ REF_ADDR .Lvar_out - d /* referenced DIE */
|
||
|
+ .sleb128 0 /* offset */
|
||
|
+2:
|
||
|
+ .4byte .Ltype_structptr - d /* DW_AT_type */
|
||
|
+
|
||
|
+ .byte 0x0 /* end of children of main */
|
||
|
+
|
||
|
+ .byte 0x0 /* end of children of CU */
|
||
|
+debug_end:
|
||
|
+
|
||
|
+ .section .debug_abbrev
|
||
|
+.Ldebug_abbrev0:
|
||
|
+
|
||
|
+ .uleb128 0x1 /* (abbrev code) */
|
||
|
+ .uleb128 0x11 /* (TAG: DW_TAG_compile_unit) */
|
||
|
+ .byte 0x1 /* DW_children_yes */
|
||
|
+ .uleb128 0x25 /* (DW_AT_producer) */
|
||
|
+ .uleb128 0x8 /* (DW_FORM_string) */
|
||
|
+ .uleb128 0x13 /* (DW_AT_language) */
|
||
|
+ .uleb128 0xb /* (DW_FORM_data1) */
|
||
|
+ .uleb128 0x3 /* (DW_AT_name) */
|
||
|
+ .uleb128 0x8 /* (DW_FORM_string) */
|
||
|
+ .byte 0x0
|
||
|
+ .byte 0x0
|
||
|
+
|
||
|
+ .uleb128 0x2 /* (abbrev code) */
|
||
|
+ .uleb128 0x13 /* (TAG: DW_TAG_structure_type) */
|
||
|
+ .byte 0x1 /* DW_children_yes */
|
||
|
+ .uleb128 0x3 /* (DW_AT_name) */
|
||
|
+ .uleb128 0x8 /* (DW_FORM_string) */
|
||
|
+ .uleb128 0xb /* (DW_AT_byte_size) */
|
||
|
+ .uleb128 0xb /* (DW_FORM_data1) */
|
||
|
+ .byte 0
|
||
|
+ .byte 0
|
||
|
+
|
||
|
+ .uleb128 0x3 /* (abbrev code) */
|
||
|
+ .uleb128 0xd /* (TAG: DW_TAG_member) */
|
||
|
+ .byte 0 /* DW_children_no */
|
||
|
+ .uleb128 0x3 /* (DW_AT_name) */
|
||
|
+ .uleb128 0x8 /* (DW_FORM_string) */
|
||
|
+ .uleb128 0x49 /* (DW_AT_type) */
|
||
|
+ .uleb128 0x13 /* (DW_FORM_ref4) */
|
||
|
+ .uleb128 0x38 /* (DW_AT_data_member_location) */
|
||
|
+ .uleb128 0xb /* (DW_FORM_data1) */
|
||
|
+ .byte 0
|
||
|
+ .byte 0
|
||
|
+
|
||
|
+ .uleb128 0x4 /* (abbrev code) */
|
||
|
+ .uleb128 0x34 /* (TAG: DW_TAG_variable) */
|
||
|
+ .byte 0x0 /* DW_children_yes */
|
||
|
+ .uleb128 0x3 /* (DW_AT_name) */
|
||
|
+ .uleb128 0x8 /* (DW_FORM_string) */
|
||
|
+ .uleb128 0x02 /* (DW_AT_location) */
|
||
|
+ .uleb128 0xa /* (DW_FORM_block1) */
|
||
|
+ .uleb128 0x49 /* (DW_AT_type) */
|
||
|
+ .uleb128 0x13 /* (DW_FORM_ref4) */
|
||
|
+ .byte 0x0
|
||
|
+ .byte 0x0
|
||
|
+
|
||
|
+ .uleb128 0x5 /* (abbrev code) */
|
||
|
+ .uleb128 0xf /* (TAG: DW_TAG_pointer_type) */
|
||
|
+ .byte 0x0 /* DW_children_no */
|
||
|
+ .uleb128 0xb /* (DW_AT_byte_size) */
|
||
|
+ .uleb128 0xb /* (DW_FORM_data1) */
|
||
|
+ .uleb128 0x49 /* (DW_AT_type) */
|
||
|
+ .uleb128 0x13 /* (DW_FORM_ref4) */
|
||
|
+ .byte 0x0
|
||
|
+ .byte 0x0
|
||
|
+
|
||
|
+ .uleb128 6 /* Abbrev code */
|
||
|
+ .uleb128 0x2e /* DW_TAG_subprogram */
|
||
|
+ .byte 1 /* has_children */
|
||
|
+ .uleb128 0x3 /* DW_AT_name */
|
||
|
+ .uleb128 0x8 /* DW_FORM_string */
|
||
|
+ .uleb128 0x11 /* DW_AT_low_pc */
|
||
|
+ .uleb128 0x1 /* DW_FORM_addr */
|
||
|
+ .uleb128 0x12 /* DW_AT_high_pc */
|
||
|
+ .uleb128 0x1 /* DW_FORM_addr */
|
||
|
+ .uleb128 0x49 /* DW_AT_type */
|
||
|
+ .uleb128 0x13 /* DW_FORM_ref4 */
|
||
|
+ .uleb128 0x3f /* DW_AT_external */
|
||
|
+ .uleb128 0xc /* DW_FORM_flag */
|
||
|
+ .byte 0x0 /* Terminator */
|
||
|
+ .byte 0x0 /* Terminator */
|
||
|
+
|
||
|
+ .uleb128 0x7 /* (abbrev code) */
|
||
|
+ .uleb128 0x24 /* (TAG: DW_TAG_base_type) */
|
||
|
+ .byte 0 /* DW_children_no */
|
||
|
+ .uleb128 0xb /* (DW_AT_byte_size) */
|
||
|
+ .uleb128 0xb /* (DW_FORM_data1) */
|
||
|
+ .uleb128 0x3e /* (DW_AT_encoding) */
|
||
|
+ .uleb128 0xb /* (DW_FORM_data1) */
|
||
|
+ .uleb128 0x3 /* (DW_AT_name) */
|
||
|
+ .uleb128 0x8 /* (DW_FORM_string) */
|
||
|
+ .byte 0
|
||
|
+ .byte 0
|
||
|
+
|
||
|
+ .byte 0x0
|
||
|
--- /dev/null
|
||
|
+++ b/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp
|
||
|
@@ -0,0 +1,51 @@
|
||
|
+# Copyright 2011 Free Software Foundation, Inc.
|
||
|
+
|
||
|
+# This program is free software; you can redistribute it and/or modify
|
||
|
+# it under the terms of the GNU General Public License as published by
|
||
|
+# the Free Software Foundation; either version 3 of the License, or
|
||
|
+# (at your option) any later version.
|
||
|
+#
|
||
|
+# This program is distributed in the hope that it will be useful,
|
||
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+# GNU General Public License for more details.
|
||
|
+#
|
||
|
+# You should have received a copy of the GNU General Public License
|
||
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+load_lib dwarf.exp
|
||
|
+
|
||
|
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||
|
+if {![dwarf2_support]} {
|
||
|
+ return 0
|
||
|
+}
|
||
|
+
|
||
|
+set testfile "implptr-64bit"
|
||
|
+set srcfile ${testfile}.S
|
||
|
+set mainfile main.c
|
||
|
+
|
||
|
+proc test { dwarf_version offset_size addr_size ref_addr_size } {
|
||
|
+ global testfile srcfile mainfile
|
||
|
+
|
||
|
+ set opts {}
|
||
|
+ foreach n { dwarf_version offset_size addr_size ref_addr_size } {
|
||
|
+ lappend opts "additional_flags=-D[string toupper $n]=[expr "\$$n"]"
|
||
|
+ }
|
||
|
+
|
||
|
+ set name "d${dwarf_version}o${offset_size}a${addr_size}r${ref_addr_size}"
|
||
|
+ set executable ${testfile}-${name}
|
||
|
+ if [prepare_for_testing ${testfile}.exp $executable "${srcfile} ${mainfile}" $opts] {
|
||
|
+ return -1
|
||
|
+ }
|
||
|
+
|
||
|
+ if ![runto_main] {
|
||
|
+ return -1
|
||
|
+ }
|
||
|
+
|
||
|
+ gdb_test "p/x p->f" " = 0x1010101" $name
|
||
|
+}
|
||
|
+
|
||
|
+# DWARF_VERSION OFFSET_SIZE ADDR_SIZE REF_ADDR_SIZE
|
||
|
+test 2 8 4 4
|
||
|
+test 2 4 8 8
|
||
|
+test 3 8 4 8
|
||
|
+test 3 4 8 4
|
||
|
|