2009-12-23 Stan Shebs <stan@codesourcery.com>
authorStan Shebs <shebs@codesourcery.com>
Thu, 24 Dec 2009 00:40:49 +0000 (00:40 +0000)
committerStan Shebs <shebs@codesourcery.com>
Thu, 24 Dec 2009 00:40:49 +0000 (00:40 +0000)
* ax-gdb.h (gen_trace_for_var): Declare.
* ax-gdb.c (gen_trace_for_var): New function.
* dwarf2loc.c (dwarf_expr_frame_base_1): New function, split from...
(dwarf_expr_frame_base): ...here.
(dwarf2_tracepoint_var_ref): Add computed location case.
* tracepoint.c (collect_symbol): Add scope arg and LOC_COMPUTED
case.
(add_local_symbols): Update call to collect_symbol.
(encode_actions): Ditto.

gdb/ChangeLog
gdb/ax-gdb.c
gdb/ax-gdb.h
gdb/dwarf2loc.c
gdb/tracepoint.c

index a76248189913a465ab755e16132e988b13879fad..f32d287cf6d4c6ac58f16a396a6b8c1e7f7d0521 100644 (file)
@@ -1,3 +1,15 @@
+2009-12-23  Stan Shebs  <stan@codesourcery.com>
+
+       * ax-gdb.h (gen_trace_for_var): Declare.
+       * ax-gdb.c (gen_trace_for_var): New function.
+       * dwarf2loc.c (dwarf_expr_frame_base_1): New function, split from...
+       (dwarf_expr_frame_base): ...here.
+       (dwarf2_tracepoint_var_ref): Add computed location case.
+       * tracepoint.c (collect_symbol): Add scope arg and LOC_COMPUTED
+       case.
+       (add_local_symbols): Update call to collect_symbol.
+       (encode_actions): Ditto.
+
 2009-12-23  Dmitry Gorbachev  <d.g.gorbachev@gmail.com>
 
        PR gdb/11110
index 999b27cc1cea584d229d045a1e1e8d629505a882..4d3f3ace57c25b88831f712cee2bbd8729168fac 100644 (file)
@@ -1768,6 +1768,35 @@ gen_expr (struct expression *exp, union exp_element **pc,
 }
 \f
 
+/* Given a single variable and a scope, generate bytecodes to trace
+   its value.  This is for use in situations where we have only a
+   variable's name, and no parsed expression; for instance, when the
+   name comes from a list of local variables of a function.  */
+
+struct agent_expr *
+gen_trace_for_var (CORE_ADDR scope, struct symbol *var)
+{
+  struct cleanup *old_chain = 0;
+  struct agent_expr *ax = new_agent_expr (scope);
+  struct axs_value value;
+
+  old_chain = make_cleanup_free_agent_expr (ax);
+
+  trace_kludge = 1;
+  gen_var_ref (NULL, ax, &value, var);
+
+  /* Make sure we record the final object, and get rid of it.  */
+  gen_traced_pop (ax, &value);
+
+  /* Oh, and terminate.  */
+  ax_simple (ax, aop_end);
+
+  /* We have successfully built the agent expr, so cancel the cleanup
+     request.  If we add more cleanups that we always want done, this
+     will have to get more complicated.  */
+  discard_cleanups (old_chain);
+  return ax;
+}
 
 /* Generating bytecode from GDB expressions: driver */
 
index 5d03c1849613c813989f6904c2c65fffa1ebb038..2366e0115dbf108731040ea18d2596c1cb64abdf 100644 (file)
@@ -99,6 +99,8 @@ struct axs_value
    function to discover which registers the expression uses.  */
 extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
 
+extern struct agent_expr *gen_trace_for_var (CORE_ADDR, struct symbol *);
+
 extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
 
 #endif /* AX_GDB_H */
index 3a8120244808c16757d7041abcccc199160efa5d..9d0cd9ecff208c7d0e2cad0f28d788a888e8c675 100644 (file)
 #include "gdb_string.h"
 #include "gdb_assert.h"
 
+static void
+dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
+                        gdb_byte **start, size_t *length);
+
 /* A helper function for dealing with location lists.  Given a
    symbol baton (BATON) and a pc value (PC), find the appropriate
    location expression, set *LOCEXPR_LENGTH, and return a pointer
@@ -166,16 +170,23 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length)
      something has gone wrong.  */
   gdb_assert (framefunc != NULL);
 
