From 9f6f94ff251ac7faaed16ff4cc13b6e8a9ad8997 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 17 Feb 2011 16:20:44 +0000 Subject: [PATCH] * dwarf2loc.h (dwarf2_compile_expr_to_ax): Declare. * dwarf2loc.c (dwarf2_compile_expr_to_ax): Rename from compile_dwarf_to_ax. No longer static. Call dwarf2_compile_cfa_to_ax. (locexpr_tracepoint_var_ref): Update. (loclist_tracepoint_var_ref): Update. * dwarf2-frame.h (dwarf2_compile_cfa_to_ax): Declare. * dwarf2-frame.c (execute_cfa_program): Remove 'this_frame' argument; add 'gdbarch' and 'pc'. (dwarf2_compile_cfa_to_ax): New function. (dwarf2_frame_cache): Update. --- gdb/ChangeLog | 14 +++++++ gdb/dwarf2-frame.c | 92 +++++++++++++++++++++++++++++++++++++++++++--- gdb/dwarf2-frame.h | 14 +++++++ gdb/dwarf2loc.c | 33 +++++++++-------- gdb/dwarf2loc.h | 23 ++++++++++++ 5 files changed, 154 insertions(+), 22 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 09e12489254..42f77a8085e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2011-02-17 Tom Tromey + + * dwarf2loc.h (dwarf2_compile_expr_to_ax): Declare. + * dwarf2loc.c (dwarf2_compile_expr_to_ax): Rename from + compile_dwarf_to_ax. No longer static. Call + dwarf2_compile_cfa_to_ax. + (locexpr_tracepoint_var_ref): Update. + (loclist_tracepoint_var_ref): Update. + * dwarf2-frame.h (dwarf2_compile_cfa_to_ax): Declare. + * dwarf2-frame.c (execute_cfa_program): Remove 'this_frame' + argument; add 'gdbarch' and 'pc'. + (dwarf2_compile_cfa_to_ax): New function. + (dwarf2_frame_cache): Update. + 2011-02-17 Joel Brobecker * ada-lang.c (ada_type_of_array): Fix the size of the array diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 48f47affe37..edd6a9c5267 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -38,6 +38,8 @@ #include "complaints.h" #include "dwarf2-frame.h" +#include "ax.h" +#include "dwarf2loc.h" struct comp_unit; @@ -428,13 +430,11 @@ Not implemented: computing unwound register using explicit value operator")); static void execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr, - const gdb_byte *insn_end, struct frame_info *this_frame, - struct dwarf2_frame_state *fs) + const gdb_byte *insn_end, struct gdbarch *gdbarch, + CORE_ADDR pc, struct dwarf2_frame_state *fs) { int eh_frame_p = fde->eh_frame_p; - CORE_ADDR pc = get_frame_pc (this_frame); int bytes_read; - struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); while (insn_ptr < insn_end && fs->pc <= pc) @@ -902,6 +902,85 @@ dwarf2_frame_find_quirks (struct dwarf2_frame_state *fs, } +void +dwarf2_compile_cfa_to_ax (struct agent_expr *expr, struct axs_value *loc, + struct gdbarch *gdbarch, + CORE_ADDR pc, + struct dwarf2_per_cu_data *data) +{ + const int num_regs = gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch); + struct dwarf2_fde *fde; + CORE_ADDR text_offset, cfa; + struct dwarf2_frame_state fs; + int addr_size; + + memset (&fs, 0, sizeof (struct dwarf2_frame_state)); + + fs.pc = pc; + + /* Find the correct FDE. */ + fde = dwarf2_frame_find_fde (&fs.pc, &text_offset); + if (fde == NULL) + error (_("Could not compute CFA; needed to translate this expression")); + + /* Extract any interesting information from the CIE. */ + fs.data_align = fde->cie->data_alignment_factor; + fs.code_align = fde->cie->code_alignment_factor; + fs.retaddr_column = fde->cie->return_address_register; + addr_size = fde->cie->addr_size; + + /* Check for "quirks" - known bugs in producers. */ + dwarf2_frame_find_quirks (&fs, fde); + + /* First decode all the insns in the CIE. */ + execute_cfa_program (fde, fde->cie->initial_instructions, + fde->cie->end, gdbarch, pc, &fs); + + /* Save the initialized register set. */ + fs.initial = fs.regs; + fs.initial.reg = dwarf2_frame_state_copy_regs (&fs.regs); + + /* Then decode the insns in the FDE up to our target PC. */ + execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, pc, &fs); + + /* Calculate the CFA. */ + switch (fs.regs.cfa_how) + { + case CFA_REG_OFFSET: + { + int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, fs.regs.cfa_reg); + + if (regnum == -1) + error (_("Unable to access DWARF register number %d"), + (int) fs.regs.cfa_reg); /* FIXME */ + ax_reg (expr, regnum); + + if (fs.regs.cfa_offset != 0) + { + if (fs.armcc_cfa_offsets_reversed) + ax_const_l (expr, -fs.regs.cfa_offset); + else + ax_const_l (expr, fs.regs.cfa_offset); + ax_simple (expr, aop_add); + } + } + break; + + case CFA_EXP: + ax_const_l (expr, text_offset); + dwarf2_compile_expr_to_ax (expr, loc, gdbarch, addr_size, + fs.regs.cfa_exp, + fs.regs.cfa_exp + fs.regs.cfa_exp_len, + data); + break; + + default: + internal_error (__FILE__, __LINE__, _("Unknown CFA rule.")); + } +} + + struct dwarf2_frame_cache { /* DWARF Call Frame Address. */ @@ -979,14 +1058,15 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) /* First decode all the insns in the CIE. */ execute_cfa_program (fde, fde->cie->initial_instructions, - fde->cie->end, this_frame, fs); + fde->cie->end, gdbarch, get_frame_pc (this_frame), fs); /* Save the initialized register set. */ fs->initial = fs->regs; fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs); /* Then decode the insns in the FDE up to our target PC. */ - execute_cfa_program (fde, fde->instructions, fde->end, this_frame, fs); + execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, + get_frame_pc (this_frame), fs); /* Calculate the CFA. */ switch (fs->regs.cfa_how) diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h index bf7134de28f..91d7643be62 100644 --- a/gdb/dwarf2-frame.h +++ b/gdb/dwarf2-frame.h @@ -26,6 +26,9 @@ struct gdbarch; struct objfile; struct frame_info; +struct dwarf2_per_cu_data; +struct agent_expr; +struct axs_value; /* Register rule. */ @@ -118,4 +121,15 @@ extern const struct frame_base * CORE_ADDR dwarf2_frame_cfa (struct frame_info *this_frame); +/* Update the agent expression EXPR with code to compute the CFA for a + frame at PC. GDBARCH is the architecture of the function at PC. + This function may call dwarf2_compile_expr_to_ax; DATA is passed + through to that function if needed. */ + +extern void dwarf2_compile_cfa_to_ax (struct agent_expr *expr, + struct axs_value *loc, + struct gdbarch *gdbarch, + CORE_ADDR pc, + struct dwarf2_per_cu_data *data); + #endif /* dwarf2-frame.h */ diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 3a297c7fcfa..4d31afa33cc 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -1426,11 +1426,11 @@ get_ax_pc (void *baton) example, if the expression cannot be compiled, or if the expression is invalid. */ -static void -compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, - struct gdbarch *arch, unsigned int addr_size, - const gdb_byte *op_ptr, const gdb_byte *op_end, - struct dwarf2_per_cu_data *per_cu) +void +dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc, + struct gdbarch *arch, unsigned int addr_size, + const gdb_byte *op_ptr, const gdb_byte *op_end, + struct dwarf2_per_cu_data *per_cu) { struct cleanup *cleanups; int i, *offsets; @@ -1717,8 +1717,8 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, &datastart, &datalen); op_ptr = read_sleb128 (op_ptr, op_end, &offset); - compile_dwarf_to_ax (expr, loc, arch, addr_size, datastart, - datastart + datalen, per_cu); + dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size, datastart, + datastart + datalen, per_cu); if (offset != 0) { @@ -1955,7 +1955,8 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, break; case DW_OP_call_frame_cfa: - unimplemented (op); + dwarf2_compile_cfa_to_ax (expr, loc, arch, expr->scope, per_cu); + loc->kind = axs_lvalue_memory; break; case DW_OP_GNU_push_tls_address: @@ -2069,9 +2070,9 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, /* DW_OP_call_ref is currently not supported. */ gdb_assert (block.per_cu == per_cu); - compile_dwarf_to_ax (expr, loc, arch, addr_size, - block.data, block.data + block.size, - per_cu); + dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size, + block.data, block.data + block.size, + per_cu); } break; @@ -2673,9 +2674,9 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, if (dlbaton->data == NULL || dlbaton->size == 0) value->optimized_out = 1; else - compile_dwarf_to_ax (ax, value, gdbarch, addr_size, - dlbaton->data, dlbaton->data + dlbaton->size, - dlbaton->per_cu); + dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, + dlbaton->data, dlbaton->data + dlbaton->size, + dlbaton->per_cu); } /* The set of location functions used with the DWARF-2 expression @@ -2826,8 +2827,8 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, if (data == NULL || size == 0) value->optimized_out = 1; else - compile_dwarf_to_ax (ax, value, gdbarch, addr_size, data, data + size, - dlbaton->per_cu); + dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, data, data + size, + dlbaton->per_cu); } /* The set of location functions used with the DWARF-2 expression diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index ee525061608..96a490e5def 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -25,6 +25,8 @@ struct symbol_computed_ops; struct objfile; struct dwarf2_per_cu_data; struct dwarf2_loclist_baton; +struct agent_expr; +struct axs_value; /* This header is private to the DWARF-2 reader. It is shared between dwarf2read.c and dwarf2loc.c. */ @@ -106,4 +108,25 @@ struct dwarf2_loclist_baton extern const struct symbol_computed_ops dwarf2_locexpr_funcs; extern const struct symbol_computed_ops dwarf2_loclist_funcs; +/* Compile a DWARF location expression to an agent expression. + + EXPR is the agent expression we are building. + LOC is the agent value we modify. + ARCH is the architecture. + ADDR_SIZE is the size of addresses, in bytes. + OP_PTR is the start of the location expression. + OP_END is one past the last byte of the location expression. + + This will throw an exception for various kinds of errors -- for + example, if the expression cannot be compiled, or if the expression + is invalid. */ + +extern void dwarf2_compile_expr_to_ax (struct agent_expr *expr, + struct axs_value *loc, + struct gdbarch *arch, + unsigned int addr_size, + const gdb_byte *op_ptr, + const gdb_byte *op_end, + struct dwarf2_per_cu_data *per_cu); + #endif /* dwarf2loc.h */ -- 2.30.2