ptrace.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * linux/arch/h8300/kernel/ptrace.c
  3. *
  4. * Yoshinori Sato <ysato@users.sourceforge.jp>
  5. *
  6. * Based on:
  7. * linux/arch/m68k/kernel/ptrace.c
  8. *
  9. * Copyright (C) 1994 by Hamish Macdonald
  10. * Taken from linux/kernel/ptrace.c and modified for M680x0.
  11. * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
  12. *
  13. * This file is subject to the terms and conditions of the GNU General
  14. * Public License. See the file COPYING in the main directory of
  15. * this archive for more details.
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/sched.h>
  19. #include <linux/mm.h>
  20. #include <linux/smp.h>
  21. #include <linux/smp_lock.h>
  22. #include <linux/errno.h>
  23. #include <linux/ptrace.h>
  24. #include <linux/user.h>
  25. #include <linux/config.h>
  26. #include <linux/signal.h>
  27. #include <asm/uaccess.h>
  28. #include <asm/page.h>
  29. #include <asm/pgtable.h>
  30. #include <asm/system.h>
  31. #include <asm/processor.h>
  32. #include <asm/signal.h>
  33. /* cpu depend functions */
  34. extern long h8300_get_reg(struct task_struct *task, int regno);
  35. extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data);
  36. extern void h8300_disable_trace(struct task_struct *child);
  37. extern void h8300_enable_trace(struct task_struct *child);
  38. /*
  39. * does not yet catch signals sent when the child dies.
  40. * in exit.c or in signal.c.
  41. */
  42. inline
  43. static int read_long(struct task_struct * tsk, unsigned long addr,
  44. unsigned long * result)
  45. {
  46. *result = *(unsigned long *)addr;
  47. return 0;
  48. }
  49. void ptrace_disable(struct task_struct *child)
  50. {
  51. h8300_disable_trace(child);
  52. }
  53. asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
  54. {
  55. struct task_struct *child;
  56. int ret;
  57. lock_kernel();
  58. ret = -EPERM;
  59. if (request == PTRACE_TRACEME) {
  60. /* are we already being traced? */
  61. if (current->ptrace & PT_PTRACED)
  62. goto out;
  63. /* set the ptrace bit in the process flags. */
  64. current->ptrace |= PT_PTRACED;
  65. ret = 0;
  66. goto out;
  67. }
  68. ret = -ESRCH;
  69. read_lock(&tasklist_lock);
  70. child = find_task_by_pid(pid);
  71. if (child)
  72. get_task_struct(child);
  73. read_unlock(&tasklist_lock);
  74. if (!child)
  75. goto out;
  76. ret = -EPERM;
  77. if (pid == 1) /* you may not mess with init */
  78. goto out_tsk;
  79. if (request == PTRACE_ATTACH) {
  80. ret = ptrace_attach(child);
  81. goto out_tsk;
  82. }
  83. ret = ptrace_check_attach(child, request == PTRACE_KILL);
  84. if (ret < 0)
  85. goto out_tsk;
  86. switch (request) {
  87. case PTRACE_PEEKTEXT: /* read word at location addr. */
  88. case PTRACE_PEEKDATA: {
  89. unsigned long tmp;
  90. ret = read_long(child, addr, &tmp);
  91. if (ret < 0)
  92. break ;
  93. ret = put_user(tmp, (unsigned long *) data);
  94. break ;
  95. }
  96. /* read the word at location addr in the USER area. */
  97. case PTRACE_PEEKUSR: {
  98. unsigned long tmp = 0;
  99. if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
  100. ret = -EIO;
  101. break ;
  102. }
  103. ret = 0; /* Default return condition */
  104. addr = addr >> 2; /* temporary hack. */
  105. if (addr < H8300_REGS_NO)
  106. tmp = h8300_get_reg(child, addr);
  107. else {
  108. switch(addr) {
  109. case 49:
  110. tmp = child->mm->start_code;
  111. break ;
  112. case 50:
  113. tmp = child->mm->start_data;
  114. break ;
  115. case 51:
  116. tmp = child->mm->end_code;
  117. break ;
  118. case 52:
  119. tmp = child->mm->end_data;
  120. break ;
  121. default:
  122. ret = -EIO;
  123. }
  124. }
  125. if (!ret)
  126. ret = put_user(tmp,(unsigned long *) data);
  127. break ;
  128. }
  129. /* when I and D space are separate, this will have to be fixed. */
  130. case PTRACE_POKETEXT: /* write the word at location addr. */
  131. case PTRACE_POKEDATA:
  132. ret = 0;
  133. if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
  134. break;
  135. ret = -EIO;
  136. break;
  137. case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
  138. if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
  139. ret = -EIO;
  140. break ;
  141. }
  142. addr = addr >> 2; /* temporary hack. */
  143. if (addr == PT_ORIG_ER0) {
  144. ret = -EIO;
  145. break ;
  146. }
  147. if (addr < H8300_REGS_NO) {
  148. ret = h8300_put_reg(child, addr, data);
  149. break ;
  150. }
  151. ret = -EIO;
  152. break ;
  153. case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
  154. case PTRACE_CONT: { /* restart after signal. */
  155. ret = -EIO;
  156. if (!valid_signal(data))
  157. break ;
  158. if (request == PTRACE_SYSCALL)
  159. set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  160. else
  161. clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  162. child->exit_code = data;
  163. wake_up_process(child);
  164. /* make sure the single step bit is not set. */
  165. h8300_disable_trace(child);
  166. ret = 0;
  167. }
  168. /*
  169. * make the child exit. Best I can do is send it a sigkill.
  170. * perhaps it should be put in the status that it wants to
  171. * exit.
  172. */
  173. case PTRACE_KILL: {
  174. ret = 0;
  175. if (child->exit_state == EXIT_ZOMBIE) /* already dead */
  176. break;
  177. child->exit_code = SIGKILL;
  178. h8300_disable_trace(child);
  179. wake_up_process(child);
  180. break;
  181. }
  182. case PTRACE_SINGLESTEP: { /* set the trap flag. */
  183. ret = -EIO;
  184. if (!valid_signal(data))
  185. break;
  186. clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  187. child->exit_code = data;
  188. h8300_enable_trace(child);
  189. wake_up_process(child);
  190. ret = 0;
  191. break;
  192. }
  193. case PTRACE_DETACH: /* detach a process that was attached. */
  194. ret = ptrace_detach(child, data);
  195. break;
  196. case PTRACE_GETREGS: { /* Get all gp regs from the child. */
  197. int i;
  198. unsigned long tmp;
  199. for (i = 0; i < H8300_REGS_NO; i++) {
  200. tmp = h8300_get_reg(child, i);
  201. if (put_user(tmp, (unsigned long *) data)) {
  202. ret = -EFAULT;
  203. break;
  204. }
  205. data += sizeof(long);
  206. }
  207. ret = 0;
  208. break;
  209. }
  210. case PTRACE_SETREGS: { /* Set all gp regs in the child. */
  211. int i;
  212. unsigned long tmp;
  213. for (i = 0; i < H8300_REGS_NO; i++) {
  214. if (get_user(tmp, (unsigned long *) data)) {
  215. ret = -EFAULT;
  216. break;
  217. }
  218. h8300_put_reg(child, i, tmp);
  219. data += sizeof(long);
  220. }
  221. ret = 0;
  222. break;
  223. }
  224. default:
  225. ret = -EIO;
  226. break;
  227. }
  228. out_tsk:
  229. put_task_struct(child);
  230. out:
  231. unlock_kernel();
  232. return ret;
  233. }
  234. asmlinkage void syscall_trace(void)
  235. {
  236. if (!test_thread_flag(TIF_SYSCALL_TRACE))
  237. return;
  238. if (!(current->ptrace & PT_PTRACED))
  239. return;
  240. ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  241. ? 0x80 : 0));
  242. /*
  243. * this isn't the same as continuing with a signal, but it will do
  244. * for normal use. strace only continues with a signal if the
  245. * stopping signal is not SIGTRAP. -brl
  246. */
  247. if (current->exit_code) {
  248. send_sig(current->exit_code, current, 1);
  249. current->exit_code = 0;
  250. }
  251. }