+  dwarf_expr_frame_base_1 (framefunc,
+                          get_frame_address_in_block (debaton->frame),
+                          start, length);
+}
+
+static void
+dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
+                        gdb_byte **start, size_t *length)
+{
   if (SYMBOL_LOCATION_BATON (framefunc) == NULL)
     *start = NULL;
   else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_loclist_funcs)
     {
       struct dwarf2_loclist_baton *symbaton;
-      struct frame_info *frame = debaton->frame;
 
       symbaton = SYMBOL_LOCATION_BATON (framefunc);
-      *start = find_location_expression (symbaton, length,
-                                        get_frame_address_in_block (frame));
+      *start = find_location_expression (symbaton, length, pc);
     }
   else
     {
@@ -617,21 +628,52 @@ dwarf2_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
     }
   else if (data[0] == DW_OP_fbreg)
     {
-      /* And this is worse than just minimal; we should honor the frame base
-        as above.  */
-      int frame_reg;
+      struct block *b;
+      struct symbol *framefunc;
+      int frame_reg = 0;
       LONGEST frame_offset;
       gdb_byte *buf_end;
+      gdb_byte *base_data;
+      size_t base_size;
+      LONGEST base_offset = 0;
+
+      b = block_for_pc (ax->scope);
+
+      if (!b)
+       error (_("No block found for address"));
+
+      framefunc = block_linkage_function (b);
+
+      if (!framefunc)
+       error (_("No function found for block"));
+
+      dwarf_expr_frame_base_1 (framefunc, ax->scope,
+                              &base_data, &base_size);
+
+      if (base_data[0] >= DW_OP_breg0
+          && base_data[0] <= DW_OP_breg31)
+       {
+         frame_reg = base_data[0] - DW_OP_breg0;
+         buf_end = read_sleb128 (base_data + 1, base_data + base_size, &base_offset);
+         if (buf_end != base_data + base_size)
+           error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
+                  frame_reg, SYMBOL_PRINT_NAME (symbol));
+       }
+      else
+       {
+         /* We don't know what to do with the frame base expression,
+            so we can't trace this variable; give up.  */
+         error (_("Cannot generate expression to collect symbol \"%s\"; DWARF 2 encoding not handled"),
+                SYMBOL_PRINT_NAME (symbol));
+       }
 
       buf_end = read_sleb128 (data + 1, data + size, &frame_offset);
       if (buf_end != data + size)
        error (_("Unexpected opcode after DW_OP_fbreg for symbol \"%s\"."),
               SYMBOL_PRINT_NAME (symbol));
 
-      gdbarch_virtual_frame_pointer (gdbarch,
-                                    ax->scope, &frame_reg, &frame_offset);
       ax_reg (ax, frame_reg);
-      ax_const_l (ax, frame_offset);
+      ax_const_l (ax, base_offset + frame_offset);
       ax_simple (ax, aop_add);
 
       value->kind = axs_lvalue_memory;
index e37d0bec6499c6bfdcdbe8336dc6e98e02524637..87e78821269b4e449cf4f2b5b1d2666f85ff328a 100644 (file)
@@ -729,7 +729,8 @@ static void
 collect_symbol (struct collection_list *collect, 
                struct symbol *sym,
                struct gdbarch *gdbarch,
-               long frame_regno, long frame_offset)
+               long frame_regno, long frame_offset,
+               CORE_ADDR scope)
 {
   unsigned long len;
   unsigned int reg;
@@ -821,6 +822,50 @@ collect_symbol (struct collection_list *collect,
       printf_filtered ("%s has been optimized out of existence.\n",
                       SYMBOL_PRINT_NAME (sym));
       break;
+
+    case LOC_COMPUTED:
+      {
+       struct agent_expr *aexpr;
+       struct cleanup *old_chain1 = NULL;
+       struct agent_reqs areqs;
+
+       aexpr = gen_trace_for_var (scope, sym);
+
+       old_chain1 = make_cleanup_free_agent_expr (aexpr);
+
+       ax_reqs (aexpr, &areqs);
+       if (areqs.flaw != agent_flaw_none)
+         error (_("malformed expression"));
+       
+       if (areqs.min_height < 0)
+         error (_("gdb: Internal error: expression has min height < 0"));
+       if (areqs.max_height > 20)
+         error (_("expression too complicated, try simplifying"));
+
+       discard_cleanups (old_chain1);
+       add_aexpr (collect, aexpr);
+
+       /* take care of the registers */
+       if (areqs.reg_mask_len > 0)
+         {
+           int ndx1, ndx2;
+
+           for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
+             {
+               QUIT;   /* allow user to bail out with ^C */
+               if (areqs.reg_mask[ndx1] != 0)
+                 {
+                   /* assume chars have 8 bits */
+                   for (ndx2 = 0; ndx2 < 8; ndx2++)
+                     if (areqs.reg_mask[ndx1] & (1 << ndx2))
+                       /* it's used -- record it */
+                       add_register (collect, 
+                                     ndx1 * 8 + ndx2);
+                 }
+             }
+         }
+      }
+      break;
     }
 }
 
@@ -847,7 +892,7 @@ add_local_symbols (struct collection_list *collect,
            {
              count++;
              collect_symbol (collect, sym, gdbarch,
-                             frame_regno, frame_offset);
+                             frame_regno, frame_offset, pc);
            }
        }
       if (BLOCK_FUNCTION (block))
@@ -1126,7 +1171,8 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
                                      exp->elts[2].symbol,
                                      t->gdbarch,
                                      frame_reg,
-                                     frame_offset);
+                                     frame_offset,
+                                     t->loc->address);
                      break;
 
                    default:    /* full-fledged expression */