diff options
-rw-r--r-- | gdb/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/hppa-linux-tdep.c | 34 |
2 files changed, 35 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6460705..1d297c8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 2004-05-07 Randolph Chung <tausq@debian.org> + * hppa-linux-tdep.c (hppa_linux_sigtramp_find_sigcontext): Pass in pc + instead of sp, handle sigaltstack case. + (hppa_linux_sigtramp_frame_unwind_cache): Adjust calls to + hppa_linux_sigtramp_find_sigcontext, and set base to the frame of the + signal handler and not that of the caller. + (hppa_linux_sigtramp_unwind_sniffer): Adjust calls to + hppa_linux_sigtramp_find_sigcontext. + +2004-05-07 Randolph Chung <tausq@debian.org> + * Makefile.in (ALLDEPFILES): Add hppa-linux-tdep.c and hppa-linux-nat.c. (hppa-linux-tdep.o, hppa-linux-nat.o): Define rules. diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c index 8fae030..f57ef50 100644 --- a/gdb/hppa-linux-tdep.c +++ b/gdb/hppa-linux-tdep.c @@ -282,7 +282,7 @@ hppa_linux_skip_trampoline_code (CORE_ADDR pc) Note that with a 2.4 64-bit kernel, the signal context is not properly passed back to userspace so the unwind will not work correctly. */ static CORE_ADDR -hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp) +hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc) { unsigned int dummy[HPPA_MAX_INSN_PATTERN_LEN]; int offs = 0; @@ -291,6 +291,12 @@ hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp) static int pcoffs[] = { 0, 4*4, 5*4 }; /* offsets to the rt_sigframe structure */ static int sfoffs[] = { 4*4, 10*4, 10*4 }; + CORE_ADDR sp; + + /* Most of the time, this will be correct. The one case when this will + fail is if the user defined an alternate stack, in which case the + beginning of the stack will not be align_down (pc, 64). */ + sp = align_down (pc, 64); /* rt_sigreturn trampoline: 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) @@ -308,7 +314,20 @@ hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp) } if (offs == 0) - return 0; + { + if (insns_match_pattern (pc, hppa_sigtramp, dummy)) + { + /* sigaltstack case: we have no way of knowing which offset to + use in this case; default to new kernel handling. If this is + wrong the unwinding will fail. */ + try = 2; + sp = pc - pcoffs[try]; + } + else + { + return 0; + } + } /* sp + sfoffs[try] points to a struct rt_sigframe, which contains a struct siginfo and a struct ucontext. struct ucontext contains @@ -331,7 +350,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame, { struct gdbarch *gdbarch = get_frame_arch (next_frame); struct hppa_linux_sigtramp_unwind_cache *info; - CORE_ADDR sp, pc, scptr; + CORE_ADDR pc, scptr; int i; if (*this_cache) @@ -342,8 +361,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame, info->saved_regs = trad_frame_alloc_saved_regs (next_frame); pc = frame_pc_unwind (next_frame); - sp = (pc & ~63); - scptr = hppa_linux_sigtramp_find_sigcontext (sp); + scptr = hppa_linux_sigtramp_find_sigcontext (pc); /* structure of struct sigcontext: @@ -393,8 +411,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame, info->saved_regs[HPPA_PCOQ_TAIL_REGNUM].addr = scptr; scptr += 4; - info->base = read_memory_unsigned_integer ( - info->saved_regs[HPPA_SP_REGNUM].addr, 4); + info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM); return info; } @@ -439,9 +456,8 @@ static const struct frame_unwind * hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame) { CORE_ADDR pc = frame_pc_unwind (next_frame); - CORE_ADDR sp = (pc & ~63); - if (hppa_linux_sigtramp_find_sigcontext (sp)) + if (hppa_linux_sigtramp_find_sigcontext (pc)) return &hppa_linux_sigtramp_frame_unwind; return NULL; |