diff options
Diffstat (limited to 'gdb/dwarf2loc.c')
-rw-r--r-- | gdb/dwarf2loc.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 3a81202..9d0cd9e 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; |