gdb
authorTom Tromey <tromey@redhat.com>
Wed, 2 Jun 2010 19:37:56 +0000 (19:37 +0000)
committerTom Tromey <tromey@redhat.com>
Wed, 2 Jun 2010 19:37:56 +0000 (19:37 +0000)
* dwarf2loc.h (dwarf2_per_cu_data): Declare.
* dwarf2read.c (dwarf_stack_op_name): No longer static.  Return
type is const.  Add 'def' argument.  Add missing operators, remove
unhandled ones.
(decode_locdesc): Update.
(dwarf2_always_disassemble): New global.
(show_dwarf2_always_disassemble): New function.
(_initialize_dwarf2_read): Add always-disassemble.
(dwarf2_per_cu_offset_size): New function.
* dwarf2loc.c (dwarf2_always_disassemble): Declare.
(piece_end_p): New function.
(locexpr_describe_location_piece): Replace 'size' argument with
'end'.  Use piece_end_p.  Rewrite recognition of TLS.  Recognize
some constants.  Remove errors.
(disassemble_dwarf_expression): New function.
(locexpr_describe_location_1): Use disassemble_dwarf_expression.
Add 'offset_size' argument.
(loclist_describe_location): Change output formatting.
* dwarf2expr.h (dwarf_stack_op_name): Declare.
gdb/doc
* gdb.texinfo (Maintenance Commands): Document maint set dwarf2
always-disassemble.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/dwarf2loc.h
gdb/dwarf2read.c

index 7cd0030157609ccda0b580caad66a4b6ceeaf971..6c28c9ee33ee0bac43a94719b95927e2c7883dab 100644 (file)
@@ -1,3 +1,25 @@
+2010-06-02  Tom Tromey  <tromey@redhat.com>
+
+       * dwarf2loc.h (dwarf2_per_cu_data): Declare.
+       * dwarf2read.c (dwarf_stack_op_name): No longer static.  Return
+       type is const.  Add 'def' argument.  Add missing operators, remove
+       unhandled ones.
+       (decode_locdesc): Update.
+       (dwarf2_always_disassemble): New global.
+       (show_dwarf2_always_disassemble): New function.
+       (_initialize_dwarf2_read): Add always-disassemble.
+       (dwarf2_per_cu_offset_size): New function.
+       * dwarf2loc.c (dwarf2_always_disassemble): Declare.
+       (piece_end_p): New function.
+       (locexpr_describe_location_piece): Replace 'size' argument with
+       'end'.  Use piece_end_p.  Rewrite recognition of TLS.  Recognize
+       some constants.  Remove errors.
+       (disassemble_dwarf_expression): New function.
+       (locexpr_describe_location_1): Use disassemble_dwarf_expression.
+       Add 'offset_size' argument.
+       (loclist_describe_location): Change output formatting.
+       * dwarf2expr.h (dwarf_stack_op_name): Declare.
+
 2010-06-02  Sami Wagiaalla  <swagiaal@redhat.com>
 
        * cp-support.c (make_symbol_overload_list_adl_namespace): Handle
index 4ffe455299f6233ce10ea8d2e50e4b8c765d3b2c..73e226d1118d86c044e2d81c9e6ff8f0bad07f88 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-02  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.texinfo (Maintenance Commands): Document maint set dwarf2
+       always-disassemble.
+
 2010-06-01  Pedro Alves  <pedro@codesourcery.com>
 
        * gdb.texinfo (Set Tracepoints): Mention tracepoints support in
index 178ef686a45234876cbf0cc6114c19b3091ca6f1..37278c87ca4772cd6e2f4b9ed7f7abafad2ad4d5 100644 (file)
@@ -29979,6 +29979,31 @@ that symbol is described.  The type chain produced by this command is
 a recursive definition of the data type as stored in @value{GDBN}'s
 data structures, including its flags and contained types.
 
