diff options
-rw-r--r-- | gdb/ChangeLog | 15 | ||||
-rw-r--r-- | gdb/hppa-linux-tdep.c | 15 | ||||
-rw-r--r-- | gdb/hppa-tdep.c | 185 | ||||
-rw-r--r-- | gdb/hppa-tdep.h | 7 |
4 files changed, 164 insertions, 58 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e81bcf0..a4484fe 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2004-05-07 Randolph Chung <tausq@debian.org> + + * hppa-tdep.c (hppa_frame_prev_register_helper): New function to + do common handling of the pcoqt register. + (hppa_frame_prev_register, hppa_stub_frame_prev_register): Convert + to use helper function. + (hppa_frame_unwind_sniffer): Only use if unwind entry is present. + (hppa_fallback_frame_cache, hppa_fallback_frame_this_id) + (hppa_fallback_frame_prev_register, hppa_fallback_frame_unwind): New + generic fallback unwinder when all else fails. + (hppa_gdbarch_init): Add fallback sniffer. + * hppa-tdep.h (hppa_frame_prev_register_helper): Prototype. + * hppa-linux-tdep.c (hppa_linux_sigtramp_frame_prev_register): Convert + to use helper function. + 2004-05-08 Joel Brobecker <brobecker@gnat.com> * config/djgpp/fnchange.lst: Add translation rules for diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c index 1d7d047..8fae030 100644 --- a/gdb/hppa-linux-tdep.c +++ b/gdb/hppa-linux-tdep.c @@ -415,21 +415,12 @@ hppa_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *bufferp) + int *realnump, void *valuep) { struct hppa_linux_sigtramp_unwind_cache *info = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache); - int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM); - - if (pcoqt) - regnum = HPPA_PCOQ_HEAD_REGNUM; - - trad_frame_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); - - if (pcoqt) - store_unsigned_integer (bufferp, 4, - extract_unsigned_integer (bufferp, 4) + 4); + hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); } static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = { diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 9ead808..3e0e0ab 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1856,55 +1856,136 @@ hppa_frame_this_id (struct frame_info *next_frame, void **this_cache, static void hppa_frame_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) + void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *valuep) { struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache); - struct gdbarch *gdbarch = get_frame_arch (next_frame); - if (regnum == HPPA_PCOQ_TAIL_REGNUM) + hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind hppa_frame_unwind = +{ + NORMAL_FRAME, + hppa_frame_this_id, + hppa_frame_prev_register +}; + +static const struct frame_unwind * +hppa_frame_unwind_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + + if (find_unwind_entry (pc)) + return &hppa_frame_unwind; + + return NULL; +} + +/* This is a generic fallback frame unwinder that kicks in if we fail all + the other ones. Normally we would expect the stub and regular unwinder + to work, but in some cases we might hit a function that just doesn't + have any unwind information available. In this case we try to do + unwinding solely based on code reading. This is obviously going to be + slow, so only use this as a last resort. Currently this will only + identify the stack and pc for the frame. */ + +static struct hppa_frame_cache * +hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache) +{ + struct hppa_frame_cache *cache; + CORE_ADDR pc, start_pc, end_pc, cur_pc; + + cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + pc = frame_func_unwind (next_frame); + cur_pc = frame_pc_unwind (next_frame); + + find_pc_partial_function (pc, NULL, &start_pc, &end_pc); + + if (start_pc == 0 || end_pc == 0) { - /* The PCOQ TAIL, or NPC, needs to be computed from the unwound - PC register. */ - *optimizedp = 0; - *lvalp = not_lval; - *addrp = 0; - *realnump = 0; - if (valuep) + error ("Cannot find bounds of current function (@0x%s), unwinding will " + "fail.", paddr_nz (pc)); + return cache; + } + + if (end_pc > cur_pc) + end_pc = cur_pc; + + for (pc = start_pc; pc < end_pc; pc += 4) + { + unsigned int insn; + + insn = read_memory_unsigned_integer (pc, 4); + + /* There are limited ways to store the return pointer into the + stack. */ + if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */ + { + cache->saved_regs[HPPA_RP_REGNUM].addr = -20; + break; + } + else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */ { - int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM); - CORE_ADDR pc; - int optimized; - enum lval_type lval; - CORE_ADDR addr; - int realnum; - bfd_byte value[MAX_REGISTER_SIZE]; - trad_frame_prev_register (next_frame, info->saved_regs, - HPPA_PCOQ_HEAD_REGNUM, &optimized, &lval, &addr, - &realnum, &value); - pc = extract_unsigned_integer (&value, regsize); - store_unsigned_integer (valuep, regsize, pc + 4); + cache->saved_regs[HPPA_RP_REGNUM].addr = -16; + break; } } + + cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM); + + if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM)) + { + cache->saved_regs[HPPA_RP_REGNUM].addr += cache->base; + cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM]; + } else { - trad_frame_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); + ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM); + trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp); } + + return cache; } -static const struct frame_unwind hppa_frame_unwind = +static void +hppa_fallback_frame_this_id (struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct hppa_frame_cache *info = + hppa_fallback_frame_cache (next_frame, this_cache); + (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame)); +} + +static void +hppa_fallback_frame_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 hppa_frame_cache *info = + hppa_fallback_frame_cache (next_frame, this_cache); + hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind hppa_fallback_frame_unwind = { NORMAL_FRAME, - hppa_frame_this_id, - hppa_frame_prev_register + hppa_fallback_frame_this_id, + hppa_fallback_frame_prev_register }; static const struct frame_unwind * -hppa_frame_unwind_sniffer (struct frame_info *next_frame) +hppa_fallback_unwind_sniffer (struct frame_info *next_frame) { - return &hppa_frame_unwind; + return &hppa_fallback_frame_unwind; } static CORE_ADDR @@ -1971,23 +2052,12 @@ hppa_stub_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 *bufferp) + int *realnump, void *valuep) { struct hppa_stub_unwind_cache *info = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache); - int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM); - struct gdbarch *gdbarch = get_frame_arch (next_frame); - int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM); - - if (pcoqt) - regnum = HPPA_PCOQ_HEAD_REGNUM; - - trad_frame_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); - - if (pcoqt) - store_unsigned_integer (bufferp, regsize, - extract_unsigned_integer (bufferp, regsize) + 4); + hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); } static const struct frame_unwind hppa_stub_frame_unwind = { @@ -2230,6 +2300,28 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, store_unsigned_integer (buf, sizeof(tmp), tmp); } +void +hppa_frame_prev_register_helper (struct frame_info *next_frame, + struct trad_frame_saved_reg saved_regs[], + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM); + struct gdbarch *gdbarch = get_frame_arch (next_frame); + int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM); + + if (pcoqt) + regnum = HPPA_PCOQ_HEAD_REGNUM; + + trad_frame_prev_register (next_frame, saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); + + if (pcoqt) + store_unsigned_integer (valuep, regsize, + extract_unsigned_integer (valuep, regsize) + 4); +} + /* Here is a table of C type sizes on hppa with various compiles and options. I measured this on PA 9000/800 with HP-UX 11.11 and these compilers: @@ -2391,6 +2483,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Hook in the default unwinders. */ frame_unwind_append_sniffer (gdbarch, hppa_stub_unwind_sniffer); frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer); + frame_unwind_append_sniffer (gdbarch, hppa_fallback_unwind_sniffer); frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer); return gdbarch; diff --git a/gdb/hppa-tdep.h b/gdb/hppa-tdep.h index 79e8ae3..55c8bda 100644 --- a/gdb/hppa-tdep.h +++ b/gdb/hppa-tdep.h @@ -188,4 +188,11 @@ int hppa_extract_14 (unsigned); int hppa_low_sign_extend (unsigned int, unsigned int); int hppa_sign_extend (unsigned int, unsigned int); +void +hppa_frame_prev_register_helper (struct frame_info *next_frame, + struct trad_frame_saved_reg saved_regs[], + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *valuep); + #endif /* HPPA_TDEP_H */ |