1 /* $NetBSD: process_machdep.c,v 1.25 2020/10/19 17:47:37 christos Exp $ */
2
3 /*
4 * Copyright (c) 1993 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * From:
35 * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
36 */
37
38 /*
39 * Copyright (c) 1995, 1996, 1997
40 * Charles M. Hannum. All rights reserved.
41 * Copyright (c) 1993 Jan-Simon Pendry
42 * All rights reserved.
43 *
44 * This code is derived from software contributed to Berkeley by
45 * Jan-Simon Pendry.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * From:
76 * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
77 */
78
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.25 2020/10/19 17:47:37 christos Exp $");
81
82 #ifdef _KERNEL_OPT
83 #include "opt_compat_netbsd.h"
84 #include "opt_ptrace.h"
85 #endif
86
87 #include <sys/param.h>
88 #include <sys/systm.h>
89 #include <sys/time.h>
90 #include <sys/kernel.h>
91 #include <sys/proc.h>
92 #include <sys/vnode.h>
93 #include <sys/ptrace.h>
94
95 #include <machine/psl.h>
96 #include <machine/reg.h>
97
98 #ifdef COMPAT_40
99 static int process_machdep_doregs40(struct lwp *, struct lwp *, struct uio *);
100 static int process_machdep_read_regs40(struct lwp *l, struct __reg40 *);
101 static int process_machdep_write_regs40(struct lwp *l, struct __reg40 *);
102 #endif /* COMPAT_40 */
103
104
105 static inline struct trapframe *
process_frame(struct lwp * l)106 process_frame(struct lwp *l)
107 {
108
109 return (l->l_md.md_regs);
110 }
111
112 int
process_read_regs(struct lwp * l,struct reg * regs)113 process_read_regs(struct lwp *l, struct reg *regs)
114 {
115 struct trapframe *tf = process_frame(l);
116
117 regs->r_spc = tf->tf_spc;
118 regs->r_ssr = tf->tf_ssr;
119 regs->r_gbr = tf->tf_gbr;
120 regs->r_macl = tf->tf_macl;
121 regs->r_mach = tf->tf_mach;
122 regs->r_pr = tf->tf_pr;
123 regs->r_r14 = tf->tf_r14;
124 regs->r_r13 = tf->tf_r13;
125 regs->r_r12 = tf->tf_r12;
126 regs->r_r11 = tf->tf_r11;
127 regs->r_r10 = tf->tf_r10;
128 regs->r_r9 = tf->tf_r9;
129 regs->r_r8 = tf->tf_r8;
130 regs->r_r7 = tf->tf_r7;
131 regs->r_r6 = tf->tf_r6;
132 regs->r_r5 = tf->tf_r5;
133 regs->r_r4 = tf->tf_r4;
134 regs->r_r3 = tf->tf_r3;
135 regs->r_r2 = tf->tf_r2;
136 regs->r_r1 = tf->tf_r1;
137 regs->r_r0 = tf->tf_r0;
138 regs->r_r15 = tf->tf_r15;
139
140 return (0);
141 }
142
143 #ifdef PTRACE_HOOKS
144
145 int
process_write_regs(struct lwp * l,const struct reg * regs)146 process_write_regs(struct lwp *l, const struct reg *regs)
147 {
148 struct trapframe *tf = process_frame(l);
149
150 /*
151 * Check for security violations.
152 */
153 if (((regs->r_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0) {
154 return (EINVAL);
155 }
156
157 tf->tf_spc = regs->r_spc;
158 tf->tf_ssr = regs->r_ssr;
159 tf->tf_pr = regs->r_pr;
160
161 tf->tf_gbr = regs->r_gbr;
162 tf->tf_mach = regs->r_mach;
163 tf->tf_macl = regs->r_macl;
164 tf->tf_r14 = regs->r_r14;
165 tf->tf_r13 = regs->r_r13;
166 tf->tf_r12 = regs->r_r12;
167 tf->tf_r11 = regs->r_r11;
168 tf->tf_r10 = regs->r_r10;
169 tf->tf_r9 = regs->r_r9;
170 tf->tf_r8 = regs->r_r8;
171 tf->tf_r7 = regs->r_r7;
172 tf->tf_r6 = regs->r_r6;
173 tf->tf_r5 = regs->r_r5;
174 tf->tf_r4 = regs->r_r4;
175 tf->tf_r3 = regs->r_r3;
176 tf->tf_r2 = regs->r_r2;
177 tf->tf_r1 = regs->r_r1;
178 tf->tf_r0 = regs->r_r0;
179 tf->tf_r15 = regs->r_r15;
180
181 return (0);
182 }
183
184
185 #ifdef __HAVE_PTRACE_MACHDEP
186
187 int
ptrace_machdep_dorequest(struct lwp * l,struct lwp ** lt,int req,void * addr,int data)188 ptrace_machdep_dorequest(struct lwp *l, struct lwp **lt,
189 int req, void *addr, int data)
190 {
191 struct uio uio;
192 struct iovec iov;
193 int write = 0, error;
194
195 switch (req) {
196 default:
197 return EINVAL;
198
199 #ifdef COMPAT_40
200 case PT___SETREGS40:
201 write = 1;
202 /* FALLTHROUGH*/
203
204 case PT___GETREGS40:
205 if ((error = ptrace_update_lwp((*lt)->l_proc, lt, data)) != 0)
206 return error;
207 if (!process_validregs(*lt))
208 return EINVAL;
209 iov.iov_base = addr;
210 iov.iov_len = sizeof(struct __reg40);
211 uio.uio_iov = &iov;
212 uio.uio_iovcnt = 1;
213 uio.uio_offset = 0;
214 uio.uio_resid = sizeof(struct __reg40);
215 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
216 uio.uio_vmspace = l->l_proc->p_vmspace;
217 return process_machdep_doregs40(l, *lt, &uio);
218 #endif /* COMPAT_40 */
219 }
220 }
221
222
223 #ifdef COMPAT_40
224
225 static int
process_machdep_doregs40(struct lwp * curl,struct lwp * l,struct uio * uio)226 process_machdep_doregs40(struct lwp *curl, struct lwp *l, struct uio *uio)
227 {
228 struct __reg40 r;
229 int error;
230 char *kv;
231 int kl;
232
233 kl = sizeof(r);
234 kv = (char *) &r;
235
236 kv += uio->uio_offset;
237 kl -= uio->uio_offset;
238 if (kl > uio->uio_resid)
239 kl = uio->uio_resid;
240
241 if (kl < 0)
242 error = EINVAL;
243 else
244 error = process_machdep_read_regs40(l, &r);
245 if (error == 0)
246 error = uiomove(kv, kl, uio);
247 if (error == 0 && uio->uio_rw == UIO_WRITE) {
248 if (l->l_proc->p_stat != SSTOP)
249 error = EBUSY;
250 else
251 error = process_machdep_write_regs40(l, &r);
252 }
253
254 uio->uio_offset = 0;
255 return error;
256 }
257
258 /*
259 * Like process_read_regs() but for old struct reg w/out r_gbr.
260 */
261 static int
process_machdep_read_regs40(struct lwp * l,struct __reg40 * regs)262 process_machdep_read_regs40(struct lwp *l, struct __reg40 *regs)
263 {
264 struct trapframe *tf = process_frame(l);
265
266 regs->r_spc = tf->tf_spc;
267 regs->r_ssr = tf->tf_ssr;
268 /* no r_gbr in struct __reg40 */
269 regs->r_macl = tf->tf_macl;
270 regs->r_mach = tf->tf_mach;
271 regs->r_pr = tf->tf_pr;
272 regs->r_r14 = tf->tf_r14;
273 regs->r_r13 = tf->tf_r13;
274 regs->r_r12 = tf->tf_r12;
275 regs->r_r11 = tf->tf_r11;
276 regs->r_r10 = tf->tf_r10;
277 regs->r_r9 = tf->tf_r9;
278 regs->r_r8 = tf->tf_r8;
279 regs->r_r7 = tf->tf_r7;
280 regs->r_r6 = tf->tf_r6;
281 regs->r_r5 = tf->tf_r5;
282 regs->r_r4 = tf->tf_r4;
283 regs->r_r3 = tf->tf_r3;
284 regs->r_r2 = tf->tf_r2;
285 regs->r_r1 = tf->tf_r1;
286 regs->r_r0 = tf->tf_r0;
287 regs->r_r15 = tf->tf_r15;
288
289 return 0;
290 }
291
292 /*
293 * Like process_write_regs() but for old struct reg w/out r_gbr
294 */
295 static int
process_machdep_write_regs40(struct lwp * l,struct __reg40 * regs)296 process_machdep_write_regs40(struct lwp *l, struct __reg40 *regs)
297 {
298 struct trapframe *tf = process_frame(l);
299
300 /*
301 * Check for security violations.
302 */
303 if (((regs->r_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0) {
304 return EINVAL;
305 }
306
307 tf->tf_spc = regs->r_spc;
308 tf->tf_ssr = regs->r_ssr;
309 tf->tf_pr = regs->r_pr;
310
311 /* no r_gbr in struct __reg40 */
312 tf->tf_mach = regs->r_mach;
313 tf->tf_macl = regs->r_macl;
314 tf->tf_r14 = regs->r_r14;
315 tf->tf_r13 = regs->r_r13;
316 tf->tf_r12 = regs->r_r12;
317 tf->tf_r11 = regs->r_r11;
318 tf->tf_r10 = regs->r_r10;
319 tf->tf_r9 = regs->r_r9;
320 tf->tf_r8 = regs->r_r8;
321 tf->tf_r7 = regs->r_r7;
322 tf->tf_r6 = regs->r_r6;
323 tf->tf_r5 = regs->r_r5;
324 tf->tf_r4 = regs->r_r4;
325 tf->tf_r3 = regs->r_r3;
326 tf->tf_r2 = regs->r_r2;
327 tf->tf_r1 = regs->r_r1;
328 tf->tf_r0 = regs->r_r0;
329 tf->tf_r15 = regs->r_r15;
330
331 return 0;
332 }
333
334 #endif /* COMPAT_40 */
335
336 #endif /* __HAVE_PTRACE_MACHDEP */
337
338
339 int
process_sstep(struct lwp * l,int sstep)340 process_sstep(struct lwp *l, int sstep)
341 {
342
343 if (sstep)
344 l->l_md.md_flags |= MDL_SSTEP;
345 else
346 l->l_md.md_flags &= ~MDL_SSTEP;
347
348 return 0;
349 }
350
351 int
process_set_pc(struct lwp * l,void * addr)352 process_set_pc(struct lwp *l, void *addr)
353 {
354 struct trapframe *tf = process_frame(l);
355
356 tf->tf_spc = (int)addr;
357
358 return (0);
359 }
360
361 #endif /* PTRACE_HOOKS */
362