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