+@kindex maint set dwarf2 always-disassemble
+@kindex maint show dwarf2 always-disassemble
+@item maint set dwarf2 always-disassemble
+@item maint show dwarf2 always-disassemble
+Control the behavior of @code{info address} when using DWARF debugging
+information.
+
+The default is @code{off}, which means that @value{GDBN} should try to
+describe a variable's location in an easily readable format.  When
+@code{on}, @value{GDBN} will instead display the DWARF location
+expression in an assembly-like format.  Note that some locations are
+too complex for @value{GDBN} to describe simply; in this case you will
+always see the disassembly form.
+
+Here is an example of the resulting disassembly:
+
+@smallexample
+(gdb) info addr argc
+Symbol "argc" is a complex DWARF expression:
+     1: DW_OP_fbreg 0
+@end smallexample
+
+For more information on these expressions, see
+@uref{http://www.dwarfstd.org/, the DWARF standard}.
+
 @kindex maint set dwarf2 max-cache-age
 @kindex maint show dwarf2 max-cache-age
 @item maint set dwarf2 max-cache-age
index a0f4554857a145854ac7a9974f73d98bdb4935e3..8ebbf87cea1a10eea68fe5e33b1e0a84a3875e98 100644 (file)
@@ -208,4 +208,6 @@ const gdb_byte *read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end,
 CORE_ADDR dwarf2_read_address (struct gdbarch *gdbarch, const gdb_byte *buf,
                               const gdb_byte *buf_end, int addr_size);
 
+const char *dwarf_stack_op_name (unsigned int, int);
+
 #endif /* dwarf2expr.h */
index 79d22770d5f0696081dffa95a61e8b0643a72c4f..30464ff1bd472611e0e2f955833b089750150f1e 100644 (file)
@@ -42,6 +42,8 @@
 #include "gdb_string.h"
 #include "gdb_assert.h"
 
+extern int dwarf2_always_disassemble;
+
 static void
 dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
                         const gdb_byte **start, size_t *length);
@@ -1291,13 +1293,24 @@ locexpr_read_needs_frame (struct symbol *symbol)
                                      dlbaton->per_cu);
 }
 
-/* Describe a single piece of a location, returning an updated
-   position in the bytecode sequence.  */
+/* Return true if DATA points to the end of a piece.  END is one past
+   the last byte in the expression.  */
+
+static int
+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;
+}
+
+/* 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
+   DATA.  */
 
 static const gdb_byte *
 locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
                                 CORE_ADDR addr, struct objfile *objfile,
-                                const gdb_byte *data, int size,
+                                const gdb_byte *data, const gdb_byte *end,
                                 unsigned int addr_size)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
@@ -1314,7 +1327,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
     {
       ULONGEST reg;
 
-      data = read_uleb128 (data + 1, data + size, &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));
@@ -1325,10 +1338,15 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
       struct symbol *framefunc;
       int frame_reg = 0;
       LONGEST frame_offset;
-      const gdb_byte *base_data;
+      const gdb_byte *base_data, *new_data;
       size_t base_size;
       LONGEST base_offset = 0;
 
+      new_data = read_sleb128 (data + 1, end, &frame_offset);
+      if (!piece_end_p (new_data, end))
+       return data;
+      data = new_data;
+
       b = block_for_pc (addr);
 
       if (!b)
@@ -1372,19 +1390,18 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 
       regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg);
 
-      data = read_sleb128 (data + 1, data + size, &frame_offset);
-
       fprintf_filtered (stream, _("a variable at frame base reg $%s offset %s+%s"),
                        gdbarch_register_name (gdbarch, regno),
                        plongest (base_offset), plongest (frame_offset));
     }
-  else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31)
+  else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31
+          && piece_end_p (data, end))
     {
       LONGEST offset;
 
       regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_breg0);
 
