ptrace.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

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