]> granicus.if.org Git - strace/commitdiff
2003-06-03 Roland McGrath <roland@redhat.com>
authorRoland McGrath <roland@redhat.com>
Tue, 3 Jun 2003 23:29:04 +0000 (23:29 +0000)
committerRoland McGrath <roland@redhat.com>
Tue, 3 Jun 2003 23:29:04 +0000 (23:29 +0000)
Linux/ARM improvements from Russell King <rmk@arm.linux.org.uk>:
* defs.h [LINUX] (TCB_WAITEXECVE): Define for [ARM] too.
* process.c (struct_user_offsets) [LINUX] [ARM]: Add ARM registers.
* signal.c [LINUX] (sys_sigreturn) [ARM]: New case.
* syscall.c (get_scno, syscall_fixup) [LINUX] [ARM]: Case rewritten.
(get_error) [LINUX] [ARM]: Update.
(syscall_enter) [LINUX] [ARM]: New case.
* util.c (printcall) [LINUX] [ARM]: New case.

defs.h
process.c
signal.c
syscall.c

diff --git a/defs.h b/defs.h
index b42d114c1d2bd6e359d27aaf4acf049be389d9a7..98c75b971b6433c52e04ecc48240b96bf816d102 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -318,7 +318,7 @@ struct tcb {
 #define TCB_FOLLOWFORK 00400   /* Process should have forks followed */
 #define TCB_REPRINT    01000   /* We should reprint this syscall on exit */
 #ifdef LINUX
-# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SHMEDIA) || defined(S390) || defined(S390X)
+# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SHMEDIA) || defined(S390) || defined(S390X) || defined(ARM)
 #  define TCB_WAITEXECVE 02000 /* ignore SIGTRAP after exceve */
 # endif
 # define TCB_CLONE_DETACHED 04000 /* CLONE_DETACHED set in creating syscall */
index bb33a2027cb4678ddfe175d48e59406bd3b6889f..9f117e4e03924db87614e838bf43c9bf655d4274 100644 (file)
--- a/process.c
+++ b/process.c
@@ -2626,6 +2626,25 @@ struct xlat struct_user_offsets[] = {
        { uoff(regs),           "offsetof(struct user, regs)"           },
        { uoff(fpu),            "offsetof(struct user, fpu)"            },
 #endif
+#ifdef ARM
+       { uoff(regs.ARM_r0),    "r0"                                    },
+       { uoff(regs.ARM_r1),    "r1"                                    },
+       { uoff(regs.ARM_r2),    "r2"                                    },
+       { uoff(regs.ARM_r3),    "r3"                                    },
+       { uoff(regs.ARM_r4),    "r4"                                    },
+       { uoff(regs.ARM_r5),    "r5"                                    },
+       { uoff(regs.ARM_r6),    "r6"                                    },
+       { uoff(regs.ARM_r7),    "r7"                                    },
+       { uoff(regs.ARM_r8),    "r8"                                    },
+       { uoff(regs.ARM_r9),    "r9"                                    },
+       { uoff(regs.ARM_r10),   "r10"                                   },
+       { uoff(regs.ARM_fp),    "fp"                                    },
+       { uoff(regs.ARM_ip),    "ip"                                    },
+       { uoff(regs.ARM_sp),    "sp"                                    },
+       { uoff(regs.ARM_lr),    "lr"                                    },
+       { uoff(regs.ARM_pc),    "pc"                                    },
+       { uoff(regs.ARM_cpsr),  "cpsr"                                  },
+#endif
 
 #if !defined(S390) && !defined(S390X) && !defined(MIPS)
        { uoff(u_fpvalid),      "offsetof(struct user, u_fpvalid)"      },
index 43982942a0667e4d74ed440194568c5ddf516cf4..e393b0fd9d6444c94ad5c5f441e2322cc7107087 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -1183,26 +1183,51 @@ int
 sys_sigreturn(tcp)
 struct tcb *tcp;
 {
-#if defined(S390) || defined(S390X)
-    long usp;
-    struct sigcontext_struct sc;
-
-    if (entering(tcp)) {
-           tcp->u_arg[0] = 0;
-           if (upeek(tcp->pid,PT_GPR15,&usp)<0)
-                   return 0;
-           if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0)
-                   return 0;
-           tcp->u_arg[0] = 1;
-           memcpy(&tcp->u_arg[1],&sc.oldmask[0],sizeof(sigset_t));
-    } else {
-           tcp->u_rval = tcp->u_error = 0;
-           if (tcp->u_arg[0] == 0)
-                   return 0;
-           tcp->auxstr = sprintsigmask("mask now ",(sigset_t *)&tcp->u_arg[1],0);
-           return RVAL_NONE | RVAL_STR;
-    }
-    return 0;
+#ifdef ARM
+       struct pt_regs regs;
+       struct sigcontext_struct sc;
+
+       if (entering(tcp)) {
+               tcp->u_arg[0] = 0;
+
+               if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
+                       return 0;
+
+               if (umove(tcp, regs.ARM_sp, &sc) < 0)
+                       return 0;
+
+               tcp->u_arg[0] = 1;
+               tcp->u_arg[1] = sc.oldmask;
+       } else {
+               sigset_t sigm;
+               long_to_sigset(tcp->u_arg[1], &sigm);
+               tcp->u_rval = tcp->u_error = 0;
+               if (tcp->u_arg[0] == 0)
+                       return 0;
+               tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
+               return RVAL_NONE | RVAL_STR;
+       }
+       return 0;
+#elif defined(S390) || defined(S390X)
+       long usp;
+       struct sigcontext_struct sc;
+
+       if (entering(tcp)) {
+               tcp->u_arg[0] = 0;
+               if (upeek(tcp->pid,PT_GPR15,&usp)<0)
+                       return 0;
+               if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0)
+                       return 0;
+               tcp->u_arg[0] = 1;
+               memcpy(&tcp->u_arg[1],&sc.oldmask[0],sizeof(sigset_t));
+       } else {
+               tcp->u_rval = tcp->u_error = 0;
+               if (tcp->u_arg[0] == 0)
+                       return 0;
+               tcp->auxstr = sprintsigmask("mask now ",(sigset_t *)&tcp->u_arg[1],0);
+               return RVAL_NONE | RVAL_STR;
+       }
+       return 0;
 #else
 #ifdef I386
        long esp;
@@ -1256,50 +1281,50 @@ struct tcb *tcp;
        return 0;
 #else /* !IA64 */
 #ifdef POWERPC
-       long esp;
-       struct sigcontext_struct sc;
-
-       if (entering(tcp)) {
-                  tcp->u_arg[0] = 0;
-                  if (upeek(tcp->pid, sizeof(unsigned long)*PT_R1, &esp) < 0)
-                          return 0;
-                  if (umove(tcp, esp, &sc) < 0)
-                          return 0;
-                  tcp->u_arg[0] = 1;
-                  tcp->u_arg[1] = sc.oldmask;
-       }
-       else {
-                  sigset_t sigm;
-                  long_to_sigset(tcp->u_arg[1], &sigm);
-                  tcp->u_rval = tcp->u_error = 0;
-                  if (tcp->u_arg[0] == 0)
-                          return 0;
-                  tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-                  return RVAL_NONE | RVAL_STR;
-       }
-       return 0;
+       long esp;
+       struct sigcontext_struct sc;
+
+       if (entering(tcp)) {
+               tcp->u_arg[0] = 0;
+               if (upeek(tcp->pid, sizeof(unsigned long)*PT_R1, &esp) < 0)
+                       return 0;
+               if (umove(tcp, esp, &sc) < 0)
+                       return 0;
+               tcp->u_arg[0] = 1;
+               tcp->u_arg[1] = sc.oldmask;
+       }
+       else {
+               sigset_t sigm;
+               long_to_sigset(tcp->u_arg[1], &sigm);
+               tcp->u_rval = tcp->u_error = 0;
+               if (tcp->u_arg[0] == 0)
+                       return 0;
+               tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
+               return RVAL_NONE | RVAL_STR;
+       }
+       return 0;
 #else /* !POWERPC */
 #ifdef M68K
        long usp;
        struct sigcontext sc;
 
        if (entering(tcp)) {
-           tcp->u_arg[0] = 0;
-           if (upeek(tcp->pid, 4*PT_USP, &usp) < 0)
+               tcp->u_arg[0] = 0;
+               if (upeek(tcp->pid, 4*PT_USP, &usp) < 0)
                        return 0;
-           if (umove(tcp, usp, &sc) < 0)
+               if (umove(tcp, usp, &sc) < 0)
                        return 0;
-           tcp->u_arg[0] = 1;
-           tcp->u_arg[1] = sc.sc_mask;
+               tcp->u_arg[0] = 1;
+               tcp->u_arg[1] = sc.sc_mask;
        }
        else {
-           sigset_t sigm;
-           long_to_sigset(tcp->u_arg[1], &sigm);
-           tcp->u_rval = tcp->u_error = 0;
-           if (tcp->u_arg[0] == 0)
+               sigset_t sigm;
+               long_to_sigset(tcp->u_arg[1], &sigm);
+               tcp->u_rval = tcp->u_error = 0;
+               if (tcp->u_arg[0] == 0)
                        return 0;
-           tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-           return RVAL_NONE | RVAL_STR;
+               tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
+               return RVAL_NONE | RVAL_STR;
        }
        return 0;
 #else /* !M68K */
@@ -1308,22 +1333,22 @@ struct tcb *tcp;
        struct sigcontext_struct sc;
 
        if (entering(tcp)) {
-           tcp->u_arg[0] = 0;
-           if (upeek(tcp->pid, REG_FP, &fp) < 0)
+               tcp->u_arg[0] = 0;
+               if (upeek(tcp->pid, REG_FP, &fp) < 0)
                        return 0;
-           if (umove(tcp, fp, &sc) < 0)
+               if (umove(tcp, fp, &sc) < 0)
                        return 0;
-           tcp->u_arg[0] = 1;
-           tcp->u_arg[1] = sc.sc_mask;
+               tcp->u_arg[0] = 1;
+               tcp->u_arg[1] = sc.sc_mask;
        }
        else {
-           sigset_t sigm;
-           long_to_sigset(tcp->u_arg[1], &sigm);
-           tcp->u_rval = tcp->u_error = 0;
-           if (tcp->u_arg[0] == 0)
+               sigset_t sigm;
+               long_to_sigset(tcp->u_arg[1], &sigm);
+               tcp->u_rval = tcp->u_error = 0;
+               if (tcp->u_arg[0] == 0)
                        return 0;
-           tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
-           return RVAL_NONE | RVAL_STR;
+               tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
+               return RVAL_NONE | RVAL_STR;
        }
        return 0;
 #else
@@ -1333,8 +1358,8 @@ struct tcb *tcp;
        m_siginfo_t si;
 
        if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
-           perror("sigreturn: PTRACE_GETREGS ");
-           return 0;
+               perror("sigreturn: PTRACE_GETREGS ");
+               return 0;
        }
        if(entering(tcp)) {
                tcp->u_arg[0] = 0;
index f06e172cbd1dca0294d323863baeb94714e4c2bc..39ee93c32b6c7fe45710b0f828e0cdbfc299bc32 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -695,7 +695,7 @@ struct tcb *tcp;
 #elif defined (M68K)
        static int d0;
 #elif defined (ARM)
-       static int r0;
+       static struct pt_regs regs;
 #elif defined (ALPHA)
        static long r0;
        static long a3;
@@ -714,7 +714,7 @@ struct tcb *tcp;
 #elif defined(SH)
        static long r0;
 #elif defined(SHMEDIA)
-       static long r9; 
+       static long r9;
 #elif defined(X86_64)
        static long rax;
 #endif
@@ -939,11 +939,59 @@ struct tcb *tcp;
                        return -1;
        }
 #elif defined (ARM)
