diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 32f6ac0d78..0ef55f603f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,34 @@ 2009-09-15 Doug Evans + * dwarf2expr.h (dwarf_value_location): Add more comments describing + enum values. + (struct dwarf_stack_value): New struct. + (struct dwarf_expr_context): Change type of `stack' from CORE_ADDR* + to struct dwarf_stack_value*. + (struct dwarf_expr_piece): Move `v.value' into its own struct, v.expr, + all uses updated. Add v.expr.in_stack_memory. + (dwarf_expr_push): Update declaration. + (dwarf_expr_fetch_in_stack_memory): Declare. + * dwarf2expr.c (dwarf_expr_grow_stack): Update calculation of + size of stack value. + (dwarf_expr_push): New arg in_stack_memory, all callers updated. + (dwarf_expr_fetch_in_stack_memory): New function. + (add_piece): Set in_stack_memory for non-literal values. + (execute_stack_op): Allow ops to specify whether the value is on the + program's stack. + (execute_stack_op, case DW_OP_fbreg): Mark value as in stack memory. + (execute_stack_op, case DW_OP_call_frame_cfa): Ditto. + (execute_stack_op, case DW_OP_dup): Copy in_stack_memory flag. + (execute_stack_op, cases DW_OP_pick, DW_OP_over): Ditto. + (execute_stack_op, cases DW_OP_swap, DW_OP_rot): Update type of + dwarf stack value. + * dwarf2loc.c (read_pieced_value): Call read_stack for values known + to be on the program's stack. + (dwarf2_evaluate_loc_desc, case DWARF_VALUE_MEMORY): Call + set_value_stack only for objects known to be in stack memory. + * dwarf2-frame.c (execute_stack_op): New arg initial_in_stack_memory, + all callers updated. + * target.c (memory_xfer_partial): Pass correct length to dcache_update. 2009-09-15 Jan Kratochvil diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index a923edffdc..668c4344bd 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -357,7 +357,8 @@ register %s (#%d) at %s"), static CORE_ADDR execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size, - struct frame_info *this_frame, CORE_ADDR initial) + struct frame_info *this_frame, CORE_ADDR initial, + int initial_in_stack_memory) { struct dwarf_expr_context *ctx; CORE_ADDR result; @@ -375,7 +376,7 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size, ctx->get_frame_cfa = no_get_frame_cfa; ctx->get_tls_address = no_get_tls_address; - dwarf_expr_push (ctx, initial); + dwarf_expr_push (ctx, initial, initial_in_stack_memory); dwarf_expr_eval (ctx, exp, len); result = dwarf_expr_fetch (ctx, 0); @@ -975,7 +976,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) case CFA_EXP: cache->cfa = execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len, - cache->addr_size, this_frame, 0); + cache->addr_size, this_frame, 0, 0); break; default: @@ -1131,7 +1132,7 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - cache->addr_size, this_frame, cache->cfa); + cache->addr_size, this_frame, cache->cfa, 1); return frame_unwind_got_memory (this_frame, regnum, addr); case DWARF2_FRAME_REG_SAVED_VAL_OFFSET: @@ -1141,7 +1142,7 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_VAL_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - cache->addr_size, this_frame, cache->cfa); + cache->addr_size, this_frame, cache->cfa, 1); return frame_unwind_got_constant (this_frame, regnum, addr); case DWARF2_FRAME_REG_UNSPECIFIED: diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 2b0f585e3d..46bc9d758b 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -87,7 +87,7 @@ dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need) { size_t newlen = ctx->stack_len + need + 10; ctx->stack = xrealloc (ctx->stack, - newlen * sizeof (CORE_ADDR)); + newlen * sizeof (struct dwarf_stack_value)); ctx->stack_allocated = newlen; } } @@ -95,10 +95,15 @@ dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need) /* Push VALUE onto CTX's stack. */ void -dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value) +dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value, + int in_stack_memory) { + struct dwarf_stack_value *v; + dwarf_expr_grow_stack (ctx, 1); - ctx->stack[ctx->stack_len++] = value; + v = &ctx->stack[ctx->stack_len++]; + v->value = value; + v->in_stack_memory = in_stack_memory; } /* Pop the top item off of CTX's stack. */ @@ -119,7 +124,19 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n) if (ctx->stack_len <= n) error (_("Asked for position %d of stack, stack only has %d elements on it."), n, ctx->stack_len); - return ctx->stack[ctx->stack_len - (1 + n)]; + return ctx->stack[ctx->stack_len - (1 + n)].value; + +} + +/* Retrieve the in_stack_memory flag of the N'th item on CTX's stack. */ + +int +dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n) +{ + if (ctx->stack_len <= n) + error (_("Asked for position %d of stack, stack only has %d elements on it."), + n, ctx->stack_len); + return ctx->stack[ctx->stack_len - (1 + n)].in_stack_memory; } @@ -148,7 +165,10 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size) p->v.literal.length = ctx->len; } else - p->v.value = dwarf_expr_fetch (ctx, 0); + { + p->v.expr.value = dwarf_expr_fetch (ctx, 0); + p->v.expr.in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); + } } /* Evaluate the expression at ADDR (LEN bytes long) using the context @@ -329,6 +349,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, { enum dwarf_location_atom op = *op_ptr++; CORE_ADDR result; + /* Assume the value is not in stack memory. + Code that knows otherwise sets this to 1. + Some arithmetic on stack addresses can probably be assumed to still + be a stack address, but we skip this complication for now. + This is just an optimization, so it's always ok to punt + and leave this as 0. */ + int in_stack_memory = 0; ULONGEST uoffset, reg; LONGEST offset; @@ -557,12 +584,15 @@ execute_stack_op (struct dwarf_expr_context *ctx, if (ctx->location == DWARF_VALUE_REGISTER) result = (ctx->read_reg) (ctx->baton, result); result = result + offset; + in_stack_memory = 1; ctx->stack_len = before_stack_len; ctx->location = DWARF_VALUE_MEMORY; } break; + case DW_OP_dup: result = dwarf_expr_fetch (ctx, 0); + in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); break; case DW_OP_drop: @@ -572,11 +602,12 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_pick: offset = *op_ptr++; result = dwarf_expr_fetch (ctx, offset); + in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, offset); break; case DW_OP_swap: { - CORE_ADDR t1, t2; + struct dwarf_stack_value t1, t2; if (ctx->stack_len < 2) error (_("Not enough elements for DW_OP_swap. Need 2, have %d."), @@ -590,11 +621,12 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_over: result = dwarf_expr_fetch (ctx, 1); + in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 1); break; case DW_OP_rot: { - CORE_ADDR t1, t2, t3; + struct dwarf_stack_value t1, t2, t3; if (ctx->stack_len < 3) error (_("Not enough elements for DW_OP_rot. Need 3, have %d."), @@ -758,6 +790,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_call_frame_cfa: result = (ctx->get_frame_cfa) (ctx->baton); + in_stack_memory = 1; break; case DW_OP_GNU_push_tls_address: @@ -820,7 +853,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, } /* Most things push a result value. */ - dwarf_expr_push (ctx, result); + dwarf_expr_push (ctx, result, in_stack_memory); no_push:; } diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 9d9b127add..a9a8a057a8 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -26,22 +26,41 @@ /* The location of a value. */ enum dwarf_value_location { - /* The piece is in memory. */ + /* The piece is in memory. + The value on the dwarf stack is its address. */ DWARF_VALUE_MEMORY, - /* The piece is in a register. */ + + /* The piece is in a register. + The value on the dwarf stack is the register number. */ DWARF_VALUE_REGISTER, - /* The piece is on the stack. */ + + /* The piece is on the dwarf stack. */ DWARF_VALUE_STACK, + /* The piece is a literal. */ DWARF_VALUE_LITERAL }; +/* The dwarf expression stack. */ + +struct dwarf_stack_value +{ + CORE_ADDR value; + + /* Non-zero if the piece is in memory and is known to be + on the program's stack. It is always ok to set this to zero. + This is used, for example, to optimize memory access from the target. + It can vastly speed up backtraces on long latency connections when + "set stack-cache on". */ + int in_stack_memory; +}; + /* The expression evaluator works with a dwarf_expr_context, describing its current state and its callbacks. */ struct dwarf_expr_context { /* The stack of values, allocated with xmalloc. */ - CORE_ADDR *stack; + struct dwarf_stack_value *stack; /* The number of values currently pushed on the stack, and the number of elements allocated to the stack. */ @@ -111,7 +130,7 @@ struct dwarf_expr_context Each time DW_OP_piece is executed, we add a new element to the end of this array, recording the current top of the stack, the current location, and the size given as the operand to - DW_OP_piece. We then pop the top value from the stack, rest the + DW_OP_piece. We then pop the top value from the stack, reset the location, and resume evaluation. The Dwarf spec doesn't say whether DW_OP_piece pops the top value @@ -140,8 +159,14 @@ struct dwarf_expr_piece union { - /* This piece's address or register number. */ - CORE_ADDR value; + struct + { + /* This piece's address or register number. */ + CORE_ADDR value; + /* Non-zero if the piece is known to be in memory and on + the program's stack. */ + int in_stack_memory; + } expr; struct { @@ -162,11 +187,13 @@ void free_dwarf_expr_context (struct dwarf_expr_context *ctx); struct cleanup * make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx); -void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value); +void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value, + int in_stack_memory); void dwarf_expr_pop (struct dwarf_expr_context *ctx); void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, size_t len); CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n); +int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n); gdb_byte *read_uleb128 (gdb_byte *buf, gdb_byte *buf_end, ULONGEST * r); diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index c314a78a3b..3a81202448 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -265,14 +265,17 @@ read_pieced_value (struct value *v) struct gdbarch *arch = get_frame_arch (frame); bfd_byte regval[MAX_REGISTER_SIZE]; int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, - p->v.value); + p->v.expr.value); get_frame_register (frame, gdb_regnum, regval); memcpy (contents + offset, regval, p->size); } break; case DWARF_VALUE_MEMORY: - read_memory (p->v.value, contents + offset, p->size); + if (p->v.expr.in_stack_memory) + read_stack (p->v.expr.value, contents + offset, p->size); + else + read_memory (p->v.expr.value, contents + offset, p->size); break; case DWARF_VALUE_STACK: @@ -282,7 +285,7 @@ read_pieced_value (struct value *v) int addr_size = gdbarch_addr_bit (c->arch) / 8; store_unsigned_integer (bytes, addr_size, gdbarch_byte_order (c->arch), - p->v.value); + p->v.expr.value); n = p->size; if (n > addr_size) n = addr_size; @@ -330,12 +333,12 @@ write_pieced_value (struct value *to, struct value *from) case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value); + int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.expr.value); put_frame_register (frame, gdb_regnum, contents + offset); } break; case DWARF_VALUE_MEMORY: - write_memory (p->v.value, contents + offset, p->size); + write_memory (p->v.expr.value, contents + offset, p->size); break; default: set_value_optimized_out (to, 1); @@ -434,11 +437,13 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, case DWARF_VALUE_MEMORY: { CORE_ADDR address = dwarf_expr_fetch (ctx, 0); + int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = lval_memory; set_value_lazy (retval, 1); - set_value_stack (retval, 1); + if (in_stack_memory) + set_value_stack (retval, 1); set_value_address (retval, address); } break; @@ -485,10 +490,6 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, return retval; } - - - - /* Helper functions and baton for dwarf2_loc_desc_needs_frame. */