diff options
author | Jim Kingdon <jkingdon@engr.sgi.com> | 1993-07-30 20:49:52 +0000 |
---|---|---|
committer | Jim Kingdon <jkingdon@engr.sgi.com> | 1993-07-30 20:49:52 +0000 |
commit | 6cfec92912878589b836fc275d02070f5b8c23d2 (patch) | |
tree | 59baf34968fc5d17229be07612e81f1e3186d873 /gdb/hppa-tdep.c | |
parent | a4fbb03e2da5efd227faaa04a8a9b16a58253870 (diff) | |
download | gdb-6cfec92912878589b836fc275d02070f5b8c23d2.zip gdb-6cfec92912878589b836fc275d02070f5b8c23d2.tar.gz gdb-6cfec92912878589b836fc275d02070f5b8c23d2.tar.bz2 |
From Jeffrey Law:
* tm-hppa.h (TARGET_WRITE_PC): Define.
* hppa-tdep.c (hppa_fix_call_dummy): If in a syscall,
then return the address of the dummy itself rather than
the address of $$dyncall.
(target_write_pc): New function to store a new PC.
Diffstat (limited to 'gdb/hppa-tdep.c')
-rw-r--r-- | gdb/hppa-tdep.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 24701b1..c3842cf 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -817,6 +817,7 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) { CORE_ADDR dyncall_addr, sr4export_addr; struct minimal_symbol *msymbol; + int flags = read_register (FLAGS_REGNUM); msymbol = lookup_minimal_symbol ("$$dyncall", (struct objfile *) NULL); if (msymbol == NULL) @@ -837,7 +838,16 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) write_register (22, pc); - return dyncall_addr; + /* If we are in a syscall, then we should call the stack dummy + directly. $$dyncall is not needed as the kernel sets up the + space id registers properly based on the value in %r31. In + fact calling $$dyncall will not work because the value in %r22 + will be clobbered on the syscall exit path. */ + if (flags & 2) + return pc; + else + return dyncall_addr; + } /* Get the PC from %r31 if currently in a syscall. Also mask out privilege @@ -852,6 +862,23 @@ target_read_pc () return read_register (PC_REGNUM) & ~0x3; } +/* Write out the PC. If currently in a syscall, then also write the new + PC value into %r31. */ +void +target_write_pc (v) + CORE_ADDR v; +{ + int flags = read_register (FLAGS_REGNUM); + + /* If in a syscall, then set %r31. Also make sure to get the + privilege bits set correctly. */ + if (flags & 2) + write_register (31, (long) (v | 0x3)); + + write_register (PC_REGNUM, (long) v); + write_register (NPC_REGNUM, (long) v + 4); +} + /* return the alignment of a type in bytes. Structures have the maximum alignment required by their fields. */ |