This is the mail archive of the gdb-patches@sourceware.org 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]

FYI: fix some DWARF disassembler bugs


I'm checking this in on the trunk.

While investigating a different bug, I ran across a few problems in our
DWARF expression disassembler:

* In some cases, we were calling gdbarch_register_name with the DWARF
  register number, not the GDB register number.

* I forgot to update the disassembler for the typed DWARF extension.

This patch fixes these problems.

Built and regtested by the buildbot.  I also tried it by hand on a
program that uses the typed DWARF extension.

Tom

2011-07-08  Tom Tromey  <tromey@redhat.com>

	* dwarf2loc.c (locexpr_regname): New function.
	(locexpr_describe_location_piece): Use it.
	(disassemble_dwarf_expression): Add per_cu argument.  Use
	locexpr_regname.
	<DW_OP_GNU_deref_type, DW_OP_GNU_const_type,
	DW_OP_GNU_regval_type, DW_OP_GNU_convert, DW_OP_GNU_reinterpret>:
	New cases.
	(locexpr_describe_location_1): Add per_cu argument.
	(locexpr_describe_location): Update.
	(loclist_describe_location): Update.

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 9afb186..baac1c6 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2185,6 +2185,18 @@ piece_end_p (const gdb_byte *data, const gdb_byte *end)
   return data == end || data[0] == DW_OP_piece || data[0] == DW_OP_bit_piece;
 }
 