-       {
-           long pc;
-           upeek(pid, 4*15, &pc);
-           umoven(tcp, pc-4, 4, (char *)&scno);
-           scno &= 0x000fffff;
+       /*
+        * Read complete register set in one go.
+        */
+       if (ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs) == -1)
+               return -1;
+
+       /*
+        * We only need to grab the syscall number on syscall entry.
+        */
+       if (regs.ARM_ip == 0) {
+               /*
+                * Note: we only deal with only 32-bit CPUs here.
+                */
+               if (regs.ARM_cpsr & 0x20) {
+                       /*
+                        * Get the Thumb-mode system call number
+                        */
+                       scno = regs.ARM_r7;
+               } else {
+                       /*
+                        * Get the ARM-mode system call number
+                        */
+                       errno = 0;
+                       scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
+                       if (errno)
+                               return -1;
+
+                       if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
+                               tcp->flags &= ~TCB_WAITEXECVE;
+                               return 0;
+                       }
+
+                       if ((scno & 0x0ff00000) != 0x0f900000) {
+                               fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
+                                       scno);
+                               return -1;
+                       }
+
+                       /*
+                        * Fixup the syscall number
+                        */
+                       scno &= 0x000fffff;
+               }
+
+               if (tcp->flags & TCB_INSYSCALL) {
+                       fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
+                       tcp->flags &= ~TCB_INSYSCALL;
+               }
+       } else {
+               if (!(tcp->flags & TCB_INSYSCALL)) {
+                       fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
+                       tcp->flags |= TCB_INSYSCALL;
+               }
        }
 #elif defined (M68K)
        if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
