/* Frame unwinder for frames with DWARF Call Frame Information.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2017 Free Software Foundation, Inc.
Contributed by Mark Kettenis.
CORE_ADDR func_base);
\f
-enum cfa_how_kind
-{
- CFA_UNSET,
- CFA_REG_OFFSET,
- CFA_EXP
-};
-
-struct dwarf2_frame_state_reg_info
-{
- struct dwarf2_frame_state_reg *reg;
- int num_regs;
-
- LONGEST cfa_offset;
- ULONGEST cfa_reg;
- enum cfa_how_kind cfa_how;
- const gdb_byte *cfa_exp;
-
- /* Used to implement DW_CFA_remember_state. */
- struct dwarf2_frame_state_reg_info *prev;
-};
-
-/* Structure describing a frame state. */
-
-struct dwarf2_frame_state
-{
- /* Each register save state can be described in terms of a CFA slot,
- another register, or a location expression. */
- struct dwarf2_frame_state_reg_info regs;
-
- /* The PC described by the current frame state. */
- CORE_ADDR pc;
-
- /* Initial register set from the CIE.
- Used to implement DW_CFA_restore. */
- struct dwarf2_frame_state_reg_info initial;
-
- /* The information we care about from the CIE. */
- LONGEST data_align;
- ULONGEST code_align;
- ULONGEST retaddr_column;
-
- /* Flags for known producer quirks. */
-
- /* The ARM compilers, in DWARF2 mode, assume that DW_CFA_def_cfa
- and DW_CFA_def_cfa_offset takes a factored offset. */
- int armcc_cfa_offsets_sf;
-
- /* The ARM compilers, in DWARF2 or DWARF3 mode, may assume that
- the CFA is defined as REG - OFFSET rather than REG + OFFSET. */
- int armcc_cfa_offsets_reversed;
-};
-
/* Store the length the expression for the CFA in the `cfa_reg' field,
which is unused in that case. */
#define cfa_exp_len cfa_reg
/* Assert that the register set RS is large enough to store gdbarch_num_regs
columns. If necessary, enlarge the register set. */
-static void
+void
dwarf2_frame_state_alloc_regs (struct dwarf2_frame_state_reg_info *rs,
int num_regs)
{
/* Helper functions for execute_stack_op. */
static CORE_ADDR
-read_addr_from_reg (void *baton, int reg)
+read_addr_from_reg (struct frame_info *this_frame, int reg)
{
- struct frame_info *this_frame = (struct frame_info *) baton;
struct gdbarch *gdbarch = get_frame_arch (this_frame);
int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
return address_from_register (regnum, this_frame);
}
-/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback. */
-
-static struct value *
-get_reg_value (void *baton, struct type *type, int reg)
-{
- struct frame_info *this_frame = (struct frame_info *) baton;
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
-
- return value_from_register (type, regnum, this_frame);
-}
-
-static void
-read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
- read_memory (addr, buf, len);
-}
-
/* Execute the required actions for both the DW_CFA_restore and
DW_CFA_restore_extended instructions. */
static void
}
}
-/* Virtual method table for execute_stack_op below. */
-
-static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs =
+class dwarf_expr_executor : public dwarf_expr_context
{
- read_addr_from_reg,
- get_reg_value,
- read_mem,
- ctx_no_get_frame_base,
- ctx_no_get_frame_cfa,
- ctx_no_get_frame_pc,
- ctx_no_get_tls_address,
- ctx_no_dwarf_call,
- ctx_no_get_base_type,
- ctx_no_push_dwarf_reg_entry_value,
- ctx_no_get_addr_index
+ public:
+
+ struct frame_info *this_frame;
+
+ CORE_ADDR read_addr_from_reg (int reg) OVERRIDE
+ {
+ return ::read_addr_from_reg (this_frame, reg);
+ }
+
+ struct value *get_reg_value (struct type *type, int reg) OVERRIDE
+ {
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
+
+ return value_from_register (type, regnum, this_frame);
+ }
+
+ void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE
+ {
+ read_memory (addr, buf, len);
+ }
+
+ void get_frame_base (const gdb_byte **start, size_t *length) OVERRIDE
+ {
+ invalid ("DW_OP_fbreg");
+ }
+
+ void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+ union call_site_parameter_u kind_u,
+ int deref_size) OVERRIDE
+ {
+ invalid ("DW_OP_entry_value");
+ }
+
+ CORE_ADDR get_object_address () OVERRIDE
+ {
+ invalid ("DW_OP_push_object_address");
+ }
+
+ CORE_ADDR get_frame_cfa () OVERRIDE
+ {
+ invalid ("DW_OP_call_frame_cfa");
+ }
+
+ CORE_ADDR get_tls_address (CORE_ADDR offset) OVERRIDE
+ {
+ invalid ("DW_OP_form_tls_address");
+ }
+
+ void dwarf_call (cu_offset die_offset) OVERRIDE
+ {
+ invalid ("DW_OP_call*");
+ }
+
+ CORE_ADDR get_addr_index (unsigned int index)
+ {
+ invalid ("DW_OP_GNU_addr_index");
+ }
+
+ private:
+
+ void invalid (const char *op) ATTRIBUTE_NORETURN
+ {
+ error (_("%s is invalid in this context"), op);
+ }
};
static CORE_ADDR
CORE_ADDR initial, int initial_in_stack_memory)
{
CORE_ADDR result;
- struct cleanup *old_chain;
- dwarf_expr_context ctx;
- old_chain = make_cleanup_value_free_to_mark (value_mark ());
+ dwarf_expr_executor ctx;
+ scoped_value_mark free_values;
+ ctx.this_frame = this_frame;
ctx.gdbarch = get_frame_arch (this_frame);
ctx.addr_size = addr_size;
ctx.ref_addr_size = -1;
ctx.offset = offset;
- ctx.baton = this_frame;
- ctx.funcs = &dwarf2_frame_ctx_funcs;
- dwarf_expr_push_address (&ctx, initial, initial_in_stack_memory);
- dwarf_expr_eval (&ctx, exp, len);
+ ctx.push_address (initial, initial_in_stack_memory);
+ ctx.eval (exp, len);
if (ctx.location == DWARF_VALUE_MEMORY)
- result = dwarf_expr_fetch_address (&ctx, 0);
+ result = ctx.fetch_address (0);
else if (ctx.location == DWARF_VALUE_REGISTER)
- result = read_addr_from_reg (this_frame,
- value_as_long (dwarf_expr_fetch (&ctx, 0)));
+ result = ctx.read_addr_from_reg (value_as_long (ctx.fetch (0)));
else
{
/* This is actually invalid DWARF, but if we ever do run across
Not implemented: computing unwound register using explicit value operator"));
}
- do_cleanups (old_chain);
-
return result;
}
\f
/* cfa_how deliberately not set. */
break;
- case DW_CFA_GNU_window_save:
- /* This is SPARC-specific code, and contains hard-coded
- constants for the register numbering scheme used by
- GCC. Rather than having a architecture-specific
- operation that's only ever used by a single
- architecture, we provide the implementation here.
- Incidentally that's what GCC does too in its
- unwinder. */
- {
- int size = register_size (gdbarch, 0);
-
- dwarf2_frame_state_alloc_regs (&fs->regs, 32);
- for (reg = 8; reg < 16; reg++)
- {
- fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG;
- fs->regs.reg[reg].loc.reg = reg + 16;
- }
- for (reg = 16; reg < 32; reg++)
- {
- fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
- fs->regs.reg[reg].loc.offset = (reg - 16) * size;
- }
- }
- break;
-
case DW_CFA_GNU_args_size:
/* Ignored. */
insn_ptr = safe_read_uleb128 (insn_ptr, insn_end, &utmp);
break;
default:
- internal_error (__FILE__, __LINE__,
- _("Unknown CFI encountered."));
+ if (insn >= DW_CFA_lo_user && insn <= DW_CFA_hi_user)
+ {
+ /* Handle vendor-specific CFI for different architectures. */
+ if (!gdbarch_execute_dwarf_cfa_vendor_op (gdbarch, insn, fs))
+ error (_("Call Frame Instruction op %d in vendor extension "
+ "space is not handled on this architecture."),
+ insn);
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("Unknown CFI encountered."));
}
}
}