Super User's BSD Cross Reference: /FreeBSD/sys/amd64/linux/linux_ptrace.c

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2017 Edward Tomasz Napierala <trasz@FreeBSD.org>
5 *
6 * This software was developed by SRI International and the University of
7 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
8 * ("CTSRD"), as part of the DARPA CRASH research programme.
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 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35#include <sys/param.h>
36#include <sys/lock.h>
37#include <sys/proc.h>
38#include <sys/ptrace.h>
39#include <sys/sx.h>
40#include <sys/syscallsubr.h>
41
42#include <machine/pcb.h>
43#include <machine/reg.h>
44
45#include <amd64/linux/linux.h>
46#include <amd64/linux/linux_proto.h>
47#include <compat/linux/linux_emul.h>
48#include <compat/linux/linux_misc.h>
49#include <compat/linux/linux_signal.h>
50#include <compat/linux/linux_util.h>
51
52#define LINUX_PTRACE_TRACEME 0
53#define LINUX_PTRACE_PEEKTEXT 1
54#define LINUX_PTRACE_PEEKDATA 2
55#define LINUX_PTRACE_PEEKUSER 3
56#define LINUX_PTRACE_POKETEXT 4
57#define LINUX_PTRACE_POKEDATA 5
58#define LINUX_PTRACE_POKEUSER 6
59#define LINUX_PTRACE_CONT 7
60#define LINUX_PTRACE_KILL 8
61#define LINUX_PTRACE_SINGLESTEP 9
62#define LINUX_PTRACE_GETREGS 12
63#define LINUX_PTRACE_SETREGS 13
64#define LINUX_PTRACE_GETFPREGS 14
65#define LINUX_PTRACE_SETFPREGS 15
66#define LINUX_PTRACE_ATTACH 16
67#define LINUX_PTRACE_DETACH 17
68#define LINUX_PTRACE_SYSCALL 24
69#define LINUX_PTRACE_SETOPTIONS 0x4200
70#define LINUX_PTRACE_GETSIGINFO 0x4202
71#define LINUX_PTRACE_GETREGSET 0x4204
72#define LINUX_PTRACE_SEIZE 0x4206
73#define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e
74
75#define LINUX_PTRACE_EVENT_EXIT 6
76
77#define LINUX_PTRACE_O_TRACESYSGOOD 1
78#define LINUX_PTRACE_O_TRACEFORK 2
79#define LINUX_PTRACE_O_TRACEVFORK 4
80#define LINUX_PTRACE_O_TRACECLONE 8
81#define LINUX_PTRACE_O_TRACEEXEC 16
82#define LINUX_PTRACE_O_TRACEVFORKDONE 32
83#define LINUX_PTRACE_O_TRACEEXIT 64
84#define LINUX_PTRACE_O_TRACESECCOMP 128
85#define LINUX_PTRACE_O_EXITKILL 1048576
86#define LINUX_PTRACE_O_SUSPEND_SECCOMP 2097152
87
88#define LINUX_NT_PRSTATUS 1
89
90#define LINUX_PTRACE_O_MASK (LINUX_PTRACE_O_TRACESYSGOOD | \
91 LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK | \
92 LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC | \
93 LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT | \
94 LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \
95 LINUX_PTRACE_O_SUSPEND_SECCOMP)
96
97 static int
98 map_signum(int lsig, int *bsigp)
99{
100 int bsig;
101
102 if (lsig == 0) {
103 *bsigp = 0;
104 return (0);
105 }
106
107 if (lsig < 0 || lsig > LINUX_SIGRTMAX)
108 return (EINVAL);
109
110 bsig = linux_to_bsd_signal(lsig);
111 if (bsig == SIGSTOP)
112 bsig = 0;
113
114 *bsigp = bsig;
115 return (0);
116}
117
118 int
119 linux_ptrace_status(struct thread *td, pid_t pid, int status)
120{
121 struct ptrace_lwpinfo lwpinfo;
122 struct linux_pemuldata *pem;
123 register_t saved_retval;
124 int error;
125
126 saved_retval = td->td_retval[0];
127 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
128 td->td_retval[0] = saved_retval;
129 if (error != 0) {
130 linux_msg(td, "PT_LWPINFO failed with error %d", error);
131 return (status);
132 }
133
134 pem = pem_find(td->td_proc);
135 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__));
136
137 LINUX_PEM_SLOCK(pem);
138 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) &&
139 lwpinfo.pl_flags & PL_FLAG_SCE)
140 status |= (LINUX_SIGTRAP | 0x80) << 8;
141 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) &&
142 lwpinfo.pl_flags & PL_FLAG_SCX)
143 status |= (LINUX_SIGTRAP | 0x80) << 8;
144 if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACEEXIT) &&
145 lwpinfo.pl_flags & PL_FLAG_EXITED)
146 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXIT << 8) << 8;
147 LINUX_PEM_SUNLOCK(pem);
148
149 return (status);
150}
151
152 struct linux_pt_reg {
153 l_ulong r15;
154 l_ulong r14;
155 l_ulong r13;
156 l_ulong r12;
157 l_ulong rbp;
158 l_ulong rbx;
159 l_ulong r11;
160 l_ulong r10;
161 l_ulong r9;
162 l_ulong r8;
163 l_ulong rax;
164 l_ulong rcx;
165 l_ulong rdx;
166 l_ulong rsi;
167 l_ulong rdi;
168 l_ulong orig_rax;
169 l_ulong rip;
170 l_ulong cs;
171 l_ulong eflags;
172 l_ulong rsp;
173 l_ulong ss;
174};
175
176 struct linux_pt_regset {
177 l_ulong r15;
178 l_ulong r14;
179 l_ulong r13;
180 l_ulong r12;
181 l_ulong rbp;
182 l_ulong rbx;
183 l_ulong r11;
184 l_ulong r10;
185 l_ulong r9;
186 l_ulong r8;
187 l_ulong rax;
188 l_ulong rcx;
189 l_ulong rdx;
190 l_ulong rsi;
191 l_ulong rdi;
192 l_ulong orig_rax;
193 l_ulong rip;
194 l_ulong cs;
195 l_ulong eflags;
196 l_ulong rsp;
197 l_ulong ss;
198 l_ulong fs_base;
199 l_ulong gs_base;
200 l_ulong ds;
201 l_ulong es;
202 l_ulong fs;
203 l_ulong gs;
204};
205
206 /*
207 * Translate amd64 ptrace registers between Linux and FreeBSD formats.
208 * The translation is pretty straighforward, for all registers but
209 * orig_rax on Linux side and r_trapno and r_err in FreeBSD.
210 */
211 static void
212 map_regs_to_linux(struct reg *b_reg, struct linux_pt_reg *l_reg)
213{
214
215 l_reg->r15 = b_reg->r_r15;
216 l_reg->r14 = b_reg->r_r14;
217 l_reg->r13 = b_reg->r_r13;
218 l_reg->r12 = b_reg->r_r12;
219 l_reg->rbp = b_reg->r_rbp;
220 l_reg->rbx = b_reg->r_rbx;
221 l_reg->r11 = b_reg->r_r11;
222 l_reg->r10 = b_reg->r_r10;
223 l_reg->r9 = b_reg->r_r9;
224 l_reg->r8 = b_reg->r_r8;
225 l_reg->rax = b_reg->r_rax;
226 l_reg->rcx = b_reg->r_rcx;
227 l_reg->rdx = b_reg->r_rdx;
228 l_reg->rsi = b_reg->r_rsi;
229 l_reg->rdi = b_reg->r_rdi;
230 l_reg->orig_rax = b_reg->r_rax;
231 l_reg->rip = b_reg->r_rip;
232 l_reg->cs = b_reg->r_cs;
233 l_reg->eflags = b_reg->r_rflags;
234 l_reg->rsp = b_reg->r_rsp;
235 l_reg->ss = b_reg->r_ss;
236}
237
238 static void
239 map_regs_to_linux_regset(struct reg *b_reg, unsigned long fs_base,
240 unsigned long gs_base, struct linux_pt_regset *l_regset)
241{
242
243 l_regset->r15 = b_reg->r_r15;
244 l_regset->r14 = b_reg->r_r14;
245 l_regset->r13 = b_reg->r_r13;
246 l_regset->r12 = b_reg->r_r12;
247 l_regset->rbp = b_reg->r_rbp;
248 l_regset->rbx = b_reg->r_rbx;
249 l_regset->r11 = b_reg->r_r11;
250 l_regset->r10 = b_reg->r_r10;
251 l_regset->r9 = b_reg->r_r9;
252 l_regset->r8 = b_reg->r_r8;
253 l_regset->rax = b_reg->r_rax;
254 l_regset->rcx = b_reg->r_rcx;
255 l_regset->rdx = b_reg->r_rdx;
256 l_regset->rsi = b_reg->r_rsi;
257 l_regset->rdi = b_reg->r_rdi;
258 l_regset->orig_rax = b_reg->r_rax;
259 l_regset->rip = b_reg->r_rip;
260 l_regset->cs = b_reg->r_cs;
261 l_regset->eflags = b_reg->r_rflags;
262 l_regset->rsp = b_reg->r_rsp;
263 l_regset->ss = b_reg->r_ss;
264 l_regset->fs_base = fs_base;
265 l_regset->gs_base = gs_base;
266 l_regset->ds = b_reg->r_ds;
267 l_regset->es = b_reg->r_es;
268 l_regset->fs = b_reg->r_fs;
269 l_regset->gs = b_reg->r_gs;
270}
271
272 static void
273 map_regs_from_linux(struct reg *b_reg, struct linux_pt_reg *l_reg)
274{
275 b_reg->r_r15 = l_reg->r15;
276 b_reg->r_r14 = l_reg->r14;
277 b_reg->r_r13 = l_reg->r13;
278 b_reg->r_r12 = l_reg->r12;
279 b_reg->r_r11 = l_reg->r11;
280 b_reg->r_r10 = l_reg->r10;
281 b_reg->r_r9 = l_reg->r9;
282 b_reg->r_r8 = l_reg->r8;
283 b_reg->r_rdi = l_reg->rdi;
284 b_reg->r_rsi = l_reg->rsi;
285 b_reg->r_rbp = l_reg->rbp;
286 b_reg->r_rbx = l_reg->rbx;
287 b_reg->r_rdx = l_reg->rdx;
288 b_reg->r_rcx = l_reg->rcx;
289 b_reg->r_rax = l_reg->rax;
290
291 /*
292 * XXX: Are zeroes the right thing to put here?
293 */
294 b_reg->r_trapno = 0;
295 b_reg->r_fs = 0;
296 b_reg->r_gs = 0;
297 b_reg->r_err = 0;
298 b_reg->r_es = 0;
299 b_reg->r_ds = 0;
300
301 b_reg->r_rip = l_reg->rip;
302 b_reg->r_cs = l_reg->cs;
303 b_reg->r_rflags = l_reg->eflags;
304 b_reg->r_rsp = l_reg->rsp;
305 b_reg->r_ss = l_reg->ss;
306}
307
308 static int
309 linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data)
310{
311 int error;
312
313 error = kern_ptrace(td, PT_READ_I, pid, addr, 0);
314 if (error == 0)
315 error = copyout(td->td_retval, data, sizeof(l_int));
316 td->td_retval[0] = error;
317
318 return (error);
319}
320
321 static int
322 linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
323{
324
325 linux_msg(td, "PTRACE_PEEKUSER not implemented; returning EINVAL");
326 return (EINVAL);
327}
328
329 static int
330 linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data)
331{
332
333 linux_msg(td, "PTRACE_POKEUSER not implemented; returning EINVAL");
334 return (EINVAL);
335}
336
337 static int
338 linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data)
339{
340 struct linux_pemuldata *pem;
341 int mask;
342
343 mask = 0;
344
345 if (data & ~LINUX_PTRACE_O_MASK) {
346 linux_msg(td, "unknown ptrace option %lx set; "
347 "returning EINVAL",
348 data & ~LINUX_PTRACE_O_MASK);
349 return (EINVAL);
350 }
351
352 pem = pem_find(td->td_proc);
353 KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__));
354
355 /*
356 * PTRACE_O_EXITKILL is ignored, we do that by default.
357 */
358
359 LINUX_PEM_XLOCK(pem);
360 if (data & LINUX_PTRACE_O_TRACESYSGOOD) {
361 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD;
362 } else {
363 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD;
364 }
365 LINUX_PEM_XUNLOCK(pem);
366
367 if (data & LINUX_PTRACE_O_TRACEFORK)
368 mask |= PTRACE_FORK;
369
370 if (data & LINUX_PTRACE_O_TRACEVFORK)
371 mask |= PTRACE_VFORK;
372
373 if (data & LINUX_PTRACE_O_TRACECLONE)
374 mask |= PTRACE_VFORK;
375
376 if (data & LINUX_PTRACE_O_TRACEEXEC)
377 mask |= PTRACE_EXEC;
378
379 if (data & LINUX_PTRACE_O_TRACEVFORKDONE)
380 mask |= PTRACE_VFORK; /* XXX: Close enough? */
381
382 if (data & LINUX_PTRACE_O_TRACEEXIT) {
383 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT;
384 } else {
385 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT;
386 }
387
388 return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask)));
389}
390
391 static int
392 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data)
393{
394 struct ptrace_lwpinfo lwpinfo;
395 l_siginfo_t l_siginfo;
396 int error, sig;
397
398 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
399 if (error != 0) {
400 linux_msg(td, "PT_LWPINFO failed with error %d", error);
401 return (error);
402 }
403
404 if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) {
405 error = EINVAL;
406 linux_msg(td, "no PL_FLAG_SI, returning %d", error);
407 return (error);
408 }
409
410 sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo);
411 siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig);
412 error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo));
413 return (error);
414}
415
416 static int
417 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data)
418{
419 struct ptrace_lwpinfo lwpinfo;
420 struct reg b_reg;
421 struct linux_pt_reg l_reg;
422 int error;
423
424 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
425 if (error != 0)
426 return (error);
427
428 map_regs_to_linux(&b_reg, &l_reg);
429
430 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
431 if (error != 0) {
432 linux_msg(td, "PT_LWPINFO failed with error %d", error);
433 return (error);
434 }
435 if (lwpinfo.pl_flags & PL_FLAG_SCE) {
436 /*
437 * The strace(1) utility depends on RAX being set to -ENOSYS
438 * on syscall entry; otherwise it loops printing those:
439 *
440 * [ Process PID=928 runs in 64 bit mode. ]
441 * [ Process PID=928 runs in x32 mode. ]
442 */
443 l_reg.rax = -38; /* -ENOSYS */
444
445 /*
446 * Undo the mangling done in exception.S:fast_syscall_common().
447 */
448 l_reg.r10 = l_reg.rcx;
449 }
450
451 error = copyout(&l_reg, (void *)data, sizeof(l_reg));
452 return (error);
453}
454
455 static int
456 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data)
457{
458 struct reg b_reg;
459 struct linux_pt_reg l_reg;
460 int error;
461
462 error = copyin(data, &l_reg, sizeof(l_reg));
463 if (error != 0)
464 return (error);
465 map_regs_from_linux(&b_reg, &l_reg);
466 error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0);
467 return (error);
468}
469
470 static int
471 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data)
472{
473 struct ptrace_lwpinfo lwpinfo;
474 struct reg b_reg;
475 struct linux_pt_regset l_regset;
476 struct iovec iov;
477 struct pcb *pcb;
478 unsigned long fsbase, gsbase;
479 size_t len;
480 int error;
481
482 error = copyin((const void *)data, &iov, sizeof(iov));
483 if (error != 0) {
484 linux_msg(td, "copyin error %d", error);
485 return (error);
486 }
487
488 error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
489 if (error != 0)
490 return (error);
491
492 pcb = td->td_pcb;
493 if (td == curthread)
494 update_pcb_bases(pcb);
495 fsbase = pcb->pcb_fsbase;
496 gsbase = pcb->pcb_gsbase;
497
498 map_regs_to_linux_regset(&b_reg, fsbase, gsbase, &l_regset);
499
500 error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
501 if (error != 0) {
502 linux_msg(td, "PT_LWPINFO failed with error %d", error);
503 return (error);
504 }
505 if (lwpinfo.pl_flags & PL_FLAG_SCE) {
506 /*
507 * The strace(1) utility depends on RAX being set to -ENOSYS
508 * on syscall entry; otherwise it loops printing those:
509 *
510 * [ Process PID=928 runs in 64 bit mode. ]
511 * [ Process PID=928 runs in x32 mode. ]
512 */
513 l_regset.rax = -38; /* -ENOSYS */
514
515 /*
516 * Undo the mangling done in exception.S:fast_syscall_common().
517 */
518 l_regset.r10 = l_regset.rcx;
519 }
520
521 len = MIN(iov.iov_len, sizeof(l_regset));
522 error = copyout(&l_regset, (void *)iov.iov_base, len);
523 if (error != 0) {
524 linux_msg(td, "copyout error %d", error);
525 return (error);
526 }
527
528 iov.iov_len -= len;
529 error = copyout(&iov, (void *)data, sizeof(iov));
530 if (error != 0) {
531 linux_msg(td, "iov copyout error %d", error);
532 return (error);
533 }
534
535 return (error);
536}
537
538 static int
539 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
540{
541
542 switch (addr) {
543 case LINUX_NT_PRSTATUS:
544 return (linux_ptrace_getregset_prstatus(td, pid, data));
545 default:
546 linux_msg(td, "PTRACE_GETREGSET request %ld not implemented; "
547 "returning EINVAL", addr);
548 return (EINVAL);
549 }
550}
551
552 static int
553 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
554{
555
556 linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL");
557 return (EINVAL);
558}
559
560 static int
561 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
562{
563
564 linux_msg(td, "PTRACE_GET_SYSCALL_INFO not implemented; returning EINVAL");
565 return (EINVAL);
566}
567
568 int
569 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
570{
571 void *addr;
572 pid_t pid;
573 int error, sig;
574
575 pid = (pid_t)uap->pid;
576 addr = (void *)uap->addr;
577
578 switch (uap->req) {
579 case LINUX_PTRACE_TRACEME:
580 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0);
581 break;
582 case LINUX_PTRACE_PEEKTEXT:
583 case LINUX_PTRACE_PEEKDATA:
584 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data);
585 if (error != 0)
586 return (error);
587 /*
588 * Linux expects this syscall to read 64 bits, not 32.
589 */
590 error = linux_ptrace_peek(td, pid,
591 (void *)(uap->addr + 4), (void *)(uap->data + 4));
592 break;
593 case LINUX_PTRACE_PEEKUSER:
594 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data);
595 break;
596 case LINUX_PTRACE_POKETEXT:
597 error = kern_ptrace(td, PT_WRITE_I, pid, addr, uap->data);
598 break;
599 case LINUX_PTRACE_POKEDATA:
600 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data);
601 break;
602 case LINUX_PTRACE_POKEUSER:
603 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data);
604 break;
605 case LINUX_PTRACE_CONT:
606 error = map_signum(uap->data, &sig);
607 if (error != 0)
608 break;
609 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig);
610 break;
611 case LINUX_PTRACE_KILL:
612 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data);
613 break;
614 case LINUX_PTRACE_SINGLESTEP:
615 error = map_signum(uap->data, &sig);
616 if (error != 0)
617 break;
618 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig);
619 break;
620 case LINUX_PTRACE_GETREGS:
621 error = linux_ptrace_getregs(td, pid, (void *)uap->data);
622 break;
623 case LINUX_PTRACE_SETREGS:
624 error = linux_ptrace_setregs(td, pid, (void *)uap->data);
625 break;
626 case LINUX_PTRACE_ATTACH:
627 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
628 break;
629 case LINUX_PTRACE_DETACH:
630 error = map_signum(uap->data, &sig);
631 if (error != 0)
632 break;
633 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig);
634 break;
635 case LINUX_PTRACE_SYSCALL:
636 error = map_signum(uap->data, &sig);
637 if (error != 0)
638 break;
639 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig);
640 break;
641 case LINUX_PTRACE_SETOPTIONS:
642 error = linux_ptrace_setoptions(td, pid, uap->data);
643 break;
644 case LINUX_PTRACE_GETSIGINFO:
645 error = linux_ptrace_getsiginfo(td, pid, uap->data);
646 break;
647 case LINUX_PTRACE_GETREGSET:
648 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data);
649 break;
650 case LINUX_PTRACE_SEIZE:
651 error = linux_ptrace_seize(td, pid, uap->addr, uap->data);
652 break;
653 case LINUX_PTRACE_GET_SYSCALL_INFO:
654 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data);
655 break;
656 default:
657 linux_msg(td, "ptrace(%ld, ...) not implemented; "
658 "returning EINVAL", uap->req);
659 error = EINVAL;
660 break;
661 }
662
663 return (error);
664}
665 

AltStyle によって変換されたページ (->オリジナル) /