linux_ptrace.c revision 1.3 1 /* $NetBSD: linux_ptrace.c,v 1.3 1999/12/16 15:11:19 tron Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matthias Scheler.
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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/mount.h>
42 #include <sys/proc.h>
43 #include <sys/ptrace.h>
44 #include <sys/systm.h>
45 #include <sys/syscallargs.h>
46
47 #include <machine/reg.h>
48
49 #include <compat/linux/common/linux_types.h>
50 #include <compat/linux/common/linux_ptrace.h>
51 #include <compat/linux/common/linux_signal.h>
52
53 #include <compat/linux/common/linux_util.h>
54 #include <compat/linux/common/linux_machdep.h>
55
56 #include <compat/linux/linux_syscallargs.h>
57
58 #define LINUX_PTRACE_GETREGS 12
59 #define LINUX_PTRACE_SETREGS 13
60 #define LINUX_PTRACE_GETFPREGS 14
61 #define LINUX_PTRACE_SETFPREGS 15
62
63 struct linux_reg {
64 long ebx;
65 long ecx;
66 long edx;
67 long esi;
68 long edi;
69 long ebp;
70 long eax;
71 int xds;
72 int xes;
73 long orig_eax;
74 long eip;
75 int xcs;
76 long eflags;
77 long esp;
78 int xss;
79 };
80
81 #define ISSET(t, f) ((t) & (f))
82
83 int
84 linux_sys_ptrace_arch(p, v, retval)
85 struct proc *p;
86 void *v;
87 register_t *retval;
88 {
89 struct linux_sys_ptrace_args /* {
90 syscallarg(int) request;
91 syscallarg(int) pid;
92 syscallarg(int) addr;
93 syscallarg(int) data;
94 } */ *uap = v;
95 int request, error;
96 struct proc *t; /* target process */
97 struct reg regs;
98 struct linux_reg linux_regs;
99
100 request = SCARG(uap, request);
101
102 if ((request != LINUX_PTRACE_GETREGS) &&
103 (request != LINUX_PTRACE_SETREGS) &&
104 (request != LINUX_PTRACE_GETFPREGS) &&
105 (request != LINUX_PTRACE_SETFPREGS))
106 return EIO;
107
108 /* Find the process we're supposed to be operating on. */
109 if ((t = pfind(SCARG(uap, pid))) == NULL)
110 return ESRCH;
111
112 /*
113 * You can't do what you want to the process if:
114 * (1) It's not being traced at all,
115 */
116 if (!ISSET(t->p_flag, P_TRACED))
117 return EPERM;
118
119 /*
120 * (2) it's being traced by procfs (which has
121 * different signal delivery semantics),
122 */
123 if (ISSET(t->p_flag, P_FSTRACE))
124 return EBUSY;
125
126 /*
127 * (3) it's not being traced by _you_, or
128 */
129 if (t->p_pptr != p)
130 return EBUSY;
131
132 /*
133 * (4) it's not currently stopped.
134 */
135 if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
136 return EBUSY;
137
138 *retval = 0;
139
140 switch (request) {
141 case LINUX_PTRACE_GETREGS:
142 error = process_read_regs(t, ®s);
143 if (error != 0)
144 return error;
145
146 linux_regs.ebx = regs.r_ebx;
147 linux_regs.ecx = regs.r_ecx;
148 linux_regs.edx = regs.r_edx;
149 linux_regs.esi = regs.r_esi;
150 linux_regs.edi = regs.r_edi;
151 linux_regs.ebp = regs.r_ebp;
152 linux_regs.eax = regs.r_eax;
153 linux_regs.xds = regs.r_ds;
154 linux_regs.xes = regs.r_es;
155 linux_regs.orig_eax = regs.r_eax; /* XXX is this correct? */
156 linux_regs.eip = regs.r_eip;
157 linux_regs.xcs = regs.r_cs;
158 linux_regs.eflags = regs.r_eflags;
159 linux_regs.esp = regs.r_esp;
160 linux_regs.xss = regs.r_ss;
161
162 return copyout(&linux_regs, (caddr_t)SCARG(uap, data),
163 sizeof(struct linux_reg));
164 case LINUX_PTRACE_SETREGS:
165 error = copyin((caddr_t)SCARG(uap, data), &linux_regs,
166 sizeof(struct linux_reg));
167 if (error != 0)
168 return error;
169
170 regs.r_ebx = linux_regs.ebx;
171 regs.r_ecx = linux_regs.ecx;
172 regs.r_edx = linux_regs.edx;
173 regs.r_esi = linux_regs.esi;
174 regs.r_edi = linux_regs.edi;
175 regs.r_ebp = linux_regs.ebp;
176 regs.r_eax = linux_regs.eax;
177 regs.r_ds = linux_regs.xds;
178 regs.r_es = linux_regs.xes;
179 regs.r_eip = linux_regs.eip;
180 regs.r_cs = linux_regs.xcs;
181 regs.r_eflags = linux_regs.eflags;
182 regs.r_esp = linux_regs.esp;
183 regs.r_ss = linux_regs.xss;
184
185 return process_write_regs(t, ®s);
186 }
187
188 return EIO;
189 }
190