Line data Source code
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 :
7 : #include <errno.h>
8 : #include <stdlib.h>
9 : #include <sys/ptrace.h>
10 : #ifdef __i386__
11 : #include <sys/user.h>
12 : #endif
13 : #include <longjmp.h>
14 : #include <sysdep/ptrace_user.h>
15 : #include <sys/uio.h>
16 : #include <asm/sigcontext.h>
17 : #include <linux/elf.h>
18 : #include <registers.h>
19 :
20 : int have_xstate_support;
21 :
22 0 : int save_i387_registers(int pid, unsigned long *fp_regs)
23 : {
24 0 : if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
25 0 : return -errno;
26 : return 0;
27 : }
28 :
29 1 : int save_fp_registers(int pid, unsigned long *fp_regs)
30 : {
31 : #ifdef PTRACE_GETREGSET
32 : struct iovec iov;
33 :
34 1 : if (have_xstate_support) {
35 1 : iov.iov_base = fp_regs;
36 1 : iov.iov_len = FP_SIZE * sizeof(unsigned long);
37 1 : if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
38 0 : return -errno;
39 : return 0;
40 : } else
41 : #endif
42 0 : return save_i387_registers(pid, fp_regs);
43 : }
44 :
45 0 : int restore_i387_registers(int pid, unsigned long *fp_regs)
46 : {
47 0 : if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
48 0 : return -errno;
49 : return 0;
50 : }
51 :
52 0 : int restore_fp_registers(int pid, unsigned long *fp_regs)
53 : {
54 : #ifdef PTRACE_SETREGSET
55 : struct iovec iov;
56 0 : if (have_xstate_support) {
57 0 : iov.iov_base = fp_regs;
58 0 : iov.iov_len = FP_SIZE * sizeof(unsigned long);
59 0 : if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
60 0 : return -errno;
61 : return 0;
62 : } else
63 : #endif
64 0 : return restore_i387_registers(pid, fp_regs);
65 : }
66 :
67 : #ifdef __i386__
68 : int have_fpx_regs = 1;
69 : int save_fpx_registers(int pid, unsigned long *fp_regs)
70 : {
71 : if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
72 : return -errno;
73 : return 0;
74 : }
75 :
76 : int restore_fpx_registers(int pid, unsigned long *fp_regs)
77 : {
78 : if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
79 : return -errno;
80 : return 0;
81 : }
82 :
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 1 : int get_fp_registers(int pid, unsigned long *regs)
117 : {
118 1 : return save_fp_registers(pid, regs);
119 : }
120 :
121 0 : int put_fp_registers(int pid, unsigned long *regs)
122 : {
123 0 : return restore_fp_registers(pid, regs);
124 : }
125 :
126 1 : void arch_init_registers(int pid)
127 : {
128 : #ifdef PTRACE_GETREGSET
129 : void * fp_regs;
130 : struct iovec iov;
131 :
132 1 : fp_regs = malloc(FP_SIZE * sizeof(unsigned long));
133 1 : if(fp_regs == NULL)
134 0 : return;
135 :
136 1 : iov.iov_base = fp_regs;
137 1 : iov.iov_len = FP_SIZE * sizeof(unsigned long);
138 1 : if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
139 1 : have_xstate_support = 1;
140 :
141 1 : free(fp_regs);
142 : #endif
143 : }
144 : #endif
145 :
146 0 : unsigned long get_thread_reg(int reg, jmp_buf *buf)
147 : {
148 0 : switch (reg) {
149 : #ifdef __i386__
150 : case HOST_IP:
151 : return buf[0]->__eip;
152 : case HOST_SP:
153 : return buf[0]->__esp;
154 : case HOST_BP:
155 : return buf[0]->__ebp;
156 : #else
157 : case HOST_IP:
158 0 : return buf[0]->__rip;
159 : case HOST_SP:
160 0 : return buf[0]->__rsp;
161 : case HOST_BP:
162 0 : return buf[0]->__rbp;
163 : #endif
164 : default:
165 0 : printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
166 : reg);
167 0 : return 0;
168 : }
169 : }
|