@@ -1272,13 +1320,9 @@ struct tcb *tcp;
                return 0;
        }
 #elif defined (ARM)
-       if (upeek(pid, 4*0, (long *)&r0) < 0)
-               return -1;
-       if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
-               if (debug)
-                       fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0);
-               return 0;
-       }
+       /*
+        * Nothing required
+        */
 #elif defined (HPPA)
        if (upeek(pid, PT_GR28, &r28) < 0)
                return -1;
@@ -1386,12 +1430,12 @@ struct tcb *tcp;
                }
 #else /* !M68K */
 #ifdef ARM
-               if (r0 && (unsigned) -r0 < nerrnos) {
+               if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
                        tcp->u_rval = -1;
-                       u_error = -r0;
+                       u_error = -regs.ARM_r0;
                }
                else {
-                       tcp->u_rval = r0;
+                       tcp->u_rval = regs.ARM_r0;
                        u_error = 0;
                }
 #else /* !ARM */
@@ -1864,6 +1908,17 @@ struct tcb *tcp;
                                return -1;
                }
        }
+#elif defined(ARM)
+       {
+               int i;
+
+               if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+                       tcp->u_nargs = sysent[tcp->scno].nargs;
+               else
+                       tcp->u_nargs = MAX_ARGS;
+               for (i = 0; i < tcp->u_nargs; i++)
+                       tcp->u_arg[i] = regs.uregs[i];
+       }
 #elif defined(SH)
        {
                int i;