-      data = read_sleb128 (data + 1, data + size, &offset);
+      data = read_sleb128 (data + 1, end, &offset);
 
       fprintf_filtered (stream,
                        _("a variable at offset %s from base reg $%s"),
@@ -1404,13 +1421,14 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
      The operand represents the offset at which the variable is within
      the thread local storage.  */
 
-  else if (size > 1
-          && data[size - 1] == DW_OP_GNU_push_tls_address
-          && data[0] == DW_OP_addr)
+  else if (data + 1 + addr_size < end
+          && data[0] == DW_OP_addr
+          && data[1 + addr_size] == DW_OP_GNU_push_tls_address
+          && piece_end_p (data + 2 + addr_size, end))
     {
       CORE_ADDR offset = dwarf2_read_address (gdbarch,
                                              data + 1,
-                                             data + size - 1,
+                                             end,
                                              addr_size);
 
       fprintf_filtered (stream, 
@@ -1420,9 +1438,275 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 
       data += 1 + addr_size + 1;
     }
-  else
-    fprintf_filtered (stream,
-                     _("a variable with complex or multiple locations (DWARF2)"));
+  else if (data[0] >= DW_OP_lit0
+          && data[0] <= DW_OP_lit31
+          && data + 1 < end
+          && data[1] == DW_OP_stack_value)
+    {
+      fprintf_filtered (stream, _("the constant %d"), data[0] - DW_OP_lit0);
+      data += 2;
+    }
+
+  return data;
+}
+
+/* Disassemble an expression, stopping at the end of a piece or at the
+   end of the expression.  Returns a pointer to the next unread byte
+   in the input expression.  If ALL is nonzero, then this function
+   will keep going until it reaches the end of the expression.  */
+
+static const gdb_byte *
+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)
+{
+  const gdb_byte *start = data;
+
+  fprintf_filtered (stream, _("a complex DWARF expression:\n"));
+
+  while (data < end
+        && (all
+            || (data[0] != DW_OP_piece && data[0] != DW_OP_bit_piece)))
+    {
+      enum dwarf_location_atom op = *data++;
+      CORE_ADDR addr;
+      ULONGEST ul;
+      LONGEST l;
+      const char *name;
+
+      name = dwarf_stack_op_name (op, 0);
+
+      if (!name)
+       error (_("Unrecognized DWARF opcode 0x%02x at %ld"),
+              op, (long) (data - start));
+      fprintf_filtered (stream, "  % 4ld: %s", (long) (data - start), name);
+
+      switch (op)
+       {
+       case DW_OP_addr:
+         addr = dwarf2_read_address (arch, data, end, addr_size);
+         data += addr_size;
+         fprintf_filtered (stream, " %s", paddress (arch, addr));
+         break;
+
+       case DW_OP_const1u:
+         ul = extract_unsigned_integer (data, 1, gdbarch_byte_order (arch));
+         data += 1;
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+       case DW_OP_const1s:
+         l = extract_signed_integer (data, 1, gdbarch_byte_order (arch));
+         data += 1;
+         fprintf_filtered (stream, " %s", plongest (l));
+         break;
+       case DW_OP_const2u:
+         ul = extract_unsigned_integer (data, 2, gdbarch_byte_order (arch));
+         data += 2;
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+       case DW_OP_const2s:
+         l = extract_signed_integer (data, 2, gdbarch_byte_order (arch));
+         data += 2;
+         fprintf_filtered (stream, " %s", plongest (l));
+         break;
+       case DW_OP_const4u:
+         ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch));
+         data += 4;
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+       case DW_OP_const4s:
+         l = extract_signed_integer (data, 4, gdbarch_byte_order (arch));
+         data += 4;
+         fprintf_filtered (stream, " %s", plongest (l));
+         break;
+       case DW_OP_const8u:
+         ul = extract_unsigned_integer (data, 8, gdbarch_byte_order (arch));
+         data += 8;
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+       case DW_OP_const8s:
+         l = extract_signed_integer (data, 8, gdbarch_byte_order (arch));
+         data += 8;
+         fprintf_filtered (stream, " %s", plongest (l));
+         break;
+       case DW_OP_constu:
+         data = read_uleb128 (data, end, &ul);
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+       case DW_OP_consts:
+         data = read_sleb128 (data, end, &ul);
+         fprintf_filtered (stream, " %s", plongest (l));
+         break;
+
+       case DW_OP_reg0:
+       case DW_OP_reg1:
+       case DW_OP_reg2:
+       case DW_OP_reg3:
+       case DW_OP_reg4:
+       case DW_OP_reg5:
+       case DW_OP_reg6:
+       case DW_OP_reg7:
+       case DW_OP_reg8:
+       case DW_OP_reg9:
+       case DW_OP_reg10:
+       case DW_OP_reg11:
+       case DW_OP_reg12:
+       case DW_OP_reg13:
+       case DW_OP_reg14:
+       case DW_OP_reg15:
+       case DW_OP_reg16:
+       case DW_OP_reg17:
+       case DW_OP_reg18:
+       case DW_OP_reg19:
+       case DW_OP_reg20:
+       case DW_OP_reg21:
+       case DW_OP_reg22:
+       case DW_OP_reg23:
+       case DW_OP_reg24:
+       case DW_OP_reg25:
+       case DW_OP_reg26:
+       case DW_OP_reg27:
+       case DW_OP_reg28:
+       case DW_OP_reg29:
+       case DW_OP_reg30:
+       case DW_OP_reg31:
+         fprintf_filtered (stream, " [$%s]",
+                           gdbarch_register_name (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));
+         break;
+
+       case DW_OP_implicit_value:
+         data = read_uleb128 (data, end, &ul);
+         data += ul;
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+
+       case DW_OP_breg0:
+       case DW_OP_breg1:
+       case DW_OP_breg2:
+       case DW_OP_breg3:
+       case DW_OP_breg4:
+       case DW_OP_breg5:
+       case DW_OP_breg6:
+       case DW_OP_breg7:
+       case DW_OP_breg8:
+       case DW_OP_breg9:
+       case DW_OP_breg10:
+       case DW_OP_breg11:
+       case DW_OP_breg12:
+       case DW_OP_breg13:
+       case DW_OP_breg14:
+       case DW_OP_breg15:
+       case DW_OP_breg16:
+       case DW_OP_breg17:
+       case DW_OP_breg18:
+       case DW_OP_breg19:
+       case DW_OP_breg20:
+       case DW_OP_breg21:
+       case DW_OP_breg22:
+       case DW_OP_breg23:
+       case DW_OP_breg24:
+       case DW_OP_breg25:
+       case DW_OP_breg26:
+       case DW_OP_breg27:
+       case DW_OP_breg28:
+       case DW_OP_breg29:
+       case DW_OP_breg30:
+       case DW_OP_breg31:
+         data = read_sleb128 (data, end, &ul);
+         fprintf_filtered (stream, " %s [$%s]", pulongest (ul),
+                           gdbarch_register_name (arch, op - DW_OP_breg0));
+         break;
+
+       case DW_OP_bregx:
+         {
+           ULONGEST offset;
+
+           data = read_uleb128 (data, end, &ul);
+           data = read_sleb128 (data, end, &offset);
+           fprintf_filtered (stream, " register %s [$%s] offset %s",
+                             pulongest (ul),
+                             gdbarch_register_name (arch, (int) ul),
+                             pulongest (offset));
+         }
+         break;
+
+       case DW_OP_fbreg:
+         data = read_sleb128 (data, end, &ul);
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+
+       case DW_OP_xderef_size:
+       case DW_OP_deref_size:
+       case DW_OP_pick:
+         fprintf_filtered (stream, " %d", *data);
+         ++data;
+         break;
+
+       case DW_OP_plus_uconst:
+         data = read_uleb128 (data, end, &ul);
+         fprintf_filtered (stream, " %s", pulongest (ul));
+         break;
+
+       case DW_OP_skip:
+         l = extract_signed_integer (data, 2, gdbarch_byte_order (arch));
+         data += 2;
+         fprintf_filtered (stream, " to %ld",
+                           (long) (data + l - start));
+         break;
+
+       case DW_OP_bra:
+         l = extract_signed_integer (data, 2, gdbarch_byte_order (arch));
+         data += 2;
+         fprintf_filtered (stream, " %ld",
+                           (long) (data + l - start));
+         break;
+
+       case DW_OP_call2:
+         ul = extract_unsigned_integer (data, 2, gdbarch_byte_order (arch));
+         data += 2;
+         fprintf_filtered (stream, " offset %s", phex_nz (ul, 2));
+         break;
+
+       case DW_OP_call4:
+         ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch));
+         data += 4;
+         fprintf_filtered (stream, " offset %s", phex_nz (ul, 4));
+         break;
+
+       case DW_OP_call_ref:
+         ul = extract_unsigned_integer (data, offset_size,
+                                        gdbarch_byte_order (arch));
+         data += offset_size;
+         fprintf_filtered (stream, " offset %s", phex_nz (ul, offset_size));
+         break;
+
+        case DW_OP_piece:
+         data = read_uleb128 (data, end, &ul);
+         fprintf_filtered (stream, " %s (bytes)", pulongest (ul));
+         break;
+
+       case DW_OP_bit_piece:
+         {
+           ULONGEST offset;
+
+           data = read_uleb128 (data, end, &ul);
+           data = read_uleb128 (data, end, &offset);
+           fprintf_filtered (stream, " size %s offset %s (bits)",
+                             pulongest (ul), pulongest (offset));
+         }
+         break;
+       }
+
+      fprintf_filtered (stream, "\n");
+    }
 
   return data;
 }
