]> granicus.if.org Git - strace/commitdiff
mips: use PTRACE_GETREGS to fetch all registers
authorDmitry V. Levin <ldv@altlinux.org>
Sun, 15 Feb 2015 03:27:13 +0000 (03:27 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 16 Feb 2015 02:39:13 +0000 (02:39 +0000)
* linux/mips/arch_regs.h (struct mips_regs): New structure.
(mips_REG_*): New macros.
* signal.c (sys_sigreturn) [MIPS]: Use mips_REG_SP.
* syscall.c [MIPS] (struct mips_regs): New variable.
[MIPS] (ARCH_REGS_FOR_GETREGS): New macro.
(mips_a3, mips_r2): Remove.
(print_pc) [MIPS]: Use mips_REG_EPC.
(get_scno) [MIPS]: Use mips_REG_V0 and mips_REG_A3.
(get_syscall_args) [MIPS]: Use mips_REG_A[0-5].
(get_syscall_result) [MIPS]: Remove.
(get_error) [MIPS]: Use mips_REG_A3 and mips_REG_V0.

linux/mips/arch_regs.h
signal.c
syscall.c

index 59039c65e1aa0fb78accd07216f10b3947c45ed1..6372badce6465e8f69a2d91a53446e35f70af0f5 100644 (file)
@@ -1,5 +1,18 @@
+struct mips_regs {
+       uint64_t uregs[38];
+};
+
+extern struct mips_regs mips_regs;
+
 #define REG_V0 2
 #define REG_A0 4
-#define REG_A3 7
-#define REG_SP 29
-#define REG_EPC 64
+
+#define mips_REG_V0 mips_regs.uregs[REG_V0]
+#define mips_REG_A0 mips_regs.uregs[REG_A0 + 0]
+#define mips_REG_A1 mips_regs.uregs[REG_A0 + 1]
+#define mips_REG_A2 mips_regs.uregs[REG_A0 + 2]
+#define mips_REG_A3 mips_regs.uregs[REG_A0 + 3]
+#define mips_REG_A4 mips_regs.uregs[REG_A0 + 4]
+#define mips_REG_A5 mips_regs.uregs[REG_A0 + 5]
+#define mips_REG_SP mips_regs.uregs[29]
+#define mips_REG_EPC mips_regs.uregs[34]
index b1a486a60c49149bcb2d566686a9cf4f8794d95d..d877c0a0d0a2f4185b0bc582c3faabab7a6030b3 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -866,27 +866,17 @@ sys_sigreturn(struct tcb *tcp)
        /* This decodes rt_sigreturn.  The 64-bit ABIs do not have
           sigreturn.  */
        if (entering(tcp)) {
-               long sp;
                struct ucontext uc;
-               if (upeek(tcp->pid, REG_SP, &sp) < 0)
-                       return 0;
                /* There are six words followed by a 128-byte siginfo.  */
-               sp = sp + 6 * 4 + 128;
+               long sp = mips_REG_SP + 6 * 4 + 128;
                if (umove(tcp, sp, &uc) < 0)
                        return 0;
                tprintsigmask_val(") (mask ", uc.uc_sigmask);
        }
-#elif defined(MIPS)
+#elif defined(LINUX_MIPSO32)
        if (entering(tcp)) {
-               long sp;
-               struct pt_regs regs;
                m_siginfo_t si;
-               if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
-                       perror_msg("sigreturn: PTRACE_GETREGS");
-                       return 0;
-               }
-               sp = regs.regs[29];
-               if (umove(tcp, sp, &si) < 0)
+               if (umove(tcp, mips_REG_SP, &si) < 0)
                        return 0;
                tprintsigmask_val(") (mask ", si.si_mask);
        }
index 5e1e021da9c1ef516f59c28bbdd567b42835358e..29aa6d198741d994b3c8c85868f8285bcb4fb885 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -756,12 +756,10 @@ static struct pt_regs avr32_regs;
 #elif defined(SPARC) || defined(SPARC64)
 struct pt_regs sparc_regs; /* not static */
 # define ARCH_REGS_FOR_GETREGS sparc_regs
-#elif defined(LINUX_MIPSN32)
-static long long mips_a3;
-static long long mips_r2;
 #elif defined(MIPS)
-static long mips_a3;
-static long mips_r2;
+struct mips_regs mips_regs; /* not static */
+/* PTRACE_GETREGS on MIPS is available since linux v2.6.15. */
+# define ARCH_REGS_FOR_GETREGS mips_regs
 #elif defined(S390) || defined(S390X)
 static long s390_gpr2;
 #elif defined(HPPA)
@@ -865,13 +863,10 @@ print_pc(struct tcb *tcp)
                return;
        }
        tprintf("[%08lx] ", pc);
-#elif defined(MIPS)
-       long pc;
-       if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
-               tprints("[????????] ");
-               return;
-       }
-       tprintf("[%08lx] ", pc);
+#elif defined LINUX_MIPSN64
+       tprintf("[%016lx] ", mips_REG_EPC);
+#elif defined MIPS
+       tprintf("[%08lx] ", (unsigned long) mips_REG_EPC);
 #elif defined(SH)
        long pc;
        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
