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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/ppc64/kernel/ptrace32.c
  3.  *
  4.  *  PowerPC version
  5.  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  6.  *
  7.  *  Derived from "arch/m68k/kernel/ptrace.c"
  8.  *  Copyright (C) 1994 by Hamish Macdonald
  9.  *  Taken from linux/kernel/ptrace.c and modified for M680x0.
  10.  *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
  11.  *
  12.  * Modified by Cort Dougan (cort@hq.fsmlabs.com)
  13.  * and Paul Mackerras (paulus@linuxcare.com.au).
  14.  *
  15.  * This file is subject to the terms and conditions of the GNU General
  16.  * Public License.  See the file README.legal in the main directory of
  17.  * this archive for more details.
  18.  */
  19. #include <linux/kernel.h>
  20. #include <linux/sched.h>
  21. #include <linux/mm.h>
  22. #include <linux/smp.h>
  23. #include <linux/smp_lock.h>
  24. #include <linux/errno.h>
  25. #include <linux/ptrace.h>
  26. #include <linux/user.h>
  27. #include <asm/uaccess.h>
  28. #include <asm/page.h>
  29. #include <asm/pgtable.h>
  30. #include <asm/system.h>
  31. /*
  32.  * Set of msr bits that gdb can change on behalf of a process.
  33.  */
  34. #define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
  35. /*
  36.  * does not yet catch signals sent when the child dies.
  37.  * in exit.c or in signal.c.
  38.  */
  39. /*
  40.  * Get contents of register REGNO in task TASK.
  41.  */
  42. static inline unsigned long get_reg(struct task_struct *task, int regno)
  43. {
  44. if (regno < sizeof(struct pt_regs) / sizeof(unsigned long))
  45. return ((unsigned long *)task->thread.regs)[regno];
  46. return (0);
  47. }
  48. /*
  49.  * Write contents of register REGNO in task TASK.
  50.  * (Put DATA into task TASK's register REGNO.)
  51.  */
  52. static inline int put_reg(struct task_struct *task, int regno, unsigned long data)
  53. {
  54. if (regno < PT_SOFTE) 
  55.   {
  56. if (regno == PT_MSR)
  57. data = (data & MSR_DEBUGCHANGE) | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
  58. ((unsigned long *)task->thread.regs)[regno] = data;
  59. return 0;
  60. }
  61. return -EIO;
  62. }
  63. static inline void
  64. set_single_step(struct task_struct *task)
  65. {
  66. struct pt_regs *regs = task->thread.regs;
  67. if (regs != NULL)
  68. regs->msr |= MSR_SE;
  69. }
  70. static inline void
  71. clear_single_step(struct task_struct *task)
  72. {
  73. struct pt_regs *regs = task->thread.regs;
  74. if (regs != NULL)
  75. regs->msr &= ~MSR_SE;
  76. }
  77. int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
  78. {
  79. struct task_struct *child;
  80. int ret = -EPERM;
  81. lock_kernel();
  82. if (request == PTRACE_TRACEME) {
  83. /* are we already being traced? */
  84. if (current->ptrace & PT_PTRACED)
  85. goto out;
  86. /* set the ptrace bit in the process flags. */
  87. current->ptrace |= PT_PTRACED;
  88. ret = 0;
  89. goto out;
  90. }
  91. ret = -ESRCH;
  92. read_lock(&tasklist_lock);
  93. child = find_task_by_pid(pid);
  94. if (child)
  95. get_task_struct(child);
  96. read_unlock(&tasklist_lock);
  97. if (!child)
  98. goto out;
  99. ret = -EPERM;
  100. if (pid == 1) /* you may not mess with init */
  101. goto out_tsk;
  102. if (request == PTRACE_ATTACH) {
  103. ret = ptrace_attach(child);
  104. goto out_tsk;
  105. }
  106. ret = ptrace_check_attach(child, request == PTRACE_KILL);
  107. if (ret < 0)
  108. goto out_tsk;
  109. switch (request) {
  110. /* Read word at location ADDR */
  111. /* when I and D space are separate, these will need to be fixed. */
  112. case PTRACE_PEEKTEXT: /* read word at location addr. */ 
  113. case PTRACE_PEEKDATA: 
  114. {
  115. unsigned int  tmp_mem_value;
  116. int copied;
  117. copied = access_process_vm(child, addr, &tmp_mem_value, sizeof(tmp_mem_value), 0);
  118. ret = -EIO;
  119. if (copied != sizeof(tmp_mem_value))
  120. break;
  121. ret = put_user(tmp_mem_value, (u32*)data);  // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
  122. break;
  123. }
  124. /*
  125.  * Read 4 bytes of the other process' storage
  126.  *  data is a pointer specifying where the user wants the
  127.  * 4 bytes copied into
  128.  *  addr is a pointer in the user's storage that contains an 8 byte
  129.  * address in the other process of the 4 bytes that is to be read
  130.  * (this is run in a 32-bit process looking at a 64-bit process)
  131.  * when I and D space are separate, these will need to be fixed.
  132.  */
  133. case PPC_PTRACE_PEEKTEXT_3264:
  134. case PPC_PTRACE_PEEKDATA_3264: 
  135. {
  136. u32  tmp_mem_value;
  137. int  copied;
  138. u32* addrOthers;
  139. ret = -EIO;
  140. /* Get the addr in the other process that we want to read */
  141. if (get_user(addrOthers, (u32**)addr) != 0)
  142. break;
  143. copied = access_process_vm(child, (u64)addrOthers, &tmp_mem_value, sizeof(tmp_mem_value), 0);
  144. if (copied != sizeof(tmp_mem_value))
  145. break;
  146. ret = put_user(tmp_mem_value, (u32*)data);  // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
  147. break;
  148. }
  149. /* Read a register (specified by ADDR) out of the "user area" */
  150. case PTRACE_PEEKUSR: {
  151. int index;
  152. unsigned int reg32bits;
  153. unsigned long tmp_reg_value;
  154. ret = -EIO;
  155. /* convert to index and check */
  156. index = (unsigned long) addr >> 2;
  157. if ((addr & 3) || (index > PT_FPSCR32))
  158. break;
  159. if (index < PT_FPR0) {
  160. tmp_reg_value = get_reg(child,  index);
  161. } else {
  162. if (child->thread.regs->msr & MSR_FP)
  163. giveup_fpu(child);
  164. /*
  165.  * the user space code considers the floating point
  166.  * to be an array of unsigned int (32 bits) - the
  167.  * index passed in is based on this assumption.
  168.  */
  169. tmp_reg_value = ((unsigned int *)child->thread.fpr)[index - PT_FPR0];
  170. }
  171. reg32bits = tmp_reg_value;
  172. ret = put_user(reg32bits, (u32*)data);  // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
  173. break;
  174. }
  175.   
  176. /*
  177.  * Read 4 bytes out of the other process' pt_regs area
  178.  *  data is a pointer specifying where the user wants the
  179.  * 4 bytes copied into
  180.  *  addr is the offset into the other process' pt_regs structure
  181.  * that is to be read
  182.  * (this is run in a 32-bit process looking at a 64-bit process)
  183.  */
  184. case PPC_PTRACE_PEEKUSR_3264: {
  185. u32 index;
  186. u32 reg32bits;
  187. u64 tmp_reg_value;
  188. u32 numReg;
  189. u32 part;
  190. ret = -EIO;
  191. /* Determine which register the user wants */
  192. index = (u64)addr >> 2;  /* Divide addr by 4 */
  193. numReg = index / 2;
  194. /* Determine which part of the register the user wants */
  195. if (index % 2)
  196. part = 1;  /* want the 2nd half of the register (right-most). */
  197. else
  198. part = 0;  /* want the 1st half of the register (left-most). */
  199. /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
  200. if ((addr & 3) || numReg > PT_FPSCR)
  201. break;
  202. if (numReg >= PT_FPR0) {
  203. if (child->thread.regs->msr & MSR_FP)
  204. giveup_fpu(child);
  205.         if (numReg == PT_FPSCR) 
  206.         tmp_reg_value = ((unsigned int *)child->thread.fpscr);
  207.         else 
  208.         tmp_reg_value = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
  209. } else { /* register within PT_REGS struct */
  210.     tmp_reg_value = get_reg(child, numReg);
  211.                 reg32bits = ((u32*)&tmp_reg_value)[part];
  212. ret = put_user(reg32bits, (u32*)data);  /* copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". */
  213. break;
  214. }
  215. /* Write the word at location ADDR */
  216. /* If I and D space are separate, this will have to be fixed. */
  217. case PTRACE_POKETEXT: /* write the word at location addr. */
  218. case PTRACE_POKEDATA: {
  219. unsigned int tmp_value_to_write;
  220. tmp_value_to_write =  data;
  221. ret = 0;
  222. if (access_process_vm(child, addr, &tmp_value_to_write, sizeof(tmp_value_to_write), 1) == sizeof(tmp_value_to_write))
  223. break;
  224. ret = -EIO;
  225. break;
  226. }
  227. /*
  228.  * Write 4 bytes into the other process' storage
  229.  *  data is the 4 bytes that the user wants written
  230.  *  addr is a pointer in the user's storage that contains an
  231.  * 8 byte address in the other process where the 4 bytes
  232.  * that is to be written
  233.  * (this is run in a 32-bit process looking at a 64-bit process)
  234.  * when I and D space are separate, these will need to be fixed.
  235.  */
  236. case PPC_PTRACE_POKETEXT_3264:
  237. case PPC_PTRACE_POKEDATA_3264:
  238. {
  239. u32  tmp_value_to_write = data;
  240. u32* addrOthers;
  241. int  bytesWritten;
  242. /* Get the addr in the other process that we want to write into */
  243. ret = -EIO;
  244. if (get_user(addrOthers,(u32**)addr) != 0)
  245. break;
  246. ret = 0;
  247. bytesWritten = access_process_vm(child, (u64)addrOthers, &tmp_value_to_write, sizeof(tmp_value_to_write), 1);
  248. if (bytesWritten == sizeof(tmp_value_to_write))
  249. break;
  250. ret = -EIO;
  251. break;
  252. }
  253. /* Write DATA into location ADDR within the USER area  */
  254. case PTRACE_POKEUSR: {
  255. unsigned long index;
  256. ret = -EIO;
  257. /* convert to index and check */
  258. index = (unsigned long) addr >> 2;
  259. if ((addr & 3) || (index > PT_FPSCR32))
  260. break;
  261. if (index == PT_ORIG_R3)
  262. break;
  263. if (index < PT_FPR0) {
  264. ret = put_reg(child, index, data);
  265. } else {
  266. if (child->thread.regs->msr & MSR_FP)
  267. giveup_fpu(child);
  268. /*
  269.  * the user space code considers the floating point
  270.  * to be an array of unsigned int (32 bits) - the
  271.  * index passed in is based on this assumption.
  272.  */
  273. ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data;
  274. ret = 0;
  275. }
  276. break;
  277. }
  278. /*
  279.  * Write 4 bytes into the other process' pt_regs area
  280.  *  data is the 4 bytes that the user wants written
  281.  *  addr is the offset into the other process' pt_regs structure
  282.  * that is to be written into
  283.  * (this is run in a 32-bit process looking at a 64-bit process)
  284.  */
  285. case PPC_PTRACE_POKEUSR_3264: {
  286. u32 index;
  287. u32 numReg;
  288. ret = -EIO;
  289. /* Determine which register the user wants */
  290. index = (u64)addr >> 2;  /* Divide addr by 4 */
  291. numReg = index / 2;
  292. /*
  293.  * Validate the input - check to see if address is on the
  294.  * wrong boundary or beyond the end of the user area
  295.  */
  296. if ((addr & 3) || (numReg > PT_FPSCR))
  297. break;
  298. /* Insure it is a register we let them change */
  299. if ((numReg == PT_ORIG_R3)
  300. || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
  301. break;
  302. if (numReg >= PT_FPR0) {
  303. if (child->thread.regs->msr & MSR_FP)
  304. giveup_fpu(child);
  305. }
  306. if (numReg == PT_MSR)
  307. data = (data & MSR_DEBUGCHANGE)
  308. | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
  309. ((u32*)child->thread.regs)[index] = data;
  310. ret = 0;
  311. break;
  312. }
  313. case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
  314. case PTRACE_CONT: { /* restart after signal. */
  315. ret = -EIO;
  316. if ((unsigned long) data > _NSIG)
  317. break;
  318. if (request == PTRACE_SYSCALL)
  319. child->ptrace |= PT_TRACESYS;
  320. else
  321. child->ptrace &= ~PT_TRACESYS;
  322. child->exit_code = data;
  323. /* make sure the single step bit is not set. */
  324. clear_single_step(child);
  325. wake_up_process(child);
  326. ret = 0;
  327. break;
  328. }
  329. /*
  330.  * make the child exit.  Best I can do is send it a sigkill.
  331.  * perhaps it should be put in the status that it wants to
  332.  * exit.
  333.  */
  334. case PTRACE_KILL: {
  335. ret = 0;
  336. if (child->state == TASK_ZOMBIE) /* already dead */
  337. break;
  338. child->exit_code = SIGKILL;
  339. /* make sure the single step bit is not set. */
  340. clear_single_step(child);
  341. wake_up_process(child);
  342. break;
  343. }
  344. case PTRACE_SINGLESTEP: {  /* set the trap flag. */
  345. ret = -EIO;
  346. if ((unsigned long) data > _NSIG)
  347. break;
  348. child->ptrace &= ~PT_TRACESYS;
  349. set_single_step(child);
  350. child->exit_code = data;
  351. /* give it a chance to run. */
  352. wake_up_process(child);
  353. ret = 0;
  354. break;
  355. }
  356. case PTRACE_DETACH:
  357. ret = ptrace_detach(child, data);
  358. break;
  359. default:
  360. ret = -EIO;
  361. break;
  362. }
  363. out_tsk:
  364. free_task_struct(child);
  365. out:
  366. unlock_kernel();
  367. return ret;
  368. }