* hppa-tdep.h (hppa_read_pc, hppa_write_pc, hppa_unwind_pc): New

prototypes.
* hppa-tdep.c (hppa_read_pc): Rename from hppa_target_read_pc.
Make global.  Remove HP-UX specific code.  Use
frame_unwind_register_unsigned instead of
frame_unwind_register_signed.
(hppa_write_pc): Rename from hppa_target_write_pc.  Make global.
Remove HP-UX specific code.
(hppa_unwind_pc): Make global.  Remove HP-UX specific code.
(hppa_frame_prev_register_helper): Set "flags" register to zero
for all unwound frames.
(hppa_gdbarch_init): Adjust.
* hppa-hpux-tdep.c (HPPA_HPUX_SS_INSYSCALL): New define.
(hppa_hpux_read_pc, hppa_hpux_write_pc)
(hppa_hpux_unwind_pc): New functions.
(hppa_hpux_init_abi): Set read_pc, write_pc and unwind_pc.
This commit is contained in:
Mark Kettenis 2004-12-07 18:04:11 +00:00
parent cb9faf63f8
commit cc72850f95
4 changed files with 114 additions and 45 deletions

View file

@ -1,3 +1,22 @@
2004-12-07 Mark Kettenis <kettenis@gnu.org>
* hppa-tdep.h (hppa_read_pc, hppa_write_pc, hppa_unwind_pc): New
prototypes.
* hppa-tdep.c (hppa_read_pc): Rename from hppa_target_read_pc.
Make global. Remove HP-UX specific code. Use
frame_unwind_register_unsigned instead of
frame_unwind_register_signed.
(hppa_write_pc): Rename from hppa_target_write_pc. Make global.
Remove HP-UX specific code.
(hppa_unwind_pc): Make global. Remove HP-UX specific code.
(hppa_frame_prev_register_helper): Set "flags" register to zero
for all unwound frames.
(hppa_gdbarch_init): Adjust.
* hppa-hpux-tdep.c (HPPA_HPUX_SS_INSYSCALL): New define.
(hppa_hpux_read_pc, hppa_hpux_write_pc)
(hppa_hpux_unwind_pc): New functions.
(hppa_hpux_init_abi): Set read_pc, write_pc and unwind_pc.
2004-12-07 Andreas Schwab <schwab@suse.de> 2004-12-07 Andreas Schwab <schwab@suse.de>
* main.c (long_options): Add entry for "-l". * main.c (long_options): Add entry for "-l".

View file

@ -1415,6 +1415,52 @@ hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
return sp; return sp;
} }
/* Bit in the `ss_flag' member of `struct save_state' that indicates
the state was saved from a system call. From
<machine/save_state.h>. */
#define HPPA_HPUX_SS_INSYSCALL 0x02
static CORE_ADDR
hppa_hpux_read_pc (ptid_t ptid)
{
ULONGEST flags;
/* If we're currently in a system call return the contents of %r31. */
flags = read_register_pid (HPPA_FLAGS_REGNUM, ptid);
if (flags & HPPA_HPUX_SS_INSYSCALL)
return read_register_pid (HPPA_R31_REGNUM, ptid) & ~0x3;
return hppa_read_pc (ptid);
}
static void
hppa_hpux_write_pc (CORE_ADDR pc, ptid_t ptid)
{
ULONGEST flags;
/* If we're currently in a system call also write PC into %r31. */
flags = read_register_pid (HPPA_FLAGS_REGNUM, ptid);
if (flags & HPPA_HPUX_SS_INSYSCALL)
write_register_pid (HPPA_R31_REGNUM, pc | 0x3, ptid);
return hppa_write_pc (pc, ptid);
}
static CORE_ADDR
hppa_hpux_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
ULONGEST flags;
/* If we're currently in a system call return the contents of %r31. */
flags = frame_unwind_register_unsigned (next_frame, HPPA_FLAGS_REGNUM);
if (flags & HPPA_HPUX_SS_INSYSCALL)
return frame_unwind_register_unsigned (next_frame, HPPA_R31_REGNUM) & ~0x3;
return hppa_unwind_pc (gdbarch, next_frame);
}
static void static void
hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty) hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
@ -1442,6 +1488,10 @@ hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code); set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code);
set_gdbarch_call_dummy_location (gdbarch, ON_STACK); set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
set_gdbarch_read_pc (gdbarch, hppa_hpux_read_pc);
set_gdbarch_write_pc (gdbarch, hppa_hpux_write_pc);
set_gdbarch_unwind_pc (gdbarch, hppa_hpux_unwind_pc);
frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer); frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
observer_attach_inferior_created (hppa_hpux_inferior_created); observer_attach_inferior_created (hppa_hpux_inferior_created);

View file

