xref: /csrg-svn/sys/kern/sys_process.c (revision 12496)
1 /*	sys_process.c	5.9	83/05/18	*/
2 
3 #include "../machine/reg.h"
4 #include "../machine/psl.h"
5 #include "../machine/pte.h"
6 
7 #include "../h/param.h"
8 #include "../h/systm.h"
9 #include "../h/dir.h"
10 #include "../h/user.h"
11 #include "../h/proc.h"
12 #include "../h/inode.h"
13 #include "../h/text.h"
14 #include "../h/seg.h"
15 #include "../h/vm.h"
16 #include "../h/buf.h"
17 #include "../h/acct.h"
18 
19 /*
20  * Priority for tracing
21  */
22 #define	IPCPRI	PZERO
23 
24 /*
25  * Tracing variables.
26  * Used to pass trace command from
27  * parent to child being traced.
28  * This data base cannot be
29  * shared and is locked
30  * per user.
31  */
32 struct {
33 	int	ip_lock;
34 	int	ip_req;
35 	int	*ip_addr;
36 	int	ip_data;
37 } ipc;
38 
39 /*
40  * sys-trace system call.
41  */
42 ptrace()
43 {
44 	register struct proc *p;
45 	register struct a {
46 		int	req;
47 		int	pid;
48 		int	*addr;
49 		int	data;
50 	} *uap;
51 
52 	uap = (struct a *)u.u_ap;
53 	if (uap->req <= 0) {
54 		u.u_procp->p_flag |= STRC;
55 		return;
56 	}
57 	p = pfind(uap->pid);
58 	if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid ||
59 	    !(p->p_flag & STRC)) {
60 		u.u_error = ESRCH;
61 		return;
62 	}
63 	while (ipc.ip_lock)
64 		sleep((caddr_t)&ipc, IPCPRI);
65 	ipc.ip_lock = p->p_pid;
66 	ipc.ip_data = uap->data;
67 	ipc.ip_addr = uap->addr;
68 	ipc.ip_req = uap->req;
69 	p->p_flag &= ~SWTED;
70 	while (ipc.ip_req > 0) {
71 		if (p->p_stat==SSTOP)
72 			setrun(p);
73 		sleep((caddr_t)&ipc, IPCPRI);
74 	}
75 	u.u_r.r_val1 = ipc.ip_data;
76 	if (ipc.ip_req < 0)
77 		u.u_error = EIO;
78 	ipc.ip_lock = 0;
79 	wakeup((caddr_t)&ipc);
80 }
81 
82 #ifdef vax
83 #define	NIPCREG 16
84 #endif
85 #ifdef sun
86 #define	NIPCREG 17
87 #endif
88 int ipcreg[NIPCREG] =
89 #ifdef vax
90 	{R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC};
91 #endif
92 #ifdef sun
93 	{R0,R1,R2,R3,R4,R5,R6,R7,AR0,AR1,AR2,AR3,AR4,AR5,AR6,AR7,PC};
94 #endif
95 
96 #define	PHYSOFF(p, o) \
97 	((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
98 
99 /*
100  * Code that the child process
101  * executes to implement the command
102  * of the parent process in tracing.
103  */
104 procxmt()
105 {
106 	register int i;
107 	register *p;
108 	register struct text *xp;
109 
110 	if (ipc.ip_lock != u.u_procp->p_pid)
111 		return (0);
112 	u.u_procp->p_slptime = 0;
113 	i = ipc.ip_req;
114 	ipc.ip_req = 0;
115 	switch (i) {
116 
117 	/* read user I */
118 	case 1:
119 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
120 			goto error;
121 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
122 		break;
123 
124 	/* read user D */
125 	case 2:
126 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
127 			goto error;
128 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
129 		break;
130 
131 	/* read u */
132 	case 3:
133 		i = (int)ipc.ip_addr;
134 		if (i<0 || i >= ctob(UPAGES))
135 			goto error;
136 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
137 		break;
138 
139 	/* write user I */
140 	/* Must set up to allow writing */
141 	case 4:
142 		/*
143 		 * If text, must assure exclusive use
144 		 */
145 		if (xp = u.u_procp->p_textp) {
146 			if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
147 				goto error;
148 			xp->x_iptr->i_flag &= ~ITEXT;
149 		}
150 		i = -1;
151 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
152 			if (chgprot((caddr_t)ipc.ip_addr, RW) &&
153 			    chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
154 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
155 			(void) chgprot((caddr_t)ipc.ip_addr, RO);
156 			(void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
157 		}
158 		if (i < 0)
159 			goto error;
160 		if (xp)
161 			xp->x_flag |= XWRIT;
162 		break;
163 
164 	/* write user D */
165 	case 5:
166 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
167 			goto error;
168 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
169 		break;
170 
171 	/* write u */
172 	case 6:
173 		i = (int)ipc.ip_addr;
174 		p = (int *)PHYSOFF(&u, i);
175 		for (i=0; i<NIPCREG; i++)
176 			if (p == &u.u_ar0[ipcreg[i]])
177 				goto ok;
178 		if (p == &u.u_ar0[PS]) {
179 			ipc.ip_data |= PSL_USERSET;
180 			ipc.ip_data &=  ~PSL_USERCLR;
181 #ifdef sun
182 			if (ipc.ip_data & PSL_T)
183 				traceon();
184 			else
185 				traceoff();
186 #endif
187 			goto ok;
188 		}
189 		goto error;
190 
191 	ok:
192 		*p = ipc.ip_data;
193 		break;
194 
195 	/* set signal and continue */
196 	/* one version causes a trace-trap */
197 	case 9:
198 	case 7:
199 		if ((int)ipc.ip_addr != 1)
200 			u.u_ar0[PC] = (int)ipc.ip_addr;
201 		if ((unsigned)ipc.ip_data > NSIG)
202 			goto error;
203 		u.u_procp->p_cursig = ipc.ip_data;	/* see issig */
204 		if (i == 9)
205 #ifdef sun
206 			traceon();
207 #else
208 			u.u_ar0[PS] |= PSL_T;
209 #endif
210 		wakeup((caddr_t)&ipc);
211 		return (1);
212 
213 	/* force exit */
214 	case 8:
215 		wakeup((caddr_t)&ipc);
216 		exit(u.u_procp->p_cursig);
217 
218 	default:
219 	error:
220 		ipc.ip_req = -1;
221 	}
222 	wakeup((caddr_t)&ipc);
223 	return (0);
224 }
225