@@ -1434,40 +1718,78 @@ static void
 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)
+                            struct objfile *objfile, unsigned int addr_size,
+                            int offset_size)
 {
   const gdb_byte *end = data + size;
-  int piece_done = 0, first_piece = 1, bad = 0;
+  int first_piece = 1, bad = 0;
 
-  /* A multi-piece description consists of multiple sequences of bytes
-     each followed by DW_OP_piece + length of piece.  */
   while (data < end)
     {
-      if (!piece_done)
-       {
-         if (first_piece)
-           first_piece = 0;
-         else
-           fprintf_filtered (stream, _(", and "));
+      const gdb_byte *here = data;
+      int disassemble = 1;
+
+      if (first_piece)
+       first_piece = 0;
+      else
+       fprintf_filtered (stream, _(", and "));
 
+      if (!dwarf2_always_disassemble)
+       {
          data = locexpr_describe_location_piece (symbol, stream, addr, objfile,
-                                                 data, size, addr_size);
-         piece_done = 1;
+                                                 data, end, addr_size);
+         /* If we printed anything, or if we have an empty piece,
+            then don't disassemble.  */
+         if (data != here
+             || data[0] == DW_OP_piece
+             || data[0] == DW_OP_bit_piece)
+           disassemble = 0;
        }
-      else if (data[0] == DW_OP_piece)
+      if (disassemble)
+       data = disassemble_dwarf_expression (stream, get_objfile_arch (objfile),
+                                            addr_size, offset_size, data, end,
+                                            dwarf2_always_disassemble);
+
+      if (data < end)
        {
-         ULONGEST bytes;
+         int empty = data == here;
              
-         data = read_uleb128 (data + 1, end, &bytes);
+         if (disassemble)
+           fprintf_filtered (stream, "   ");
+         if (data[0] == DW_OP_piece)
+           {
+             ULONGEST bytes;
 
-         fprintf_filtered (stream, _(" [%s-byte piece]"), pulongest (bytes));
+             data = read_uleb128 (data + 1, end, &bytes);
 
-         piece_done = 0;
-       }
-      else
-       {
-         bad = 1;
-         break;
+             if (empty)
+               fprintf_filtered (stream, _("an empty %s-byte piece"),
+                                 pulongest (bytes));
+             else
+               fprintf_filtered (stream, _(" [%s-byte piece]"),
+                                 pulongest (bytes));
+           }
+         else if (data[0] == DW_OP_bit_piece)
+           {
+             ULONGEST bits, offset;
+
+             data = read_uleb128 (data + 1, end, &bits);
+             data = read_uleb128 (data, end, &offset);
+
+             if (empty)
+               fprintf_filtered (stream,
+                                 _("an empty %s-bit piece"),
+                                 pulongest (bits));
+             else
+               fprintf_filtered (stream,
+                                 _(" [%s-bit piece, offset %s bits]"),
+                                 pulongest (bits), pulongest (offset));
+           }
+         else
+           {
+             bad = 1;
+             break;
+           }
        }
     }
 
@@ -1486,9 +1808,10 @@ locexpr_describe_location (struct symbol *symbol, CORE_ADDR addr,
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+  int offset_size = dwarf2_per_cu_offset_size (dlbaton->per_cu);
 
   locexpr_describe_location_1 (symbol, addr, stream, dlbaton->data, dlbaton->size,
-                              objfile, addr_size);
+                              objfile, addr_size, offset_size);
 }
 
 /* Describe the location of SYMBOL as an agent value in VALUE, generating
@@ -1572,6 +1895,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+  int offset_size = dwarf2_per_cu_offset_size (dlbaton->per_cu);
   CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Adjust base_address for relocatable objects.  */
   CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets,
