This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: interface to partial support for DW_OP_piece in dwarf2expr.[ch]


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  <jimb@redhat.com>

	* 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:
+ #
+ #   <upper half> DW_OP_piece 4 <lower half> 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:
+   
+      <upper half> DW_OP_piece 4 <lower half> 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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]