http://sourceware.org/ml/gdb-patches/2009-06/msg00191.html GCC developers would like to change GCC to emit DW_OP_call_frame_cfa, as this would reduce the size of the generated debuginfo. A prerequisite to this is that GDB understand this. So, this patch implements this feature. This is PR 10224. I'm interested in feedback on this. I am not sure whether the implementation of dwarf2_frame_cfa is ok. No test case since at some point GCC will start generating this (perhaps optionally -- but I feel certain we'll do it by default in Fedora), and since it therefore seemed like a lot of work for little payoff. Tom 2009-06-08 Tom Tromey PR gdb/10224: * dwarf2loc.c: Include dwarf2-frame.h. (dwarf_expr_frame_cfa): New function. (dwarf2_evaluate_loc_desc): Initialize new field. (needs_frame_frame_cfa): New function. (dwarf2_loc_desc_needs_frame): Initialize new field. * dwarf2expr.h (struct dwarf_expr_context) : New field. * dwarf2expr.c (execute_stack_op) : New case. * dwarf2-frame.h (dwarf2_frame_cfa): Declare. * dwarf2-frame.c (no_get_frame_cfa): New function. (execute_stack_op): Initialize new field. (dwarf2_frame_cfa): New function. [ Backported for Fedora Rawhide. ] --- ./gdb/dwarf2-frame.c 2009-06-12 11:12:51.000000000 +0200 +++ ./gdb/dwarf2-frame.c 2009-06-12 11:13:30.000000000 +0200 @@ -306,6 +306,13 @@ no_get_frame_base (void *baton, gdb_byte } 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) { internal_error (__FILE__, __LINE__, @@ -356,6 +363,7 @@ execute_stack_op (gdb_byte *exp, ULONGES 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); @@ -1221,6 +1229,13 @@ dwarf2_frame_base_address (struct frame_ return cache->cfa; } +CORE_ADDR +dwarf2_frame_cfa (struct frame_info *this_frame) +{ + void *cache = NULL; + return dwarf2_frame_base_address (this_frame, &cache); +} + static const struct frame_base dwarf2_frame_base = { &dwarf2_frame_unwind, --- ./gdb/dwarf2-frame.h 2009-01-03 06:57:51.000000000 +0100 +++ ./gdb/dwarf2-frame.h 2009-06-12 11:13:30.000000000 +0200 @@ -118,4 +118,8 @@ extern const struct frame_base * void dwarf2_frame_build_info (struct objfile *objfile); +/* Compute the DWARF CFA for a frame. */ + +CORE_ADDR dwarf2_frame_cfa (struct frame_info *this_frame); + #endif /* dwarf2-frame.h */ --- ./gdb/dwarf2expr.c 2009-06-12 11:12:51.000000000 +0200 +++ ./gdb/dwarf2expr.c 2009-06-12 11:13:44.000000000 +0200 @@ -697,6 +697,10 @@ execute_stack_op (struct dwarf_expr_cont } break; + case DW_OP_call_frame_cfa: + result = (ctx->get_frame_cfa) (ctx->baton); + break; + case DW_OP_GNU_push_tls_address: /* Variable is at a constant offset in the thread-local storage block into the objfile for the current thread and --- ./gdb/dwarf2expr.h 2009-06-12 11:12:51.000000000 +0200 +++ ./gdb/dwarf2expr.h 2009-06-12 11:15:36.000000000 +0200 @@ -55,6 +55,9 @@ struct dwarf_expr_context expression evaluation is complete. */ void (*get_frame_base) (void *baton, gdb_byte **start, size_t *length); + /* Return the CFA for the frame. */ + CORE_ADDR (*get_frame_cfa) (void *baton); + /* Return the thread-local storage address for DW_OP_GNU_push_tls_address. */ CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); --- ./gdb/dwarf2loc.c 2009-06-12 11:12:55.000000000 +0200 +++ ./gdb/dwarf2loc.c 2009-06-12 11:15:07.000000000 +0200 @@ -32,6 +32,7 @@ #include "objfiles.h" #include "exceptions.h" #include "block.h" +#include "dwarf2-frame.h" #include "elf/dwarf2.h" #include "dwarf2expr.h" @@ -200,6 +201,13 @@ dwarf_expr_frame_base (void *baton, gdb_ SYMBOL_PRINT_NAME (framefunc)); } +static CORE_ADDR +dwarf_expr_frame_cfa (void *baton) +{ + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + return dwarf2_frame_cfa (debaton->frame); +} + /* Using the objfile specified in BATON, find the address for the current thread's thread-local storage with offset OFFSET. */ static CORE_ADDR @@ -286,6 +294,7 @@ dwarf_expr_prep_ctx (struct frame_info * ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; ctx->get_frame_base = dwarf_expr_frame_base; + ctx->get_frame_cfa = dwarf_expr_frame_cfa; ctx->get_tls_address = dwarf_expr_tls_address; ctx->get_object_address = dwarf_expr_object_address; @@ -439,6 +448,15 @@ needs_frame_frame_base (void *baton, gdb nf_baton->needs_frame = 1; } +/* CFA accesses require a frame. */ +static CORE_ADDR +needs_frame_frame_cfa (void *baton) +{ + struct needs_frame_baton *nf_baton = baton; + nf_baton->needs_frame = 1; + return 1; +} + /* Thread-local accesses do require a frame. */ static CORE_ADDR needs_frame_tls_address (void *baton, CORE_ADDR offset) @@ -468,6 +486,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *d ctx->read_reg = needs_frame_read_reg; ctx->read_mem = needs_frame_read_mem; ctx->get_frame_base = needs_frame_frame_base; + ctx->get_frame_cfa = needs_frame_frame_cfa; ctx->get_tls_address = needs_frame_tls_address; dwarf_expr_eval (ctx, data, size);