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.
This commit is contained in:
Randolph Chung 2004-05-08 03:17:57 +00:00
parent b9ec757a56
commit 0da28f8a58
4 changed files with 167 additions and 61 deletions

View File

@ -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

View File

@ -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 = {

View File

@ -1856,42 +1856,14 @@ 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)
{
/* 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)
{
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);
}
}
else
{
trad_frame_prev_register (next_frame, info->saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
}
hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
}
static const struct frame_unwind hppa_frame_unwind =
@ -1904,7 +1876,116 @@ static const struct frame_unwind hppa_frame_unwind =
static const struct frame_unwind *
hppa_frame_unwind_sniffer (struct frame_info *next_frame)
{
return &hppa_frame_unwind;
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)
{
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) */
{
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
{
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 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_fallback_frame_this_id,
hppa_fallback_frame_prev_register
};
static const struct frame_unwind *
hppa_fallback_unwind_sniffer (struct frame_info *next_frame)
{
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;

View File

@ -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 */