[PATCH v4 09/14] split dwarf2_fetch_cfa_info from dwarf2_compile_expr_to_ax

Jan Kratochvil
2014-11-23T19:28:31Z

From: Tom Tromey <tromey@redhat.com>

This removes dwarf2_compile_expr_to_ax, replacing it with a utility
function that fetches the CFA data and adding the code to actually
compile to an agent expression directly into
dwarf2_compile_expr_to_ax. This refactoring lets a later patch reuse
the new dwarf2_fetch_cfa_info.

2014-10-07 Tom Tromey <tromey@redhat.com>

* dwarf2loc.c (dwarf2_compile_expr_to_ax) <DW_OP_call_frame_cfa>:
Update.
* dwarf2-frame.c (dwarf2_fetch_cfa_info): New function, based on
dwarf2_compile_cfa_to_ax.
(dwarf2_compile_cfa_to_ax): Remove.
* dwarf2-frame.h (dwarf2_fetch_cfa_info): Declare.
(dwarf2_compile_cfa_to_ax): Remove.
---
gdb/ChangeLog | 10 ++++++++++
gdb/dwarf2-frame.c | 40 +++++++++++++++++++---------------------
gdb/dwarf2-frame.h | 31 +++++++++++++++++++++----------
gdb/dwarf2loc.c | 30 ++++++++++++++++++++++++++++--
4 files changed, 78 insertions(+), 33 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fc60169..922d8c9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2014-10-07 Tom Tromey <tromey@redhat.com>
+
+ * dwarf2loc.c (dwarf2_compile_expr_to_ax) <DW_OP_call_frame_cfa>:
+ Update.
+ * dwarf2-frame.c (dwarf2_fetch_cfa_info): New function, based on
+ dwarf2_compile_cfa_to_ax.
+ (dwarf2_compile_cfa_to_ax): Remove.
+ * dwarf2-frame.h (dwarf2_fetch_cfa_info): Declare.
+ (dwarf2_compile_cfa_to_ax): Remove.
+
2014-10-07 Jan Kratochvil <jan.kratochvil@redhat.com>

* infcall.h (call_function_by_hand_dummy): Declare.
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 586f134..db21cd4 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -882,11 +882,15 @@ dwarf2_frame_find_quirks (struct dwarf2_frame_state *fs,
}
\f

-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)
+/* See dwarf2-frame.h. */
+
+int
+dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc,
+ struct dwarf2_per_cu_data *data,
+ int *regnum_out, LONGEST *offset_out,
+ CORE_ADDR *text_offset_out,
+ const gdb_byte **cfa_start_out,
+ const gdb_byte **cfa_end_out)
{
struct dwarf2_fde *fde;
CORE_ADDR text_offset;
@@ -932,26 +936,20 @@ dwarf2_compile_cfa_to_ax (struct agent_expr *expr, struct axs_value *loc,
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);
- }
+ *regnum_out = regnum;
+ if (fs.armcc_cfa_offsets_reversed)
+ *offset_out = -fs.regs.cfa_offset;
+ else
+ *offset_out = fs.regs.cfa_offset;
+ return 1;
}
- 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;
+ *text_offset_out = text_offset;
+ *cfa_start_out = fs.regs.cfa_exp;
+ *cfa_end_out = fs.regs.cfa_exp + fs.regs.cfa_exp_len;
+ return 0;

default:
internal_error (__FILE__, __LINE__, _("Unknown CFA rule."));
diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h
index 0470cac..5ccf0c8 100644
--- a/gdb/dwarf2-frame.h
+++ b/gdb/dwarf2-frame.h
@@ -120,15 +120,26 @@ 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);
+/* Find the CFA information for PC.
+
+ Return 1 if a register is used for the CFA, or 0 if another
+ expression is used. Throw an exception on error.
+
+ GDBARCH is the architecture to use.
+ DATA is the per-CU data.
+
+ REGNUM_OUT is an out parameter that is set to the register number.
+ OFFSET_OUT is the offset to use from this register.
+ These are only filled in when 1 is returned.
+
+ TEXT_OFFSET_OUT, CFA_START_OUT, and CFA_END_OUT describe the CFA
+ in other cases. These are only used when 0 is returned. */
+
+extern int dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc,
+ struct dwarf2_per_cu_data *data,
+ int *regnum_out, LONGEST *offset_out,
+ CORE_ADDR *text_offset_out,
+ const gdb_byte **cfa_start_out,
+ const gdb_byte **cfa_end_out);

#endif /* dwarf2-frame.h */
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 6e461bc..ffae7a5 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -3282,8 +3282,34 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
break;

case DW_OP_call_frame_cfa:
- dwarf2_compile_cfa_to_ax (expr, loc, arch, expr->scope, per_cu);
- loc->kind = axs_lvalue_memory;
+ {
+ int regnum;
+ CORE_ADDR text_offset;
+ LONGEST off;
+ const gdb_byte *cfa_start, *cfa_end;
+
+ if (dwarf2_fetch_cfa_info (arch, expr->scope, per_cu,
+ &regnum, &off,
+ &text_offset, &cfa_start, &cfa_end))
+ {
+ /* Register. */
+ ax_reg (expr, regnum);
+ if (off != 0)
+ {
+ ax_const_l (expr, off);
+ ax_simple (expr, aop_add);
+ }
+ }
+ else
+ {
+ /* Another expression. */
+ ax_const_l (expr, text_offset);
+ dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size,
+ cfa_start, cfa_end, per_cu);
+ }
+
+ loc->kind = axs_lvalue_memory;
+ }
break;