[rfa:NetBSD/ppc] Implement signal trampoline unwinder

Andrew Cagney
2004-03-01T01:05:34Z

[-- Attachment #1: Type: text/plain, Size: 378 bytes --]

It appears to work (but doesn't have much effect without an rs6000
unwinder).

One question (and to follow up my earlier post) is there a better way of
doing this:

+ if (frame_pc_unwind (next_frame) > 0x7f000000)
+ /* Assume anything that is vaguely on the stack is a signal
+ trampoline. */
+ return &ppcnbsd_sigtramp_unwind;

ok?, eventually for 6.1?

Andrew

[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 3939 bytes --]

2004-02-29 Andrew Cagney <cagney@redhat.com>

* ppcnbsd-tdep.c: Include "trad-frame.h", and "frame-unwind.h".
(struct ppcnbsd_sigtramp_cache, ppcnbsd_sigtramp_this_id)
(ppcnbsd_sigtramp_prev_register, ppcnbsd_sigtramp_cache)
(ppcnbsd_sigtramp_sniffer, ppcnbsd_sigtramp_unwind)
(ppcnbsd_init_abi): Implement a NetBSD/PPC signal trampline
unwinder, register.

Index: ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.11
diff -u -r1.11 ppcnbsd-tdep.c
--- ppcnbsd-tdep.c 10 Nov 2003 22:47:28 -0000 1.11
+++ ppcnbsd-tdep.c 1 Mar 2004 00:58:20 -0000
@@ -26,6 +26,8 @@
#include "breakpoint.h"
#include "value.h"
#include "osabi.h"
+#include "trad-frame.h"
+#include "frame-unwind.h"

#include "ppc-tdep.h"
#include "ppcnbsd-tdep.h"
@@ -227,6 +229,89 @@
readbuf, writebuf);
}

+struct ppcnbsd_sigtramp_cache
+{
+ CORE_ADDR base;
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct ppcnbsd_sigtramp_cache *
+ppcnbsd_sigtramp_cache (struct frame_info *next_frame, void **this_cache)
+{
+ CORE_ADDR offset;
+ int i;
+ struct ppcnbsd_sigtramp_cache *cache;
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if ((*this_cache) != NULL)
+ return (*this_cache);
+ cache = FRAME_OBSTACK_ZALLOC (struct ppcnbsd_sigtramp_cache);
+ (*this_cache) = cache;
+ cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+ cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+ offset = cache->base + 0x18 + 2 * tdep->wordsize;
+ for (i = 0; i < 32; i++)
+ {
+ int regnum = i + tdep->ppc_gp0_regnum;
+ cache->saved_regs[regnum].addr = offset;
+ offset += tdep->wordsize;
+ }
+ cache->saved_regs[tdep->ppc_lr_regnum].addr = offset;
+ offset += tdep->wordsize;
+ cache->saved_regs[tdep->ppc_cr_regnum].addr = offset;
+ offset += tdep->wordsize;
+ cache->saved_regs[tdep->ppc_xer_regnum].addr = offset;
+ offset += tdep->wordsize;
+ cache->saved_regs[tdep->ppc_ctr_regnum].addr = offset;
+ offset += tdep->wordsize;
+ cache->saved_regs[PC_REGNUM].addr = offset; /* SRR0? */
+ offset += tdep->wordsize;
+ return cache;
+}
+
+static void
+ppcnbsd_sigtramp_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct ppcnbsd_sigtramp_cache *info = ppcnbsd_sigtramp_cache (next_frame,
+ this_cache);
+ (*this_id) = frame_id_build (info->base, frame_pc_unwind (next_frame));
+}
+
+static void
+ppcnbsd_sigtramp_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ struct ppcnbsd_sigtramp_cache *info = ppcnbsd_sigtramp_cache (next_frame,
+ this_cache);
+ trad_frame_prev_register (next_frame, info->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind ppcnbsd_sigtramp_unwind =
+{
+ SIGTRAMP_FRAME,
+ ppcnbsd_sigtramp_this_id,
+ ppcnbsd_sigtramp_prev_register
+};
+
+static const struct frame_unwind *
+ppcnbsd_sigtramp_sniffer (struct frame_info *next_frame)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
+ if (frame_pc_unwind (next_frame) > 0x7f000000)
+ /* Assume anything that is vaguely on the stack is a signal
+ trampoline. */
+ return &ppcnbsd_sigtramp_unwind;
+ else
+ return NULL;
+}
+
static void
ppcnbsd_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
@@ -237,6 +322,7 @@
set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
+ frame_unwind_append_sniffer (gdbarch, ppcnbsd_sigtramp_sniffer);
}

void