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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/kernel/ptrace.c
  3.  *
  4.  *  By Ross Biro 1/23/92
  5.  * edited by Linus Torvalds
  6.  * ARM modifications Copyright (C) 2000 Russell King
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License version 2 as
  10.  * published by the Free Software Foundation.
  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/ptrace.h>
  18. #include <linux/user.h>
  19. #include <asm/uaccess.h>
  20. #include <asm/pgtable.h>
  21. #include <asm/system.h>
  22. #include "ptrace.h"
  23. #define REG_PC 15
  24. #define REG_PSR 16
  25. /*
  26.  * does not yet catch signals sent when the child dies.
  27.  * in exit.c or in signal.c.
  28.  */
  29. /*
  30.  * Breakpoint SWI instruction: SWI &9F0001
  31.  */
  32. #define BREAKINST 0xef9f0001
  33. /*
  34.  * Get the address of the live pt_regs for the specified task.
  35.  * These are saved onto the top kernel stack when the process
  36.  * is not running.
  37.  */
  38. static inline struct pt_regs *
  39. get_user_regs(struct task_struct *task)
  40. {
  41. return (struct pt_regs *)
  42. ((unsigned long)task + 8192 - sizeof(struct pt_regs));
  43. }
  44. /*
  45.  * this routine will get a word off of the processes privileged stack.
  46.  * the offset is how far from the base addr as stored in the THREAD.
  47.  * this routine assumes that all the privileged stacks are in our
  48.  * data space.
  49.  */
  50. static inline long get_stack_long(struct task_struct *task, int offset)
  51. {
  52. return get_user_regs(task)->uregs[offset];
  53. }
  54. /*
  55.  * this routine will put a word on the processes privileged stack.
  56.  * the offset is how far from the base addr as stored in the THREAD.
  57.  * this routine assumes that all the privileged stacks are in our
  58.  * data space.
  59.  */
  60. static inline int
  61. put_stack_long(struct task_struct *task, int offset, long data)
  62. {
  63. struct pt_regs newregs, *regs = get_user_regs(task);
  64. int ret = -EINVAL;
  65. newregs = *regs;
  66. newregs.uregs[offset] = data;
  67. if (valid_user_regs(&newregs)) {
  68. regs->uregs[offset] = data;
  69. ret = 0;
  70. }
  71. return ret;
  72. }
  73. static inline int
  74. read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res)
  75. {
  76. int copied;
  77. copied = access_process_vm(child, addr, res, sizeof(*res), 0);
  78. return copied != sizeof(*res) ? -EIO : 0;
  79. }
  80. static inline int
  81. write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val)
  82. {
  83. int copied;
  84. copied = access_process_vm(child, addr, &val, sizeof(val), 1);
  85. return copied != sizeof(val) ? -EIO : 0;
  86. }
  87. /*
  88.  * Get value of register `rn' (in the instruction)
  89.  */
  90. static unsigned long
  91. ptrace_getrn(struct task_struct *child, unsigned long insn)
  92. {
  93. unsigned int reg = (insn >> 16) & 15;
  94. unsigned long val;
  95. val = get_stack_long(child, reg);
  96. if (reg == 15)
  97. val = pc_pointer(val + 8);
  98. return val;
  99. }
  100. /*
  101.  * Get value of operand 2 (in an ALU instruction)
  102.  */
  103. static unsigned long
  104. ptrace_getaluop2(struct task_struct *child, unsigned long insn)
  105. {
  106. unsigned long val;
  107. int shift;
  108. int type;
  109. if (insn & 1 << 25) {
  110. val = insn & 255;
  111. shift = (insn >> 8) & 15;
  112. type = 3;
  113. } else {
  114. val = get_stack_long (child, insn & 15);
  115. if (insn & (1 << 4))
  116. shift = (int)get_stack_long (child, (insn >> 8) & 15);
  117. else
  118. shift = (insn >> 7) & 31;
  119. type = (insn >> 5) & 3;
  120. }
  121. switch (type) {
  122. case 0: val <<= shift; break;
  123. case 1: val >>= shift; break;
  124. case 2:
  125. val = (((signed long)val) >> shift);
  126. break;
  127. case 3:
  128.   val = (val >> shift) | (val << (32 - shift));
  129. break;
  130. }
  131. return val;
  132. }
  133. /*
  134.  * Get value of operand 2 (in a LDR instruction)
  135.  */
  136. static unsigned long
  137. ptrace_getldrop2(struct task_struct *child, unsigned long insn)
  138. {
  139. unsigned long val;
  140. int shift;
  141. int type;
  142. val = get_stack_long(child, insn & 15);
  143. shift = (insn >> 7) & 31;
  144. type = (insn >> 5) & 3;
  145. switch (type) {
  146. case 0: val <<= shift; break;
  147. case 1: val >>= shift; break;
  148. case 2:
  149. val = (((signed long)val) >> shift);
  150. break;
  151. case 3:
  152.   val = (val >> shift) | (val << (32 - shift));
  153. break;
  154. }
  155. return val;
  156. }
  157. static unsigned long
  158. get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
  159. {
  160. unsigned long alt = 0;
  161. switch (insn & 0x0e000000) {
  162. case 0x00000000:
  163. case 0x02000000: {
  164. /*
  165.  * data processing
  166.  */
  167. long aluop1, aluop2, ccbit;
  168. if ((insn & 0xf000) != 0xf000)
  169. break;
  170. aluop1 = ptrace_getrn(child, insn);
  171. aluop2 = ptrace_getaluop2(child, insn);
  172. ccbit  = get_stack_long(child, REG_PSR) & CC_C_BIT ? 1 : 0;
  173. switch (insn & 0x01e00000) {
  174. case 0x00000000: alt = aluop1 & aluop2; break;
  175. case 0x00200000: alt = aluop1 ^ aluop2; break;
  176. case 0x00400000: alt = aluop1 - aluop2; break;
  177. case 0x00600000: alt = aluop2 - aluop1; break;
  178. case 0x00800000: alt = aluop1 + aluop2; break;
  179. case 0x00a00000: alt = aluop1 + aluop2 + ccbit; break;
  180. case 0x00c00000: alt = aluop1 - aluop2 + ccbit; break;
  181. case 0x00e00000: alt = aluop2 - aluop1 + ccbit; break;
  182. case 0x01800000: alt = aluop1 | aluop2; break;
  183. case 0x01a00000: alt = aluop2; break;
  184. case 0x01c00000: alt = aluop1 & ~aluop2; break;
  185. case 0x01e00000: alt = ~aluop2; break;
  186. }
  187. break;
  188. }
  189. case 0x04000000:
  190. case 0x06000000:
  191. /*
  192.  * ldr
  193.  */
  194. if ((insn & 0x0010f000) == 0x0010f000) {
  195. unsigned long base;
  196. base = ptrace_getrn(child, insn);
  197. if (insn & 1 << 24) {
  198. long aluop2;
  199. if (insn & 0x02000000)
  200. aluop2 = ptrace_getldrop2(child, insn);
  201. else
  202. aluop2 = insn & 0xfff;
  203. if (insn & 1 << 23)
  204. base += aluop2;
  205. else
  206. base -= aluop2;
  207. }
  208. if (read_tsk_long(child, base, &alt) == 0)
  209. alt = pc_pointer(alt);
  210. }
  211. break;
  212. case 0x08000000:
  213. /*
  214.  * ldm
  215.  */
  216. if ((insn & 0x00108000) == 0x00108000) {
  217. unsigned long base;
  218. unsigned int nr_regs;
  219. if (insn & (1 << 23)) {
  220. nr_regs = insn & 65535;
  221. nr_regs = (nr_regs & 0x5555) + ((nr_regs & 0xaaaa) >> 1);
  222. nr_regs = (nr_regs & 0x3333) + ((nr_regs & 0xcccc) >> 2);
  223. nr_regs = (nr_regs & 0x0707) + ((nr_regs & 0x7070) >> 4);
  224. nr_regs = (nr_regs & 0x000f) + ((nr_regs & 0x0f00) >> 8);
  225. nr_regs <<= 2;
  226. if (!(insn & (1 << 24)))
  227. nr_regs -= 4;
  228. } else {
  229. if (insn & (1 << 24))
  230. nr_regs = -4;
  231. else
  232. nr_regs = 0;
  233. }
  234. base = ptrace_getrn(child, insn);
  235. if (read_tsk_long(child, base + nr_regs, &alt) == 0)
  236. alt = pc_pointer (alt);
  237. break;
  238. }
  239. break;
  240. case 0x0a000000: {
  241. /*
  242.  * bl or b
  243.  */
  244. signed long displ;
  245. /* It's a branch/branch link: instead of trying to
  246.  * figure out whether the branch will be taken or not,
  247.  * we'll put a breakpoint at both locations.  This is
  248.  * simpler, more reliable, and probably not a whole lot
  249.  * slower than the alternative approach of emulating the
  250.  * branch.
  251.  */
  252. displ = (insn & 0x00ffffff) << 8;
  253. displ = (displ >> 6) + 8;
  254. if (displ != 0 && displ != 4)
  255. alt = pc + displ;
  256.     }
  257.     break;
  258. }
  259. return alt;
  260. }
  261. static int
  262. add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr)
  263. {
  264. int nr = dbg->nsaved;
  265. int res = -EINVAL;
  266. if (nr < 2) {
  267. res = read_tsk_long(child, addr, &dbg->bp[nr].insn);
  268. if (res == 0)
  269. res = write_tsk_long(child, addr, BREAKINST);
  270. if (res == 0) {
  271. dbg->bp[nr].address = addr;
  272. dbg->nsaved += 1;
  273. }
  274. } else
  275. printk(KERN_ERR "ptrace: too many breakpointsn");
  276. return res;
  277. }
  278. int ptrace_set_bpt(struct task_struct *child)
  279. {
  280. struct pt_regs *regs;
  281. unsigned long pc, insn;
  282. int res;
  283. regs = get_user_regs(child);
  284. pc = instruction_pointer(regs);
  285. res = read_tsk_long(child, pc, &insn);
  286. if (!res) {
  287. struct debug_info *dbg = &child->thread.debug;
  288. unsigned long alt;
  289. dbg->nsaved = 0;
  290. alt = get_branch_address(child, pc, insn);
  291. if (alt)
  292. res = add_breakpoint(child, dbg, alt);
  293. /*
  294.  * Note that we ignore the result of setting the above
  295.  * breakpoint since it may fail.  When it does, this is
  296.  * not so much an error, but a forewarning that we may
  297.  * be receiving a prefetch abort shortly.
  298.  *
  299.  * If we don't set this breakpoint here, then we can
  300.  * loose control of the thread during single stepping.
  301.  */
  302. if (!alt || predicate(insn) != PREDICATE_ALWAYS)
  303. res = add_breakpoint(child, dbg, pc + 4);
  304. }
  305. return res;
  306. }
  307. /*
  308.  * Ensure no single-step breakpoint is pending.  Returns non-zero
  309.  * value if child was being single-stepped.
  310.  */
  311. void __ptrace_cancel_bpt(struct task_struct *child)
  312. {
  313. struct debug_info *dbg = &child->thread.debug;
  314. int i, nsaved = dbg->nsaved;
  315. dbg->nsaved = 0;
  316. if (nsaved > 2) {
  317. printk("ptrace_cancel_bpt: bogus nsaved: %d!n", nsaved);
  318. nsaved = 2;
  319. }
  320. for (i = 0; i < nsaved; i++) {
  321. unsigned long tmp;
  322. read_tsk_long(child, dbg->bp[i].address, &tmp);
  323. write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn);
  324. if (tmp != BREAKINST)
  325. printk(KERN_ERR "ptrace_cancel_bpt: weirdnessn");
  326. }
  327. }
  328. /*
  329.  * Called by kernel/ptrace.c when detaching..
  330.  *
  331.  * Make sure the single step bit is not set.
  332.  */
  333. void ptrace_disable(struct task_struct *child)
  334. {
  335. __ptrace_cancel_bpt(child);
  336. }
  337. static int do_ptrace(int request, struct task_struct *child, long addr, long data)
  338. {
  339. unsigned long tmp;
  340. int ret;
  341. switch (request) {
  342. /*
  343.  * read word at location "addr" in the child process.
  344.  */
  345. case PTRACE_PEEKTEXT:
  346. case PTRACE_PEEKDATA:
  347. ret = read_tsk_long(child, addr, &tmp);
  348. if (!ret)
  349. ret = put_user(tmp, (unsigned long *) data);
  350. break;
  351. /*
  352.  * read the word at location "addr" in the user registers.
  353.  */
  354. case PTRACE_PEEKUSR:
  355. ret = -EIO;
  356. if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
  357. break;
  358. tmp = 0;  /* Default return condition */
  359. if (addr < sizeof(struct pt_regs))
  360. tmp = get_stack_long(child, (int)addr >> 2);
  361. ret = put_user(tmp, (unsigned long *)data);
  362. break;
  363. /*
  364.  * write the word at location addr.
  365.  */
  366. case PTRACE_POKETEXT:
  367. case PTRACE_POKEDATA:
  368. ret = write_tsk_long(child, addr, data);
  369. break;
  370. /*
  371.  * write the word at location addr in the user registers.
  372.  */
  373. case PTRACE_POKEUSR:
  374. ret = -EIO;
  375. if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
  376. break;
  377. if (addr < sizeof(struct pt_regs))
  378. ret = put_stack_long(child, (int)addr >> 2, data);
  379. break;
  380. /*
  381.  * continue/restart and stop at next (return from) syscall
  382.  */
  383. case PTRACE_SYSCALL:
  384. case PTRACE_CONT:
  385. ret = -EIO;
  386. if ((unsigned long) data > _NSIG)
  387. break;
  388. if (request == PTRACE_SYSCALL)
  389. child->ptrace |= PT_TRACESYS;
  390. else
  391. child->ptrace &= ~PT_TRACESYS;
  392. child->exit_code = data;
  393. /* make sure single-step breakpoint is gone. */
  394. __ptrace_cancel_bpt(child);
  395. wake_up_process(child);
  396. ret = 0;
  397. break;
  398. /*
  399.  * make the child exit.  Best I can do is send it a sigkill.
  400.  * perhaps it should be put in the status that it wants to
  401.  * exit.
  402.  */
  403. case PTRACE_KILL:
  404. /* already dead */
  405. ret = 0;
  406. if (child->state == TASK_ZOMBIE)
  407. break;
  408. child->exit_code = SIGKILL;
  409. /* make sure single-step breakpoint is gone. */
  410. __ptrace_cancel_bpt(child);
  411. wake_up_process(child);
  412. ret = 0;
  413. break;
  414. /*
  415.  * execute single instruction.
  416.  */
  417. case PTRACE_SINGLESTEP:
  418. ret = -EIO;
  419. if ((unsigned long) data > _NSIG)
  420. break;
  421. child->thread.debug.nsaved = -1;
  422. child->ptrace &= ~PT_TRACESYS;
  423. child->exit_code = data;
  424. /* give it a chance to run. */
  425. wake_up_process(child);
  426. ret = 0;
  427. break;
  428. /*
  429.  * detach a process that was attached.
  430.  */
  431. case PTRACE_DETACH:
  432. ret = ptrace_detach(child, data);
  433. break;
  434. /*
  435.  * Get all gp regs from the child.
  436.  */
  437. case PTRACE_GETREGS: {
  438. struct pt_regs *regs = get_user_regs(child);
  439. ret = 0;
  440. if (copy_to_user((void *)data, regs,
  441.  sizeof(struct pt_regs)))
  442. ret = -EFAULT;
  443. break;
  444. }
  445. /*
  446.  * Set all gp regs in the child.
  447.  */
  448. case PTRACE_SETREGS: {
  449. struct pt_regs newregs;
  450. ret = -EFAULT;
  451. if (copy_from_user(&newregs, (void *)data,
  452.    sizeof(struct pt_regs)) == 0) {
  453. struct pt_regs *regs = get_user_regs(child);
  454. ret = -EINVAL;
  455. if (valid_user_regs(&newregs)) {
  456. *regs = newregs;
  457. ret = 0;
  458. }
  459. }
  460. break;
  461. }
  462. /*
  463.  * Get the child FPU state.
  464.  */
  465. case PTRACE_GETFPREGS:
  466. ret = -EIO;
  467. if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp)))
  468. break;
  469. /* we should check child->used_math here */
  470. ret = __copy_to_user((void *)data, &child->thread.fpstate,
  471.      sizeof(struct user_fp)) ? -EFAULT : 0;
  472. break;
  473. /*
  474.  * Set the child FPU state.
  475.  */
  476. case PTRACE_SETFPREGS:
  477. ret = -EIO;
  478. if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp)))
  479. break;
  480. child->used_math = 1;
  481. ret = __copy_from_user(&child->thread.fpstate, (void *)data,
  482.    sizeof(struct user_fp)) ? -EFAULT : 0;
  483. break;
  484. default:
  485. ret = -EIO;
  486. break;
  487. }
  488. return ret;
  489. }
  490. asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
  491. {
  492. struct task_struct *child;
  493. int ret;
  494. lock_kernel();
  495. ret = -EPERM;
  496. if (request == PTRACE_TRACEME) {
  497. /* are we already being traced? */
  498. if (current->ptrace & PT_PTRACED)
  499. goto out;
  500. /* set the ptrace bit in the process flags. */
  501. current->ptrace |= PT_PTRACED;
  502. ret = 0;
  503. goto out;
  504. }
  505. ret = -ESRCH;
  506. read_lock(&tasklist_lock);
  507. child = find_task_by_pid(pid);
  508. if (child)
  509. get_task_struct(child);
  510. read_unlock(&tasklist_lock);
  511. if (!child)
  512. goto out;
  513. ret = -EPERM;
  514. if (pid == 1) /* you may not mess with init */
  515. goto out_tsk;
  516. if (request == PTRACE_ATTACH) {
  517. ret = ptrace_attach(child);
  518. goto out_tsk;
  519. }
  520. ret = -ESRCH;
  521. if (!(child->ptrace & PT_PTRACED))
  522. goto out_tsk;
  523. if (child->state != TASK_STOPPED && request != PTRACE_KILL)
  524. goto out_tsk;
  525. if (child->p_pptr != current)
  526. goto out_tsk;
  527. ret = do_ptrace(request, child, addr, data);
  528. out_tsk:
  529. free_task_struct(child);
  530. out:
  531. unlock_kernel();
  532. return ret;
  533. }
  534. asmlinkage void syscall_trace(int why, struct pt_regs *regs)
  535. {
  536. unsigned long ip;
  537. if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
  538. != (PT_PTRACED|PT_TRACESYS))
  539. return;
  540. /*
  541.  * Save IP.  IP is used to denote syscall entry/exit:
  542.  *  IP = 0 -> entry, = 1 -> exit
  543.  */
  544. ip = regs->ARM_ip;
  545. regs->ARM_ip = why;
  546. /* the 0x80 provides a way for the tracing parent to distinguish
  547.    between a syscall stop and SIGTRAP delivery */
  548. current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  549. ? 0x80 : 0);
  550. current->state = TASK_STOPPED;
  551. notify_parent(current, SIGCHLD);
  552. schedule();
  553. /*
  554.  * this isn't the same as continuing with a signal, but it will do
  555.  * for normal use.  strace only continues with a signal if the
  556.  * stopping signal is not SIGTRAP.  -brl
  557.  */
  558. if (current->exit_code) {
  559. send_sig(current->exit_code, current, 1);
  560. current->exit_code = 0;
  561. }
  562. regs->ARM_ip = ip;
  563. }