This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch/rfa] Signal trampoline unwinder for hppa-hpux
- From: Randolph Chung <randolph at tausq dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Wed, 19 May 2004 21:17:46 -0700
- Subject: [patch/rfa] Signal trampoline unwinder for hppa-hpux
- Reply-to: Randolph Chung <randolph at tausq dot org>
This patch implements a signal trampoline unwinder for hpux. It also
cleans up some old sigtramp cruft that was in hppa-hpux-tdep.c.
I tested this against hppa2.0w-hp-hpux11.11 and hppa2.0w-hp-hpux11.00,
but I don't have a hpux machine running a 32-bit kernel to test. If
anyone is interested in that target, please give it a try. It *should*
work :)
Unfortunately this still fails a lot of the signal related testcases.
It is not because of a problem with the signal unwinder though:
On HPUX-SOM, there is an export stub inserted into the call sequence in
some cases; the export stub is hit on the return path from indirect
function calls, and apparently on return from a signal handler. This
creates an extra frame in the backtrace, viz:
(gdb) bt
#0 0x000029e4 in handle_USR1 (sig=0)
at ../../../gdb/gdb/testsuite/gdb.base/annota1.c:18
#1 0x000029c8 in handle_USR1 ()
at ../../../gdb/gdb/testsuite/gdb.base/annota1.c:17
#2 <signal handler called>
#3 main () at ../../../gdb/gdb/testsuite/gdb.base/annota1.c:40
Frame 1 comes from the export stub. Because of this, the pattern
matching in the backtrace test fails. I am not sure if this is a
problem with the test script or with the handling of export stubs -- am
I supposed to somehow supress the export stub from showing up in the
backtrace? (if so, how?)
Comments? ok to check in?
randolph
2004-05-19 Randolph Chung <tausq@debian.org>
* hppa-hpux-tdep.c (offsetof): Define.
(hppa_hpux_pc_in_sigtramp, hppa32_hpux_frame_saved_pc_in_sigtramp)
(hppa32_hpux_frame_base_before_sigtramp)
(hppa32_hpux_frame_find_saved_regs_in_sigtramp)
(hppa64_hpux_frame_saved_pc_in_sigtramp)
(hppa64_hpux_frame_base_before_sigtramp)
(hppa64_hpux_frame_find_saved_regs_in_sigtramp): Remove unused functions.
(hppa_hpux_sigtramp_find_sigcontext, hppa_hpux_sigtramp_unwind_cache)
(hppa_hpux_sigtramp_frame_unwind_cache, hppa_hpux_sigtramp_frame_this_id)
(hppa_hpux_sigtramp_frame_prev_register, hppa_hpux_sigtramp_frame_unwind)
(hppa_hpux_sigtramp_unwind_sniffer): New signal trampoline unwinder.
(hppa_hpux_init_abi): Register sigtramp unwinder.
Index: hppa-hpux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-hpux-tdep.c,v
retrieving revision 1.18
diff -u -p -r1.18 hppa-hpux-tdep.c
--- hppa-hpux-tdep.c 7 May 2004 05:48:48 -0000 1.18
+++ hppa-hpux-tdep.c 20 May 2004 03:45:07 -0000
@@ -24,15 +24,21 @@ Foundation, Inc., 59 Temple Place - Suit
#include "osabi.h"
#include "gdb_string.h"
#include "frame.h"
+#include "frame-unwind.h"
+#include "trad-frame.h"
#include "symtab.h"
#include "objfiles.h"
#include "inferior.h"
#include "infcall.h"
#include "hppa-tdep.h"
#include <dl.h>
#include <machine/save_state.h>
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
/* Forward declarations. */
extern void _initialize_hppa_hpux_tdep (void);
extern initialize_file_ftype _initialize_hppa_hpux_tdep;
@@ -45,125 +52,6 @@ typedef struct
}
args_for_find_stub;
-/* FIXME: brobecker 2002-12-25. The following functions will eventually
- become static, after the multiarching conversion is done. */
-int hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name);
-void hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
- CORE_ADDR *tmp);
-void hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
- CORE_ADDR *tmp);
-void hppa32_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
- CORE_ADDR *fsr);
-void hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
- CORE_ADDR *tmp);
-void hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
- CORE_ADDR *tmp);
-void hppa64_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
- CORE_ADDR *fsr);
-
-int
-hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name)
-{
- /* Actually, for a PA running HPUX the kernel calls the signal handler
- without an intermediate trampoline. Luckily the kernel always sets
- the return pointer for the signal handler to point to _sigreturn. */
- return (name && (strcmp ("_sigreturn", name) == 0));
-}
-
-/* For hppa32_hpux_frame_saved_pc_in_sigtramp,
- hppa32_hpux_frame_base_before_sigtramp and
- hppa32_hpux_frame_find_saved_regs_in_sigtramp:
-
- The signal context structure pointer is always saved at the base
- of the frame which "calls" the signal handler. We only want to find
- the hardware save state structure, which lives 10 32bit words into
- sigcontext structure.
-
- Within the hardware save state structure, registers are found in the
- same order as the register numbers in GDB.
-
- At one time we peeked at %r31 rather than the PC queues to determine
- what instruction took the fault. This was done on purpose, but I don't
- remember why. Looking at the PC queues is really the right way, and
- I don't remember why that didn't work when this code was originally
- written. */
-
-void
-hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi, CORE_ADDR *tmp)
-{
- *tmp = read_memory_integer (get_frame_base (fi) + (43 * 4), 4);
-}
-
-void
-hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
- CORE_ADDR *tmp)
-{
- *tmp = read_memory_integer (get_frame_base (fi) + (40 * 4), 4);
-}
-
-void
-hppa32_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
- CORE_ADDR *fsr)
-{
- int i;
- const CORE_ADDR tmp = get_frame_base (fi) + (10 * 4);
-
- for (i = 0; i < NUM_REGS; i++)
- {
- if (i == HPPA_SP_REGNUM)
- fsr[HPPA_SP_REGNUM] = read_memory_integer (tmp + HPPA_SP_REGNUM * 4, 4);
- else
- fsr[i] = tmp + i * 4;
- }
-}
-
-/* For hppa64_hpux_frame_saved_pc_in_sigtramp,
- hppa64_hpux_frame_base_before_sigtramp and
- hppa64_hpux_frame_find_saved_regs_in_sigtramp:
-
- These functions are the PA64 ABI equivalents of the 32bits counterparts
- above. See the comments there.
-
- For PA64, the save_state structure is at an offset of 24 32-bit words
- from the sigcontext structure. The 64 bit general registers are at an
- offset of 640 bytes from the beginning of the save_state structure,
- and the floating pointer register are at an offset of 256 bytes from
- the beginning of the save_state structure. */
-
-void
-hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi, CORE_ADDR *tmp)
-{
- *tmp = read_memory_integer
- (get_frame_base (fi) + (24 * 4) + 640 + (33 * 8), 8);
-}
-
-void
-hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
- CORE_ADDR *tmp)
-{
- *tmp = read_memory_integer
- (get_frame_base (fi) + (24 * 4) + 640 + (30 * 8), 8);
-}
-
-void
-hppa64_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
- CORE_ADDR *fsr)
-{
- int i;
- const CORE_ADDR tmp1 = get_frame_base (fi) + (24 * 4) + 640;
- const CORE_ADDR tmp2 = get_frame_base (fi) + (24 * 4) + 256;
-
- for (i = 0; i < NUM_REGS; i++)
- {
- if (i == HPPA_SP_REGNUM)
- fsr[HPPA_SP_REGNUM] = read_memory_integer (tmp1 + HPPA_SP_REGNUM * 8, 8);
- else if (i >= HPPA_FP0_REGNUM)
- fsr[i] = tmp2 + (i - HPPA_FP0_REGNUM) * 8;
- else
- fsr[i] = tmp1 + i * 8;
- }
-}
-
/* Return one if PC is in the call path of a trampoline, else return zero.
Note we return one for *any* call trampoline (long-call, arg-reloc), not
@@ -1222,6 +1060,202 @@ child_get_current_exception_event (void)
return ¤t_ex_event;
}
+/* Signal frames. */
+
+static CORE_ADDR
+hppa_hpux_sigtramp_find_sigcontext (CORE_ADDR sp, CORE_ADDR pc)
+{
+ unsigned int insns[5];
+
+ read_memory_nobpt (pc, (char *)insns, sizeof(insns));
+
+ /* This comes from _sigreturn:
+ 379a0000 ldo 0(%r28), %r26
+ 6bd33fc9 stw %r19, -28(%sp)
+ 20200801 ldil -40000000, %r1
+ e420e008 be,l 4(%sr7, %rr1), %sr0, %r31
+ 34160116 ldi 139, %r22 */
+
+ if (extract_unsigned_integer (&insns[0], 4) != 0x379a0000
+ || extract_unsigned_integer (&insns[1], 4) != 0x6bd33fc9
+ || extract_unsigned_integer (&insns[2], 4) != 0x20200801
+ || extract_unsigned_integer (&insns[3], 4) != 0xe420e008
+ || extract_unsigned_integer (&insns[4], 4) != 0x34160116)
+ return 0;
+
+ /* We can find a ucontext_t 1352 bytes above the stack. The first
+ element of the ucontext_t is a mcontext_t (save_state_t), which
+ contains the registers we want. */
+ return sp - 1352;
+}
+
+struct hppa_hpux_sigtramp_unwind_cache
+{
+ CORE_ADDR base;
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct hppa_hpux_sigtramp_unwind_cache *
+hppa_hpux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
+ void **this_cache)
+{
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct hppa_hpux_sigtramp_unwind_cache *info;
+ unsigned int flag;
+ CORE_ADDR sp, pc, scptr;
+ int i, incr, off, szoff;
+
+ if (*this_cache)
+ return *this_cache;
+
+ info = FRAME_OBSTACK_ZALLOC (struct hppa_hpux_sigtramp_unwind_cache);
+ *this_cache = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+ sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+ pc = frame_pc_unwind (next_frame);
+ scptr = hppa_hpux_sigtramp_find_sigcontext (sp, pc);
+
+ /* See /usr/include/machine/save_state.h for the structure of the save_state_t
+ structure. */
+
+ off = scptr;
+ flag = read_memory_unsigned_integer(scptr, 4);
+
+ if (!(flag & 0x40))
+ {
+ /* Narrow registers. */
+ off = scptr + offsetof (save_state_t, ss_narrow);
+ incr = 4;
+ szoff = 0;
+ }
+ else
+ {
+ /* Wide registers. */
+ off = scptr + offsetof (save_state_t, ss_wide) + 8;
+ incr = 8;
+ szoff = (tdep->bytes_per_address == 4 ? 4 : 0);
+ }
+
+ for (i = 1; i < 32; i++)
+ {
+ info->saved_regs[HPPA_R0_REGNUM + i].addr = off + szoff;
+ off += incr;
+ }
+
+ info->saved_regs[HPPA_SAR_REGNUM].addr = off + szoff;
+ off += incr;
+
+ info->saved_regs[HPPA_PCOQ_HEAD_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PCSQ_HEAD_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PCOQ_TAIL_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PCSQ_TAIL_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_EIEM_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_IIR_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_ISR_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_IOR_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_IPSW_REGNUM].addr = off + szoff;
+ off += incr;
+
+ /* ignore ss_cpustate */
+ off += incr;
+
+ info->saved_regs[HPPA_SR4_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+1].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+2].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+3].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+4].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+5].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+6].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_SR4_REGNUM+7].addr = off + szoff;
+ off += incr;
+
+ info->saved_regs[HPPA_RCR_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PID0_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PID1_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_CCR_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PID2_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_PID3_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_TR0_REGNUM].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_TR0_REGNUM + 1].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_TR0_REGNUM + 2].addr = off + szoff;
+ off += incr;
+ info->saved_regs[HPPA_CR27_REGNUM].addr = off + szoff;
+ off += incr;
+
+ /* TODO: fp regs */
+
+ info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+
+ return info;
+}
+
+static void
+hppa_hpux_sigtramp_frame_this_id (struct frame_info *next_frame,
+ void **this_prologue_cache,
+ struct frame_id *this_id)
+{
+ struct hppa_hpux_sigtramp_unwind_cache *info
+ = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
+ *this_id = frame_id_build (info->base, frame_pc_unwind (next_frame));
+}
+
+static void
+hppa_hpux_sigtramp_frame_prev_register (struct frame_info *next_frame,
+ void **this_prologue_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp,
+ CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ struct hppa_hpux_sigtramp_unwind_cache *info
+ = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
+ hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
+ SIGTRAMP_FRAME,
+ hppa_hpux_sigtramp_frame_this_id,
+ hppa_hpux_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+hppa_hpux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
+{
+ CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+
+ if (hppa_hpux_sigtramp_find_sigcontext (sp, pc))
+ return &hppa_hpux_sigtramp_frame_unwind;
+
+ return NULL;
+}
+
static void
hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1237,6 +1277,8 @@ hppa_hpux_init_abi (struct gdbarch_info
set_gdbarch_in_solib_return_trampoline (gdbarch,
hppa_hpux_in_solib_return_trampoline);
set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
+
+ frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
}
static void
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/