do it right
[unix-history] / usr / src / sys / kern / sys_process.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
ff32eb64 6 * @(#)sys_process.c 7.3 (Berkeley) %G%
da7c5cc6 7 */
961945a8 8
ff32eb64 9#define IPCREG
961945a8
SL
10#include "../machine/reg.h"
11#include "../machine/psl.h"
12#include "../machine/pte.h"
9ce4de2d 13
94368568
JB
14#include "param.h"
15#include "systm.h"
16#include "dir.h"
17#include "user.h"
18#include "proc.h"
19#include "inode.h"
20#include "text.h"
21#include "seg.h"
22#include "vm.h"
23#include "buf.h"
24#include "acct.h"
01b0e233 25#include "ptrace.h"
9ce4de2d 26
4147b3f6
BJ
27/*
28 * Priority for tracing
29 */
30#define IPCPRI PZERO
31
32/*
33 * Tracing variables.
34 * Used to pass trace command from
35 * parent to child being traced.
36 * This data base cannot be
37 * shared and is locked
38 * per user.
39 */
40struct {
41 int ip_lock;
42 int ip_req;
43 int *ip_addr;
44 int ip_data;
45} ipc;
46
47/*
48 * sys-trace system call.
49 */
50ptrace()
51{
52 register struct proc *p;
53 register struct a {
54 int req;
55 int pid;
56 int *addr;
57 int data;
58 } *uap;
59
60 uap = (struct a *)u.u_ap;
61 if (uap->req <= 0) {
62 u.u_procp->p_flag |= STRC;
63 return;
64 }
65 p = pfind(uap->pid);
f05cf4fe
SL
66 if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid ||
67 !(p->p_flag & STRC)) {
4147b3f6
BJ
68 u.u_error = ESRCH;
69 return;
70 }
71 while (ipc.ip_lock)
72 sleep((caddr_t)&ipc, IPCPRI);
73 ipc.ip_lock = p->p_pid;
74 ipc.ip_data = uap->data;
75 ipc.ip_addr = uap->addr;
76 ipc.ip_req = uap->req;
77 p->p_flag &= ~SWTED;
78 while (ipc.ip_req > 0) {
79 if (p->p_stat==SSTOP)
80 setrun(p);
81 sleep((caddr_t)&ipc, IPCPRI);
82 }
83 u.u_r.r_val1 = ipc.ip_data;
84 if (ipc.ip_req < 0)
85 u.u_error = EIO;
86 ipc.ip_lock = 0;
87 wakeup((caddr_t)&ipc);
88}
89
fc0890b1 90#define PHYSOFF(p, o) \
883d0f83
BJ
91 ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
92
4147b3f6
BJ
93/*
94 * Code that the child process
95 * executes to implement the command
96 * of the parent process in tracing.
97 */
98procxmt()
99{
100 register int i;
101 register *p;
102 register struct text *xp;
103
104 if (ipc.ip_lock != u.u_procp->p_pid)
105 return (0);
106 u.u_procp->p_slptime = 0;
107 i = ipc.ip_req;
108 ipc.ip_req = 0;
109 switch (i) {
110
01b0e233 111 case PT_READ_I: /* read the child's text space */
4147b3f6
BJ
112 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
113 goto error;
114 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
115 break;
116
01b0e233 117 case PT_READ_D: /* read the child's data space */
4147b3f6
BJ
118 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
119 goto error;
120 ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
121 break;
122
01b0e233 123 case PT_READ_U: /* read the child's u. */
4147b3f6
BJ
124 i = (int)ipc.ip_addr;
125 if (i<0 || i >= ctob(UPAGES))
126 goto error;
883d0f83 127 ipc.ip_data = *(int *)PHYSOFF(&u, i);
4147b3f6
BJ
128 break;
129
01b0e233 130 case PT_WRITE_I: /* write the child's text space */
4147b3f6
BJ
131 /*
132 * If text, must assure exclusive use
133 */
134 if (xp = u.u_procp->p_textp) {
135 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
136 goto error;
cdb14d96 137 xp->x_flag |= XTRC;
4147b3f6
BJ
138 }
139 i = -1;
883d0f83
BJ
140 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
141 if (chgprot((caddr_t)ipc.ip_addr, RW) &&
142 chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
143 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
144 (void) chgprot((caddr_t)ipc.ip_addr, RO);
145 (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
146 }
4147b3f6
BJ
147 if (i < 0)
148 goto error;
fb1db32c
MK
149#if defined(tahoe)
150 /* make sure the old value is not in cache */
151 ckeyrelease(u.u_procp->p_ckey);
152 u.u_procp->p_ckey = getcodekey();
153#endif
154 if (xp) {
4147b3f6 155 xp->x_flag |= XWRIT;
fb1db32c
MK
156#if defined(tahoe)
157 xp->x_ckey = u.u_procp->p_ckey;
158#endif
159 }
4147b3f6
BJ
160 break;
161
01b0e233 162 case PT_WRITE_D: /* write the child's data space */
4147b3f6
BJ
163 if (suword((caddr_t)ipc.ip_addr, 0) < 0)
164 goto error;
165 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
166 break;
167
01b0e233 168 case PT_WRITE_U: /* write the child's u. */
4147b3f6 169 i = (int)ipc.ip_addr;
883d0f83
BJ
170 p = (int *)PHYSOFF(&u, i);
171 for (i=0; i<NIPCREG; i++)
4147b3f6
BJ
172 if (p == &u.u_ar0[ipcreg[i]])
173 goto ok;
174 if (p == &u.u_ar0[PS]) {
883d0f83 175 ipc.ip_data |= PSL_USERSET;
4147b3f6
BJ
176 ipc.ip_data &= ~PSL_USERCLR;
177 goto ok;
178 }
179 goto error;
180
181 ok:
182 *p = ipc.ip_data;
183 break;
184
01b0e233
MK
185 case PT_STEP: /* single step the child */
186 case PT_CONTINUE: /* continue the child */
4147b3f6
BJ
187 if ((int)ipc.ip_addr != 1)
188 u.u_ar0[PC] = (int)ipc.ip_addr;
189 if ((unsigned)ipc.ip_data > NSIG)
190 goto error;
191 u.u_procp->p_cursig = ipc.ip_data; /* see issig */
01b0e233 192 if (i == PT_STEP)
4147b3f6
BJ
193 u.u_ar0[PS] |= PSL_T;
194 wakeup((caddr_t)&ipc);
195 return (1);
196
01b0e233 197 case PT_KILL: /* kill the child process */
4147b3f6
BJ
198 wakeup((caddr_t)&ipc);
199 exit(u.u_procp->p_cursig);
200
201 default:
202 error:
203 ipc.ip_req = -1;
204 }
205 wakeup((caddr_t)&ipc);
206 return (0);
207}