[PATCH/RFC] Per-architecture DWARF CFI register state initialization hooks

Mark Kettenis
2004-02-07T22:38:28Z

Here's my proposal for the per-architecture DWARF CFI register state
initialization hooks needed for S/390, and others. This is a RFC,
since I'm not entirely confident whether my approach is acceptable. I
chose to implement this using per-architecture data instead of adding
a function to the architecture vector. I think it is cleaner since it
keeps things localized and modular, and the architecture vector is big
enough as it stands. However you folks might think otherwise.

Ulrich, this should privide the hooks you need. For S/390 you should
provide a function with the following signature:

void
s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
struct gdbarch dwarf2_frame_state_reg *reg);

and initialize REG according to your needs for the REGNUMs you care
about. Note that REGNUM is the GDB register number.

Comments?

Mark

Index: ChangeLog
from Mark Kettenis <kettenis@gnu.org>

* dwarf2-frame.h (dwarf2_frame_set_init_reg): New prototype.
* dwarf2-frame.c (dwarf2_frame_init_reg_data): New variable.
(dwarf2_frame_default_init_reg): Renamed from
dwarf2_frame_init_reg. Tweak comments.
(dwarf2_frame_init_reg_init, dwarf2_frame_set_init_reg,
dwarf2_frame_init_reg): New functions.
(_initialize_dwarf2_frame): Initialize dwarf2_frame_init_reg_data.

Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.28
diff -u -p -r1.28 dwarf2-frame.c
--- dwarf2-frame.c 7 Feb 2004 14:44:50 -0000 1.28
+++ dwarf2-frame.c 7 Feb 2004 22:28:15 -0000
@@ -454,53 +454,94 @@ execute_cfa_program (unsigned char *insn
dwarf2_frame_state_free_regs (fs->regs.prev);
fs->regs.prev = NULL;
}
+\f

-struct dwarf2_frame_cache
-{
- /* DWARF Call Frame Address. */
- CORE_ADDR cfa;
+/* Per-architecture data keys. */

- /* Saved registers, indexed by GDB register number, not by DWARF
- register number. */
- struct dwarf2_frame_state_reg *reg;
-};
+static struct gdbarch_data *dwarf2_frame_init_reg_data;

-/* Initialize the register state REG. If we have a register that acts
- as a program counter, mark it as a destination for the return
- address. If we have a register that serves as the stack pointer,
- arrange for it to be filled with the call frame address (CFA). The
- other registers are marked as unspecified.
-
- We copy the return address to the program counter, since many parts
- in GDB assume that it is possible to get the return address by
- unwind the program counter register. However, on ISA's with a
- dedicated return address register, the CFI usually only contains
- information to unwind that return address register.
-
- The reason we're treating the stack pointer special here is because
- in many cases GCC doesn't emit CFI for the stack pointer and
- implicitly assumes that it is equal to the CFA. This makes some
- sense since the DWARF specification (version 3, draft 8, p. 102)
- says that:
-
- "Typically, the CFA is defined to be the value of the stack pointer
- at the call site in the previous frame (which may be different from
- its value on entry to the current frame)."
-
- However, this isn't true for all platforms supported by GCC
- (e.g. IBM S/390 and zSeries). For those targets we should override
- the defaults given here. */
+/* Default acrhitecture-specific register state initialization
+ function. */

static void
-dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
- struct dwarf2_frame_state_reg *reg)
+dwarf2_frame_default_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg)
{
+ /* If we have a register that acts as a program counter, mark it as
+ a destination for the return address. If we have a register that
+ serves as the stack pointer, arrange for it to be filled with the
+ call frame address (CFA). The other registers are marked as
+ unspecified.
+
+ We copy the return address to the program counter, since many
+ parts in GDB assume that it is possible to get the return address
+ by unwinding the program counter register. However, on ISA's
+ with a dedicated return address register, the CFI usually only
+ contains information to unwind that return address register.
+
+ The reason we're treating the stack pointer special here is
+ because in many cases GCC doesn't emit CFI for the stack pointer
+ and implicitly assumes that it is equal to the CFA. This makes
+ some sense since the DWARF specification (version 3, draft 8,
+ p. 102) says that:
+
+ "Typically, the CFA is defined to be the value of the stack
+ pointer at the call site in the previous frame (which may be
+ different from its value on entry to the current frame)."
+
+ However, this isn't true for all platforms supported by GCC
+ (e.g. IBM S/390 and zSeries). Those architectures should provide
+ their own architecture-specific initialization function. */
+
if (regnum == PC_REGNUM)
reg->how = DWARF2_FRAME_REG_RA;
else if (regnum == SP_REGNUM)
reg->how = DWARF2_FRAME_REG_CFA;
}

+/* Return a default for the architecture-specific register state
+ initialization function. */
+
+static void *
+dwarf2_frame_init_reg_init (struct gdbarch *gdbarch)
+{
+ return dwarf2_frame_default_init_reg;
+}
+
+/* Set the architecture-specific register state initialization
+ function for GDBARCH to INIT_REG. */
+
+void
+dwarf2_frame_set_init_reg (struct gdbarch *gdbarch,
+ void (*init_reg) (struct gdbarch *, int,
+ struct dwarf2_frame_state_reg *))
+{
+ set_gdbarch_data (gdbarch, dwarf2_frame_init_reg_data, init_reg);
+}
+
+/* Pre-initialize the register state REG for register REGNUM. */
+
+static void
+dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg)
+{
+ void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *);
+
+ init_reg = gdbarch_data (gdbarch, dwarf2_frame_init_reg_data);
+ init_reg (gdbarch, regnum, reg);
+}
+\f
+
+struct dwarf2_frame_cache
+{
+ /* DWARF Call Frame Address. */
+ CORE_ADDR cfa;
+
+ /* Saved registers, indexed by GDB register number, not by DWARF
+ register number. */
+ struct dwarf2_frame_state_reg *reg;
+};
+
static struct dwarf2_frame_cache *
dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
{
@@ -1461,7 +1502,6 @@ decode_frame_entry (struct comp_unit *un

return ret;
}
-
\f

/* FIXME: kettenis/20030504: This still needs to be integrated with
@@ -1542,4 +1582,6 @@ void
_initialize_dwarf2_frame (void)
{
dwarf2_frame_data = register_objfile_data ();
+ dwarf2_frame_init_reg_data =
+ register_gdbarch_data (dwarf2_frame_init_reg_init);
}
Index: dwarf2-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.h,v
retrieving revision 1.4
diff -u -p -r1.4 dwarf2-frame.h
--- dwarf2-frame.h 7 Feb 2004 14:44:50 -0000 1.4
+++ dwarf2-frame.h 7 Feb 2004 22:28:15 -0000
@@ -71,6 +71,13 @@ struct dwarf2_frame_state_reg
enum dwarf2_frame_reg_rule how;
};

+/* Set the architecture-specific register state initialization
+ function for GDBARCH to INIT_REG. */
+
+extern void dwarf2_frame_set_init_reg (struct gdbarch *gdbarch,
+ void (*init_reg) (struct gdbarch *, int,
+ struct dwarf2_frame_state_reg *));
+
/* Return the frame unwind methods for the function that contains PC,
or NULL if it can't be handled by DWARF CFI frame unwinder. */