_("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)
{
{
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);
if (ctx->in_reg)
result = read_reg (this_frame, result);
- free_dwarf_expr_context (ctx);
+ do_cleanups (old_chain);
return result;
}
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;
{
struct dwarf2_fde *aa = *(struct dwarf2_fde **)a;
struct dwarf2_fde *bb = *(struct dwarf2_fde **)b;
+
if (aa->initial_location == bb->initial_location)
- /* Put eh_frame entries after debug_frame ones. */
- return aa->eh_frame_p - bb->eh_frame_p;
+ {
+ if (aa->address_range != bb->address_range
+ && aa->eh_frame_p == 0 && bb->eh_frame_p == 0)
+ /* Linker bug, e.g. gold/10400.
+ Work around it by keeping stable sort order. */
+ return (a < b) ? -1 : 1;
+ else
+ /* Put eh_frame entries after debug_frame ones. */
+ return aa->eh_frame_p - bb->eh_frame_p;
+ }
return (aa->initial_location < bb->initial_location) ? -1 : 1;
}