aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog15
-rw-r--r--gdb/hppa-linux-tdep.c15
-rw-r--r--gdb/hppa-tdep.c185
-rw-r--r--gdb/hppa-tdep.h7
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 */