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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* ptrace.c */
  2. /* By Ross Biro 1/23/92 */
  3. /* edited by Linus Torvalds */
  4. /* mangled further by Bob Manson (manson@santafe.edu) */
  5. /* more mutilation by David Mosberger (davidm@azstarnet.com) */
  6. #include <linux/kernel.h>
  7. #include <linux/sched.h>
  8. #include <linux/mm.h>
  9. #include <linux/smp.h>
  10. #include <linux/smp_lock.h>
  11. #include <linux/errno.h>
  12. #include <linux/ptrace.h>
  13. #include <linux/user.h>
  14. #include <linux/slab.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/pgtable.h>
  17. #include <asm/system.h>
  18. #include <asm/fpu.h>
  19. #include "proto.h"
  20. #define DEBUG DBG_MEM
  21. #undef DEBUG
  22. #ifdef DEBUG
  23. enum {
  24. DBG_MEM = (1<<0),
  25. DBG_BPT = (1<<1),
  26. DBG_MEM_ALL = (1<<2)
  27. };
  28. #define DBG(fac,args) {if ((fac) & DEBUG) printk args;}
  29. #else
  30. #define DBG(fac,args)
  31. #endif
  32. #define BREAKINST 0x00000080 /* call_pal bpt */
  33. /*
  34.  * does not yet catch signals sent when the child dies.
  35.  * in exit.c or in signal.c.
  36.  */
  37. /*
  38.  * Processes always block with the following stack-layout:
  39.  *
  40.  *  +================================+ <---- task + 2*PAGE_SIZE
  41.  *  | PALcode saved frame (ps, pc,   | ^
  42.  *  | gp, a0, a1, a2)      | |
  43.  *  +================================+ | struct pt_regs
  44.  *  |               | |
  45.  *  | frame generated by SAVE_ALL    | |
  46.  *  |               | v
  47.  *  +================================+
  48.  *  |               | ^
  49.  *  | frame saved by do_switch_stack | | struct switch_stack
  50.  *  |               | v
  51.  *  +================================+
  52.  */
  53. /* 
  54.  * The following table maps a register index into the stack offset at
  55.  * which the register is saved.  Register indices are 0-31 for integer
  56.  * regs, 32-63 for fp regs, and 64 for the pc.  Notice that sp and
  57.  * zero have no stack-slot and need to be treated specially (see
  58.  * get_reg/put_reg below).
  59.  */
  60. enum {
  61. REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
  62. };
  63. static int regoff[] = {
  64. PT_REG(    r0), PT_REG(    r1), PT_REG(    r2), PT_REG(   r3),
  65. PT_REG(    r4), PT_REG(    r5), PT_REG(    r6), PT_REG(   r7),
  66. PT_REG(    r8), SW_REG(    r9), SW_REG(   r10), SW_REG(  r11),
  67. SW_REG(   r12), SW_REG(   r13), SW_REG(   r14), SW_REG(  r15),
  68. PT_REG(   r16), PT_REG(   r17), PT_REG(   r18), PT_REG(  r19),
  69. PT_REG(   r20), PT_REG(   r21), PT_REG(   r22), PT_REG(  r23),
  70. PT_REG(   r24), PT_REG(   r25), PT_REG(   r26), PT_REG(  r27),
  71. PT_REG(   r28), PT_REG(    gp),    -1,    -1,
  72. SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
  73. SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
  74. SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
  75. SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
  76. SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
  77. SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
  78. SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
  79. SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
  80. PT_REG(    pc)
  81. };
  82. static long zero;
  83. /*
  84.  * Get address of register REGNO in task TASK.
  85.  */
  86. static long *
  87. get_reg_addr(struct task_struct * task, unsigned long regno)
  88. {
  89. long *addr;
  90. if (regno == 30) {
  91. addr = &task->thread.usp;
  92. } else if (regno == 31 || regno > 64) {
  93. zero = 0;
  94. addr = &zero;
  95. } else {
  96. addr = (long *)((long)task + regoff[regno]);
  97. }
  98. return addr;
  99. }
  100. /*
  101.  * Get contents of register REGNO in task TASK.
  102.  */
  103. static long
  104. get_reg(struct task_struct * task, unsigned long regno)
  105. {
  106. /* Special hack for fpcr -- combine hardware and software bits.  */
  107. if (regno == 63) {
  108. unsigned long fpcr = *get_reg_addr(task, regno);
  109. unsigned long swcr = task->thread.flags & IEEE_SW_MASK;
  110. swcr = swcr_update_status(swcr, fpcr);
  111. return fpcr | swcr;
  112. }
  113. return *get_reg_addr(task, regno);
  114. }
  115. /*
  116.  * Write contents of register REGNO in task TASK.
  117.  */
  118. static int
  119. put_reg(struct task_struct *task, unsigned long regno, long data)
  120. {
  121. if (regno == 63) {
  122. task->thread.flags = ((task->thread.flags & ~IEEE_SW_MASK)
  123.       | (data & IEEE_SW_MASK));
  124. data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
  125. }
  126. *get_reg_addr(task, regno) = data;
  127. return 0;
  128. }
  129. static inline int
  130. read_int(struct task_struct *task, unsigned long addr, int * data)
  131. {
  132. int copied = access_process_vm(task, addr, data, sizeof(int), 0);
  133. return (copied == sizeof(int)) ? 0 : -EIO;
  134. }
  135. static inline int
  136. write_int(struct task_struct *task, unsigned long addr, int data)
  137. {
  138. int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
  139. return (copied == sizeof(int)) ? 0 : -EIO;
  140. }
  141. /*
  142.  * Set breakpoint.
  143.  */
  144. int
  145. ptrace_set_bpt(struct task_struct * child)
  146. {
  147. int displ, i, res, reg_b, nsaved = 0;
  148. u32 insn, op_code;
  149. unsigned long pc;
  150. pc  = get_reg(child, REG_PC);
  151. res = read_int(child, pc, &insn);
  152. if (res < 0)
  153. return res;
  154. op_code = insn >> 26;
  155. if (op_code >= 0x30) {
  156. /*
  157.  * It's a branch: instead of trying to figure out
  158.  * whether the branch will be taken or not, we'll put
  159.  * a breakpoint at either location.  This is simpler,
  160.  * more reliable, and probably not a whole lot slower
  161.  * than the alternative approach of emulating the
  162.  * branch (emulation can be tricky for fp branches).
  163.  */
  164. displ = ((s32)(insn << 11)) >> 9;
  165. child->thread.bpt_addr[nsaved++] = pc + 4;
  166. if (displ) /* guard against unoptimized code */
  167. child->thread.bpt_addr[nsaved++] = pc + 4 + displ;
  168. DBG(DBG_BPT, ("execing branchn"));
  169. } else if (op_code == 0x1a) {
  170. reg_b = (insn >> 16) & 0x1f;
  171. child->thread.bpt_addr[nsaved++] = get_reg(child, reg_b);
  172. DBG(DBG_BPT, ("execing jumpn"));
  173. } else {
  174. child->thread.bpt_addr[nsaved++] = pc + 4;
  175. DBG(DBG_BPT, ("execing normal insnn"));
  176. }
  177. /* install breakpoints: */
  178. for (i = 0; i < nsaved; ++i) {
  179. res = read_int(child, child->thread.bpt_addr[i], &insn);
  180. if (res < 0)
  181. return res;
  182. child->thread.bpt_insn[i] = insn;
  183. DBG(DBG_BPT, ("    -> next_pc=%lxn", child->thread.bpt_addr[i]));
  184. res = write_int(child, child->thread.bpt_addr[i], BREAKINST);
  185. if (res < 0)
  186. return res;
  187. }
  188. child->thread.bpt_nsaved = nsaved;
  189. return 0;
  190. }
  191. /*
  192.  * Ensure no single-step breakpoint is pending.  Returns non-zero
  193.  * value if child was being single-stepped.
  194.  */
  195. int
  196. ptrace_cancel_bpt(struct task_struct * child)
  197. {
  198. int i, nsaved = child->thread.bpt_nsaved;
  199. child->thread.bpt_nsaved = 0;
  200. if (nsaved > 2) {
  201. printk("ptrace_cancel_bpt: bogus nsaved: %d!n", nsaved);
  202. nsaved = 2;
  203. }
  204. for (i = 0; i < nsaved; ++i) {
  205. write_int(child, child->thread.bpt_addr[i],
  206.   child->thread.bpt_insn[i]);
  207. }
  208. return (nsaved != 0);
  209. }
  210. /*
  211.  * Called by kernel/ptrace.c when detaching..
  212.  *
  213.  * Make sure the single step bit is not set.
  214.  */
  215. void ptrace_disable(struct task_struct *child)
  216. ptrace_cancel_bpt(child);
  217. }
  218. asmlinkage long
  219. sys_ptrace(long request, long pid, long addr, long data,
  220.    int a4, int a5, struct pt_regs regs)
  221. {
  222. struct task_struct *child;
  223. long ret;
  224. lock_kernel();
  225. DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lxn",
  226.       request, pid, addr, data));
  227. ret = -EPERM;
  228. if (request == PTRACE_TRACEME) {
  229. /* are we already being traced? */
  230. if (current->ptrace & PT_PTRACED)
  231. goto out_notsk;
  232. /* set the ptrace bit in the process ptrace flags. */
  233. current->ptrace |= PT_PTRACED;
  234. ret = 0;
  235. goto out_notsk;
  236. }
  237. if (pid == 1) /* you may not mess with init */
  238. goto out_notsk;
  239. ret = -ESRCH;
  240. read_lock(&tasklist_lock);
  241. child = find_task_by_pid(pid);
  242. if (child)
  243. get_task_struct(child);
  244. read_unlock(&tasklist_lock);
  245. if (!child)
  246. goto out_notsk;
  247. if (request == PTRACE_ATTACH) {
  248. ret = ptrace_attach(child);
  249. goto out;
  250. }
  251. ret = -ESRCH;
  252. if (!(child->ptrace & PT_PTRACED)) {
  253. DBG(DBG_MEM, ("child not tracedn"));
  254. goto out;
  255. }
  256. if (child->state != TASK_STOPPED) {
  257. DBG(DBG_MEM, ("child process not stoppedn"));
  258. if (request != PTRACE_KILL)
  259. goto out;
  260. }
  261. if (child->p_pptr != current) {
  262. DBG(DBG_MEM, ("child not parent of this processn"));
  263. goto out;
  264. }
  265. switch (request) {
  266. /* When I and D space are separate, these will need to be fixed.  */
  267. case PTRACE_PEEKTEXT: /* read word at location addr. */
  268. case PTRACE_PEEKDATA: {
  269. unsigned long tmp;
  270. int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
  271. ret = -EIO;
  272. if (copied != sizeof(tmp))
  273. goto out;
  274. regs.r0 = 0; /* special return: no errors */
  275. ret = tmp;
  276. goto out;
  277. }
  278. /* Read register number ADDR. */
  279. case PTRACE_PEEKUSR:
  280. regs.r0 = 0; /* special return: no errors */
  281. ret = get_reg(child, addr);
  282. DBG(DBG_MEM, ("peek $%ld->%#lxn", addr, ret));
  283. goto out;
  284. /* When I and D space are separate, this will have to be fixed.  */
  285. case PTRACE_POKETEXT: /* write the word at location addr. */
  286. case PTRACE_POKEDATA: {
  287. unsigned long tmp = data;
  288. int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
  289. ret = (copied == sizeof(tmp)) ? 0 : -EIO;
  290. goto out;
  291. }
  292. case PTRACE_POKEUSR: /* write the specified register */
  293. DBG(DBG_MEM, ("poke $%ld<-%#lxn", addr, data));
  294. ret = put_reg(child, addr, data);
  295. goto out;
  296. case PTRACE_SYSCALL: /* continue and stop at next
  297. (return from) syscall */
  298. case PTRACE_CONT:    /* restart after signal. */
  299. ret = -EIO;
  300. if ((unsigned long) data > _NSIG)
  301. goto out;
  302. if (request == PTRACE_SYSCALL)
  303. child->ptrace |= PT_TRACESYS;
  304. else
  305. child->ptrace &= ~PT_TRACESYS;
  306. child->exit_code = data;
  307. wake_up_process(child);
  308. /* make sure single-step breakpoint is gone. */
  309. ptrace_cancel_bpt(child);
  310. ret = data;
  311. goto out;
  312. /*
  313.  * Make the child exit.  Best I can do is send it a sigkill.
  314.  * perhaps it should be put in the status that it wants to
  315.  * exit.
  316.  */
  317. case PTRACE_KILL:
  318. if (child->state != TASK_ZOMBIE) {
  319. wake_up_process(child);
  320. child->exit_code = SIGKILL;
  321. }
  322. /* make sure single-step breakpoint is gone. */
  323. ptrace_cancel_bpt(child);
  324. ret = 0;
  325. goto out;
  326. case PTRACE_SINGLESTEP:  /* execute single instruction. */
  327. ret = -EIO;
  328. if ((unsigned long) data > _NSIG)
  329. goto out;
  330. child->thread.bpt_nsaved = -1; /* mark single-stepping */
  331. child->ptrace &= ~PT_TRACESYS;
  332. wake_up_process(child);
  333. child->exit_code = data;
  334. /* give it a chance to run. */
  335. ret = 0;
  336. goto out;
  337. case PTRACE_DETACH:  /* detach a process that was attached. */
  338. ret = ptrace_detach(child, data);
  339. goto out;
  340. default:
  341. ret = -EIO;
  342. goto out;
  343. }
  344.  out:
  345. free_task_struct(child);
  346.  out_notsk:
  347. unlock_kernel();
  348. return ret;
  349. }
  350. asmlinkage void
  351. syscall_trace(void)
  352. {
  353. if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
  354.     != (PT_PTRACED|PT_TRACESYS))
  355. return;
  356. current->exit_code = SIGTRAP;
  357. current->state = TASK_STOPPED;
  358. notify_parent(current, SIGCHLD);
  359. schedule();
  360. /*
  361.  * This isn't the same as continuing with a signal, but it will do
  362.  * for normal use.  strace only continues with a signal if the
  363.  * stopping signal is not SIGTRAP.  -brl
  364.  */
  365. if (current->exit_code) {
  366. send_sig(current->exit_code, current, 1);
  367. current->exit_code = 0;
  368. }
  369. }