ptrace.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Kernel support for the ptrace() and syscall tracing interfaces.
  3.  *
  4.  * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
  5.  * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
  6.  * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
  7.  */
  8. #include <linux/kernel.h>
  9. #include <linux/sched.h>
  10. #include <linux/mm.h>
  11. #include <linux/smp.h>
  12. #include <linux/smp_lock.h>
  13. #include <linux/errno.h>
  14. #include <linux/ptrace.h>
  15. #include <linux/user.h>
  16. #include <linux/personality.h>
  17. #include <asm/uaccess.h>
  18. #include <asm/pgtable.h>
  19. #include <asm/system.h>
  20. #include <asm/processor.h>
  21. #include <asm/offset.h>
  22. /* These are used in entry.S, syscall_restore_rfi.  We need to record the
  23.  * current stepping mode somewhere other than in PSW, because there is no
  24.  * concept of saving and restoring the users PSW over a syscall.  We choose
  25.  * to use these two bits in task->ptrace.  These bits must not clash with
  26.  * any PT_* defined in include/linux/sched.h, and must match with the bit
  27.  * tests in entry.S
  28.  */
  29. #define PT_SINGLESTEP 0x10000
  30. #define PT_BLOCKSTEP 0x20000
  31. /* PSW bits we allow the debugger to modify */
  32. #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
  33. #undef DEBUG_PTRACE
  34. #ifdef DEBUG_PTRACE
  35. #define DBG(x) printk x
  36. #else
  37. #define DBG(x)
  38. #endif
  39. #ifdef __LP64__
  40. #define CHILD_IS_32BIT (child->personality == PER_LINUX_32BIT)
  41. /* This function is needed to translate 32 bit pt_regs offsets in to
  42.  * 64 bit pt_regs offsets.  For example, a 32 bit gdb under a 64 bit kernel
  43.  * will request offset 12 if it wants gr3, but the lower 32 bits of
  44.  * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4).
  45.  * This code relies on a 32 bit pt_regs being comprised of 32 bit values
  46.  * except for the fp registers which (a) are 64 bits, and (b) follow
  47.  * the gr registers at the start of pt_regs.  The 32 bit pt_regs should
  48.  * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[]
  49.  * being 64 bit in both cases.
  50.  */
  51. static long translate_usr_offset(long offset)
  52. {
  53. if (offset < 0)
  54. return -1;
  55. else if (offset <= 32*4) /* gr[0..31] */
  56. return offset * 2 + 4;
  57. else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
  58. return offset + 32*4;
  59. else if (offset < sizeof(struct pt_regs)/2 + 32*4)
  60. return offset * 2 + 4 - 32*8;
  61. else
  62. return -1;
  63. }
  64. #endif
  65. /*
  66.  * Called by kernel/ptrace.c when detaching..
  67.  *
  68.  * Make sure single step bits etc are not set.
  69.  */
  70. void ptrace_disable(struct task_struct *child)
  71. {
  72. /* make sure the trap bits are not set */
  73. pa_psw(child)->r = 0;
  74. pa_psw(child)->t = 0;
  75. pa_psw(child)->h = 0;
  76. pa_psw(child)->l = 0;
  77. }
  78. long sys_ptrace(long request, pid_t pid, long addr, long data)
  79. {
  80. struct task_struct *child;
  81. long ret;
  82. #ifdef DEBUG_PTRACE
  83. long oaddr=addr, odata=data;
  84. #endif
  85. lock_kernel();
  86. ret = -EPERM;
  87. if (request == PTRACE_TRACEME) {
  88. /* are we already being traced? */
  89. if (current->ptrace & PT_PTRACED)
  90. goto out;
  91. /* set the ptrace bit in the process flags. */
  92. current->ptrace |= PT_PTRACED;
  93. ret = 0;
  94. goto out;
  95. }
  96. ret = -ESRCH;
  97. read_lock(&tasklist_lock);
  98. child = find_task_by_pid(pid);
  99. if (child)
  100. get_task_struct(child);
  101. read_unlock(&tasklist_lock);
  102. if (!child)
  103. goto out;
  104. ret = -EPERM;
  105. if (pid == 1) /* no messing around with init! */
  106. goto out_tsk;
  107. if (request == PTRACE_ATTACH) {
  108. ret = ptrace_attach(child);
  109. goto out_tsk;
  110. }
  111. ret = -ESRCH;
  112. if (!(child->ptrace & PT_PTRACED))
  113. goto out_tsk;
  114. if (child->state != TASK_STOPPED) {
  115. if (request != PTRACE_KILL)
  116. goto out_tsk;
  117. }
  118. if (child->p_pptr != current)
  119. goto out_tsk;
  120. switch (request) {
  121. case PTRACE_PEEKTEXT: /* read word at location addr. */ 
  122. case PTRACE_PEEKDATA: {
  123. int copied;
  124. #ifdef __LP64__
  125. if (CHILD_IS_32BIT) {
  126. unsigned int tmp;
  127. addr &= 0xffffffffL;
  128. copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
  129. ret = -EIO;
  130. if (copied != sizeof(tmp))
  131. goto out_tsk;
  132. ret = put_user(tmp,(unsigned int *) data);
  133. DBG(("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %xn",
  134. request == PTRACE_PEEKTEXT ? "TEXT" : "DATA",
  135. pid, oaddr, odata, ret, tmp));
  136. }
  137. else
  138. #endif
  139. {
  140. unsigned long tmp;
  141. copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
  142. ret = -EIO;
  143. if (copied != sizeof(tmp))
  144. goto out_tsk;
  145. ret = put_user(tmp,(unsigned long *) data);
  146. }
  147. goto out_tsk;
  148. }
  149. /* when I and D space are separate, this will have to be fixed. */
  150. case PTRACE_POKETEXT: /* write the word at location addr. */
  151. case PTRACE_POKEDATA:
  152. ret = 0;
  153. #ifdef __LP64__
  154. if (CHILD_IS_32BIT) {
  155. unsigned int tmp = (unsigned int)data;
  156. DBG(("sys_ptrace(POKE%s, %d, %lx, %lx)n",
  157. request == PTRACE_POKETEXT ? "TEXT" : "DATA",
  158. pid, oaddr, odata));
  159. addr &= 0xffffffffL;
  160. if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp))
  161. goto out_tsk;
  162. }
  163. else
  164. #endif
  165. {
  166. if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
  167. goto out_tsk;
  168. }
  169. ret = -EIO;
  170. goto out_tsk;
  171. /* Read the word at location addr in the USER area.  For ptraced
  172.    processes, the kernel saves all regs on a syscall. */
  173. case PTRACE_PEEKUSR: {
  174. ret = -EIO;
  175. #ifdef __LP64__
  176. if (CHILD_IS_32BIT) {
  177. unsigned int tmp;
  178. if (addr & (sizeof(int)-1))
  179. goto out_tsk;
  180. if ((addr = translate_usr_offset(addr)) < 0)
  181. goto out_tsk;
  182. tmp = *(unsigned int *) ((char *) task_regs(child) + addr);
  183. ret = put_user(tmp, (unsigned int *) data);
  184. DBG(("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %xn",
  185. pid, oaddr, odata, ret, addr, tmp));
  186. }
  187. else
  188. #endif
  189. {
  190. unsigned long tmp;
  191. if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
  192. goto out_tsk;
  193. tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
  194. ret = put_user(tmp, (unsigned long *) data);
  195. }
  196. goto out_tsk;
  197. }
  198. /* Write the word at location addr in the USER area.  This will need
  199.    to change when the kernel no longer saves all regs on a syscall.
  200.    FIXME.  There is a problem at the moment in that r3-r18 are only
  201.    saved if the process is ptraced on syscall entry, and even then
  202.    those values are overwritten by actual register values on syscall
  203.    exit. */
  204. case PTRACE_POKEUSR:
  205. ret = -EIO;
  206. /* Some register values written here may be ignored in
  207.  * entry.S:syscall_restore_rfi; e.g. iaoq is written with
  208.  * r31/r31+4, and not with the values in pt_regs.
  209.  */
  210.  /* PT_PSW=0, so this is valid for 32 bit processes under 64
  211.  * bit kernels.
  212.  */
  213. if (addr == PT_PSW) {
  214. /* PT_PSW=0, so this is valid for 32 bit processes
  215.  * under 64 bit kernels.
  216.  *
  217.  * Allow writing to Nullify, Divide-step-correction,
  218.  * and carry/borrow bits.
  219.  * BEWARE, if you set N, and then single step, it wont
  220.  * stop on the nullified instruction.
  221.  */
  222. DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx)n",
  223. pid, oaddr, odata));
  224. data &= USER_PSW_BITS;
  225. task_regs(child)->gr[0] &= ~USER_PSW_BITS;
  226. task_regs(child)->gr[0] |= data;
  227. ret = 0;
  228. goto out_tsk;
  229. }
  230. #ifdef __LP64__
  231. if (CHILD_IS_32BIT) {
  232. if (addr & (sizeof(int)-1))
  233. goto out_tsk;
  234. if ((addr = translate_usr_offset(addr)) < 0)
  235. goto out_tsk;
  236. DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lxn",
  237. pid, oaddr, odata, addr));
  238. if (addr >= PT_FR0 && addr <= PT_FR31) {
  239. /* Special case, fp regs are 64 bits anyway */
  240. *(unsigned int *) ((char *) task_regs(child) + addr) = data;
  241. ret = 0;
  242. }
  243. else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
  244. addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 ||
  245. addr == PT_SAR+4) {
  246. /* Zero the top 32 bits */
  247. *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0;
  248. *(unsigned int *) ((char *) task_regs(child) + addr) = data;
  249. ret = 0;
  250. }
  251. goto out_tsk;
  252. }
  253. else
  254. #endif
  255. {
  256. if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
  257. goto out_tsk;
  258. if ((addr >= PT_GR1 && addr <= PT_GR31) ||
  259. addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
  260. (addr >= PT_FR0 && addr <= PT_FR31) ||
  261. addr == PT_SAR) {
  262. *(unsigned long *) ((char *) task_regs(child) + addr) = data;
  263. ret = 0;
  264. }
  265. goto out_tsk;
  266. }
  267. case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
  268. case PTRACE_CONT:
  269. ret = -EIO;
  270. DBG(("sys_ptrace(%s)n",
  271. request == PTRACE_SYSCALL ? "SYSCALL" : "CONT"));
  272. if ((unsigned long) data > _NSIG)
  273. goto out_tsk;
  274. child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
  275. if (request == PTRACE_SYSCALL)
  276. child->ptrace |= PT_TRACESYS;
  277. else
  278. child->ptrace &= ~PT_TRACESYS;
  279. child->exit_code = data;
  280. goto out_wake_notrap;
  281. case PTRACE_KILL:
  282. /*
  283.  * make the child exit.  Best I can do is send it a
  284.  * sigkill.  perhaps it should be put in the status
  285.  * that it wants to exit.
  286.  */
  287. DBG(("sys_ptrace(KILL)n"));
  288. if (child->state == TASK_ZOMBIE) /* already dead */
  289. goto out_tsk;
  290. child->exit_code = SIGKILL;
  291. goto out_wake_notrap;
  292. case PTRACE_SINGLEBLOCK:
  293. DBG(("sys_ptrace(SINGLEBLOCK)n"));
  294. ret = -EIO;
  295. if ((unsigned long) data > _NSIG)
  296. goto out_tsk;
  297. child->ptrace &= ~(PT_TRACESYS|PT_SINGLESTEP);
  298. child->ptrace |= PT_BLOCKSTEP;
  299. child->exit_code = data;
  300. /* Enable taken branch trap. */
  301. pa_psw(child)->r = 0;
  302. pa_psw(child)->t = 1;
  303. pa_psw(child)->h = 0;
  304. pa_psw(child)->l = 0;
  305. goto out_wake;
  306. case PTRACE_SINGLESTEP:
  307. DBG(("sys_ptrace(SINGLESTEP)n"));
  308. ret = -EIO;
  309. if ((unsigned long) data > _NSIG)
  310. goto out_tsk;
  311. child->ptrace &= ~(PT_TRACESYS|PT_BLOCKSTEP);
  312. child->ptrace |= PT_SINGLESTEP;
  313. child->exit_code = data;
  314. if (pa_psw(child)->n) {
  315. struct siginfo si;
  316. /* Nullified, just crank over the queue. */
  317. task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1];
  318. task_regs(child)->iasq[0] = task_regs(child)->iasq[1];
  319. task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4;
  320. pa_psw(child)->n = 0;
  321. pa_psw(child)->x = 0;
  322. pa_psw(child)->y = 0;
  323. pa_psw(child)->z = 0;
  324. pa_psw(child)->b = 0;
  325. ptrace_disable(child);
  326. /* Don't wake up the child, but let the
  327.    parent know something happened. */
  328. si.si_code = TRAP_TRACE;
  329. si.si_addr = (void *) (task_regs(child)->iaoq[0] & ~3);
  330. si.si_signo = SIGTRAP;
  331. si.si_errno = 0;
  332. force_sig_info(SIGTRAP, &si, child);
  333. //notify_parent(child, SIGCHLD);
  334. //ret = 0;
  335. goto out_wake;
  336. }
  337. /* Enable recovery counter traps.  The recovery counter
  338.  * itself will be set to zero on a task switch.  If the
  339.  * task is suspended on a syscall then the syscall return
  340.  * path will overwrite the recovery counter with a suitable
  341.  * value such that it traps once back in user space.  We
  342.  * disable interrupts in the childs PSW here also, to avoid
  343.  * interrupts while the recovery counter is decrementing.
  344.  */
  345. pa_psw(child)->r = 1;
  346. pa_psw(child)->t = 0;
  347. pa_psw(child)->h = 0;
  348. pa_psw(child)->l = 0;
  349. /* give it a chance to run. */
  350. goto out_wake;
  351. case PTRACE_DETACH:
  352. ret = ptrace_detach(child, data);
  353. goto out_tsk;
  354. default:
  355. ret = -EIO;
  356. goto out_tsk;
  357. }
  358. out_wake_notrap:
  359. ptrace_disable(child);
  360. out_wake:
  361. wake_up_process(child);
  362. ret = 0;
  363. out_tsk:
  364. free_task_struct(child);
  365. out:
  366. unlock_kernel();
  367. DBG(("sys_ptrace(%ld, %d, %lx, %lx) returning %ldn",
  368. request, pid, oaddr, odata, ret));
  369. return ret;
  370. }
  371. void syscall_trace(void)
  372. {
  373. if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
  374. (PT_PTRACED|PT_TRACESYS))
  375. return;
  376. current->exit_code = SIGTRAP;
  377. current->state = TASK_STOPPED;
  378. notify_parent(current, SIGCHLD);
  379. schedule();
  380. /*
  381.  * this isn't the same as continuing with a signal, but it will do
  382.  * for normal use.  strace only continues with a signal if the
  383.  * stopping signal is not SIGTRAP.  -brl
  384.  */
  385. if (current->exit_code) {
  386. send_sig(current->exit_code, current, 1);
  387. current->exit_code = 0;
  388. }
  389. }