diff options
Diffstat (limited to 'tools/testing/selftests/powerpc/ptrace/ptrace.h')
-rw-r--r-- | tools/testing/selftests/powerpc/ptrace/ptrace.h | 79 |
1 files changed, 73 insertions, 6 deletions
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h index 5181ad9b4b6c..4e0233c0f2b3 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace.h +++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h @@ -4,6 +4,9 @@ * * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. */ + +#define __SANE_USERSPACE_TYPES__ + #include <inttypes.h> #include <unistd.h> #include <stdlib.h> @@ -20,6 +23,7 @@ #include <sys/ipc.h> #include <sys/shm.h> #include <sys/user.h> +#include <sys/syscall.h> #include <linux/elf.h> #include <linux/types.h> #include <linux/auxvec.h> @@ -30,8 +34,8 @@ #define TEST_FAIL 1 struct fpr_regs { - unsigned long fpr[32]; - unsigned long fpscr; + __u64 fpr[32]; + __u64 fpscr; }; struct tm_spr_regs { @@ -318,7 +322,7 @@ fail: } /* FPR */ -int show_fpr(pid_t child, unsigned long *fpr) +int show_fpr(pid_t child, __u64 *fpr) { struct fpr_regs *regs; int ret, i; @@ -337,7 +341,7 @@ int show_fpr(pid_t child, unsigned long *fpr) return TEST_PASS; } -int write_fpr(pid_t child, unsigned long val) +int write_fpr(pid_t child, __u64 val) { struct fpr_regs *regs; int ret, i; @@ -360,7 +364,7 @@ int write_fpr(pid_t child, unsigned long val) return TEST_PASS; } -int show_ckpt_fpr(pid_t child, unsigned long *fpr) +int show_ckpt_fpr(pid_t child, __u64 *fpr) { struct fpr_regs *regs; struct iovec iov; @@ -437,6 +441,70 @@ int show_gpr(pid_t child, unsigned long *gpr) return TEST_PASS; } +long sys_ptrace(enum __ptrace_request request, pid_t pid, unsigned long addr, unsigned long data) +{ + return syscall(__NR_ptrace, request, pid, (void *)addr, data); +} + +// 33 because of FPSCR +#define PT_NUM_FPRS (33 * (sizeof(__u64) / sizeof(unsigned long))) + +__u64 *peek_fprs(pid_t child) +{ + unsigned long *fprs, *p, addr; + long ret; + int i; + + fprs = malloc(sizeof(unsigned long) * PT_NUM_FPRS); + if (!fprs) { + perror("malloc() failed"); + return NULL; + } + + for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) { + addr = sizeof(unsigned long) * (PT_FPR0 + i); + ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)p); + if (ret) { + perror("ptrace(PTRACE_PEEKUSR) failed"); + return NULL; + } + } + + addr = sizeof(unsigned long) * (PT_FPR0 + i); + ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)&addr); + if (!ret) { + printf("ptrace(PTRACE_PEEKUSR) succeeded unexpectedly!\n"); + return NULL; + } + + return (__u64 *)fprs; +} + +int poke_fprs(pid_t child, unsigned long *fprs) +{ + unsigned long *p, addr; + long ret; + int i; + + for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) { + addr = sizeof(unsigned long) * (PT_FPR0 + i); + ret = sys_ptrace(PTRACE_POKEUSER, child, addr, *p); + if (ret) { + perror("ptrace(PTRACE_POKEUSR) failed"); + return -1; + } + } + + addr = sizeof(unsigned long) * (PT_FPR0 + i); + ret = sys_ptrace(PTRACE_POKEUSER, child, addr, addr); + if (!ret) { + printf("ptrace(PTRACE_POKEUSR) succeeded unexpectedly!\n"); + return -1; + } + + return 0; +} + int write_gpr(pid_t child, unsigned long val) { struct pt_regs *regs; @@ -742,4 +810,3 @@ void analyse_texasr(unsigned long texasr) } void store_gpr(unsigned long *addr); -void store_fpr(float *addr); |