ptrace.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /* ptrace.c: Sparc process tracing support.
  2. *
  3. * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
  4. * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5. *
  6. * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
  7. * and David Mosberger.
  8. *
  9. * Added Linux support -miguel (weird, eh?, the original code was meant
  10. * to emulate SunOS).
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/sched.h>
  14. #include <linux/mm.h>
  15. #include <linux/errno.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/user.h>
  18. #include <linux/smp.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/security.h>
  21. #include <asm/asi.h>
  22. #include <asm/pgtable.h>
  23. #include <asm/system.h>
  24. #include <asm/uaccess.h>
  25. #include <asm/psrcompat.h>
  26. #include <asm/visasm.h>
  27. #include <asm/spitfire.h>
  28. /* Returning from ptrace is a bit tricky because the syscall return
  29. * low level code assumes any value returned which is negative and
  30. * is a valid errno will mean setting the condition codes to indicate
  31. * an error return. This doesn't work, so we have this hook.
  32. */
  33. static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
  34. {
  35. regs->u_regs[UREG_I0] = error;
  36. regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
  37. regs->tpc = regs->tnpc;
  38. regs->tnpc += 4;
  39. }
  40. static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
  41. {
  42. regs->u_regs[UREG_I0] = value;
  43. regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
  44. regs->tpc = regs->tnpc;
  45. regs->tnpc += 4;
  46. }
  47. static inline void
  48. pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
  49. {
  50. if (test_thread_flag(TIF_32BIT)) {
  51. if (put_user(value, (unsigned int __user *) addr)) {
  52. pt_error_return(regs, EFAULT);
  53. return;
  54. }
  55. } else {
  56. if (put_user(value, (long __user *) addr)) {
  57. pt_error_return(regs, EFAULT);
  58. return;
  59. }
  60. }
  61. regs->u_regs[UREG_I0] = 0;
  62. regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
  63. regs->tpc = regs->tnpc;
  64. regs->tnpc += 4;
  65. }
  66. static void
  67. pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
  68. {
  69. if (current->personality == PER_SUNOS)
  70. pt_succ_return (regs, val);
  71. else
  72. pt_succ_return_linux (regs, val, addr);
  73. }
  74. /* #define ALLOW_INIT_TRACING */
  75. /* #define DEBUG_PTRACE */
  76. #ifdef DEBUG_PTRACE
  77. char *pt_rq [] = {
  78. /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
  79. /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
  80. /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
  81. /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
  82. /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
  83. /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
  84. /* 24 */ "SYSCALL", ""
  85. };
  86. #endif
  87. /*
  88. * Called by kernel/ptrace.c when detaching..
  89. *
  90. * Make sure single step bits etc are not set.
  91. */
  92. void ptrace_disable(struct task_struct *child)
  93. {
  94. /* nothing to do */
  95. }
  96. asmlinkage void do_ptrace(struct pt_regs *regs)
  97. {
  98. int request = regs->u_regs[UREG_I0];
  99. pid_t pid = regs->u_regs[UREG_I1];
  100. unsigned long addr = regs->u_regs[UREG_I2];
  101. unsigned long data = regs->u_regs[UREG_I3];
  102. unsigned long addr2 = regs->u_regs[UREG_I4];
  103. struct task_struct *child;
  104. int ret;
  105. if (test_thread_flag(TIF_32BIT)) {
  106. addr &= 0xffffffffUL;
  107. data &= 0xffffffffUL;
  108. addr2 &= 0xffffffffUL;
  109. }
  110. lock_kernel();
  111. #ifdef DEBUG_PTRACE
  112. {
  113. char *s;
  114. if ((request >= 0) && (request <= 24))
  115. s = pt_rq [request];
  116. else
  117. s = "unknown";
  118. if (request == PTRACE_POKEDATA && data == 0x91d02001){
  119. printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n",
  120. pid, addr, addr2);
  121. } else
  122. printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n",
  123. s, request, pid, addr, data, addr2);
  124. }
  125. #endif
  126. if (request == PTRACE_TRACEME) {
  127. int ret;
  128. /* are we already being traced? */
  129. if (current->ptrace & PT_PTRACED) {
  130. pt_error_return(regs, EPERM);
  131. goto out;
  132. }
  133. ret = security_ptrace(current->parent, current);
  134. if (ret) {
  135. pt_error_return(regs, -ret);
  136. goto out;
  137. }
  138. /* set the ptrace bit in the process flags. */
  139. current->ptrace |= PT_PTRACED;
  140. pt_succ_return(regs, 0);
  141. goto out;
  142. }
  143. #ifndef ALLOW_INIT_TRACING
  144. if (pid == 1) {
  145. /* Can't dork with init. */
  146. pt_error_return(regs, EPERM);
  147. goto out;
  148. }
  149. #endif
  150. read_lock(&tasklist_lock);
  151. child = find_task_by_pid(pid);
  152. if (child)
  153. get_task_struct(child);
  154. read_unlock(&tasklist_lock);
  155. if (!child) {
  156. pt_error_return(regs, ESRCH);
  157. goto out;
  158. }
  159. if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
  160. || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
  161. if (ptrace_attach(child)) {
  162. pt_error_return(regs, EPERM);
  163. goto out_tsk;
  164. }
  165. pt_succ_return(regs, 0);
  166. goto out_tsk;
  167. }
  168. ret = ptrace_check_attach(child, request == PTRACE_KILL);
  169. if (ret < 0) {
  170. pt_error_return(regs, -ret);
  171. goto out_tsk;
  172. }
  173. if (!(test_thread_flag(TIF_32BIT)) &&
  174. ((request == PTRACE_READDATA64) ||
  175. (request == PTRACE_WRITEDATA64) ||
  176. (request == PTRACE_READTEXT64) ||
  177. (request == PTRACE_WRITETEXT64) ||
  178. (request == PTRACE_PEEKTEXT64) ||
  179. (request == PTRACE_POKETEXT64) ||
  180. (request == PTRACE_PEEKDATA64) ||
  181. (request == PTRACE_POKEDATA64))) {
  182. addr = regs->u_regs[UREG_G2];
  183. addr2 = regs->u_regs[UREG_G3];
  184. request -= 30; /* wheee... */
  185. }
  186. switch(request) {
  187. case PTRACE_PEEKTEXT: /* read word at location addr. */
  188. case PTRACE_PEEKDATA: {
  189. unsigned long tmp64;
  190. unsigned int tmp32;
  191. int res, copied;
  192. res = -EIO;
  193. if (test_thread_flag(TIF_32BIT)) {
  194. copied = access_process_vm(child, addr,
  195. &tmp32, sizeof(tmp32), 0);
  196. tmp64 = (unsigned long) tmp32;
  197. if (copied == sizeof(tmp32))
  198. res = 0;
  199. } else {
  200. copied = access_process_vm(child, addr,
  201. &tmp64, sizeof(tmp64), 0);
  202. if (copied == sizeof(tmp64))
  203. res = 0;
  204. }
  205. if (res < 0)
  206. pt_error_return(regs, -res);
  207. else
  208. pt_os_succ_return(regs, tmp64, (void __user *) data);
  209. goto flush_and_out;
  210. }
  211. case PTRACE_POKETEXT: /* write the word at location addr. */
  212. case PTRACE_POKEDATA: {
  213. unsigned long tmp64;
  214. unsigned int tmp32;
  215. int copied, res = -EIO;
  216. if (test_thread_flag(TIF_32BIT)) {
  217. tmp32 = data;
  218. copied = access_process_vm(child, addr,
  219. &tmp32, sizeof(tmp32), 1);
  220. if (copied == sizeof(tmp32))
  221. res = 0;
  222. } else {
  223. tmp64 = data;
  224. copied = access_process_vm(child, addr,
  225. &tmp64, sizeof(tmp64), 1);
  226. if (copied == sizeof(tmp64))
  227. res = 0;
  228. }
  229. if (res < 0)
  230. pt_error_return(regs, -res);
  231. else
  232. pt_succ_return(regs, res);
  233. goto flush_and_out;
  234. }
  235. case PTRACE_GETREGS: {
  236. struct pt_regs32 __user *pregs =
  237. (struct pt_regs32 __user *) addr;
  238. struct pt_regs *cregs = child->thread_info->kregs;
  239. int rval;
  240. if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
  241. __put_user(cregs->tpc, (&pregs->pc)) ||
  242. __put_user(cregs->tnpc, (&pregs->npc)) ||
  243. __put_user(cregs->y, (&pregs->y))) {
  244. pt_error_return(regs, EFAULT);
  245. goto out_tsk;
  246. }
  247. for (rval = 1; rval < 16; rval++)
  248. if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
  249. pt_error_return(regs, EFAULT);
  250. goto out_tsk;
  251. }
  252. pt_succ_return(regs, 0);
  253. #ifdef DEBUG_PTRACE
  254. printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
  255. #endif
  256. goto out_tsk;
  257. }
  258. case PTRACE_GETREGS64: {
  259. struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
  260. struct pt_regs *cregs = child->thread_info->kregs;
  261. unsigned long tpc = cregs->tpc;
  262. int rval;
  263. if ((child->thread_info->flags & _TIF_32BIT) != 0)
  264. tpc &= 0xffffffff;
  265. if (__put_user(cregs->tstate, (&pregs->tstate)) ||
  266. __put_user(tpc, (&pregs->tpc)) ||
  267. __put_user(cregs->tnpc, (&pregs->tnpc)) ||
  268. __put_user(cregs->y, (&pregs->y))) {
  269. pt_error_return(regs, EFAULT);
  270. goto out_tsk;
  271. }
  272. for (rval = 1; rval < 16; rval++)
  273. if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
  274. pt_error_return(regs, EFAULT);
  275. goto out_tsk;
  276. }
  277. pt_succ_return(regs, 0);
  278. #ifdef DEBUG_PTRACE
  279. printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
  280. #endif
  281. goto out_tsk;
  282. }
  283. case PTRACE_SETREGS: {
  284. struct pt_regs32 __user *pregs =
  285. (struct pt_regs32 __user *) addr;
  286. struct pt_regs *cregs = child->thread_info->kregs;
  287. unsigned int psr, pc, npc, y;
  288. int i;
  289. /* Must be careful, tracing process can only set certain
  290. * bits in the psr.
  291. */
  292. if (__get_user(psr, (&pregs->psr)) ||
  293. __get_user(pc, (&pregs->pc)) ||
  294. __get_user(npc, (&pregs->npc)) ||
  295. __get_user(y, (&pregs->y))) {
  296. pt_error_return(regs, EFAULT);
  297. goto out_tsk;
  298. }
  299. cregs->tstate &= ~(TSTATE_ICC);
  300. cregs->tstate |= psr_to_tstate_icc(psr);
  301. if (!((pc | npc) & 3)) {
  302. cregs->tpc = pc;
  303. cregs->tnpc = npc;
  304. }
  305. cregs->y = y;
  306. for (i = 1; i < 16; i++) {
  307. if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
  308. pt_error_return(regs, EFAULT);
  309. goto out_tsk;
  310. }
  311. }
  312. pt_succ_return(regs, 0);
  313. goto out_tsk;
  314. }
  315. case PTRACE_SETREGS64: {
  316. struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
  317. struct pt_regs *cregs = child->thread_info->kregs;
  318. unsigned long tstate, tpc, tnpc, y;
  319. int i;
  320. /* Must be careful, tracing process can only set certain
  321. * bits in the psr.
  322. */
  323. if (__get_user(tstate, (&pregs->tstate)) ||
  324. __get_user(tpc, (&pregs->tpc)) ||
  325. __get_user(tnpc, (&pregs->tnpc)) ||
  326. __get_user(y, (&pregs->y))) {
  327. pt_error_return(regs, EFAULT);
  328. goto out_tsk;
  329. }
  330. if ((child->thread_info->flags & _TIF_32BIT) != 0) {
  331. tpc &= 0xffffffff;
  332. tnpc &= 0xffffffff;
  333. }
  334. tstate &= (TSTATE_ICC | TSTATE_XCC);
  335. cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
  336. cregs->tstate |= tstate;
  337. if (!((tpc | tnpc) & 3)) {
  338. cregs->tpc = tpc;
  339. cregs->tnpc = tnpc;
  340. }
  341. cregs->y = y;
  342. for (i = 1; i < 16; i++) {
  343. if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
  344. pt_error_return(regs, EFAULT);
  345. goto out_tsk;
  346. }
  347. }
  348. pt_succ_return(regs, 0);
  349. goto out_tsk;
  350. }
  351. case PTRACE_GETFPREGS: {
  352. struct fps {
  353. unsigned int regs[32];
  354. unsigned int fsr;
  355. unsigned int flags;
  356. unsigned int extra;
  357. unsigned int fpqd;
  358. struct fq {
  359. unsigned int insnaddr;
  360. unsigned int insn;
  361. } fpq[16];
  362. };
  363. struct fps __user *fps = (struct fps __user *) addr;
  364. unsigned long *fpregs = child->thread_info->fpregs;
  365. if (copy_to_user(&fps->regs[0], fpregs,
  366. (32 * sizeof(unsigned int))) ||
  367. __put_user(child->thread_info->xfsr[0], (&fps->fsr)) ||
  368. __put_user(0, (&fps->fpqd)) ||
  369. __put_user(0, (&fps->flags)) ||
  370. __put_user(0, (&fps->extra)) ||
  371. clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
  372. pt_error_return(regs, EFAULT);
  373. goto out_tsk;
  374. }
  375. pt_succ_return(regs, 0);
  376. goto out_tsk;
  377. }
  378. case PTRACE_GETFPREGS64: {
  379. struct fps {
  380. unsigned int regs[64];
  381. unsigned long fsr;
  382. };
  383. struct fps __user *fps = (struct fps __user *) addr;
  384. unsigned long *fpregs = child->thread_info->fpregs;
  385. if (copy_to_user(&fps->regs[0], fpregs,
  386. (64 * sizeof(unsigned int))) ||
  387. __put_user(child->thread_info->xfsr[0], (&fps->fsr))) {
  388. pt_error_return(regs, EFAULT);
  389. goto out_tsk;
  390. }
  391. pt_succ_return(regs, 0);
  392. goto out_tsk;
  393. }
  394. case PTRACE_SETFPREGS: {
  395. struct fps {
  396. unsigned int regs[32];
  397. unsigned int fsr;
  398. unsigned int flags;
  399. unsigned int extra;
  400. unsigned int fpqd;
  401. struct fq {
  402. unsigned int insnaddr;
  403. unsigned int insn;
  404. } fpq[16];
  405. };
  406. struct fps __user *fps = (struct fps __user *) addr;
  407. unsigned long *fpregs = child->thread_info->fpregs;
  408. unsigned fsr;
  409. if (copy_from_user(fpregs, &fps->regs[0],
  410. (32 * sizeof(unsigned int))) ||
  411. __get_user(fsr, (&fps->fsr))) {
  412. pt_error_return(regs, EFAULT);
  413. goto out_tsk;
  414. }
  415. child->thread_info->xfsr[0] &= 0xffffffff00000000UL;
  416. child->thread_info->xfsr[0] |= fsr;
  417. if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
  418. child->thread_info->gsr[0] = 0;
  419. child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
  420. pt_succ_return(regs, 0);
  421. goto out_tsk;
  422. }
  423. case PTRACE_SETFPREGS64: {
  424. struct fps {
  425. unsigned int regs[64];
  426. unsigned long fsr;
  427. };
  428. struct fps __user *fps = (struct fps __user *) addr;
  429. unsigned long *fpregs = child->thread_info->fpregs;
  430. if (copy_from_user(fpregs, &fps->regs[0],
  431. (64 * sizeof(unsigned int))) ||
  432. __get_user(child->thread_info->xfsr[0], (&fps->fsr))) {
  433. pt_error_return(regs, EFAULT);
  434. goto out_tsk;
  435. }
  436. if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
  437. child->thread_info->gsr[0] = 0;
  438. child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
  439. pt_succ_return(regs, 0);
  440. goto out_tsk;
  441. }
  442. case PTRACE_READTEXT:
  443. case PTRACE_READDATA: {
  444. int res = ptrace_readdata(child, addr,
  445. (char __user *)addr2, data);
  446. if (res == data) {
  447. pt_succ_return(regs, 0);
  448. goto flush_and_out;
  449. }
  450. if (res >= 0)
  451. res = -EIO;
  452. pt_error_return(regs, -res);
  453. goto flush_and_out;
  454. }
  455. case PTRACE_WRITETEXT:
  456. case PTRACE_WRITEDATA: {
  457. int res = ptrace_writedata(child, (char __user *) addr2,
  458. addr, data);
  459. if (res == data) {
  460. pt_succ_return(regs, 0);
  461. goto flush_and_out;
  462. }
  463. if (res >= 0)
  464. res = -EIO;
  465. pt_error_return(regs, -res);
  466. goto flush_and_out;
  467. }
  468. case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
  469. addr = 1;
  470. case PTRACE_CONT: { /* restart after signal. */
  471. if (data > _NSIG) {
  472. pt_error_return(regs, EIO);
  473. goto out_tsk;
  474. }
  475. if (request == PTRACE_SYSCALL) {
  476. set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  477. } else {
  478. clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  479. }
  480. child->exit_code = data;
  481. #ifdef DEBUG_PTRACE
  482. printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
  483. child->pid, child->exit_code,
  484. child->thread_info->kregs->tpc,
  485. child->thread_info->kregs->tnpc);
  486. #endif
  487. wake_up_process(child);
  488. pt_succ_return(regs, 0);
  489. goto out_tsk;
  490. }
  491. /*
  492. * make the child exit. Best I can do is send it a sigkill.
  493. * perhaps it should be put in the status that it wants to
  494. * exit.
  495. */
  496. case PTRACE_KILL: {
  497. if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
  498. pt_succ_return(regs, 0);
  499. goto out_tsk;
  500. }
  501. child->exit_code = SIGKILL;
  502. wake_up_process(child);
  503. pt_succ_return(regs, 0);
  504. goto out_tsk;
  505. }
  506. case PTRACE_SUNDETACH: { /* detach a process that was attached. */
  507. int error = ptrace_detach(child, data);
  508. if (error) {
  509. pt_error_return(regs, EIO);
  510. goto out_tsk;
  511. }
  512. pt_succ_return(regs, 0);
  513. goto out_tsk;
  514. }
  515. /* PTRACE_DUMPCORE unsupported... */
  516. default: {
  517. int err = ptrace_request(child, request, addr, data);
  518. if (err)
  519. pt_error_return(regs, -err);
  520. else
  521. pt_succ_return(regs, 0);
  522. goto out_tsk;
  523. }
  524. }
  525. flush_and_out:
  526. {
  527. unsigned long va;
  528. if (tlb_type == cheetah || tlb_type == cheetah_plus) {
  529. for (va = 0; va < (1 << 16); va += (1 << 5))
  530. spitfire_put_dcache_tag(va, 0x0);
  531. /* No need to mess with I-cache on Cheetah. */
  532. } else {
  533. for (va = 0; va < L1DCACHE_SIZE; va += 32)
  534. spitfire_put_dcache_tag(va, 0x0);
  535. if (request == PTRACE_PEEKTEXT ||
  536. request == PTRACE_POKETEXT ||
  537. request == PTRACE_READTEXT ||
  538. request == PTRACE_WRITETEXT) {
  539. for (va = 0; va < (PAGE_SIZE << 1); va += 32)
  540. spitfire_put_icache_tag(va, 0x0);
  541. __asm__ __volatile__("flush %g6");
  542. }
  543. }
  544. }
  545. out_tsk:
  546. if (child)
  547. put_task_struct(child);
  548. out:
  549. unlock_kernel();
  550. }
  551. asmlinkage void syscall_trace(void)
  552. {
  553. #ifdef DEBUG_PTRACE
  554. printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
  555. #endif
  556. if (!test_thread_flag(TIF_SYSCALL_TRACE))
  557. return;
  558. if (!(current->ptrace & PT_PTRACED))
  559. return;
  560. ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  561. ? 0x80 : 0));
  562. /*
  563. * this isn't the same as continuing with a signal, but it will do
  564. * for normal use. strace only continues with a signal if the
  565. * stopping signal is not SIGTRAP. -brl
  566. */
  567. #ifdef DEBUG_PTRACE
  568. printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
  569. current->pid, current->exit_code);
  570. #endif
  571. if (current->exit_code) {
  572. send_sig (current->exit_code, current, 1);
  573. current->exit_code = 0;
  574. }
  575. }