@@ -1581,7 +1905,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
   loc_ptr = dlbaton->data;
   buf_end = dlbaton->data + dlbaton->size;
 
-  fprintf_filtered (stream, _("multi-location ("));
+  fprintf_filtered (stream, _("multi-location:\n"));
 
   /* Iterate through locations until we run out.  */
   while (1)
@@ -1598,7 +1922,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
        {
          base_address = dwarf2_read_address (gdbarch,
                                              loc_ptr, buf_end, addr_size);
-         fprintf_filtered (stream, _("[base address %s]"),
+         fprintf_filtered (stream, _("  Base address %s"),
                            paddress (gdbarch, base_address));
          loc_ptr += addr_size;
          continue;
@@ -1609,11 +1933,7 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
 
       /* An end-of-list entry.  */
       if (low == 0 && high == 0)
-       {
-         /* Indicate the end of the list, for readability.  */
-         fprintf_filtered (stream, _(")"));
-         return;
-       }
+       break;
 
       /* Otherwise, a location expression entry.  */
       low += base_address;
@@ -1622,20 +1942,16 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
       length = extract_unsigned_integer (loc_ptr, 2, byte_order);
       loc_ptr += 2;
 
-      /* Separate the different locations with a semicolon.  */
-      if (first)
-       first = 0;
-      else
-       fprintf_filtered (stream, _("; "));
-
       /* (It would improve readability to print only the minimum
         necessary digits of the second number of the range.)  */
-      fprintf_filtered (stream, _("range %s-%s, "),
+      fprintf_filtered (stream, _("  Range %s-%s: "),
                        paddress (gdbarch, low), paddress (gdbarch, high));
 
       /* Now describe this particular location.  */
       locexpr_describe_location_1 (symbol, low, stream, loc_ptr, length,
-                                  objfile, addr_size);
+                                  objfile, addr_size, offset_size);
+
+      fprintf_filtered (stream, "\n");
 
       loc_ptr += length;
     }
index d246e7c30e6a7b346f17af0acfc5a539fb1f2185..4938241dcc09cb3c5fcc640ad7e486646ee12f23 100644 (file)
@@ -34,6 +34,9 @@ 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 offset size given in the compilation unit header for CU.  */
+int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu);
+
 /* The symbol location baton types used by the DWARF-2 reader (i.e.
    SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol).  "struct
    dwarf2_locexpr_baton" is for a symbol with a single location
index da895737dced49979f7cc738e6ab157d4b038224..b05b99a3c8fbfe065aab9f59b2f236120fae5b1c 100644 (file)
@@ -1002,8 +1002,6 @@ static char *dwarf_attr_name (unsigned int);
 
 static char *dwarf_form_name (unsigned int);
 
-static char *dwarf_stack_op_name (unsigned int);
-
 static char *dwarf_bool_name (unsigned int);
 
 static char *dwarf_type_encoding_name (unsigned int);
@@ -9890,8 +9888,8 @@ dwarf_form_name (unsigned form)
 
 /* Convert a DWARF stack opcode into its string name.  */
 
