|
16 | 16 | #include <asm/sigcontext.h> |
17 | 17 | #include <linux/elf.h> |
18 | 18 | #include <registers.h> |
| 19 | +#include <sys/mman.h> |
19 | 20 |
|
20 | | -static int have_xstate_support; |
| 21 | +unsigned long host_fp_size; |
21 | 22 |
|
22 | | -static int save_i387_registers(int pid, unsigned long *fp_regs) |
23 | | -{ |
24 | | - if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) |
25 | | - return -errno; |
26 | | - return 0; |
27 | | -} |
28 | | - |
29 | | -static int save_fp_registers(int pid, unsigned long *fp_regs) |
| 23 | +int get_fp_registers(int pid, unsigned long *regs) |
30 | 24 | { |
31 | | -#ifdef PTRACE_GETREGSET |
32 | | - struct iovec iov; |
| 25 | + struct iovec iov = { |
| 26 | + .iov_base = regs, |
| 27 | + .iov_len = host_fp_size, |
| 28 | + }; |
33 | 29 |
|
34 | | - if (have_xstate_support) { |
35 | | - iov.iov_base = fp_regs; |
36 | | - iov.iov_len = FP_SIZE * sizeof(unsigned long); |
37 | | - if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
38 | | - return -errno; |
39 | | - return 0; |
40 | | - } else |
41 | | -#endif |
42 | | - return save_i387_registers(pid, fp_regs); |
43 | | -} |
44 | | - |
45 | | -static int restore_i387_registers(int pid, unsigned long *fp_regs) |
46 | | -{ |
47 | | - if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) |
| 30 | + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
48 | 31 | return -errno; |
49 | 32 | return 0; |
50 | 33 | } |
51 | 34 |
|
52 | | -static int restore_fp_registers(int pid, unsigned long *fp_regs) |
53 | | -{ |
54 | | -#ifdef PTRACE_SETREGSET |
55 | | - struct iovec iov; |
56 | | - if (have_xstate_support) { |
57 | | - iov.iov_base = fp_regs; |
58 | | - iov.iov_len = FP_SIZE * sizeof(unsigned long); |
59 | | - if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
60 | | - return -errno; |
61 | | - return 0; |
62 | | - } else |
63 | | -#endif |
64 | | - return restore_i387_registers(pid, fp_regs); |
65 | | -} |
66 | | - |
67 | | -#ifdef __i386__ |
68 | | -int have_fpx_regs = 1; |
69 | | -static int save_fpx_registers(int pid, unsigned long *fp_regs) |
| 35 | +int put_fp_registers(int pid, unsigned long *regs) |
70 | 36 | { |
71 | | - if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) |
72 | | - return -errno; |
73 | | - return 0; |
74 | | -} |
| 37 | + struct iovec iov = { |
| 38 | + .iov_base = regs, |
| 39 | + .iov_len = host_fp_size, |
| 40 | + }; |
75 | 41 |
|
76 | | -static int restore_fpx_registers(int pid, unsigned long *fp_regs) |
77 | | -{ |
78 | | - if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) |
| 42 | + if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
79 | 43 | return -errno; |
80 | 44 | return 0; |
81 | 45 | } |
82 | 46 |
|
83 | | -int get_fp_registers(int pid, unsigned long *regs) |
84 | | -{ |
85 | | - if (have_fpx_regs) |
86 | | - return save_fpx_registers(pid, regs); |
87 | | - else |
88 | | - return save_fp_registers(pid, regs); |
89 | | -} |
90 | | - |
91 | | -int put_fp_registers(int pid, unsigned long *regs) |
92 | | -{ |
93 | | - if (have_fpx_regs) |
94 | | - return restore_fpx_registers(pid, regs); |
95 | | - else |
96 | | - return restore_fp_registers(pid, regs); |
97 | | -} |
98 | | - |
99 | | -void arch_init_registers(int pid) |
100 | | -{ |
101 | | - struct user_fpxregs_struct fpx_regs; |
102 | | - int err; |
103 | | - |
104 | | - err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); |
105 | | - if (!err) |
106 | | - return; |
107 | | - |
108 | | - if (errno != EIO) |
109 | | - panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", |
110 | | - errno); |
111 | | - |
112 | | - have_fpx_regs = 0; |
113 | | -} |
114 | | -#else |
115 | | - |
116 | | -int get_fp_registers(int pid, unsigned long *regs) |
| 47 | +int arch_init_registers(int pid) |
117 | 48 | { |
118 | | - return save_fp_registers(pid, regs); |
| 49 | + struct iovec iov = { |
| 50 | + /* Just use plenty of space, it does not cost us anything */ |
| 51 | + .iov_len = 2 * 1024 * 1024, |
| 52 | + }; |
| 53 | + int ret; |
| 54 | + |
| 55 | + iov.iov_base = mmap(NULL, iov.iov_len, PROT_WRITE | PROT_READ, |
| 56 | + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
| 57 | + if (iov.iov_base == MAP_FAILED) |
| 58 | + return -ENOMEM; |
| 59 | + |
| 60 | + /* GDB has x86_xsave_length, which uses x86_cpuid_count */ |
| 61 | + ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov); |
| 62 | + if (ret) |
| 63 | + ret = -errno; |
| 64 | + munmap(iov.iov_base, 2 * 1024 * 1024); |
| 65 | + |
| 66 | + host_fp_size = iov.iov_len; |
| 67 | + |
| 68 | + return ret; |
119 | 69 | } |
120 | 70 |
|
121 | | -int put_fp_registers(int pid, unsigned long *regs) |
122 | | -{ |
123 | | - return restore_fp_registers(pid, regs); |
124 | | -} |
125 | | - |
126 | | -void arch_init_registers(int pid) |
127 | | -{ |
128 | | -#ifdef PTRACE_GETREGSET |
129 | | - void * fp_regs; |
130 | | - struct iovec iov; |
131 | | - |
132 | | - fp_regs = malloc(FP_SIZE * sizeof(unsigned long)); |
133 | | - if(fp_regs == NULL) |
134 | | - return; |
135 | | - |
136 | | - iov.iov_base = fp_regs; |
137 | | - iov.iov_len = FP_SIZE * sizeof(unsigned long); |
138 | | - if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) |
139 | | - have_xstate_support = 1; |
140 | | - |
141 | | - free(fp_regs); |
142 | | -#endif |
143 | | -} |
144 | | -#endif |
145 | | - |
146 | 71 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
147 | 72 | { |
148 | 73 | switch (reg) { |
|
0 commit comments