_("Support for DW_OP_fbreg is unimplemented"));
}
+/* Helper function for execute_stack_op. */
+
+static CORE_ADDR
+no_get_frame_cfa (void *baton)
+{
+ internal_error (__FILE__, __LINE__,
+ _("Support for DW_OP_call_frame_cfa is unimplemented"));
+}
+
static CORE_ADDR
no_get_tls_address (void *baton, CORE_ADDR offset)
{
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;
+ struct cleanup *old_chain;
ctx = new_dwarf_expr_context ();
+ old_chain = make_cleanup_free_dwarf_expr_context (ctx);
+
ctx->gdbarch = get_frame_arch (this_frame);
ctx->addr_size = addr_size;
ctx->baton = this_frame;
ctx->read_reg = read_reg;
ctx->read_mem = read_mem;
ctx->get_frame_base = no_get_frame_base;
+ 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);
- if (ctx->in_reg)
+ if (ctx->location == DWARF_VALUE_REGISTER)
result = read_reg (this_frame, result);
+ else if (ctx->location != DWARF_VALUE_MEMORY)
+ {
+ /* This is actually invalid DWARF, but if we ever do run across
+ it somehow, we might as well support it. So, instead, report
+ it as unimplemented. */
+ error (_("Not implemented: computing unwound register using explicit value operator"));
+ }
- free_dwarf_expr_context (ctx);
+ do_cleanups (old_chain);
return result;
}
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:
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:
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:
return NULL;
}
+
+/* Compute the CFA for THIS_FRAME, but only if THIS_FRAME came from
+ the DWARF unwinder. This is used to implement
+ DW_OP_call_frame_cfa. */
+
+CORE_ADDR
+dwarf2_frame_cfa (struct frame_info *this_frame)
+{
+ while (get_frame_type (this_frame) == INLINE_FRAME)
+ this_frame = get_prev_frame (this_frame);
+ /* This restriction could be lifted if other unwinders are known to
+ compute the frame base in a way compatible with the DWARF
+ unwinder. */
+ if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind))
+ error (_("can't compute CFA for this frame"));
+ return get_frame_base (this_frame);
+}
\f
const struct objfile_data *dwarf2_frame_objfile_data;