@@ -1406,30 +1401,11 @@ get_scno(struct tcb *tcp)
 #elif defined(M68K)
        if (upeek(tcp->pid, 4*PT_ORIG_D0, &scno) < 0)
                return -1;
-#elif defined(LINUX_MIPSN32)
-       unsigned long long regs[38];
-
-       if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
-               return -1;
-       mips_a3 = regs[REG_A3];
-       mips_r2 = regs[REG_V0];
-
-       scno = mips_r2;
-       if (!SCNO_IN_RANGE(scno)) {
-               if (mips_a3 == 0 || mips_a3 == -1) {
-                       if (debug_flag)
-                               fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
-                       return 0;
-               }
-       }
 #elif defined(MIPS)
-       if (upeek(tcp->pid, REG_A3, &mips_a3) < 0)
-               return -1;
-       if (upeek(tcp->pid, REG_V0, &scno) < 0)
-               return -1;
+       scno = mips_REG_V0;
 
        if (!SCNO_IN_RANGE(scno)) {
-               if (mips_a3 == 0 || mips_a3 == -1) {
+               if (mips_REG_A3 == 0 || mips_REG_A3 == -1) {
                        if (debug_flag)
                                fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
                        return 0;
@@ -1858,34 +1834,35 @@ get_syscall_args(struct tcb *tcp)
                        tcp->u_arg[i] &= 0xffffffff;
                }
        }
-#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
-       /* N32 and N64 both use up to six registers.  */
-       unsigned long long regs[38];
-
-       if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 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)
+#elif defined LINUX_MIPSN64
+       (void)i;
+       (void)nargs;
+       tcp->u_arg[0] = mips_REG_A0;
+       tcp->u_arg[1] = mips_REG_A1;
+       tcp->u_arg[2] = mips_REG_A2;
+       tcp->u_arg[3] = mips_REG_A3;
+       tcp->u_arg[4] = mips_REG_A4;
+       tcp->u_arg[5] = mips_REG_A5;
+#elif defined LINUX_MIPSN32
+       (void)i;
+       (void)nargs;
+       tcp->u_arg[0] = tcp->ext_arg[0] = mips_REG_A0;
+       tcp->u_arg[1] = tcp->ext_arg[1] = mips_REG_A1;
+       tcp->u_arg[2] = tcp->ext_arg[2] = mips_REG_A2;
+       tcp->u_arg[3] = tcp->ext_arg[3] = mips_REG_A3;
+       tcp->u_arg[4] = tcp->ext_arg[4] = mips_REG_A4;
+       tcp->u_arg[5] = tcp->ext_arg[5] = mips_REG_A5;
+#elif defined LINUX_MIPSO32
+       (void)i;
+       (void)nargs;
+       tcp->u_arg[0] = mips_REG_A0;
+       tcp->u_arg[1] = mips_REG_A1;
+       tcp->u_arg[2] = mips_REG_A2;
+       tcp->u_arg[3] = mips_REG_A3;
        if (nargs > 4) {
-               long sp;
-
-               if (upeek(tcp->pid, REG_SP, &sp) < 0)
-                       return -1;
-               for (i = 0; i < 4; ++i)
-                       if (upeek(tcp->pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
-                               return -1;
-               umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
+               umoven(tcp, mips_REG_SP + 4 * 4,
+                      (nargs - 4) * sizeof(tcp->u_arg[0]),
                       (char *)(tcp->u_arg + 4));
-       } else {
-               for (i = 0; i < nargs; ++i)
-                       if (upeek(tcp->pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
-                               return -1;
        }
 #elif defined(POWERPC)
        (void)i;
@@ -2168,18 +2145,6 @@ get_syscall_result(struct tcb *tcp)
 #elif defined(M68K)
        if (upeek(tcp->pid, 4*PT_D0, &m68k_d0) < 0)
                return -1;
-#elif defined(LINUX_MIPSN32)
-       unsigned long long regs[38];
-
-       if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
-               return -1;
-       mips_a3 = regs[REG_A3];
-       mips_r2 = regs[REG_V0];
-#elif defined(MIPS)
-       if (upeek(tcp->pid, REG_A3, &mips_a3) < 0)
-               return -1;
-       if (upeek(tcp->pid, REG_V0, &mips_r2) < 0)
-               return -1;
 #elif defined(ALPHA)
        if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
                return -1;
@@ -2302,14 +2267,14 @@ get_error(struct tcb *tcp)
                }
        }
 #elif defined(MIPS)
-       if (check_errno && mips_a3) {
+       if (check_errno && mips_REG_A3) {
                tcp->u_rval = -1;
-               u_error = mips_r2;
+               u_error = mips_REG_V0;
        } else {
-               tcp->u_rval = mips_r2;
-# if defined(LINUX_MIPSN32)
-               tcp->u_lrval = mips_r2;
+# if defined LINUX_MIPSN32
+               tcp->u_lrval = mips_REG_V0;
 # endif
+               tcp->u_rval = mips_REG_V0;
        }
 #elif defined(POWERPC)
        if (check_errno && (ppc_regs.ccr & 0x10000000)) {