From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10021 invoked by alias); 10 Aug 2004 19:55:59 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 10014 invoked from network); 10 Aug 2004 19:55:56 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 10 Aug 2004 19:55:56 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.10/8.12.10) with ESMTP id i7AJtue1026779 for ; Tue, 10 Aug 2004 15:55:56 -0400 Received: from zenia.home.redhat.com (porkchop.devel.redhat.com [172.16.58.2]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id i7AJtqa12971; Tue, 10 Aug 2004 15:55:52 -0400 To: Eli Zaretskii Cc: kettenis@jive.nl, drow@false.org, cagney@gnu.org, gdb@sources.redhat.com Subject: Re: interface to partial support for DW_OP_piece in dwarf2expr.[ch] References: <4111145F.7000504@gnu.org> <41112BAE dot 9080304 at gnu dot org> <41115B4F dot 1080700 at gnu dot org> <20040804230242 dot GA10332 at nevyn dot them dot org> <200408050952.i759qXFK010181@juw15.nfra.nl> <9787-Fri06Aug2004123633+0300-eliz@gnu.org> From: Jim Blandy Date: Tue, 10 Aug 2004 19:55:00 -0000 In-Reply-To: <9787-Fri06Aug2004123633+0300-eliz@gnu.org> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2004-08/txt/msg00153.txt.bz2 To put (part of) the discussion of the Dwarf piece support on a concrete basis, here's a patch that adds the gdbarch method; it depends on the dwarf2expr piece interface patch I posted earlier. This change, or something like it, would allow immediate improvements over GDB's current behavior, and I don't see that it has much structural cost: - It doesn't affect the design of full scattered values: when that is implemented, dwarf2_evaluate_loc_desc will just become able to construct 'struct value' objects for more kinds of Dwarf expression results. - When we do support full scattered values, the clause this patch adds to dwarf2_evaluate_loc_desc, the gdbarch method, and whatever arch-specific implementations people have written for it can be simply deleted, with no change in user-visible behavior. 2004-08-09 Jim Blandy * gdbarch.sh (dwarf_simplify_register_pieces): New method. Add forward declaration for 'struct dwarf_expr_piece'. * gdbarch.c, gdbarch.h: Regenerated. * dwarf2loc.c (dwarf2_evaluate_loc_desc): Try to simplify multi-piece expression results before giving up. * arch-utils.c (dwarf_never_simplify_pieces): New function. * arch-utils.h (struct dwarf_expr_piece): Forward decl for struct type, used in ... (dwarf_never_simplify_pieces): New declaration. diff -crp -x '*~' -x '.#*' -x CVS gdb/gdbarch.sh gdb/gdbarch.sh *** gdb/gdbarch.sh 2004-08-09 19:29:28.000000000 -0500 --- gdb/gdbarch.sh 2004-08-10 11:31:22.000000000 -0500 *************** f:=:int:dwarf_reg_to_regnum:int dwarf_re *** 451,456 **** --- 451,480 ---- # Convert from an sdb register number to an internal gdb register number. f:=:int:sdb_reg_to_regnum:int sdb_regnr:sdb_regnr::no_op_reg_to_regnum::0 f:=:int:dwarf2_reg_to_regnum:int dwarf2_regnr:dwarf2_regnr::no_op_reg_to_regnum::0 + + # On some architectures, GDB has registers that Dwarf treats as the + # concatenation of two separate registers. For example, PowerPC + # variants implementing the SPE APU have 64-bit general-purpose + # registers. GDB refers to the lower 32 bits of each register as 'r0' + # -- 'r31', and the full 64-bit registers as 'ev0' -- 'ev31'. + # However, the Dwarf register numbering treats the upper halves as + # separate registers. + # + # Dwarf location expressions describe variables allocated to such + # registers using a series of DW_OP_piece operations. In the case + # above, the expressions would have the form: + # + # DW_OP_piece 4 DW_OP_piece 4. + # + # However, since GDB does have a register that corresponds to the + # entire variable, it can simply say the variable lives in that + # register; it needn't use a complicated location description. + # + # Given an array of NUM_PIECES pieces PIECES, return the number of the + # register that is equivalent to those pieces, or -1 if there is no + # such register. + m::int:dwarf_simplify_register_pieces:int num_pieces, struct dwarf_expr_piece *pieces:num_pieces, pieces::dwarf_never_simplify_pieces + f:=:const char *:register_name:int regnr:regnr # REGISTER_TYPE is a direct replacement for DEPRECATED_REGISTER_VIRTUAL_TYPE. *************** struct regset; *** 773,778 **** --- 797,803 ---- struct disassemble_info; struct target_ops; struct obstack; + struct dwarf_expr_piece; extern struct gdbarch *current_gdbarch; diff -crp -x '*~' -x '.#*' -x CVS gdb/dwarf2loc.c gdb/dwarf2loc.c *** gdb/dwarf2loc.c 2004-08-10 02:01:24.000000000 -0500 --- gdb/dwarf2loc.c 2004-08-10 11:34:39.000000000 -0500 *************** dwarf2_evaluate_loc_desc (struct symbol *** 230,240 **** dwarf_expr_eval (ctx, data, size); if (ctx->num_pieces > 0) { ! /* We haven't implemented splicing together pieces from ! arbitrary sources yet. */ ! error ("The value of variable '%s' is distributed across several\n" ! "locations, and GDB cannot access its value.\n", ! SYMBOL_NATURAL_NAME (var)); } else if (ctx->in_reg) { --- 230,247 ---- dwarf_expr_eval (ctx, data, size); if (ctx->num_pieces > 0) { ! CORE_ADDR simplified ! = gdbarch_dwarf_simplify_register_pieces (arch, ctx->num_pieces, ! ctx->pieces); ! if (simplified >= 0) ! retval = value_from_register (SYMBOL_TYPE (var), simplified, frame); ! ! /* We haven't implemented the more complex case of splicing ! together pieces from arbitrary sources yet. */ ! else ! error ("The value of variable '%s' is distributed across several\n" ! "locations, and GDB cannot access its value.\n", ! SYMBOL_NATURAL_NAME (var)); } else if (ctx->in_reg) { diff -crp -x '*~' -x '.#*' -x CVS gdb/arch-utils.h gdb/arch-utils.h *** gdb/arch-utils.h 2004-08-09 19:29:27.000000000 -0500 --- gdb/arch-utils.h 2004-08-10 11:32:03.000000000 -0500 *************** struct frame_info; *** 28,33 **** --- 28,34 ---- struct minimal_symbol; struct type; struct gdbarch_info; + struct dwarf_expr_piece; /* gdbarch trace variable */ extern int gdbarch_debug; *************** extern gdbarch_convert_from_func_ptr_add *** 72,77 **** --- 73,82 ---- extern int no_op_reg_to_regnum (int reg); + /* Dwarf piece simplifier that never simplifies anything. */ + extern int dwarf_never_simplify_pieces (int num_pieces, + struct dwarf_expr_piece *pieces); + /* Do nothing version of elf_make_msymbol_special. */ void default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym); diff -crp -x '*~' -x '.#*' -x CVS gdb/arch-utils.c gdb/arch-utils.c *** gdb/arch-utils.c 2004-08-09 19:29:27.000000000 -0500 --- gdb/arch-utils.c 2004-08-10 11:32:17.000000000 -0500 *************** no_op_reg_to_regnum (int reg) *** 228,233 **** --- 228,240 ---- return reg; } + int + dwarf_never_simplify_pieces (int num_pieces, + struct dwarf_expr_piece *pieces) + { + return -1; + } + void default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym) { diff -crp -x '*~' -x '.#*' -x CVS gdb/gdbarch.c gdb/gdbarch.c *** gdb/gdbarch.c 2004-08-09 19:29:28.000000000 -0500 --- gdb/gdbarch.c 2004-08-10 11:28:42.000000000 -0500 *************** struct gdbarch *** 155,160 **** --- 155,161 ---- gdbarch_dwarf_reg_to_regnum_ftype *dwarf_reg_to_regnum; gdbarch_sdb_reg_to_regnum_ftype *sdb_reg_to_regnum; gdbarch_dwarf2_reg_to_regnum_ftype *dwarf2_reg_to_regnum; + gdbarch_dwarf_simplify_register_pieces_ftype *dwarf_simplify_register_pieces; gdbarch_register_name_ftype *register_name; gdbarch_register_type_ftype *register_type; gdbarch_deprecated_register_byte_ftype *deprecated_register_byte; *************** struct gdbarch startup_gdbarch = *** 281,286 **** --- 282,288 ---- 0, /* dwarf_reg_to_regnum */ 0, /* sdb_reg_to_regnum */ 0, /* dwarf2_reg_to_regnum */ + dwarf_never_simplify_pieces, /* dwarf_simplify_register_pieces */ 0, /* register_name */ 0, /* register_type */ generic_register_byte, /* deprecated_register_byte */ *************** gdbarch_alloc (const struct gdbarch_info *** 414,419 **** --- 416,422 ---- current_gdbarch->dwarf_reg_to_regnum = no_op_reg_to_regnum; current_gdbarch->sdb_reg_to_regnum = no_op_reg_to_regnum; current_gdbarch->dwarf2_reg_to_regnum = no_op_reg_to_regnum; + current_gdbarch->dwarf_simplify_register_pieces = dwarf_never_simplify_pieces; current_gdbarch->deprecated_register_byte = generic_register_byte; current_gdbarch->deprecated_fp_regnum = -1; current_gdbarch->call_dummy_location = AT_ENTRY_POINT; *************** verify_gdbarch (struct gdbarch *current_ *** 541,546 **** --- 544,552 ---- /* Skip verify of dwarf_reg_to_regnum, invalid_p == 0 */ /* Skip verify of sdb_reg_to_regnum, invalid_p == 0 */ /* Skip verify of dwarf2_reg_to_regnum, invalid_p == 0 */ + if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) + && (current_gdbarch->dwarf_simplify_register_pieces == dwarf_never_simplify_pieces)) + fprintf_unfiltered (log, "\n\tdwarf_simplify_register_pieces"); /* Skip verify of register_type, has predicate */ /* Skip verify of deprecated_register_byte, has predicate */ /* Skip verify of unwind_dummy_id, has predicate */ *************** gdbarch_dump (struct gdbarch *current_gd *** 1027,1032 **** --- 1033,1041 ---- fprintf_unfiltered (file, "gdbarch_dump: dwarf_reg_to_regnum = <0x%lx>\n", (long) current_gdbarch->dwarf_reg_to_regnum); + fprintf_unfiltered (file, + "gdbarch_dump: dwarf_simplify_register_pieces = <0x%lx>\n", + (long) current_gdbarch->dwarf_simplify_register_pieces); #ifdef ECOFF_REG_TO_REGNUM fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", *************** set_gdbarch_dwarf2_reg_to_regnum (struct *** 2220,2225 **** --- 2229,2251 ---- gdbarch->dwarf2_reg_to_regnum = dwarf2_reg_to_regnum; } + int + gdbarch_dwarf_simplify_register_pieces (struct gdbarch *gdbarch, int num_pieces, struct dwarf_expr_piece *pieces) + { + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->dwarf_simplify_register_pieces != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_dwarf_simplify_register_pieces called\n"); + return gdbarch->dwarf_simplify_register_pieces (gdbarch, num_pieces, pieces); + } + + void + set_gdbarch_dwarf_simplify_register_pieces (struct gdbarch *gdbarch, + gdbarch_dwarf_simplify_register_pieces_ftype dwarf_simplify_register_pieces) + { + gdbarch->dwarf_simplify_register_pieces = dwarf_simplify_register_pieces; + } + const char * gdbarch_register_name (struct gdbarch *gdbarch, int regnr) { diff -crp -x '*~' -x '.#*' -x CVS gdb/gdbarch.h gdb/gdbarch.h *** gdb/gdbarch.h 2004-08-09 19:29:28.000000000 -0500 --- gdb/gdbarch.h 2004-08-10 11:28:42.000000000 -0500 *************** struct regset; *** 49,54 **** --- 49,55 ---- struct disassemble_info; struct target_ops; struct obstack; + struct dwarf_expr_piece; extern struct gdbarch *current_gdbarch; *************** extern void set_gdbarch_dwarf2_reg_to_re *** 461,466 **** --- 462,493 ---- #define DWARF2_REG_TO_REGNUM(dwarf2_regnr) (gdbarch_dwarf2_reg_to_regnum (current_gdbarch, dwarf2_regnr)) #endif + /* On some architectures, GDB has registers that Dwarf treats as the + concatenation of two separate registers. For example, PowerPC + variants implementing the SPE APU have 64-bit general-purpose + registers. GDB refers to the lower 32 bits of each register as 'r0' + -- 'r31', and the full 64-bit registers as 'ev0' -- 'ev31'. + However, the Dwarf register numbering treats the upper halves as + separate registers. + + Dwarf location expressions describe variables allocated to such + registers using a series of DW_OP_piece operations. In the case + above, the expressions would have the form: + + DW_OP_piece 4 DW_OP_piece 4. + + However, since GDB does have a register that corresponds to the + entire variable, it can simply say the variable lives in that + register; it needn't use a complicated location description. + + Given an array of NUM_PIECES pieces PIECES, return the number of the + register that is equivalent to those pieces, or -1 if there is no + such register. */ + + typedef int (gdbarch_dwarf_simplify_register_pieces_ftype) (struct gdbarch *gdbarch, int num_pieces, struct dwarf_expr_piece *pieces); + extern int gdbarch_dwarf_simplify_register_pieces (struct gdbarch *gdbarch, int num_pieces, struct dwarf_expr_piece *pieces); + extern void set_gdbarch_dwarf_simplify_register_pieces (struct gdbarch *gdbarch, gdbarch_dwarf_simplify_register_pieces_ftype *dwarf_simplify_register_pieces); + typedef const char * (gdbarch_register_name_ftype) (int regnr); extern const char * gdbarch_register_name (struct gdbarch *gdbarch, int regnr); extern void set_gdbarch_register_name (struct gdbarch *gdbarch, gdbarch_register_name_ftype *register_name);