+/* Helper for locexpr_describe_location_piece that finds the name of a
+   DWARF register.  */
+
+static const char *
+locexpr_regname (struct gdbarch *gdbarch, int dwarf_regnum)
+{
+  int regnum;
+
+  regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum);
+  return gdbarch_register_name (gdbarch, regnum);
+}
+
 /* Nicely describe a single piece of a location, returning an updated
    position in the bytecode sequence.  This function cannot recognize
    all locations; if a location is not recognized, it simply returns
@@ -2197,13 +2209,11 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 				 unsigned int addr_size)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  int regno;
 
   if (data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31)
     {
-      regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_reg0);
       fprintf_filtered (stream, _("a variable in $%s"),
-			gdbarch_register_name (gdbarch, regno));
+			locexpr_regname (gdbarch, data[0] - DW_OP_reg0));
       data += 1;
     }
   else if (data[0] == DW_OP_regx)
@@ -2211,9 +2221,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
       ULONGEST reg;
 
       data = read_uleb128 (data + 1, end, &reg);
-      regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg);
       fprintf_filtered (stream, _("a variable in $%s"),
-			gdbarch_register_name (gdbarch, regno));
+			locexpr_regname (gdbarch, reg));
     }
   else if (data[0] == DW_OP_fbreg)
     {
@@ -2269,11 +2278,9 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 	  return save_data;
 	}
 
-      regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg);
-
       fprintf_filtered (stream,
 			_("a variable at frame base reg $%s offset %s+%s"),
-			gdbarch_register_name (gdbarch, regno),
+			locexpr_regname (gdbarch, frame_reg),
 			plongest (base_offset), plongest (frame_offset));
     }
   else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31
@@ -2281,14 +2288,12 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
     {
       LONGEST offset;
 
-      regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_breg0);
-
       data = read_sleb128 (data + 1, end, &offset);
 
       fprintf_filtered (stream,
 			_("a variable at offset %s from base reg $%s"),
 			plongest (offset),
-			gdbarch_register_name (gdbarch, regno));
+			locexpr_regname (gdbarch, data[0] - DW_OP_breg0));
     }
 
   /* The location expression for a TLS variable looks like this (on a
@@ -2345,7 +2350,8 @@ disassemble_dwarf_expression (struct ui_file *stream,
 			      struct gdbarch *arch, unsigned int addr_size,
 			      int offset_size,
 			      const gdb_byte *data, const gdb_byte *end,
-			      int all)
+			      int all,
+			      struct dwarf2_per_cu_data *per_cu)
 {
   const gdb_byte *start = data;
 
@@ -2458,13 +2464,13 @@ disassemble_dwarf_expression (struct ui_file *stream,
 	case DW_OP_reg30:
 	case DW_OP_reg31:
 	  fprintf_filtered (stream, " [$%s]",
-			    gdbarch_register_name (arch, op - DW_OP_reg0));
+			    locexpr_regname (arch, op - DW_OP_reg0));
 	  break;
 
 	case DW_OP_regx:
 	  data = read_uleb128 (data, end, &ul);
 	  fprintf_filtered (stream, " %s [$%s]", pulongest (ul),
-			    gdbarch_register_name (arch, (int) ul));
+			    locexpr_regname (arch, (int) ul));
 	  break;
 
 	case DW_OP_implicit_value:
@@ -2507,7 +2513,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
 	case DW_OP_breg31:
 	  data = read_sleb128 (data, end, &l);
 	  fprintf_filtered (stream, " %s [$%s]", plongest (l),
-			    gdbarch_register_name (arch, op - DW_OP_breg0));
+			    locexpr_regname (arch, op - DW_OP_breg0));
 	  break;
 
 	case DW_OP_bregx:
@@ -2515,7 +2521,7 @@ disassemble_dwarf_expression (struct ui_file *stream,
 	  data = read_sleb128 (data, end, &l);
 	  fprintf_filtered (stream, " register %s [$%s] offset %s",
 			    pulongest (ul),
-			    gdbarch_register_name (arch, (int) ul),
+			    locexpr_regname (arch, (int) ul),
 			    plongest (l));
 	  break;
 
@@ -2598,6 +2604,71 @@ disassemble_dwarf_expression (struct ui_file *stream,
 			      plongest (l));
 	  }
 	  break;
+
+	case DW_OP_GNU_deref_type:
+	  {
+	    int addr_size = *data++;
+	    ULONGEST offset;
+	    struct type *type;
+
+	    data = read_uleb128 (data, end, &offset);
+	    type = dwarf2_get_die_type (offset, per_cu);
+	    fprintf_filtered (stream, "<");
+	    type_print (type, "", stream, -1);
+	    fprintf_filtered (stream, " [0x%s]> %d", phex_nz (offset, 0),
+			      addr_size);
+	  }
+	  break;
+
+	case DW_OP_GNU_const_type:
+	  {
+	    ULONGEST type_die;
+	    struct type *type;
+
+	    data = read_uleb128 (data, end, &type_die);
+	    type = dwarf2_get_die_type (type_die, per_cu);
+	    fprintf_filtered (stream, "<");
+	    type_print (type, "", stream, -1);
+	    fprintf_filtered (stream, " [0x%s]>", phex_nz (type_die, 0));
+	  }
+	  break;
+
+	case DW_OP_GNU_regval_type:
+	  {
+	    ULONGEST type_die, reg;
+	    struct type *type;
+
+	    data = read_uleb128 (data, end, &reg);
+	    data = read_uleb128 (data, end, &type_die);
+
+	    type = dwarf2_get_die_type (type_die, per_cu);
+	    fprintf_filtered (stream, "<");
+	    type_print (type, "", stream, -1);
+	    fprintf_filtered (stream, " [0x%s]> [$%s]", phex_nz (type_die, 0),
+			      locexpr_regname (arch, reg));
+	  }
+	  break;
+
+	case DW_OP_GNU_convert:
+	case DW_OP_GNU_reinterpret:
+	  {
+	    ULONGEST type_die;
+
+	    data = read_uleb128 (data, end, &type_die);
+
+	    if (type_die == 0)
+	      fprintf_filtered (stream, "<0>");
+	    else
+	      {
+		struct type *type;
+
+		type = dwarf2_get_die_type (type_die, per_cu);
+		fprintf_filtered (stream, "<");
+		type_print (type, "", stream, -1);
+		fprintf_filtered (stream, " [0x%s]>", phex_nz (type_die, 0));
+	      }
+	  }
+	  break;
 	}
 
       fprintf_filtered (stream, "\n");
@@ -2614,7 +2685,7 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
 			     struct ui_file *stream,
 			     const gdb_byte *data, int size,
 			     struct objfile *objfile, unsigned int addr_size,
-			     int offset_size)
+			     int offset_size, struct dwarf2_per_cu_data *per_cu)
 {
   const gdb_byte *end = data + size;
   int first_piece = 1, bad = 0;
@@ -2645,7 +2716,8 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
 	data = disassemble_dwarf_expression (stream,
 					     get_objfile_arch (objfile),
 					     addr_size, offset_size, data, end,
-					     dwarf2_always_disassemble);
+					     dwarf2_always_disassemble,
+					     per_cu);
 
       if (data < end)
 	{
@@ -2709,7 +2781,8 @@ locexpr_describe_location (struct symbol *symbol, CORE_ADDR addr,
 
   locexpr_describe_location_1 (symbol, addr, stream,
 			       dlbaton->data, dlbaton->size,
-			       objfile, addr_size, offset_size);
+			       objfile, addr_size, offset_size,
+			       dlbaton->per_cu);
 }
 
 /* Describe the location of SYMBOL as an agent value in VALUE, generating
@@ -2855,7 +2928,8 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
 
       /* Now describe this particular location.  */
       locexpr_describe_location_1 (symbol, low, stream, loc_ptr, length,
-				   objfile, addr_size, offset_size);
+				   objfile, addr_size, offset_size,
+				   dlbaton->per_cu);
 
       fprintf_filtered (stream, "\n");
 


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