Merge branch 'master' of /home/tglx/work/mtd/git/linux-2.6.git/
[linux-2.6] / arch / frv / kernel / ptrace.c
1 /* ptrace.c: FRV specific parts of process tracing
2  *
3  * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  * - Derived from arch/m68k/kernel/ptrace.c
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/mm.h>
16 #include <linux/smp.h>
17 #include <linux/smp_lock.h>
18 #include <linux/errno.h>
19 #include <linux/ptrace.h>
20 #include <linux/user.h>
21 #include <linux/config.h>
22 #include <linux/security.h>
23 #include <linux/signal.h>
24
25 #include <asm/uaccess.h>
26 #include <asm/page.h>
27 #include <asm/pgtable.h>
28 #include <asm/system.h>
29 #include <asm/processor.h>
30 #include <asm/unistd.h>
31
32 /*
33  * does not yet catch signals sent when the child dies.
34  * in exit.c or in signal.c.
35  */
36
37 /*
38  * Get contents of register REGNO in task TASK.
39  */
40 static inline long get_reg(struct task_struct *task, int regno)
41 {
42         struct user_context *user = task->thread.user;
43
44         if (regno < 0 || regno >= PT__END)
45                 return 0;
46
47         return ((unsigned long *) user)[regno];
48 }
49
50 /*
51  * Write contents of register REGNO in task TASK.
52  */
53 static inline int put_reg(struct task_struct *task, int regno,
54                           unsigned long data)
55 {
56         struct user_context *user = task->thread.user;
57
58         if (regno < 0 || regno >= PT__END)
59                 return -EIO;
60
61         switch (regno) {
62         case PT_GR(0):
63                 return 0;
64         case PT_PSR:
65         case PT__STATUS:
66                 return -EIO;
67         default:
68                 ((unsigned long *) user)[regno] = data;
69                 return 0;
70         }
71 }
72
73 /*
74  * check that an address falls within the bounds of the target process's memory mappings
75  */
76 static inline int is_user_addr_valid(struct task_struct *child,
77                                      unsigned long start, unsigned long len)
78 {
79 #ifdef CONFIG_MMU
80         if (start >= PAGE_OFFSET || len > PAGE_OFFSET - start)
81                 return -EIO;
82         return 0;
83 #else
84         struct vm_list_struct *vml;
85
86         for (vml = child->mm->context.vmlist; vml; vml = vml->next)
87                 if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end)
88                         return 0;
89
90         return -EIO;
91 #endif
92 }
93
94 /*
95  * Called by kernel/ptrace.c when detaching..
96  *
97  * Control h/w single stepping
98  */
99 void ptrace_disable(struct task_struct *child)
100 {
101         child->thread.frame0->__status &= ~REG__STATUS_STEP;
102 }
103
104 void ptrace_enable(struct task_struct *child)
105 {
106         child->thread.frame0->__status |= REG__STATUS_STEP;
107 }
108
109 asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
110 {
111         struct task_struct *child;
112         unsigned long tmp;
113         int ret;
114
115         lock_kernel();
116         ret = -EPERM;
117         if (request == PTRACE_TRACEME) {
118                 /* are we already being traced? */
119                 if (current->ptrace & PT_PTRACED)
120                         goto out;
121                 ret = security_ptrace(current->parent, current);
122                 if (ret)
123                         goto out;
124                 /* set the ptrace bit in the process flags. */
125                 current->ptrace |= PT_PTRACED;
126                 ret = 0;
127                 goto out;
128         }
129         ret = -ESRCH;
130         read_lock(&tasklist_lock);
131         child = find_task_by_pid(pid);
132         if (child)
133                 get_task_struct(child);
134         read_unlock(&tasklist_lock);
135         if (!child)
136                 goto out;
137
138         ret = -EPERM;
139         if (pid == 1)           /* you may not mess with init */
140                 goto out_tsk;
141
142         if (request == PTRACE_ATTACH) {
143                 ret = ptrace_attach(child);
144                 goto out_tsk;
145         }
146
147         ret = ptrace_check_attach(child, request == PTRACE_KILL);
148         if (ret < 0)
149                 goto out_tsk;
150
151         switch (request) {
152                 /* when I and D space are separate, these will need to be fixed. */
153         case PTRACE_PEEKTEXT: /* read word at location addr. */
154         case PTRACE_PEEKDATA: {
155                 int copied;
156
157                 ret = -EIO;
158                 if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
159                         break;
160
161                 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
162                 if (copied != sizeof(tmp))
163                         break;
164
165                 ret = put_user(tmp,(unsigned long *) data);
166                 break;
167         }
168
169                 /* read the word at location addr in the USER area. */
170         case PTRACE_PEEKUSR: {
171                 tmp = 0;
172                 ret = -EIO;
173                 if ((addr & 3) || addr < 0)
174                         break;
175
176                 ret = 0;
177                 switch (addr >> 2) {
178                 case 0 ... PT__END - 1:
179                         tmp = get_reg(child, addr >> 2);
180                         break;
181
182                 case PT__END + 0:
183                         tmp = child->mm->end_code - child->mm->start_code;
184                         break;
185
186                 case PT__END + 1:
187                         tmp = child->mm->end_data - child->mm->start_data;
188                         break;
189
190                 case PT__END + 2:
191                         tmp = child->mm->start_stack - child->mm->start_brk;
192                         break;
193
194                 case PT__END + 3:
195                         tmp = child->mm->start_code;
196                         break;
197
198                 case PT__END + 4:
199                         tmp = child->mm->start_stack;
200                         break;
201
202                 default:
203                         ret = -EIO;
204                         break;
205                 }
206
207                 if (ret == 0)
208                         ret = put_user(tmp, (unsigned long *) data);
209                 break;
210         }
211
212                 /* when I and D space are separate, this will have to be fixed. */
213         case PTRACE_POKETEXT: /* write the word at location addr. */
214         case PTRACE_POKEDATA:
215                 ret = -EIO;
216                 if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
217                         break;
218                 if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data))
219                         break;
220                 ret = 0;
221                 break;
222
223         case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
224                 ret = -EIO;
225                 if ((addr & 3) || addr < 0)
226                         break;
227
228                 ret = 0;
229                 switch (addr >> 2) {
230                 case 0 ... PT__END-1:
231                         ret = put_reg(child, addr >> 2, data);
232                         break;
233
234                 default:
235                         ret = -EIO;
236                         break;
237                 }
238                 break;
239
240         case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
241         case PTRACE_CONT: /* restart after signal. */
242                 ret = -EIO;
243                 if (!valid_signal(data))
244                         break;
245                 if (request == PTRACE_SYSCALL)
246                         set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
247                 else
248                         clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
249                 child->exit_code = data;
250                 ptrace_disable(child);
251                 wake_up_process(child);
252                 ret = 0;
253                 break;
254
255                 /* make the child exit.  Best I can do is send it a sigkill.
256                  * perhaps it should be put in the status that it wants to
257                  * exit.
258                  */
259         case PTRACE_KILL:
260                 ret = 0;
261                 if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
262                         break;
263                 child->exit_code = SIGKILL;
264                 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
265                 ptrace_disable(child);
266                 wake_up_process(child);
267                 break;
268
269         case PTRACE_SINGLESTEP:  /* set the trap flag. */
270                 ret = -EIO;
271                 if (!valid_signal(data))
272                         break;
273                 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
274                 ptrace_enable(child);
275                 child->exit_code = data;
276                 wake_up_process(child);
277                 ret = 0;
278                 break;
279
280         case PTRACE_DETACH:     /* detach a process that was attached. */
281                 ret = ptrace_detach(child, data);
282                 break;
283
284         case PTRACE_GETREGS: { /* Get all integer regs from the child. */
285                 int i;
286                 for (i = 0; i < PT__GPEND; i++) {
287                         tmp = get_reg(child, i);
288                         if (put_user(tmp, (unsigned long *) data)) {
289                                 ret = -EFAULT;
290                                 break;
291                         }
292                         data += sizeof(long);
293                 }
294                 ret = 0;
295                 break;
296         }
297
298         case PTRACE_SETREGS: { /* Set all integer regs in the child. */
299                 int i;
300                 for (i = 0; i < PT__GPEND; i++) {
301                         if (get_user(tmp, (unsigned long *) data)) {
302                                 ret = -EFAULT;
303                                 break;
304                         }
305                         put_reg(child, i, tmp);
306                         data += sizeof(long);
307                 }
308                 ret = 0;
309                 break;
310         }
311
312         case PTRACE_GETFPREGS: { /* Get the child FP/Media state. */
313                 ret = 0;
314                 if (copy_to_user((void *) data,
315                                  &child->thread.user->f,
316                                  sizeof(child->thread.user->f)))
317                         ret = -EFAULT;
318                 break;
319         }
320
321         case PTRACE_SETFPREGS: { /* Set the child FP/Media state. */
322                 ret = 0;
323                 if (copy_from_user(&child->thread.user->f,
324                                    (void *) data,
325                                    sizeof(child->thread.user->f)))
326                         ret = -EFAULT;
327                 break;
328         }
329
330         case PTRACE_GETFDPIC:
331                 tmp = 0;
332                 switch (addr) {
333                 case PTRACE_GETFDPIC_EXEC:
334                         tmp = child->mm->context.exec_fdpic_loadmap;
335                         break;
336                 case PTRACE_GETFDPIC_INTERP:
337                         tmp = child->mm->context.interp_fdpic_loadmap;
338                         break;
339                 default:
340                         break;
341                 }
342
343                 ret = 0;
344                 if (put_user(tmp, (unsigned long *) data)) {
345                         ret = -EFAULT;
346                         break;
347                 }
348                 break;
349
350         default:
351                 ret = -EIO;
352                 break;
353         }
354 out_tsk:
355         put_task_struct(child);
356 out:
357         unlock_kernel();
358         return ret;
359 }
360
361 int __nongprelbss kstrace;
362
363 static const struct {
364         const char      *name;
365         unsigned        argmask;
366 } __syscall_name_table[NR_syscalls] = {
367         [0]     = { "restart_syscall"                   },
368         [1]     = { "exit",             0x000001        },
369         [2]     = { "fork",             0xffffff        },
370         [3]     = { "read",             0x000141        },
371         [4]     = { "write",            0x000141        },
372         [5]     = { "open",             0x000235        },
373         [6]     = { "close",            0x000001        },
374         [7]     = { "waitpid",          0x000141        },
375         [8]     = { "creat",            0x000025        },
376         [9]     = { "link",             0x000055        },
377         [10]    = { "unlink",           0x000005        },
378         [11]    = { "execve",           0x000445        },
379         [12]    = { "chdir",            0x000005        },
380         [13]    = { "time",             0x000004        },
381         [14]    = { "mknod",            0x000325        },
382         [15]    = { "chmod",            0x000025        },
383         [16]    = { "lchown",           0x000025        },
384         [17]    = { "break" },
385         [18]    = { "oldstat",          0x000045        },
386         [19]    = { "lseek",            0x000131        },
387         [20]    = { "getpid",           0xffffff        },
388         [21]    = { "mount",            0x043555        },
389         [22]    = { "umount",           0x000005        },
390         [23]    = { "setuid",           0x000001        },
391         [24]    = { "getuid",           0xffffff        },
392         [25]    = { "stime",            0x000004        },
393         [26]    = { "ptrace",           0x004413        },
394         [27]    = { "alarm",            0x000001        },
395         [28]    = { "oldfstat",         0x000041        },
396         [29]    = { "pause",            0xffffff        },
397         [30]    = { "utime",            0x000045        },
398         [31]    = { "stty" },
399         [32]    = { "gtty" },
400         [33]    = { "access",           0x000025        },
401         [34]    = { "nice",             0x000001        },
402         [35]    = { "ftime" },
403         [36]    = { "sync",             0xffffff        },
404         [37]    = { "kill",             0x000011        },
405         [38]    = { "rename",           0x000055        },
406         [39]    = { "mkdir",            0x000025        },
407         [40]    = { "rmdir",            0x000005        },
408         [41]    = { "dup",              0x000001        },
409         [42]    = { "pipe",             0x000004        },
410         [43]    = { "times",            0x000004        },
411         [44]    = { "prof" },
412         [45]    = { "brk",              0x000004        },
413         [46]    = { "setgid",           0x000001        },
414         [47]    = { "getgid",           0xffffff        },
415         [48]    = { "signal",           0x000041        },
416         [49]    = { "geteuid",          0xffffff        },
417         [50]    = { "getegid",          0xffffff        },
418         [51]    = { "acct",             0x000005        },
419         [52]    = { "umount2",          0x000035        },
420         [53]    = { "lock" },
421         [54]    = { "ioctl",            0x000331        },
422         [55]    = { "fcntl",            0x000331        },
423         [56]    = { "mpx" },
424         [57]    = { "setpgid",          0x000011        },
425         [58]    = { "ulimit" },
426         [60]    = { "umask",            0x000002        },
427         [61]    = { "chroot",           0x000005        },
428         [62]    = { "ustat",            0x000043        },
429         [63]    = { "dup2",             0x000011        },
430         [64]    = { "getppid",          0xffffff        },
431         [65]    = { "getpgrp",          0xffffff        },
432         [66]    = { "setsid",           0xffffff        },
433         [67]    = { "sigaction" },
434         [68]    = { "sgetmask" },
435         [69]    = { "ssetmask" },
436         [70]    = { "setreuid" },
437         [71]    = { "setregid" },
438         [72]    = { "sigsuspend" },
439         [73]    = { "sigpending" },
440         [74]    = { "sethostname" },
441         [75]    = { "setrlimit" },
442         [76]    = { "getrlimit" },
443         [77]    = { "getrusage" },
444         [78]    = { "gettimeofday" },
445         [79]    = { "settimeofday" },
446         [80]    = { "getgroups" },
447         [81]    = { "setgroups" },
448         [82]    = { "select" },
449         [83]    = { "symlink" },
450         [84]    = { "oldlstat" },
451         [85]    = { "readlink" },
452         [86]    = { "uselib" },
453         [87]    = { "swapon" },
454         [88]    = { "reboot" },
455         [89]    = { "readdir" },
456         [91]    = { "munmap",           0x000034        },
457         [92]    = { "truncate" },
458         [93]    = { "ftruncate" },
459         [94]    = { "fchmod" },
460         [95]    = { "fchown" },
461         [96]    = { "getpriority" },
462         [97]    = { "setpriority" },
463         [99]    = { "statfs" },
464         [100]   = { "fstatfs" },
465         [102]   = { "socketcall" },
466         [103]   = { "syslog" },
467         [104]   = { "setitimer" },
468         [105]   = { "getitimer" },
469         [106]   = { "stat" },
470         [107]   = { "lstat" },
471         [108]   = { "fstat" },
472         [111]   = { "vhangup" },
473         [114]   = { "wait4" },
474         [115]   = { "swapoff" },
475         [116]   = { "sysinfo" },
476         [117]   = { "ipc" },
477         [118]   = { "fsync" },
478         [119]   = { "sigreturn" },
479         [120]   = { "clone" },
480         [121]   = { "setdomainname" },
481         [122]   = { "uname" },
482         [123]   = { "modify_ldt" },
483         [123]   = { "cacheflush" },
484         [124]   = { "adjtimex" },
485         [125]   = { "mprotect" },
486         [126]   = { "sigprocmask" },
487         [127]   = { "create_module" },
488         [128]   = { "init_module" },
489         [129]   = { "delete_module" },
490         [130]   = { "get_kernel_syms" },
491         [131]   = { "quotactl" },
492         [132]   = { "getpgid" },
493         [133]   = { "fchdir" },
494         [134]   = { "bdflush" },
495         [135]   = { "sysfs" },
496         [136]   = { "personality" },
497         [137]   = { "afs_syscall" },
498         [138]   = { "setfsuid" },
499         [139]   = { "setfsgid" },
500         [140]   = { "_llseek",                  0x014331        },
501         [141]   = { "getdents" },
502         [142]   = { "_newselect",               0x000141        },
503         [143]   = { "flock" },
504         [144]   = { "msync" },
505         [145]   = { "readv" },
506         [146]   = { "writev" },
507         [147]   = { "getsid",                   0x000001        },
508         [148]   = { "fdatasync",                0x000001        },
509         [149]   = { "_sysctl",                  0x000004        },
510         [150]   = { "mlock" },
511         [151]   = { "munlock" },
512         [152]   = { "mlockall" },
513         [153]   = { "munlockall" },
514         [154]   = { "sched_setparam" },
515         [155]   = { "sched_getparam" },
516         [156]   = { "sched_setscheduler" },
517         [157]   = { "sched_getscheduler" },
518         [158]   = { "sched_yield" },
519         [159]   = { "sched_get_priority_max" },
520         [160]   = { "sched_get_priority_min" },
521         [161]   = { "sched_rr_get_interval" },
522         [162]   = { "nanosleep",                0x000044        },
523         [163]   = { "mremap" },
524         [164]   = { "setresuid" },
525         [165]   = { "getresuid" },
526         [166]   = { "vm86" },
527         [167]   = { "query_module" },
528         [168]   = { "poll" },
529         [169]   = { "nfsservctl" },
530         [170]   = { "setresgid" },
531         [171]   = { "getresgid" },
532         [172]   = { "prctl",                    0x333331        },
533         [173]   = { "rt_sigreturn",             0xffffff        },
534         [174]   = { "rt_sigaction",             0x001441        },
535         [175]   = { "rt_sigprocmask",           0x001441        },
536         [176]   = { "rt_sigpending",            0x000014        },
537         [177]   = { "rt_sigtimedwait",          0x001444        },
538         [178]   = { "rt_sigqueueinfo",          0x000411        },
539         [179]   = { "rt_sigsuspend",            0x000014        },
540         [180]   = { "pread",                    0x003341        },
541         [181]   = { "pwrite",                   0x003341        },
542         [182]   = { "chown",                    0x000115        },
543         [183]   = { "getcwd" },
544         [184]   = { "capget" },
545         [185]   = { "capset" },
546         [186]   = { "sigaltstack" },
547         [187]   = { "sendfile" },
548         [188]   = { "getpmsg" },
549         [189]   = { "putpmsg" },
550         [190]   = { "vfork",                    0xffffff        },
551         [191]   = { "ugetrlimit" },
552         [192]   = { "mmap2",                    0x313314        },
553         [193]   = { "truncate64" },
554         [194]   = { "ftruncate64" },
555         [195]   = { "stat64",                   0x000045        },
556         [196]   = { "lstat64",                  0x000045        },
557         [197]   = { "fstat64",                  0x000041        },
558         [198]   = { "lchown32" },
559         [199]   = { "getuid32",                 0xffffff        },
560         [200]   = { "getgid32",                 0xffffff        },
561         [201]   = { "geteuid32",                0xffffff        },
562         [202]   = { "getegid32",                0xffffff        },
563         [203]   = { "setreuid32" },
564         [204]   = { "setregid32" },
565         [205]   = { "getgroups32" },
566         [206]   = { "setgroups32" },
567         [207]   = { "fchown32" },
568         [208]   = { "setresuid32" },
569         [209]   = { "getresuid32" },
570         [210]   = { "setresgid32" },
571         [211]   = { "getresgid32" },
572         [212]   = { "chown32" },
573         [213]   = { "setuid32" },
574         [214]   = { "setgid32" },
575         [215]   = { "setfsuid32" },
576         [216]   = { "setfsgid32" },
577         [217]   = { "pivot_root" },
578         [218]   = { "mincore" },
579         [219]   = { "madvise" },
580         [220]   = { "getdents64" },
581         [221]   = { "fcntl64" },
582         [223]   = { "security" },
583         [224]   = { "gettid" },
584         [225]   = { "readahead" },
585         [226]   = { "setxattr" },
586         [227]   = { "lsetxattr" },
587         [228]   = { "fsetxattr" },
588         [229]   = { "getxattr" },
589         [230]   = { "lgetxattr" },
590         [231]   = { "fgetxattr" },
591         [232]   = { "listxattr" },
592         [233]   = { "llistxattr" },
593         [234]   = { "flistxattr" },
594         [235]   = { "removexattr" },
595         [236]   = { "lremovexattr" },
596         [237]   = { "fremovexattr" },
597         [238]   = { "tkill" },
598         [239]   = { "sendfile64" },
599         [240]   = { "futex" },
600         [241]   = { "sched_setaffinity" },
601         [242]   = { "sched_getaffinity" },
602         [243]   = { "set_thread_area" },
603         [244]   = { "get_thread_area" },
604         [245]   = { "io_setup" },
605         [246]   = { "io_destroy" },
606         [247]   = { "io_getevents" },
607         [248]   = { "io_submit" },
608         [249]   = { "io_cancel" },
609         [250]   = { "fadvise64" },
610         [252]   = { "exit_group",               0x000001        },
611         [253]   = { "lookup_dcookie" },
612         [254]   = { "epoll_create" },
613         [255]   = { "epoll_ctl" },
614         [256]   = { "epoll_wait" },
615         [257]   = { "remap_file_pages" },
616         [258]   = { "set_tid_address" },
617         [259]   = { "timer_create" },
618         [260]   = { "timer_settime" },
619         [261]   = { "timer_gettime" },
620         [262]   = { "timer_getoverrun" },
621         [263]   = { "timer_delete" },
622         [264]   = { "clock_settime" },
623         [265]   = { "clock_gettime" },
624         [266]   = { "clock_getres" },
625         [267]   = { "clock_nanosleep" },
626         [268]   = { "statfs64" },
627         [269]   = { "fstatfs64" },
628         [270]   = { "tgkill" },
629         [271]   = { "utimes" },
630         [272]   = { "fadvise64_64" },
631         [273]   = { "vserver" },
632         [274]   = { "mbind" },
633         [275]   = { "get_mempolicy" },
634         [276]   = { "set_mempolicy" },
635         [277]   = { "mq_open" },
636         [278]   = { "mq_unlink" },
637         [279]   = { "mq_timedsend" },
638         [280]   = { "mq_timedreceive" },
639         [281]   = { "mq_notify" },
640         [282]   = { "mq_getsetattr" },
641         [283]   = { "sys_kexec_load" },
642 };
643
644 asmlinkage void do_syscall_trace(int leaving)
645 {
646 #if 0
647         unsigned long *argp;
648         const char *name;
649         unsigned argmask;
650         char buffer[16];
651
652         if (!kstrace)
653                 return;
654
655         if (!current->mm)
656                 return;
657
658         if (__frame->gr7 == __NR_close)
659                 return;
660
661 #if 0
662         if (__frame->gr7 != __NR_mmap2 &&
663             __frame->gr7 != __NR_vfork &&
664             __frame->gr7 != __NR_execve &&
665             __frame->gr7 != __NR_exit)
666                 return;
667 #endif
668
669         argmask = 0;
670         name = NULL;
671         if (__frame->gr7 < NR_syscalls) {
672                 name = __syscall_name_table[__frame->gr7].name;
673                 argmask = __syscall_name_table[__frame->gr7].argmask;
674         }
675         if (!name) {
676                 sprintf(buffer, "sys_%lx", __frame->gr7);
677                 name = buffer;
678         }
679
680         if (!leaving) {
681                 if (!argmask) {
682                         printk(KERN_CRIT "[%d] %s(%lx,%lx,%lx,%lx,%lx,%lx)\n",
683                                current->pid,
684                                name,
685                                __frame->gr8,
686                                __frame->gr9,
687                                __frame->gr10,
688                                __frame->gr11,
689                                __frame->gr12,
690                                __frame->gr13);
691                 }
692                 else if (argmask == 0xffffff) {
693                         printk(KERN_CRIT "[%d] %s()\n",
694                                current->pid,
695                                name);
696                 }
697                 else {
698                         printk(KERN_CRIT "[%d] %s(",
699                                current->pid,
700                                name);
701
702                         argp = &__frame->gr8;
703
704                         do {
705                                 switch (argmask & 0xf) {
706                                 case 1:
707                                         printk("%ld", (long) *argp);
708                                         break;
709                                 case 2:
710                                         printk("%lo", *argp);
711                                         break;
712                                 case 3:
713                                         printk("%lx", *argp);
714                                         break;
715                                 case 4:
716                                         printk("%p", (void *) *argp);
717                                         break;
718                                 case 5:
719                                         printk("\"%s\"", (char *) *argp);
720                                         break;
721                                 }
722
723                                 argp++;
724                                 argmask >>= 4;
725                                 if (argmask)
726                                         printk(",");
727
728                         } while (argmask);
729
730                         printk(")\n");
731                 }
732         }
733         else {
734                 if ((int)__frame->gr8 > -4096 && (int)__frame->gr8 < 4096)
735                         printk(KERN_CRIT "[%d] %s() = %ld\n", current->pid, name, __frame->gr8);
736                 else
737                         printk(KERN_CRIT "[%d] %s() = %lx\n", current->pid, name, __frame->gr8);
738         }
739         return;
740 #endif
741
742         if (!test_thread_flag(TIF_SYSCALL_TRACE))
743                 return;
744
745         if (!(current->ptrace & PT_PTRACED))
746                 return;
747
748         /* we need to indicate entry or exit to strace */
749         if (leaving)
750                 __frame->__status |= REG__STATUS_SYSC_EXIT;
751         else
752                 __frame->__status |= REG__STATUS_SYSC_ENTRY;
753
754         ptrace_notify(SIGTRAP);
755
756         /*
757          * this isn't the same as continuing with a signal, but it will do
758          * for normal use.  strace only continues with a signal if the
759          * stopping signal is not SIGTRAP.  -brl
760          */
761         if (current->exit_code) {
762                 send_sig(current->exit_code, current, 1);
763                 current->exit_code = 0;
764         }
765 }