MIPS: ptrace: Fix user pt_regs definition, use in ptrace_{get, set}regs()
In uapi/asm/ptrace.h, a user version of pt_regs is defined wrapped in ifndef __KERNEL__. This structure definition does not match anything used by any kernel API, in particular it does not match the format used by PTRACE_{GET,SET}REGS. Therefore, replace the structure definition with one matching what is used by PTRACE_{GET,SET}REGS. The format used by these is the same for both 32-bit and 64-bit. Also, change the implementation of PTRACE_{GET,SET}REGS to use this new structure definition. The structure is renamed to user_pt_regs when __KERNEL__ is defined to avoid conflicts with the kernel's own pt_regs. Signed-off-by: Alex Smith <alex@alex-smith.me.uk> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/7457/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Родитель
457ed7702d
Коммит
a79ebea620
|
@ -47,8 +47,10 @@ struct pt_regs {
|
||||||
|
|
||||||
struct task_struct;
|
struct task_struct;
|
||||||
|
|
||||||
extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
|
extern int ptrace_getregs(struct task_struct *child,
|
||||||
extern int ptrace_setregs(struct task_struct *child, __s64 __user *data);
|
struct user_pt_regs __user *data);
|
||||||
|
extern int ptrace_setregs(struct task_struct *child,
|
||||||
|
struct user_pt_regs __user *data);
|
||||||
|
|
||||||
extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
|
extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
|
||||||
extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
|
extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
|
||||||
|
|
|
@ -22,24 +22,27 @@
|
||||||
#define DSP_CONTROL 77
|
#define DSP_CONTROL 77
|
||||||
#define ACX 78
|
#define ACX 78
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
|
||||||
/*
|
/*
|
||||||
* This struct defines the way the registers are stored on the stack during a
|
* This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
|
||||||
* system call/exception. As usual the registers k0/k1 aren't being saved.
|
* format is the same for both 32- and 64-bit processes. Registers for 32-bit
|
||||||
|
* processes are sign extended.
|
||||||
*/
|
*/
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
struct user_pt_regs {
|
||||||
|
#else
|
||||||
struct pt_regs {
|
struct pt_regs {
|
||||||
|
#endif
|
||||||
/* Saved main processor registers. */
|
/* Saved main processor registers. */
|
||||||
unsigned long regs[32];
|
__u64 regs[32];
|
||||||
|
|
||||||
/* Saved special registers. */
|
/* Saved special registers. */
|
||||||
unsigned long cp0_status;
|
__u64 lo;
|
||||||
unsigned long hi;
|
__u64 hi;
|
||||||
unsigned long lo;
|
__u64 cp0_epc;
|
||||||
unsigned long cp0_badvaddr;
|
__u64 cp0_badvaddr;
|
||||||
unsigned long cp0_cause;
|
__u64 cp0_status;
|
||||||
unsigned long cp0_epc;
|
__u64 cp0_cause;
|
||||||
} __attribute__ ((aligned (8)));
|
} __attribute__ ((aligned (8)));
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
|
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
|
||||||
#define PTRACE_GETREGS 12
|
#define PTRACE_GETREGS 12
|
||||||
|
|
|
@ -63,7 +63,7 @@ void ptrace_disable(struct task_struct *child)
|
||||||
* for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
|
* for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
|
||||||
* Registers are sign extended to fill the available space.
|
* Registers are sign extended to fill the available space.
|
||||||
*/
|
*/
|
||||||
int ptrace_getregs(struct task_struct *child, __s64 __user *data)
|
int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
|
||||||
{
|
{
|
||||||
struct pt_regs *regs;
|
struct pt_regs *regs;
|
||||||
int i;
|
int i;
|
||||||
|
@ -74,13 +74,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
|
||||||
regs = task_pt_regs(child);
|
regs = task_pt_regs(child);
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
__put_user((long)regs->regs[i], data + i);
|
__put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
|
||||||
__put_user((long)regs->lo, data + EF_LO - EF_R0);
|
__put_user((long)regs->lo, (__s64 __user *)&data->lo);
|
||||||
__put_user((long)regs->hi, data + EF_HI - EF_R0);
|
__put_user((long)regs->hi, (__s64 __user *)&data->hi);
|
||||||
__put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
|
__put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
|
||||||
__put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
|
__put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
|
||||||
__put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
|
__put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
|
||||||
__put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
|
__put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
|
||||||
* the 64-bit format. On a 32-bit kernel only the lower order half
|
* the 64-bit format. On a 32-bit kernel only the lower order half
|
||||||
* (according to endianness) will be used.
|
* (according to endianness) will be used.
|
||||||
*/
|
*/
|
||||||
int ptrace_setregs(struct task_struct *child, __s64 __user *data)
|
int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
|
||||||
{
|
{
|
||||||
struct pt_regs *regs;
|
struct pt_regs *regs;
|
||||||
int i;
|
int i;
|
||||||
|
@ -101,10 +101,10 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
|
||||||
regs = task_pt_regs(child);
|
regs = task_pt_regs(child);
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
__get_user(regs->regs[i], data + i);
|
__get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
|
||||||
__get_user(regs->lo, data + EF_LO - EF_R0);
|
__get_user(regs->lo, (__s64 __user *)&data->lo);
|
||||||
__get_user(regs->hi, data + EF_HI - EF_R0);
|
__get_user(regs->hi, (__s64 __user *)&data->hi);
|
||||||
__get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
|
__get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
|
||||||
|
|
||||||
/* badvaddr, status, and cause may not be written. */
|
/* badvaddr, status, and cause may not be written. */
|
||||||
|
|
||||||
|
|
|
@ -256,11 +256,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||||
}
|
}
|
||||||
|
|
||||||
case PTRACE_GETREGS:
|
case PTRACE_GETREGS:
|
||||||
ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
|
ret = ptrace_getregs(child,
|
||||||
|
(struct user_pt_regs __user *) (__u64) data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_SETREGS:
|
case PTRACE_SETREGS:
|
||||||
ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
|
ret = ptrace_setregs(child,
|
||||||
|
(struct user_pt_regs __user *) (__u64) data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTRACE_GETFPREGS:
|
case PTRACE_GETFPREGS:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче