diff options
author | Anton Blanchard <anton@samba.org> | 2013-06-26 14:42:37 +1000 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2013-06-26 15:57:29 +0200 |
commit | 14d51a6423aa47378518a71e8345a3d1944d97e7 (patch) | |
tree | 10013bf9e4ecdf4be63327de7b00ecdc657400e3 /syscall.c | |
parent | ce6e33be1dbfc16620ea7991a414e879ef84fe22 (diff) | |
download | strace-14d51a6423aa47378518a71e8345a3d1944d97e7.tar.gz strace-14d51a6423aa47378518a71e8345a3d1944d97e7.tar.bz2 strace-14d51a6423aa47378518a71e8345a3d1944d97e7.tar.xz |
powerpc: Provide a fallback for old kernels without PTRACE_GETREGS
PTRACE_GETREGS was added to the ppc kernel in 2.6.23. In order to
provide backward compatibility for very old kernels, add a manual
fallback.
* syscall.c (powerpc_getreg, powerpc_getregs_old): New functions.
(get_regs): Call powerpc_getregs_old if PTRACE_GETREGS is not supported.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'syscall.c')
-rw-r--r-- | syscall.c | 51 |
1 files changed, 51 insertions, 0 deletions
@@ -994,6 +994,55 @@ undefined_scno_name(struct tcb *tcp) return buf; } +#ifdef POWERPC +/* + * PTRACE_GETREGS was added to the PowerPC kernel in v2.6.23, so we + * provide a slow fallback for very old kernels. + */ + +static long powerpc_getreg(pid_t pid, unsigned long offset, unsigned long *p) +{ + long val; + + errno = 0; + val = ptrace(PTRACE_PEEKUSER, pid, (char *)offset, 0); + if (val == -1 && errno) + return -1; + + *p = val; + return 0; +} + +static long powerpc_getregs_old(pid_t pid) +{ + int i; + long r; + + r = powerpc_getreg(pid, sizeof(unsigned long) * PT_MSR, &ppc_regs.msr); + if (r) + goto out; + + r = powerpc_getreg(pid, sizeof(unsigned long) * PT_CCR, &ppc_regs.ccr); + if (r) + goto out; + + r = powerpc_getreg(pid, sizeof(unsigned long) * PT_ORIG_R3, + &ppc_regs.orig_gpr3); + if (r) + goto out; + + for (i = 0; i <= 8; i++) { + r = powerpc_getreg(pid, sizeof(unsigned long) * (PT_R0 + i), + &ppc_regs.gpr[i]); + if (r) + goto out; + } + +out: + return r; +} +#endif + #ifndef get_regs long get_regs_error; @@ -1042,6 +1091,8 @@ get_regs(pid_t pid) 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); + if (get_regs_error && errno == EIO) + get_regs_error = powerpc_getregs_old(pid); /* try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS */ # else |