ptrace.c 18 KB

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