]> granicus.if.org Git - strace/commitdiff
powerpc: Use PTRACE_GETREGS to fetch all registers
authorAnton Blanchard <anton@samba.org>
Wed, 26 Jun 2013 13:53:33 +0000 (15:53 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 26 Jun 2013 13:56:53 +0000 (15:56 +0200)
* defs.h: declare ppc_regs and get_regs_error.
* signal.c (sys_sigreturn): Use ppc_regs instead of upeek.
* syscall.c: define ppc_regs.
(printcall): Use ppc_regs instead of upeek.
(get_scno): Replace multiple upeek calls with one PTRACE_GETREGS call.
(get_syscall_result): Likewise.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
defs.h
signal.c
syscall.c

diff --git a/defs.h b/defs.h
index 1f1602a2e69ab0024f3b9d3bd2ffd6c1a681e5d0..76eb3003821a2d8e0baca5bf81614b991228f122 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -375,6 +375,8 @@ extern struct pt_regs sparc_regs;
 extern struct pt_regs arm_regs;
 #elif defined(TILE)
 extern struct pt_regs tile_regs;
+#elif defined(POWERPC)
+extern struct pt_regs ppc_regs;
 #endif
 
 typedef struct sysent {
@@ -591,7 +593,8 @@ extern void call_summary(FILE *);
  || defined(SPARC) || defined(SPARC64) \
  || defined(TILE) \
  || defined(OR1K) \
- || defined(METAG)
+ || defined(METAG) \
+ || defined(POWERPC)
 extern long get_regs_error;
 # define clear_regs()  (get_regs_error = -1)
 extern void get_regs(pid_t pid);
index 55815aa0a691002f646fa1656beeae7bfcf3aee6..3371ee74d82da7b92590f422d69ad34109c19477 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -866,8 +866,9 @@ sys_sigreturn(struct tcb *tcp)
                long esp;
                struct sigcontext_struct sc;
                sigset_t sigm;
-               if (upeek(tcp, sizeof(unsigned long) * PT_R1, &esp) < 0)
-                       return 0;
+
+               esp = ppc_regs.gpr[1];
+
                /* Skip dummy stack frame. */
 #ifdef POWERPC64
                if (current_personality == 0)
index 7efee0e43e132c8827199c03f379ae3f636dfbab..f5263a743b7a42bfdf9c35390483c0b16275e644 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -751,6 +751,7 @@ static struct iovec x86_io = {
 long ia32 = 0; /* not static */
 static long ia64_r8, ia64_r10;
 #elif defined(POWERPC)
+struct pt_regs ppc_regs;
 static long ppc_result;
 #elif defined(M68K)
 static long m68k_d0;
@@ -849,11 +850,7 @@ printcall(struct tcb *tcp)
        }
        tprintf("[%08lx] ", ip);
 #elif defined(POWERPC)
-       long pc;
-       if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
-               PRINTBADPC;
-               return;
-       }
+       long pc = ppc_regs.nip;
 # ifdef POWERPC64
        tprintf("[%016lx] ", pc);
 # else
@@ -1043,6 +1040,8 @@ get_regs(pid_t pid)
        get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &tile_regs);
 # elif defined(SPARC) || defined(SPARC64)
        get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
+# elif defined(POWERPC)
+       get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &ppc_regs);
 
 /* try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS */
 # else
@@ -1195,20 +1194,13 @@ get_scno(struct tcb *tcp)
                }
        }
 #elif defined(POWERPC)
-       if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
-               return -1;
+       scno = ppc_regs.gpr[0];
 # ifdef POWERPC64
-       /* TODO: speed up strace by not doing this at every syscall.
-        * We only need to do it after execve.
-        */
        int currpers;
-       long val;
 
        /* Check for 64/32 bit mode. */
-       if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
-               return -1;
        /* SF is bit 0 of MSR */
-       if (val < 0)
+       if ((ppc_regs.msr >> 63) & 1)
                currpers = 0;
        else
                currpers = 1;
@@ -1805,16 +1797,14 @@ get_syscall_args(struct tcb *tcp)
                                return -1;
        }
 #elif defined(POWERPC)
-# ifndef PT_ORIG_R3
-#  define PT_ORIG_R3 34
-# endif
-       for (i = 0; i < nargs; ++i) {
-               if (upeek(tcp, (i==0) ?
-                       (sizeof(unsigned long) * PT_ORIG_R3) :
-                       ((i+PT_R3) * sizeof(unsigned long)),
-                               &tcp->u_arg[i]) < 0)
-                       return -1;
-       }
+       (void)i;
+       (void)nargs;
+       tcp->u_arg[0] = ppc_regs.orig_gpr3;
+       tcp->u_arg[1] = ppc_regs.gpr[4];
+       tcp->u_arg[2] = ppc_regs.gpr[5];
+       tcp->u_arg[3] = ppc_regs.gpr[6];
+       tcp->u_arg[4] = ppc_regs.gpr[7];
+       tcp->u_arg[5] = ppc_regs.gpr[8];
 #elif defined(SPARC) || defined(SPARC64)
        for (i = 0; i < nargs; ++i)
                tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
@@ -2060,15 +2050,9 @@ get_syscall_result(struct tcb *tcp)
                return -1;
 #elif defined(POWERPC)
 # define SO_MASK 0x10000000
-       {
-               long flags;
-               if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
-                       return -1;
-               if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
-                       return -1;
-               if (flags & SO_MASK)
-                       ppc_result = -ppc_result;
-       }
+       ppc_result = ppc_regs.gpr[3];
+       if (ppc_regs.ccr & SO_MASK)
+               ppc_result = -ppc_result;
 #elif defined(AVR32)
        /* already done by get_regs */
 #elif defined(BFIN)