]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/ptrace_machdep.c
Update Subversion to 1.14.0 LTS. See contrib/subversion/CHANGES for a
[FreeBSD/FreeBSD.git] / sys / i386 / i386 / ptrace_machdep.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2005 Doug Rabson
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include "opt_cpu.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/proc.h>
39 #include <sys/ptrace.h>
40 #include <machine/frame.h>
41 #include <machine/md_var.h>
42 #include <machine/pcb.h>
43
44 static int
45 cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
46 {
47         struct ptrace_xstate_info info;
48         char *savefpu;
49         int error;
50
51         if (!use_xsave)
52                 return (EOPNOTSUPP);
53
54         switch (req) {
55         case PT_GETXSTATE_OLD:
56                 npxgetregs(td);
57                 savefpu = (char *)(get_pcb_user_save_td(td) + 1);
58                 error = copyout(savefpu, addr,
59                     cpu_max_ext_state_size - sizeof(union savefpu));
60                 break;
61
62         case PT_SETXSTATE_OLD:
63                 if (data > cpu_max_ext_state_size - sizeof(union savefpu)) {
64                         error = EINVAL;
65                         break;
66                 }
67                 savefpu = malloc(data, M_TEMP, M_WAITOK);
68                 error = copyin(addr, savefpu, data);
69                 if (error == 0) {
70                         npxgetregs(td);
71                         error = npxsetxstate(td, savefpu, data);
72                 }
73                 free(savefpu, M_TEMP);
74                 break;
75
76         case PT_GETXSTATE_INFO:
77                 if (data != sizeof(info)) {
78                         error  = EINVAL;
79                         break;
80                 }
81                 info.xsave_len = cpu_max_ext_state_size;
82                 info.xsave_mask = xsave_mask;
83                 error = copyout(&info, addr, data);
84                 break;
85
86         case PT_GETXSTATE:
87                 npxgetregs(td);
88                 savefpu = (char *)(get_pcb_user_save_td(td));
89                 error = copyout(savefpu, addr, cpu_max_ext_state_size);
90                 break;
91
92         case PT_SETXSTATE:
93                 if (data < sizeof(union savefpu) ||
94                     data > cpu_max_ext_state_size) {
95                         error = EINVAL;
96                         break;
97                 }
98                 savefpu = malloc(data, M_TEMP, M_WAITOK);
99                 error = copyin(addr, savefpu, data);
100                 if (error == 0)
101                         error = npxsetregs(td, (union savefpu *)savefpu,
102                             savefpu + sizeof(union savefpu), data -
103                             sizeof(union savefpu));
104                 free(savefpu, M_TEMP);
105                 break;
106
107         default:
108                 error = EINVAL;
109                 break;
110         }
111
112         return (error);
113 }
114
115 static int
116 cpu_ptrace_xmm(struct thread *td, int req, void *addr, int data)
117 {
118         struct savexmm *fpstate;
119         int error;
120
121         if (!cpu_fxsr)
122                 return (EINVAL);
123
124         fpstate = &get_pcb_user_save_td(td)->sv_xmm;
125         switch (req) {
126         case PT_GETXMMREGS:
127                 npxgetregs(td);
128                 error = copyout(fpstate, addr, sizeof(*fpstate));
129                 break;
130
131         case PT_SETXMMREGS:
132                 npxgetregs(td);
133                 error = copyin(addr, fpstate, sizeof(*fpstate));
134                 fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
135                 break;
136
137         case PT_GETXSTATE_OLD:
138         case PT_SETXSTATE_OLD:
139         case PT_GETXSTATE_INFO:
140         case PT_GETXSTATE:
141         case PT_SETXSTATE:
142                 error = cpu_ptrace_xstate(td, req, addr, data);
143                 break;
144
145         default:
146                 return (EINVAL);
147         }
148
149         return (error);
150 }
151
152 int
153 cpu_ptrace(struct thread *td, int req, void *addr, int data)
154 {
155         struct segment_descriptor *sdp, sd;
156         register_t r;
157         int error;
158
159         switch (req) {
160         case PT_GETXMMREGS:
161         case PT_SETXMMREGS:
162         case PT_GETXSTATE_OLD:
163         case PT_SETXSTATE_OLD:
164         case PT_GETXSTATE_INFO:
165         case PT_GETXSTATE:
166         case PT_SETXSTATE:
167                 error = cpu_ptrace_xmm(td, req, addr, data);
168                 break;
169
170         case PT_GETFSBASE:
171         case PT_GETGSBASE:
172                 sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd :
173                     &td->td_pcb->pcb_gsd;
174                 r = sdp->sd_hibase << 24 | sdp->sd_lobase;
175                 error = copyout(&r, addr, sizeof(r));
176                 break;
177
178         case PT_SETFSBASE:
179         case PT_SETGSBASE:
180                 error = copyin(addr, &r, sizeof(r));
181                 if (error != 0)
182                         break;
183                 fill_based_sd(&sd, r);
184                 if (req == PT_SETFSBASE) {
185                         td->td_pcb->pcb_fsd = sd;
186                         td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL);
187                 } else {
188                         td->td_pcb->pcb_gsd = sd;
189                         td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL);
190                 }
191                 break;
192
193         default:
194                 return (EINVAL);
195         }
196
197         return (error);
198 }