-static char *
-dwarf_stack_op_name (unsigned op)
+const char *
+dwarf_stack_op_name (unsigned op, int def)
 {
   switch (op)
     {
@@ -10194,32 +10192,24 @@ dwarf_stack_op_name (unsigned op)
       return "DW_OP_call4";
     case DW_OP_call_ref:
       return "DW_OP_call_ref";
-    /* GNU extensions.  */
     case DW_OP_form_tls_address:
       return "DW_OP_form_tls_address";
     case DW_OP_call_frame_cfa:
       return "DW_OP_call_frame_cfa";
     case DW_OP_bit_piece:
       return "DW_OP_bit_piece";
+    /* DWARF 4 extensions.  */
+    case DW_OP_implicit_value:
+      return "DW_OP_implicit_value";
+    case DW_OP_stack_value:
+      return "DW_OP_stack_value";
+    /* GNU extensions.  */
     case DW_OP_GNU_push_tls_address:
       return "DW_OP_GNU_push_tls_address";
     case DW_OP_GNU_uninit:
       return "DW_OP_GNU_uninit";
-    /* HP extensions. */ 
-    case DW_OP_HP_is_value:
-      return "DW_OP_HP_is_value";
-    case DW_OP_HP_fltconst4:
-      return "DW_OP_HP_fltconst4";
-    case DW_OP_HP_fltconst8:
-      return "DW_OP_HP_fltconst8";
-    case DW_OP_HP_mod_range:
-      return "DW_OP_HP_mod_range";
-    case DW_OP_HP_unmod_range:
-      return "DW_OP_HP_unmod_range";
-    case DW_OP_HP_tls:
-      return "DW_OP_HP_tls";
     default:
-      return "OP_<unknown>";
+      return def ? "OP_<unknown>" : NULL;
     }
 }
 
