ptrace.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * arch/v850/kernel/ptrace.c -- `ptrace' system call
  3. *
  4. * Copyright (C) 2002,03,04 NEC Electronics Corporation
  5. * Copyright (C) 2002,03,04 Miles Bader <miles@gnu.org>
  6. *
  7. * Derived from arch/mips/kernel/ptrace.c:
  8. *
  9. * Copyright (C) 1992 Ross Biro
  10. * Copyright (C) Linus Torvalds
  11. * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
  12. * Copyright (C) 1996 David S. Miller
  13. * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  14. * Copyright (C) 1999 MIPS Technologies, Inc.
  15. *
  16. * This file is subject to the terms and conditions of the GNU General
  17. * Public License. See the file COPYING in the main directory of this
  18. * archive for more details.
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/mm.h>
  22. #include <linux/sched.h>
  23. #include <linux/ptrace.h>
  24. #include <linux/signal.h>
  25. #include <asm/errno.h>
  26. #include <asm/ptrace.h>
  27. #include <asm/processor.h>
  28. #include <asm/uaccess.h>
  29. /* Returns the address where the register at REG_OFFS in P is stashed away. */
  30. static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t)
  31. {
  32. struct pt_regs *regs;
  33. /* Three basic cases:
  34. (1) A register normally saved before calling the scheduler, is
  35. available in the kernel entry pt_regs structure at the top
  36. of the kernel stack. The kernel trap/irq exit path takes
  37. care to save/restore almost all registers for ptrace'd
  38. processes.
  39. (2) A call-clobbered register, where the process P entered the
  40. kernel via [syscall] trap, is not stored anywhere; that's
  41. OK, because such registers are not expected to be preserved
  42. when the trap returns anyway (so we don't actually bother to
  43. test for this case).
  44. (3) A few registers not used at all by the kernel, and so
  45. normally never saved except by context-switches, are in the
  46. context switch state. */
  47. if (reg_offs == PT_CTPC || reg_offs == PT_CTPSW || reg_offs == PT_CTBP)
  48. /* Register saved during context switch. */
  49. regs = thread_saved_regs (t);
  50. else
  51. /* Register saved during kernel entry (or not available). */
  52. regs = task_pt_regs (t);
  53. return (v850_reg_t *)((char *)regs + reg_offs);
  54. }
  55. /* Set the bits SET and clear the bits CLEAR in the v850e DIR
  56. (`debug information register'). Returns the new value of DIR. */
  57. static inline v850_reg_t set_dir (v850_reg_t set, v850_reg_t clear)
  58. {
  59. register v850_reg_t rval asm ("r10");
  60. register v850_reg_t arg0 asm ("r6") = set;
  61. register v850_reg_t arg1 asm ("r7") = clear;
  62. /* The dbtrap handler has exactly this functionality when called
  63. from kernel mode. 0xf840 is a `dbtrap' insn. */
  64. asm (".short 0xf840" : "=r" (rval) : "r" (arg0), "r" (arg1));
  65. return rval;
  66. }
  67. /* Makes sure hardware single-stepping is (globally) enabled.
  68. Returns true if successful. */
  69. static inline int enable_single_stepping (void)
  70. {
  71. static int enabled = 0; /* Remember whether we already did it. */
  72. if (! enabled) {
  73. /* Turn on the SE (`single-step enable') bit, 0x100, in the
  74. DIR (`debug information register'). This may fail if a
  75. processor doesn't support it or something. We also try
  76. to clear bit 0x40 (`INI'), which is necessary to use the
  77. debug stuff on the v850e2; on the v850e, clearing 0x40
  78. shouldn't cause any problem. */
  79. v850_reg_t dir = set_dir (0x100, 0x40);
  80. /* Make sure it really got set. */
  81. if (dir & 0x100)
  82. enabled = 1;
  83. }
  84. return enabled;
  85. }
  86. /* Try to set CHILD's single-step flag to VAL. Returns true if successful. */
  87. static int set_single_step (struct task_struct *t, int val)
  88. {
  89. v850_reg_t *psw_addr = reg_save_addr(PT_PSW, t);
  90. if (val) {
  91. /* Make sure single-stepping is enabled. */
  92. if (! enable_single_stepping ())
  93. return 0;
  94. /* Set T's single-step flag. */
  95. *psw_addr |= 0x800;
  96. } else
  97. *psw_addr &= ~0x800;
  98. return 1;
  99. }
  100. long arch_ptrace(struct task_struct *child, long request, long addr, long data)
  101. {
  102. int rval;
  103. switch (request) {
  104. unsigned long val;
  105. case PTRACE_PEEKTEXT: /* read word at location addr. */
  106. case PTRACE_PEEKDATA:
  107. rval = generic_ptrace_peekdata(child, addr, data);
  108. goto out;
  109. case PTRACE_POKETEXT: /* write the word at location addr. */
  110. case PTRACE_POKEDATA:
  111. rval = generic_ptrace_pokedata(child, addr, data);
  112. goto out;
  113. /* Read/write the word at location ADDR in the registers. */
  114. case PTRACE_PEEKUSR:
  115. case PTRACE_POKEUSR:
  116. rval = 0;
  117. if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
  118. /* Special requests that don't actually correspond
  119. to offsets in struct pt_regs. */
  120. if (addr == PT_TEXT_ADDR)
  121. val = child->mm->start_code;
  122. else if (addr == PT_DATA_ADDR)
  123. val = child->mm->start_data;
  124. else if (addr == PT_TEXT_LEN)
  125. val = child->mm->end_code
  126. - child->mm->start_code;
  127. else
  128. rval = -EIO;
  129. } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
  130. v850_reg_t *reg_addr = reg_save_addr(addr, child);
  131. if (request == PTRACE_PEEKUSR)
  132. val = *reg_addr;
  133. else
  134. *reg_addr = data;
  135. } else
  136. rval = -EIO;
  137. if (rval == 0 && request == PTRACE_PEEKUSR)
  138. rval = put_user (val, (unsigned long *)data);
  139. goto out;
  140. /* Continue and stop at next (return from) syscall */
  141. case PTRACE_SYSCALL:
  142. /* Restart after a signal. */
  143. case PTRACE_CONT:
  144. /* Execute a single instruction. */
  145. case PTRACE_SINGLESTEP:
  146. rval = -EIO;
  147. if (!valid_signal(data))
  148. break;
  149. /* Turn CHILD's single-step flag on or off. */
  150. if (! set_single_step (child, request == PTRACE_SINGLESTEP))
  151. break;
  152. if (request == PTRACE_SYSCALL)
  153. set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  154. else
  155. clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  156. child->exit_code = data;
  157. wake_up_process(child);
  158. rval = 0;
  159. break;
  160. /*
  161. * make the child exit. Best I can do is send it a sigkill.
  162. * perhaps it should be put in the status that it wants to
  163. * exit.
  164. */
  165. case PTRACE_KILL:
  166. rval = 0;
  167. if (child->exit_state == EXIT_ZOMBIE) /* already dead */
  168. break;
  169. child->exit_code = SIGKILL;
  170. wake_up_process(child);
  171. break;
  172. case PTRACE_DETACH: /* detach a process that was attached. */
  173. set_single_step (child, 0); /* Clear single-step flag */
  174. rval = ptrace_detach(child, data);
  175. break;
  176. default:
  177. rval = -EIO;
  178. goto out;
  179. }
  180. out:
  181. return rval;
  182. }
  183. asmlinkage void syscall_trace(void)
  184. {
  185. if (!test_thread_flag(TIF_SYSCALL_TRACE))
  186. return;
  187. if (!(current->ptrace & PT_PTRACED))
  188. return;
  189. /* The 0x80 provides a way for the tracing parent to distinguish
  190. between a syscall stop and SIGTRAP delivery */
  191. ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  192. ? 0x80 : 0));
  193. /*
  194. * this isn't the same as continuing with a signal, but it will do
  195. * for normal use. strace only continues with a signal if the
  196. * stopping signal is not SIGTRAP. -brl
  197. */
  198. if (current->exit_code) {
  199. send_sig(current->exit_code, current, 1);
  200. current->exit_code = 0;
  201. }
  202. }
  203. void ptrace_disable (struct task_struct *child)
  204. {
  205. /* nothing to do */
  206. }