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