* 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 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
}
\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 */
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 */
#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
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
{
}
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;
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;
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;
}
}
{
count++;
collect_symbol (collect, sym, gdbarch,
- frame_regno, frame_offset);
+ frame_regno, frame_offset, pc);
}
}
if (BLOCK_FUNCTION (block))
exp->elts[2].symbol,
t->gdbarch,
frame_reg,
- frame_offset);
+ frame_offset,
+ t->loc->address);
break;
default: /* full-fledged expression */