@ -1034,54 +1034,31 @@ hppa64_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
return align_up (addr, 16); return align_up (addr, 16);
} }
CORE_ADDR
/* Get the PC from %r31 if currently in a syscall. Also mask out privilege hppa_read_pc (ptid_t ptid)
bits. */
static CORE_ADDR
hppa_target_read_pc (ptid_t ptid)
{ {
int flags = read_register_pid (HPPA_FLAGS_REGNUM, ptid); ULONGEST ipsw;
ULONGEST ipsw = read_register_pid (HPPA_IPSW_REGNUM, ptid);
CORE_ADDR pc; CORE_ADDR pc;
/* The following test does not belong here. It is OS-specific, and belongs ipsw = read_register_pid (HPPA_IPSW_REGNUM, ptid);
in native code. */ pc = read_register_pid (HPPA_PCOQ_HEAD_REGNUM, ptid);
/* Test SS_INSYSCALL */
if (flags & 2)
return read_register_pid (31, ptid) & ~0x3;
pc = read_register_pid (HPPA_PCOQ_HEAD_REGNUM, ptid) & ~0x3;
/* If the current instruction is nullified, then we are effectively /* If the current instruction is nullified, then we are effectively
still executing the previous instruction. Pretend we are still still executing the previous instruction. Pretend we are still
there. This is needed when single stepping; if the nullified instruction there. This is needed when single stepping; if the nullified
is on a different line, we don't want gdb to think we've stepped onto instruction is on a different line, we don't want GDB to think
that line. */ we've stepped onto that line. */
if (ipsw & 0x00200000) if (ipsw & 0x00200000)
pc -= 4; pc -= 4;
return pc; return pc & ~0x3;
} }
/* Write out the PC. If currently in a syscall, then also write the new void
PC value into %r31. */ hppa_write_pc (CORE_ADDR pc, ptid_t ptid)
static void
hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
{ {
int flags = read_register_pid (HPPA_FLAGS_REGNUM, ptid); write_register_pid (HPPA_PCOQ_HEAD_REGNUM, pc, ptid);
write_register_pid (HPPA_PCOQ_TAIL_REGNUM, pc + 4, ptid);
/* The following test does not belong here. It is OS-specific, and belongs
in native code. */
/* If in a syscall, then set %r31. Also make sure to get the
privilege bits set correctly. */
/* Test SS_INSYSCALL */
if (flags & 2)
write_register_pid (31, v | 0x3, ptid);
write_register_pid (HPPA_PCOQ_HEAD_REGNUM, v, ptid);
write_register_pid (HPPA_PCOQ_TAIL_REGNUM, v + 4, ptid);
} }
/* return the alignment of a type in bytes. Structures have the maximum /* return the alignment of a type in bytes. Structures have the maximum
@ -2194,24 +2171,24 @@ hppa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
frame_pc_unwind (next_frame)); frame_pc_unwind (next_frame));
} }
static CORE_ADDR CORE_ADDR
hppa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) hppa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{ {
ULONGEST ipsw; ULONGEST ipsw;
CORE_ADDR pc; CORE_ADDR pc;
ipsw = frame_unwind_register_signed (next_frame, HPPA_IPSW_REGNUM); ipsw = frame_unwind_register_unsigned (next_frame, HPPA_IPSW_REGNUM);
pc = frame_unwind_register_signed (next_frame, HPPA_PCOQ_HEAD_REGNUM) & ~3; pc = frame_unwind_register_unsigned (next_frame, HPPA_PCOQ_HEAD_REGNUM);
/* If the current instruction is nullified, then we are effectively /* If the current instruction is nullified, then we are effectively
still executing the previous instruction. Pretend we are still still executing the previous instruction. Pretend we are still
there. This is needed when single stepping; if the nullified instruction there. This is needed when single stepping; if the nullified
is on a different line, we don't want gdb to think we've stepped onto instruction is on a different line, we don't want GDB to think
that line. */ we've stepped onto that line. */
if (ipsw & 0x00200000) if (ipsw & 0x00200000)
pc -= 4; pc -= 4;
return pc; return pc & ~0x3;
} }
/* Instead of this nasty cast, add a method pvoid() that prints out a /* Instead of this nasty cast, add a method pvoid() that prints out a
@ -2449,6 +2426,24 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame,
return; return;
} }
/* Make sure the "flags" register is zero in all unwound frames.
The "flags" registers is a HP-UX specific wart, and only the code
in hppa-hpux-tdep.c depends on it. However, it is easier to deal
with it here. This shouldn't affect other systems since those
should provide zero for the "flags" register anyway. */
if (regnum == HPPA_FLAGS_REGNUM)
{
if (valuep)
store_unsigned_integer (valuep, 4, 0);
/* It's a computed value. */
*optimizedp = 0;
*lvalp = not_lval;
*addrp = 0;
*realnump = -1;
return;
}
trad_frame_get_prev_register (next_frame, saved_regs, regnum, trad_frame_get_prev_register (next_frame, saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, valuep); optimizedp, lvalp, addrp, realnump, valuep);
} }
@ -2562,8 +2557,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address); set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address);
set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address); set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address);
set_gdbarch_believe_pcc_promotion (gdbarch, 1); set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_read_pc (gdbarch, hppa_target_read_pc); set_gdbarch_read_pc (gdbarch, hppa_read_pc);
set_gdbarch_write_pc (gdbarch, hppa_target_write_pc); set_gdbarch_write_pc (gdbarch, hppa_write_pc);
/* Helper for function argument information. */ /* Helper for function argument information. */
set_gdbarch_fetch_pointer_argument (gdbarch, hppa_fetch_pointer_argument); set_gdbarch_fetch_pointer_argument (gdbarch, hppa_fetch_pointer_argument);

View file

@ -209,4 +209,9 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame,
enum lval_type *lvalp, CORE_ADDR *addrp, enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *valuep); int *realnump, void *valuep);
extern CORE_ADDR hppa_read_pc (ptid_t ptid);
extern void hppa_write_pc (CORE_ADDR pc, ptid_t ptid);
extern CORE_ADDR hppa_unwind_pc (struct gdbarch *gdbarch,
struct frame_info *next_frame);
#endif /* HPPA_TDEP_H */ #endif /* HPPA_TDEP_H */