@@ -11060,7 +11050,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
 
        default:
          complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
-                    dwarf_stack_op_name (op));
+                    dwarf_stack_op_name (op, 1));
          return (stack[stacki]);
        }
     }
@@ -11787,6 +11777,28 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
     }
 }
 
+/* Return the offset size given in the compilation unit header for CU.  */
+
+int
+dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu)
+{
+  if (per_cu->cu)
+    return per_cu->cu->header.offset_size;
+  else
+    {
+      /* If the CU is not currently read in, we re-read its header.  */
+      struct objfile *objfile = per_cu->psymtab->objfile;
+      struct dwarf2_per_objfile *per_objfile
+       = objfile_data (objfile, dwarf2_objfile_data_key);
+      gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset;
+      struct comp_unit_head cu_header;
+
+      memset (&cu_header, 0, sizeof cu_header);
+      read_comp_unit_head (&cu_header, info_ptr, objfile->obfd);
+      return cu_header.offset_size;
+    }
+}
+
 /* Locate the .debug_info compilation unit from CU's objfile which contains
    the DIE at OFFSET.  Raises an error on failure.  */
 
@@ -12241,6 +12253,17 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
   munmap_section_buffer (&data->eh_frame);
 }
 
+int dwarf2_always_disassemble;
+
+static void
+show_dwarf2_always_disassemble (struct ui_file *file, int from_tty,
+                               struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+Whether to always disassemble DWARF expressions is %s.\n"),
+                   value);
+}
+
 void _initialize_dwarf2_read (void);
 
 void
@@ -12273,6 +12296,18 @@ caching, which can slow down startup."),
                            &set_dwarf2_cmdlist,
                            &show_dwarf2_cmdlist);
 
+  add_setshow_boolean_cmd ("always-disassemble", class_obscure,
+                          &dwarf2_always_disassemble, _("\
+Set whether `info address' always disassembles DWARF expressions."), _("\
+Show whether `info address' always disassembles DWARF expressions."), _("\
+When enabled, DWARF expressions are always printed in an assembly-like\n\
+syntax.  When disabled, expressions will be printed in a more\n\
+conversational style, when possible."),
+                          NULL,
+                          show_dwarf2_always_disassemble,
+                          &set_dwarf2_cmdlist,
+                          &show_dwarf2_cmdlist);
+
   add_setshow_zinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\
 Set debugging of the dwarf2 DIE reader."), _("\
 Show debugging of the dwarf2 DIE reader."), _("\