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