ptrace_user.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include <stdio.h>
  6. #include <stddef.h>
  7. #include <errno.h>
  8. #include <unistd.h>
  9. #include "ptrace_user.h"
  10. /* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */
  11. #include <asm/user.h>
  12. #include "kern_util.h"
  13. #include "sysdep/thread.h"
  14. #include "user.h"
  15. #include "os.h"
  16. #include "uml-config.h"
  17. int ptrace_getregs(long pid, unsigned long *regs_out)
  18. {
  19. if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
  20. return -errno;
  21. return 0;
  22. }
  23. int ptrace_setregs(long pid, unsigned long *regs)
  24. {
  25. if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
  26. return -errno;
  27. return 0;
  28. }
  29. int ptrace_getfpregs(long pid, unsigned long *regs)
  30. {
  31. if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
  32. return -errno;
  33. return 0;
  34. }
  35. int ptrace_setfpregs(long pid, unsigned long *regs)
  36. {
  37. if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
  38. return -errno;
  39. return 0;
  40. }
  41. #ifdef UML_CONFIG_MODE_TT
  42. static void write_debugregs(int pid, unsigned long *regs)
  43. {
  44. struct user *dummy;
  45. int nregs, i;
  46. dummy = NULL;
  47. nregs = ARRAY_SIZE(dummy->u_debugreg);
  48. for(i = 0; i < nregs; i++){
  49. if((i == 4) || (i == 5)) continue;
  50. if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
  51. regs[i]) < 0)
  52. printk("write_debugregs - ptrace failed on "
  53. "register %d, value = 0x%lx, errno = %d\n", i,
  54. regs[i], errno);
  55. }
  56. }
  57. static void read_debugregs(int pid, unsigned long *regs)
  58. {
  59. struct user *dummy;
  60. int nregs, i;
  61. dummy = NULL;
  62. nregs = ARRAY_SIZE(dummy->u_debugreg);
  63. for(i = 0; i < nregs; i++){
  64. regs[i] = ptrace(PTRACE_PEEKUSR, pid,
  65. &dummy->u_debugreg[i], 0);
  66. }
  67. }
  68. /* Accessed only by the tracing thread */
  69. static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
  70. void arch_enter_kernel(void *task, int pid)
  71. {
  72. read_debugregs(pid, TASK_DEBUGREGS(task));
  73. write_debugregs(pid, kernel_debugregs);
  74. }
  75. void arch_leave_kernel(void *task, int pid)
  76. {
  77. read_debugregs(pid, kernel_debugregs);
  78. write_debugregs(pid, TASK_DEBUGREGS(task));
  79. }
  80. #ifdef UML_CONFIG_PT_PROXY
  81. /* Accessed only by the tracing thread */
  82. static int debugregs_seq;
  83. /* Only called by the ptrace proxy */
  84. void ptrace_pokeuser(unsigned long addr, unsigned long data)
  85. {
  86. if((addr < offsetof(struct user, u_debugreg[0])) ||
  87. (addr > offsetof(struct user, u_debugreg[7])))
  88. return;
  89. addr -= offsetof(struct user, u_debugreg[0]);
  90. addr = addr >> 2;
  91. if(kernel_debugregs[addr] == data) return;
  92. kernel_debugregs[addr] = data;
  93. debugregs_seq++;
  94. }
  95. static void update_debugregs_cb(void *arg)
  96. {
  97. int pid = *((int *) arg);
  98. write_debugregs(pid, kernel_debugregs);
  99. }
  100. /* Optimized out in its header when not defined */
  101. void update_debugregs(int seq)
  102. {
  103. int me;
  104. if(seq == debugregs_seq) return;
  105. me = os_getpid();
  106. initial_thread_cb(update_debugregs_cb, &me);
  107. }
  108. #endif
  109. #endif