2005-04-16 15:20:36 -07:00
/* ptrace.c: FRV specific parts of process tracing
*
* Copyright ( C ) 2003 - 5 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
* - Derived from arch / m68k / kernel / ptrace . c
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/kernel.h>
# include <linux/sched.h>
# include <linux/mm.h>
# include <linux/smp.h>
# include <linux/errno.h>
# include <linux/ptrace.h>
# include <linux/user.h>
# include <linux/security.h>
2005-05-01 08:59:14 -07:00
# include <linux/signal.h>
2005-04-16 15:20:36 -07:00
# include <asm/uaccess.h>
# include <asm/page.h>
# include <asm/pgtable.h>
# include <asm/system.h>
# include <asm/processor.h>
# include <asm/unistd.h>
/*
* does not yet catch signals sent when the child dies .
* in exit . c or in signal . c .
*/
/*
* Get contents of register REGNO in task TASK .
*/
static inline long get_reg ( struct task_struct * task , int regno )
{
struct user_context * user = task - > thread . user ;
if ( regno < 0 | | regno > = PT__END )
return 0 ;
return ( ( unsigned long * ) user ) [ regno ] ;
}
/*
* Write contents of register REGNO in task TASK .
*/
static inline int put_reg ( struct task_struct * task , int regno ,
unsigned long data )
{
struct user_context * user = task - > thread . user ;
if ( regno < 0 | | regno > = PT__END )
return - EIO ;
switch ( regno ) {
case PT_GR ( 0 ) :
return 0 ;
case PT_PSR :
case PT__STATUS :
return - EIO ;
default :
( ( unsigned long * ) user ) [ regno ] = data ;
return 0 ;
}
}
/*
* check that an address falls within the bounds of the target process ' s memory mappings
*/
static inline int is_user_addr_valid ( struct task_struct * child ,
unsigned long start , unsigned long len )
{
# ifdef CONFIG_MMU
if ( start > = PAGE_OFFSET | | len > PAGE_OFFSET - start )
return - EIO ;
return 0 ;
# else
struct vm_list_struct * vml ;
for ( vml = child - > mm - > context . vmlist ; vml ; vml = vml - > next )
if ( start > = vml - > vma - > vm_start & & start + len < = vml - > vma - > vm_end )
return 0 ;
return - EIO ;
# endif
}
/*
* Called by kernel / ptrace . c when detaching . .
*
* Control h / w single stepping
*/
void ptrace_disable ( struct task_struct * child )
{
child - > thread . frame0 - > __status & = ~ REG__STATUS_STEP ;
}
void ptrace_enable ( struct task_struct * child )
{
child - > thread . frame0 - > __status | = REG__STATUS_STEP ;
}
2005-11-07 00:59:47 -08:00
long arch_ptrace ( struct task_struct * child , long request , long addr , long data )
2005-04-16 15:20:36 -07:00
{
unsigned long tmp ;
int ret ;
switch ( request ) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT : /* read word at location addr. */
2007-07-17 04:03:43 -07:00
case PTRACE_PEEKDATA :
2005-04-16 15:20:36 -07:00
ret = - EIO ;
if ( is_user_addr_valid ( child , addr , sizeof ( tmp ) ) < 0 )
break ;
2007-07-17 04:03:43 -07:00
ret = generic_ptrace_peekdata ( child , addr , data ) ;
2005-04-16 15:20:36 -07:00
break ;
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR : {
tmp = 0 ;
ret = - EIO ;
if ( ( addr & 3 ) | | addr < 0 )
break ;
ret = 0 ;
switch ( addr > > 2 ) {
case 0 . . . PT__END - 1 :
tmp = get_reg ( child , addr > > 2 ) ;
break ;
case PT__END + 0 :
tmp = child - > mm - > end_code - child - > mm - > start_code ;
break ;
case PT__END + 1 :
tmp = child - > mm - > end_data - child - > mm - > start_data ;
break ;
case PT__END + 2 :
tmp = child - > mm - > start_stack - child - > mm - > start_brk ;
break ;
case PT__END + 3 :
tmp = child - > mm - > start_code ;
break ;
case PT__END + 4 :
tmp = child - > mm - > start_stack ;
break ;
default :
ret = - EIO ;
break ;
}
if ( ret = = 0 )
ret = put_user ( tmp , ( unsigned long * ) data ) ;
break ;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT : /* write the word at location addr. */
case PTRACE_POKEDATA :
ret = - EIO ;
if ( is_user_addr_valid ( child , addr , sizeof ( tmp ) ) < 0 )
break ;
2007-07-17 04:03:44 -07:00
ret = generic_ptrace_pokedata ( child , addr , data ) ;
2005-04-16 15:20:36 -07:00
break ;
case PTRACE_POKEUSR : /* write the word at location addr in the USER area */
ret = - EIO ;
if ( ( addr & 3 ) | | addr < 0 )
break ;
ret = 0 ;
switch ( addr > > 2 ) {
case 0 . . . PT__END - 1 :
ret = put_reg ( child , addr > > 2 , data ) ;
break ;
default :
ret = - EIO ;
break ;
}
break ;
case PTRACE_SYSCALL : /* continue and stop at next (return from) syscall */
case PTRACE_CONT : /* restart after signal. */
ret = - EIO ;
2005-05-01 08:59:14 -07:00
if ( ! valid_signal ( data ) )
2005-04-16 15:20:36 -07:00
break ;
if ( request = = PTRACE_SYSCALL )
set_tsk_thread_flag ( child , TIF_SYSCALL_TRACE ) ;
else
clear_tsk_thread_flag ( child , TIF_SYSCALL_TRACE ) ;
child - > exit_code = data ;
ptrace_disable ( child ) ;
wake_up_process ( child ) ;
ret = 0 ;
break ;
/* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit .
*/
case PTRACE_KILL :
ret = 0 ;
if ( child - > exit_state = = EXIT_ZOMBIE ) /* already dead */
break ;
child - > exit_code = SIGKILL ;
clear_tsk_thread_flag ( child , TIF_SINGLESTEP ) ;
ptrace_disable ( child ) ;
wake_up_process ( child ) ;
break ;
case PTRACE_SINGLESTEP : /* set the trap flag. */
ret = - EIO ;
2005-05-01 08:59:14 -07:00
if ( ! valid_signal ( data ) )
2005-04-16 15:20:36 -07:00
break ;
clear_tsk_thread_flag ( child , TIF_SYSCALL_TRACE ) ;
ptrace_enable ( child ) ;
child - > exit_code = data ;
wake_up_process ( child ) ;
ret = 0 ;
break ;
case PTRACE_DETACH : /* detach a process that was attached. */
ret = ptrace_detach ( child , data ) ;
break ;
case PTRACE_GETREGS : { /* Get all integer regs from the child. */
int i ;
for ( i = 0 ; i < PT__GPEND ; i + + ) {
tmp = get_reg ( child , i ) ;
if ( put_user ( tmp , ( unsigned long * ) data ) ) {
ret = - EFAULT ;
break ;
}
data + = sizeof ( long ) ;
}
ret = 0 ;
break ;
}
case PTRACE_SETREGS : { /* Set all integer regs in the child. */
int i ;
for ( i = 0 ; i < PT__GPEND ; i + + ) {
if ( get_user ( tmp , ( unsigned long * ) data ) ) {
ret = - EFAULT ;
break ;
}
put_reg ( child , i , tmp ) ;
data + = sizeof ( long ) ;
}
ret = 0 ;
break ;
}
case PTRACE_GETFPREGS : { /* Get the child FP/Media state. */
ret = 0 ;
if ( copy_to_user ( ( void * ) data ,
& child - > thread . user - > f ,
sizeof ( child - > thread . user - > f ) ) )
ret = - EFAULT ;
break ;
}
case PTRACE_SETFPREGS : { /* Set the child FP/Media state. */
ret = 0 ;
if ( copy_from_user ( & child - > thread . user - > f ,
( void * ) data ,
sizeof ( child - > thread . user - > f ) ) )
ret = - EFAULT ;
break ;
}
case PTRACE_GETFDPIC :
tmp = 0 ;
switch ( addr ) {
case PTRACE_GETFDPIC_EXEC :
tmp = child - > mm - > context . exec_fdpic_loadmap ;
break ;
case PTRACE_GETFDPIC_INTERP :
tmp = child - > mm - > context . interp_fdpic_loadmap ;
break ;
default :
break ;
}
ret = 0 ;
if ( put_user ( tmp , ( unsigned long * ) data ) ) {
ret = - EFAULT ;
break ;
}
break ;
default :
ret = - EIO ;
break ;
}
return ret ;
}
int __nongprelbss kstrace ;
static const struct {
const char * name ;
unsigned argmask ;
} __syscall_name_table [ NR_syscalls ] = {
[ 0 ] = { " restart_syscall " } ,
[ 1 ] = { " exit " , 0x000001 } ,
[ 2 ] = { " fork " , 0xffffff } ,
[ 3 ] = { " read " , 0x000141 } ,
[ 4 ] = { " write " , 0x000141 } ,
[ 5 ] = { " open " , 0x000235 } ,
[ 6 ] = { " close " , 0x000001 } ,
[ 7 ] = { " waitpid " , 0x000141 } ,
[ 8 ] = { " creat " , 0x000025 } ,
[ 9 ] = { " link " , 0x000055 } ,
[ 10 ] = { " unlink " , 0x000005 } ,
[ 11 ] = { " execve " , 0x000445 } ,
[ 12 ] = { " chdir " , 0x000005 } ,
[ 13 ] = { " time " , 0x000004 } ,
[ 14 ] = { " mknod " , 0x000325 } ,
[ 15 ] = { " chmod " , 0x000025 } ,
[ 16 ] = { " lchown " , 0x000025 } ,
[ 17 ] = { " break " } ,
[ 18 ] = { " oldstat " , 0x000045 } ,
[ 19 ] = { " lseek " , 0x000131 } ,
[ 20 ] = { " getpid " , 0xffffff } ,
[ 21 ] = { " mount " , 0x043555 } ,
[ 22 ] = { " umount " , 0x000005 } ,
[ 23 ] = { " setuid " , 0x000001 } ,
[ 24 ] = { " getuid " , 0xffffff } ,
[ 25 ] = { " stime " , 0x000004 } ,
[ 26 ] = { " ptrace " , 0x004413 } ,
[ 27 ] = { " alarm " , 0x000001 } ,
[ 28 ] = { " oldfstat " , 0x000041 } ,
[ 29 ] = { " pause " , 0xffffff } ,
[ 30 ] = { " utime " , 0x000045 } ,
[ 31 ] = { " stty " } ,
[ 32 ] = { " gtty " } ,
[ 33 ] = { " access " , 0x000025 } ,
[ 34 ] = { " nice " , 0x000001 } ,
[ 35 ] = { " ftime " } ,
[ 36 ] = { " sync " , 0xffffff } ,
[ 37 ] = { " kill " , 0x000011 } ,
[ 38 ] = { " rename " , 0x000055 } ,
[ 39 ] = { " mkdir " , 0x000025 } ,
[ 40 ] = { " rmdir " , 0x000005 } ,
[ 41 ] = { " dup " , 0x000001 } ,
[ 42 ] = { " pipe " , 0x000004 } ,
[ 43 ] = { " times " , 0x000004 } ,
[ 44 ] = { " prof " } ,
[ 45 ] = { " brk " , 0x000004 } ,
[ 46 ] = { " setgid " , 0x000001 } ,
[ 47 ] = { " getgid " , 0xffffff } ,
[ 48 ] = { " signal " , 0x000041 } ,
[ 49 ] = { " geteuid " , 0xffffff } ,
[ 50 ] = { " getegid " , 0xffffff } ,
[ 51 ] = { " acct " , 0x000005 } ,
[ 52 ] = { " umount2 " , 0x000035 } ,
[ 53 ] = { " lock " } ,
[ 54 ] = { " ioctl " , 0x000331 } ,
[ 55 ] = { " fcntl " , 0x000331 } ,
[ 56 ] = { " mpx " } ,
[ 57 ] = { " setpgid " , 0x000011 } ,
[ 58 ] = { " ulimit " } ,
[ 60 ] = { " umask " , 0x000002 } ,
[ 61 ] = { " chroot " , 0x000005 } ,
[ 62 ] = { " ustat " , 0x000043 } ,
[ 63 ] = { " dup2 " , 0x000011 } ,
[ 64 ] = { " getppid " , 0xffffff } ,
[ 65 ] = { " getpgrp " , 0xffffff } ,
[ 66 ] = { " setsid " , 0xffffff } ,
[ 67 ] = { " sigaction " } ,
[ 68 ] = { " sgetmask " } ,
[ 69 ] = { " ssetmask " } ,
[ 70 ] = { " setreuid " } ,
[ 71 ] = { " setregid " } ,
[ 72 ] = { " sigsuspend " } ,
[ 73 ] = { " sigpending " } ,
[ 74 ] = { " sethostname " } ,
[ 75 ] = { " setrlimit " } ,
[ 76 ] = { " getrlimit " } ,
[ 77 ] = { " getrusage " } ,
[ 78 ] = { " gettimeofday " } ,
[ 79 ] = { " settimeofday " } ,
[ 80 ] = { " getgroups " } ,
[ 81 ] = { " setgroups " } ,
[ 82 ] = { " select " } ,
[ 83 ] = { " symlink " } ,
[ 84 ] = { " oldlstat " } ,
[ 85 ] = { " readlink " } ,
[ 86 ] = { " uselib " } ,
[ 87 ] = { " swapon " } ,
[ 88 ] = { " reboot " } ,
[ 89 ] = { " readdir " } ,
[ 91 ] = { " munmap " , 0x000034 } ,
[ 92 ] = { " truncate " } ,
[ 93 ] = { " ftruncate " } ,
[ 94 ] = { " fchmod " } ,
[ 95 ] = { " fchown " } ,
[ 96 ] = { " getpriority " } ,
[ 97 ] = { " setpriority " } ,
[ 99 ] = { " statfs " } ,
[ 100 ] = { " fstatfs " } ,
[ 102 ] = { " socketcall " } ,
[ 103 ] = { " syslog " } ,
[ 104 ] = { " setitimer " } ,
[ 105 ] = { " getitimer " } ,
[ 106 ] = { " stat " } ,
[ 107 ] = { " lstat " } ,
[ 108 ] = { " fstat " } ,
[ 111 ] = { " vhangup " } ,
[ 114 ] = { " wait4 " } ,
[ 115 ] = { " swapoff " } ,
[ 116 ] = { " sysinfo " } ,
[ 117 ] = { " ipc " } ,
[ 118 ] = { " fsync " } ,
[ 119 ] = { " sigreturn " } ,
[ 120 ] = { " clone " } ,
[ 121 ] = { " setdomainname " } ,
[ 122 ] = { " uname " } ,
[ 123 ] = { " modify_ldt " } ,
[ 123 ] = { " cacheflush " } ,
[ 124 ] = { " adjtimex " } ,
[ 125 ] = { " mprotect " } ,
[ 126 ] = { " sigprocmask " } ,
[ 127 ] = { " create_module " } ,
[ 128 ] = { " init_module " } ,
[ 129 ] = { " delete_module " } ,
[ 130 ] = { " get_kernel_syms " } ,
[ 131 ] = { " quotactl " } ,
[ 132 ] = { " getpgid " } ,
[ 133 ] = { " fchdir " } ,
[ 134 ] = { " bdflush " } ,
[ 135 ] = { " sysfs " } ,
[ 136 ] = { " personality " } ,
[ 137 ] = { " afs_syscall " } ,
[ 138 ] = { " setfsuid " } ,
[ 139 ] = { " setfsgid " } ,
[ 140 ] = { " _llseek " , 0x014331 } ,
[ 141 ] = { " getdents " } ,
[ 142 ] = { " _newselect " , 0x000141 } ,
[ 143 ] = { " flock " } ,
[ 144 ] = { " msync " } ,
[ 145 ] = { " readv " } ,
[ 146 ] = { " writev " } ,
[ 147 ] = { " getsid " , 0x000001 } ,
[ 148 ] = { " fdatasync " , 0x000001 } ,
[ 149 ] = { " _sysctl " , 0x000004 } ,
[ 150 ] = { " mlock " } ,
[ 151 ] = { " munlock " } ,
[ 152 ] = { " mlockall " } ,
[ 153 ] = { " munlockall " } ,
[ 154 ] = { " sched_setparam " } ,
[ 155 ] = { " sched_getparam " } ,
[ 156 ] = { " sched_setscheduler " } ,
[ 157 ] = { " sched_getscheduler " } ,
[ 158 ] = { " sched_yield " } ,
[ 159 ] = { " sched_get_priority_max " } ,
[ 160 ] = { " sched_get_priority_min " } ,
[ 161 ] = { " sched_rr_get_interval " } ,
[ 162 ] = { " nanosleep " , 0x000044 } ,
[ 163 ] = { " mremap " } ,
[ 164 ] = { " setresuid " } ,
[ 165 ] = { " getresuid " } ,
[ 166 ] = { " vm86 " } ,
[ 167 ] = { " query_module " } ,
[ 168 ] = { " poll " } ,
[ 169 ] = { " nfsservctl " } ,
[ 170 ] = { " setresgid " } ,
[ 171 ] = { " getresgid " } ,
[ 172 ] = { " prctl " , 0x333331 } ,
[ 173 ] = { " rt_sigreturn " , 0xffffff } ,
[ 174 ] = { " rt_sigaction " , 0x001441 } ,
[ 175 ] = { " rt_sigprocmask " , 0x001441 } ,
[ 176 ] = { " rt_sigpending " , 0x000014 } ,
[ 177 ] = { " rt_sigtimedwait " , 0x001444 } ,
[ 178 ] = { " rt_sigqueueinfo " , 0x000411 } ,
[ 179 ] = { " rt_sigsuspend " , 0x000014 } ,
[ 180 ] = { " pread " , 0x003341 } ,
[ 181 ] = { " pwrite " , 0x003341 } ,
[ 182 ] = { " chown " , 0x000115 } ,
[ 183 ] = { " getcwd " } ,
[ 184 ] = { " capget " } ,
[ 185 ] = { " capset " } ,
[ 186 ] = { " sigaltstack " } ,
[ 187 ] = { " sendfile " } ,
[ 188 ] = { " getpmsg " } ,
[ 189 ] = { " putpmsg " } ,
[ 190 ] = { " vfork " , 0xffffff } ,
[ 191 ] = { " ugetrlimit " } ,
[ 192 ] = { " mmap2 " , 0x313314 } ,
[ 193 ] = { " truncate64 " } ,
[ 194 ] = { " ftruncate64 " } ,
[ 195 ] = { " stat64 " , 0x000045 } ,
[ 196 ] = { " lstat64 " , 0x000045 } ,
[ 197 ] = { " fstat64 " , 0x000041 } ,
[ 198 ] = { " lchown32 " } ,
[ 199 ] = { " getuid32 " , 0xffffff } ,
[ 200 ] = { " getgid32 " , 0xffffff } ,
[ 201 ] = { " geteuid32 " , 0xffffff } ,
[ 202 ] = { " getegid32 " , 0xffffff } ,
[ 203 ] = { " setreuid32 " } ,
[ 204 ] = { " setregid32 " } ,
[ 205 ] = { " getgroups32 " } ,
[ 206 ] = { " setgroups32 " } ,
[ 207 ] = { " fchown32 " } ,
[ 208 ] = { " setresuid32 " } ,
[ 209 ] = { " getresuid32 " } ,
[ 210 ] = { " setresgid32 " } ,
[ 211 ] = { " getresgid32 " } ,
[ 212 ] = { " chown32 " } ,
[ 213 ] = { " setuid32 " } ,
[ 214 ] = { " setgid32 " } ,
[ 215 ] = { " setfsuid32 " } ,
[ 216 ] = { " setfsgid32 " } ,
[ 217 ] = { " pivot_root " } ,
[ 218 ] = { " mincore " } ,
[ 219 ] = { " madvise " } ,
[ 220 ] = { " getdents64 " } ,
[ 221 ] = { " fcntl64 " } ,
[ 223 ] = { " security " } ,
[ 224 ] = { " gettid " } ,
[ 225 ] = { " readahead " } ,
[ 226 ] = { " setxattr " } ,
[ 227 ] = { " lsetxattr " } ,
[ 228 ] = { " fsetxattr " } ,
[ 229 ] = { " getxattr " } ,
[ 230 ] = { " lgetxattr " } ,
[ 231 ] = { " fgetxattr " } ,
[ 232 ] = { " listxattr " } ,
[ 233 ] = { " llistxattr " } ,
[ 234 ] = { " flistxattr " } ,
[ 235 ] = { " removexattr " } ,
[ 236 ] = { " lremovexattr " } ,
[ 237 ] = { " fremovexattr " } ,
[ 238 ] = { " tkill " } ,
[ 239 ] = { " sendfile64 " } ,
[ 240 ] = { " futex " } ,
[ 241 ] = { " sched_setaffinity " } ,
[ 242 ] = { " sched_getaffinity " } ,
[ 243 ] = { " set_thread_area " } ,
[ 244 ] = { " get_thread_area " } ,
[ 245 ] = { " io_setup " } ,
[ 246 ] = { " io_destroy " } ,
[ 247 ] = { " io_getevents " } ,
[ 248 ] = { " io_submit " } ,
[ 249 ] = { " io_cancel " } ,
[ 250 ] = { " fadvise64 " } ,
[ 252 ] = { " exit_group " , 0x000001 } ,
[ 253 ] = { " lookup_dcookie " } ,
[ 254 ] = { " epoll_create " } ,
[ 255 ] = { " epoll_ctl " } ,
[ 256 ] = { " epoll_wait " } ,
[ 257 ] = { " remap_file_pages " } ,
[ 258 ] = { " set_tid_address " } ,
[ 259 ] = { " timer_create " } ,
[ 260 ] = { " timer_settime " } ,
[ 261 ] = { " timer_gettime " } ,
[ 262 ] = { " timer_getoverrun " } ,
[ 263 ] = { " timer_delete " } ,
[ 264 ] = { " clock_settime " } ,
[ 265 ] = { " clock_gettime " } ,
[ 266 ] = { " clock_getres " } ,
[ 267 ] = { " clock_nanosleep " } ,
[ 268 ] = { " statfs64 " } ,
[ 269 ] = { " fstatfs64 " } ,
[ 270 ] = { " tgkill " } ,
[ 271 ] = { " utimes " } ,
[ 272 ] = { " fadvise64_64 " } ,
[ 273 ] = { " vserver " } ,
[ 274 ] = { " mbind " } ,
[ 275 ] = { " get_mempolicy " } ,
[ 276 ] = { " set_mempolicy " } ,
[ 277 ] = { " mq_open " } ,
[ 278 ] = { " mq_unlink " } ,
[ 279 ] = { " mq_timedsend " } ,
[ 280 ] = { " mq_timedreceive " } ,
[ 281 ] = { " mq_notify " } ,
[ 282 ] = { " mq_getsetattr " } ,
[ 283 ] = { " sys_kexec_load " } ,
} ;
asmlinkage void do_syscall_trace ( int leaving )
{
#if 0
unsigned long * argp ;
const char * name ;
unsigned argmask ;
char buffer [ 16 ] ;
if ( ! kstrace )
return ;
if ( ! current - > mm )
return ;
if ( __frame - > gr7 = = __NR_close )
return ;
#if 0
if ( __frame - > gr7 ! = __NR_mmap2 & &
__frame - > gr7 ! = __NR_vfork & &
__frame - > gr7 ! = __NR_execve & &
__frame - > gr7 ! = __NR_exit )
return ;
# endif
argmask = 0 ;
name = NULL ;
if ( __frame - > gr7 < NR_syscalls ) {
name = __syscall_name_table [ __frame - > gr7 ] . name ;
argmask = __syscall_name_table [ __frame - > gr7 ] . argmask ;
}
if ( ! name ) {
sprintf ( buffer , " sys_%lx " , __frame - > gr7 ) ;
name = buffer ;
}
if ( ! leaving ) {
if ( ! argmask ) {
printk ( KERN_CRIT " [%d] %s(%lx,%lx,%lx,%lx,%lx,%lx) \n " ,
current - > pid ,
name ,
__frame - > gr8 ,
__frame - > gr9 ,
__frame - > gr10 ,
__frame - > gr11 ,
__frame - > gr12 ,
__frame - > gr13 ) ;
}
else if ( argmask = = 0xffffff ) {
printk ( KERN_CRIT " [%d] %s() \n " ,
current - > pid ,
name ) ;
}
else {
printk ( KERN_CRIT " [%d] %s( " ,
current - > pid ,
name ) ;
argp = & __frame - > gr8 ;
do {
switch ( argmask & 0xf ) {
case 1 :
printk ( " %ld " , ( long ) * argp ) ;
break ;
case 2 :
printk ( " %lo " , * argp ) ;
break ;
case 3 :
printk ( " %lx " , * argp ) ;
break ;
case 4 :
printk ( " %p " , ( void * ) * argp ) ;
break ;
case 5 :
printk ( " \" %s \" " , ( char * ) * argp ) ;
break ;
}
argp + + ;
argmask > > = 4 ;
if ( argmask )
printk ( " , " ) ;
} while ( argmask ) ;
printk ( " ) \n " ) ;
}
}
else {
if ( ( int ) __frame - > gr8 > - 4096 & & ( int ) __frame - > gr8 < 4096 )
printk ( KERN_CRIT " [%d] %s() = %ld \n " , current - > pid , name , __frame - > gr8 ) ;
else
printk ( KERN_CRIT " [%d] %s() = %lx \n " , current - > pid , name , __frame - > gr8 ) ;
}
return ;
# endif
if ( ! test_thread_flag ( TIF_SYSCALL_TRACE ) )
return ;
if ( ! ( current - > ptrace & PT_PTRACED ) )
return ;
/* we need to indicate entry or exit to strace */
if ( leaving )
__frame - > __status | = REG__STATUS_SYSC_EXIT ;
else
__frame - > __status | = REG__STATUS_SYSC_ENTRY ;
ptrace_notify ( SIGTRAP ) ;
/*
* this isn ' t the same as continuing with a signal , but it will do
* for normal use . strace only continues with a signal if the
* stopping signal is not SIGTRAP . - brl
*/
if ( current - > exit_code ) {
send_sig ( current - > exit_code , current , 1 ) ;
current - > exit_code = 0 ;
}
}