From 0936ad1d22457136c65383681c475e5a0e30db14 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Thu, 24 Dec 2009 00:40:49 +0000 Subject: [PATCH] 2009-12-23 Stan Shebs * 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 | 12 ++++++++++ gdb/ax-gdb.c | 29 +++++++++++++++++++++++ gdb/ax-gdb.h | 2 ++ gdb/dwarf2loc.c | 60 ++++++++++++++++++++++++++++++++++++++++-------- gdb/tracepoint.c | 52 ++++++++++++++++++++++++++++++++++++++--- 5 files changed, 143 insertions(+), 12 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a762481899..f32d287cf6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2009-12-23 Stan Shebs + + * 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 PR gdb/11110 diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 999b27cc1c..4d3f3ace57 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -1768,6 +1768,35 @@ gen_expr (struct expression *exp, union exp_element **pc, } +/* 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 */ diff --git a/gdb/ax-gdb.h b/gdb/ax-gdb.h index 5d03c18496..2366e0115d 100644 --- a/gdb/ax-gdb.h +++ b/gdb/ax-gdb.h @@ -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 */ diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 3a81202448..9d0cd9ecff 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -41,6 +41,10 @@ #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; diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index e37d0bec64..87e7882126 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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 */ -- 2.34.1