2007-08-26 Daniel Jacobowitz <dan@codesourcery.com>
* defs.h [MIPS]: Include <sgidefs.h>.
(MAX_QUALS): Update for MIPS.
(LINUX_MIPSO32, LINUX_MIPSN32, LINUX_MIPSN64, LINUX_MIPS64): Define.
(struct tcb): Add ext_arg for MIPS N32.
(TCB_WAITEXECVE): Define for MIPS.
(ALIGN64): Use LINUX_MIPSO32.
* file.c (sys_lseek): Use ext_arg for MIPS N32.
(sys_readahead, sys_fadvise64_64): Likewise.
* io.c (sys_pread64, sys_pwrite64): Likewise.
* mem.c (print_mmap): Take OFFSET argument.
(sys_old_mmap): Update call to print_mmap.
(sys_mmap): Use ext_arg for MIPS N32.
* process.c (struct_user_offsets): Add MIPS registers.
* signal.c (sys_sigreturn): Handle MIPS N32 and MIPS N64. Correct
MIPS O32 call to sprintsigmask.
* syscall.c (internal_syscall): Handle MIPS N32. Check for
TCB_WAITEXECVE on MIPS.
(force_result): Add a comment about MIPS N32.
(syscall_enter): Handle MIPS N32 and MIPS N64.
* linux/syscall.h (sys_pread64, sys_pwrite64): Declare.
* linux/mips/syscallent.h: Include "dummy.h". Handle alternate
MIPS ABIs.
diff --git a/syscall.c b/syscall.c
index f42b121..e699c61 100644
--- a/syscall.c
+++ b/syscall.c
@@ -754,6 +754,9 @@
#elif defined (SPARC) || defined (SPARC64)
static struct regs regs;
static unsigned long trap;
+#elif defined(LINUX_MIPSN32)
+ static long long a3;
+ static long long r2;
#elif defined(MIPS)
static long a3;
static long r2;
@@ -1066,14 +1069,44 @@
#elif defined (M68K)
if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
return -1;
+#elif defined (LINUX_MIPSN32)
+ unsigned long long regs[38];
+
+ if (ptrace (PTRACE_GETREGS, pid, NULL, (long) ®s) < 0)
+ return -1;
+ a3 = regs[REG_A3];
+ r2 = regs[REG_V0];
+
+ if(!(tcp->flags & TCB_INSYSCALL)) {
+ scno = r2;
+
+ /* Check if we return from execve. */
+ if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
+ tcp->flags &= ~TCB_WAITEXECVE;
+ return 0;
+ }
+
+ if (scno < 0 || scno > nsyscalls) {
+ if(a3 == 0 || a3 == -1) {
+ if(debug)
+ fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
+ return 0;
+ }
+ }
+ }
#elif defined (MIPS)
if (upeek(pid, REG_A3, &a3) < 0)
return -1;
-
if(!(tcp->flags & TCB_INSYSCALL)) {
if (upeek(pid, REG_V0, &scno) < 0)
return -1;
+ /* Check if we return from execve. */
+ if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
+ tcp->flags &= ~TCB_WAITEXECVE;
+ return 0;
+ }
+
if (scno < 0 || scno > nsyscalls) {
if(a3 == 0 || a3 == -1) {
if(debug)
@@ -1732,6 +1765,7 @@
r2 = rval;
a3 = 0;
}
+ /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
return -1;
@@ -1957,6 +1991,27 @@
tcp->u_nargs = 5;
}
}
+#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
+ /* N32 and N64 both use up to six registers. */
+ {
+ unsigned long long regs[38];
+ int i, nargs;
+
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ nargs = tcp->u_nargs = MAX_ARGS;
+
+ if (ptrace (PTRACE_GETREGS, pid, NULL, (long) ®s) < 0)
+ return -1;
+
+ for(i = 0; i < nargs; i++) {
+ tcp->u_arg[i] = regs[REG_A0 + i];
+# if defined (LINUX_MIPSN32)
+ tcp->ext_arg[i] = regs[REG_A0 + i];
+# endif
+ }
+ }
#elif defined (MIPS)
{
long sp;