registers.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright (C) 2004 PathScale, Inc
  3. * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  4. * Licensed under the GPL
  5. */
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <sys/ptrace.h>
  9. #ifdef __i386__
  10. #include <sys/user.h>
  11. #endif
  12. #include <longjmp.h>
  13. #include <sysdep/ptrace_user.h>
  14. #include <sys/uio.h>
  15. #include <asm/sigcontext.h>
  16. #include <linux/elf.h>
  17. int have_xstate_support;
  18. int save_i387_registers(int pid, unsigned long *fp_regs)
  19. {
  20. if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
  21. return -errno;
  22. return 0;
  23. }
  24. int save_fp_registers(int pid, unsigned long *fp_regs)
  25. {
  26. #ifdef PTRACE_GETREGSET
  27. struct iovec iov;
  28. if (have_xstate_support) {
  29. iov.iov_base = fp_regs;
  30. iov.iov_len = FP_SIZE * sizeof(unsigned long);
  31. if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
  32. return -errno;
  33. return 0;
  34. } else
  35. #endif
  36. return save_i387_registers(pid, fp_regs);
  37. }
  38. int restore_i387_registers(int pid, unsigned long *fp_regs)
  39. {
  40. if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
  41. return -errno;
  42. return 0;
  43. }
  44. int restore_fp_registers(int pid, unsigned long *fp_regs)
  45. {
  46. #ifdef PTRACE_SETREGSET
  47. struct iovec iov;
  48. if (have_xstate_support) {
  49. iov.iov_base = fp_regs;
  50. iov.iov_len = FP_SIZE * sizeof(unsigned long);
  51. if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
  52. return -errno;
  53. return 0;
  54. } else
  55. #endif
  56. return restore_i387_registers(pid, fp_regs);
  57. }
  58. #ifdef __i386__
  59. int have_fpx_regs = 1;
  60. int save_fpx_registers(int pid, unsigned long *fp_regs)
  61. {
  62. if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
  63. return -errno;
  64. return 0;
  65. }
  66. int restore_fpx_registers(int pid, unsigned long *fp_regs)
  67. {
  68. if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
  69. return -errno;
  70. return 0;
  71. }
  72. int get_fp_registers(int pid, unsigned long *regs)
  73. {
  74. if (have_fpx_regs)
  75. return save_fpx_registers(pid, regs);
  76. else
  77. return save_fp_registers(pid, regs);
  78. }
  79. int put_fp_registers(int pid, unsigned long *regs)
  80. {
  81. if (have_fpx_regs)
  82. return restore_fpx_registers(pid, regs);
  83. else
  84. return restore_fp_registers(pid, regs);
  85. }
  86. void arch_init_registers(int pid)
  87. {
  88. struct user_fpxregs_struct fpx_regs;
  89. int err;
  90. err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
  91. if (!err)
  92. return;
  93. if (errno != EIO)
  94. panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
  95. errno);
  96. have_fpx_regs = 0;
  97. }
  98. #else
  99. int get_fp_registers(int pid, unsigned long *regs)
  100. {
  101. return save_fp_registers(pid, regs);
  102. }
  103. int put_fp_registers(int pid, unsigned long *regs)
  104. {
  105. return restore_fp_registers(pid, regs);
  106. }
  107. void arch_init_registers(int pid)
  108. {
  109. #ifdef PTRACE_GETREGSET
  110. void * fp_regs;
  111. struct iovec iov;
  112. fp_regs = malloc(FP_SIZE * sizeof(unsigned long));
  113. if(fp_regs == NULL)
  114. return;
  115. iov.iov_base = fp_regs;
  116. iov.iov_len = FP_SIZE * sizeof(unsigned long);
  117. if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
  118. have_xstate_support = 1;
  119. free(fp_regs);
  120. #endif
  121. }
  122. #endif
  123. unsigned long get_thread_reg(int reg, jmp_buf *buf)
  124. {
  125. switch (reg) {
  126. #ifdef __i386__
  127. case HOST_IP:
  128. return buf[0]->__eip;
  129. case HOST_SP:
  130. return buf[0]->__esp;
  131. case HOST_BP:
  132. return buf[0]->__ebp;
  133. #else
  134. case HOST_IP:
  135. return buf[0]->__rip;
  136. case HOST_SP:
  137. return buf[0]->__rsp;
  138. case HOST_BP:
  139. return buf[0]->__rbp;
  140. #endif
  141. default:
  142. printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
  143. reg);
  144. return 0;
  145. }
  146. }