2005-04-17 02:20:36 +04:00
/*
* Copyright 2003 PathScale , Inc .
2007-10-16 12:27:18 +04:00
* Copyright ( C ) 2003 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-17 02:20:36 +04:00
*
* Licensed under the GPL
*/
2008-02-05 09:31:20 +03:00
# include <linux/mm.h>
2005-05-21 00:59:07 +04:00
# include <linux/sched.h>
# include <linux/errno.h>
2008-02-05 09:31:20 +03:00
# define __FRAME_OFFSETS
# include <asm/ptrace.h>
2005-05-21 00:59:07 +04:00
# include <asm/uaccess.h>
2005-04-17 02:20:36 +04:00
2007-10-16 12:27:18 +04:00
/*
* determines which flags the user has access to .
* 1 = access 0 = no access
*/
2005-04-17 02:20:36 +04:00
# define FLAG_MASK 0x44dd5UL
int putreg ( struct task_struct * child , int regno , unsigned long value )
{
unsigned long tmp ;
# ifdef TIF_IA32
2008-02-05 09:31:20 +03:00
/*
* Some code in the 64 bit emulation may not be 64 bit clean .
* Don ' t take any chances .
*/
2005-04-17 02:20:36 +04:00
if ( test_tsk_thread_flag ( child , TIF_IA32 ) )
value & = 0xffffffff ;
# endif
2008-02-05 09:31:20 +03:00
switch ( regno ) {
2005-04-17 02:20:36 +04:00
case FS :
case GS :
case DS :
case ES :
case SS :
case CS :
if ( value & & ( value & 3 ) ! = 3 )
return - EIO ;
value & = 0xffff ;
break ;
case FS_BASE :
case GS_BASE :
if ( ! ( ( value > > 48 ) = = 0 | | ( value > > 48 ) = = 0xffff ) )
return - EIO ;
break ;
case EFLAGS :
value & = FLAG_MASK ;
tmp = PT_REGS_EFLAGS ( & child - > thread . regs ) & ~ FLAG_MASK ;
value | = tmp ;
break ;
}
PT_REGS_SET ( & child - > thread . regs , regno , value ) ;
return 0 ;
}
[PATCH] uml: S390 preparation, peekusr/pokeusr defined by subarch
s390 needs to change some parts of arch/um/kernel/ptrace.c. Thus, the code
regarding PEEKUSER and POKEUSER are shifted to arch/um/sys-<subarch>/ptrace.c.
Also s390 debug registers need to be updated, when singlestepping is switched
on / off. Thus, setting/resetting of singlestepping is centralized in the new
function set_singlestep(), which also inserts the macro
SUBARCH_SET_SINGLESTEP(mode), if defined.
Finally, s390 has the "ieee_instruction_pointer" in its
registers, which also is allowed to be read via
ptrace( PTRACE_PEEKUSER, getpid(), PT_IEEE_IP, 0);
To implement this feature, sys_ptrace inserts the macro
SUBARCH_PTRACE_SPECIAL, if defined.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-07 08:30:46 +04:00
int poke_user ( struct task_struct * child , long addr , long data )
{
2007-10-16 12:27:18 +04:00
if ( ( addr & 3 ) | | addr < 0 )
return - EIO ;
if ( addr < MAX_REG_OFFSET )
return putreg ( child , addr , data ) ;
else if ( ( addr > = offsetof ( struct user , u_debugreg [ 0 ] ) ) & &
2008-02-05 09:31:20 +03:00
( addr < = offsetof ( struct user , u_debugreg [ 7 ] ) ) ) {
2007-10-16 12:27:18 +04:00
addr - = offsetof ( struct user , u_debugreg [ 0 ] ) ;
addr = addr > > 2 ;
if ( ( addr = = 4 ) | | ( addr = = 5 ) )
return - EIO ;
child - > thread . arch . debugregs [ addr ] = data ;
return 0 ;
}
return - EIO ;
[PATCH] uml: S390 preparation, peekusr/pokeusr defined by subarch
s390 needs to change some parts of arch/um/kernel/ptrace.c. Thus, the code
regarding PEEKUSER and POKEUSER are shifted to arch/um/sys-<subarch>/ptrace.c.
Also s390 debug registers need to be updated, when singlestepping is switched
on / off. Thus, setting/resetting of singlestepping is centralized in the new
function set_singlestep(), which also inserts the macro
SUBARCH_SET_SINGLESTEP(mode), if defined.
Finally, s390 has the "ieee_instruction_pointer" in its
registers, which also is allowed to be read via
ptrace( PTRACE_PEEKUSER, getpid(), PT_IEEE_IP, 0);
To implement this feature, sys_ptrace inserts the macro
SUBARCH_PTRACE_SPECIAL, if defined.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-07 08:30:46 +04:00
}
2005-04-17 02:20:36 +04:00
unsigned long getreg ( struct task_struct * child , int regno )
{
unsigned long retval = ~ 0UL ;
switch ( regno ) {
case FS :
case GS :
case DS :
case ES :
case SS :
case CS :
retval = 0xffff ;
/* fall through */
default :
retval & = PT_REG ( & child - > thread . regs , regno ) ;
# ifdef TIF_IA32
if ( test_tsk_thread_flag ( child , TIF_IA32 ) )
retval & = 0xffffffff ;
# endif
}
return retval ;
}
[PATCH] uml: S390 preparation, peekusr/pokeusr defined by subarch
s390 needs to change some parts of arch/um/kernel/ptrace.c. Thus, the code
regarding PEEKUSER and POKEUSER are shifted to arch/um/sys-<subarch>/ptrace.c.
Also s390 debug registers need to be updated, when singlestepping is switched
on / off. Thus, setting/resetting of singlestepping is centralized in the new
function set_singlestep(), which also inserts the macro
SUBARCH_SET_SINGLESTEP(mode), if defined.
Finally, s390 has the "ieee_instruction_pointer" in its
registers, which also is allowed to be read via
ptrace( PTRACE_PEEKUSER, getpid(), PT_IEEE_IP, 0);
To implement this feature, sys_ptrace inserts the macro
SUBARCH_PTRACE_SPECIAL, if defined.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-07 08:30:46 +04:00
int peek_user ( struct task_struct * child , long addr , long data )
{
/* read the word at location addr in the USER area. */
2007-10-16 12:27:18 +04:00
unsigned long tmp ;
[PATCH] uml: S390 preparation, peekusr/pokeusr defined by subarch
s390 needs to change some parts of arch/um/kernel/ptrace.c. Thus, the code
regarding PEEKUSER and POKEUSER are shifted to arch/um/sys-<subarch>/ptrace.c.
Also s390 debug registers need to be updated, when singlestepping is switched
on / off. Thus, setting/resetting of singlestepping is centralized in the new
function set_singlestep(), which also inserts the macro
SUBARCH_SET_SINGLESTEP(mode), if defined.
Finally, s390 has the "ieee_instruction_pointer" in its
registers, which also is allowed to be read via
ptrace( PTRACE_PEEKUSER, getpid(), PT_IEEE_IP, 0);
To implement this feature, sys_ptrace inserts the macro
SUBARCH_PTRACE_SPECIAL, if defined.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-07 08:30:46 +04:00
2007-10-16 12:27:18 +04:00
if ( ( addr & 3 ) | | addr < 0 )
return - EIO ;
tmp = 0 ; /* Default return condition */
2008-02-05 09:31:20 +03:00
if ( addr < MAX_REG_OFFSET )
2007-10-16 12:27:18 +04:00
tmp = getreg ( child , addr ) ;
else if ( ( addr > = offsetof ( struct user , u_debugreg [ 0 ] ) ) & &
2008-02-05 09:31:20 +03:00
( addr < = offsetof ( struct user , u_debugreg [ 7 ] ) ) ) {
2007-10-16 12:27:18 +04:00
addr - = offsetof ( struct user , u_debugreg [ 0 ] ) ;
addr = addr > > 2 ;
tmp = child - > thread . arch . debugregs [ addr ] ;
}
return put_user ( tmp , ( unsigned long * ) data ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-27 13:14:34 +04:00
/* XXX Mostly copied from sys-i386 */
2005-04-17 02:20:36 +04:00
int is_syscall ( unsigned long addr )
{
2006-03-27 13:14:34 +04:00
unsigned short instr ;
int n ;
n = copy_from_user ( & instr , ( void __user * ) addr , sizeof ( instr ) ) ;
2008-02-05 09:31:20 +03:00
if ( n ) {
/*
* access_process_vm ( ) grants access to vsyscall and stub ,
2006-03-27 13:14:34 +04:00
* while copy_from_user doesn ' t . Maybe access_process_vm is
* slow , but that doesn ' t matter , since it will be called only
* in case of singlestepping , if copy_from_user failed .
*/
n = access_process_vm ( current , addr , & instr , sizeof ( instr ) , 0 ) ;
2007-10-16 12:27:18 +04:00
if ( n ! = sizeof ( instr ) ) {
2006-03-27 13:14:34 +04:00
printk ( " is_syscall : failed to read instruction from "
" 0x%lx \n " , addr ) ;
2007-10-16 12:27:18 +04:00
return 1 ;
2006-03-27 13:14:34 +04:00
}
}
/* sysenter */
2007-10-16 12:27:18 +04:00
return instr = = 0x050f ;
2005-04-17 02:20:36 +04:00
}
2007-10-16 12:27:16 +04:00
int get_fpregs ( struct user_i387_struct __user * buf , struct task_struct * child )
2005-04-17 02:20:36 +04:00
{
2007-10-16 12:27:16 +04:00
int err , n , cpu = ( ( struct thread_info * ) child - > stack ) - > cpu ;
long fpregs [ HOST_FP_SIZE ] ;
2005-04-17 02:20:36 +04:00
2007-10-16 12:27:16 +04:00
BUG_ON ( sizeof ( * buf ) ! = sizeof ( fpregs ) ) ;
err = save_fp_registers ( userspace_pid [ cpu ] , fpregs ) ;
if ( err )
return err ;
2007-10-29 07:36:10 +03:00
n = copy_to_user ( buf , fpregs , sizeof ( fpregs ) ) ;
2008-02-05 09:31:20 +03:00
if ( n > 0 )
2007-10-16 12:27:16 +04:00
return - EFAULT ;
return n ;
2005-04-17 02:20:36 +04:00
}
2007-10-16 12:27:16 +04:00
int set_fpregs ( struct user_i387_struct __user * buf , struct task_struct * child )
2005-04-17 02:20:36 +04:00
{
2007-10-16 12:27:16 +04:00
int n , cpu = ( ( struct thread_info * ) child - > stack ) - > cpu ;
long fpregs [ HOST_FP_SIZE ] ;
BUG_ON ( sizeof ( * buf ) ! = sizeof ( fpregs ) ) ;
2007-10-29 07:36:10 +03:00
n = copy_from_user ( fpregs , buf , sizeof ( fpregs ) ) ;
2007-10-16 12:27:16 +04:00
if ( n > 0 )
return - EFAULT ;
return restore_fp_registers ( userspace_pid [ cpu ] , fpregs ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-16 12:27:16 +04:00
long subarch_ptrace ( struct task_struct * child , long request , long addr ,
long data )
2005-04-17 02:20:36 +04:00
{
2007-10-16 12:27:16 +04:00
int ret = - EIO ;
switch ( request ) {
case PTRACE_GETFPXREGS : /* Get the child FPU state. */
ret = get_fpregs ( ( struct user_i387_struct __user * ) data ,
child ) ;
break ;
case PTRACE_SETFPXREGS : /* Set the child FPU state. */
ret = set_fpregs ( ( struct user_i387_struct __user * ) data ,
child ) ;
break ;
}
return ret ;
2005-04-17 02:20:36 +04:00
}