From 181cebd4f8897990b94df2d979b16911d2281657 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 9 Oct 2011 18:46:41 +0000 Subject: [PATCH] gdb/ 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) : 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/ 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. --- gdb/ChangeLog | 13 ++ gdb/dwarf2-frame.c | 1 + gdb/dwarf2expr.c | 8 +- gdb/dwarf2expr.h | 4 + gdb/dwarf2loc.c | 2 + gdb/dwarf2loc.h | 4 + gdb/dwarf2read.c | 17 ++ gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.dwarf2/implptr-64bit.S | 197 +++++++++++++++++++++ gdb/testsuite/gdb.dwarf2/implptr-64bit.exp | 52 ++++++ 10 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/implptr-64bit.S create mode 100644 gdb/testsuite/gdb.dwarf2/implptr-64bit.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a3ca67f74b7..ee69551aad3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2011-10-09 Jan Kratochvil + + 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) : 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. + 2011-10-09 Jan Kratochvil Code cleanup. diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index ee80cb0b22e..232b223dbec 100644 --- 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; diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 83c7db7f5d8..c2966070385 100644 --- 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); diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 9e8a04e1672..9bd7268971c 100644 --- 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; diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 12b4997fb2f..b0881dbc29d 100644 --- 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; diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index 08849ed5474..a0ea031e8dd 100644 --- 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); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index a755f9a0c4c..c8b3f11cfa2 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14223,6 +14223,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) ctx->gdbarch = get_objfile_arch (objfile); ctx->addr_size = cu->header.addr_size; + ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (cu->per_cu); ctx->offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ctx->baton = ctx; ctx->funcs = &decode_locdesc_ctx_funcs; @@ -15313,6 +15314,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 diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8c9a7195775..d21d922247b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-10-09 Jan Kratochvil + + 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. + 2011-10-09 Jan Kratochvil Fix initial language detection with -readnow. diff --git a/gdb/testsuite/gdb.dwarf2/implptr-64bit.S b/gdb/testsuite/gdb.dwarf2/implptr-64bit.S new file mode 100644 index 00000000000..6efb7deb4c2 --- /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 . */ + + .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 diff --git a/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp b/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp new file mode 100644 index 00000000000..c2bcd2347fa --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp @@ -0,0 +1,52 @@ +# 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 . +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 + + # 32-bit targets do not support any of the testcases; keep quiet there. + set opts {quiet} + 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 -- 2.30.2