xref: /csrg-svn/sys/kern/sys_process.c (revision 8037)
1 /*	sys_process.c	5.3	82/09/04	*/
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/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 		u.u_error = ESRCH;
60 		return;
61 	}
62 	while (ipc.ip_lock)
63 		sleep((caddr_t)&ipc, IPCPRI);
64 	ipc.ip_lock = p->p_pid;
65 	ipc.ip_data = uap->data;
66 	ipc.ip_addr = uap->addr;
67 	ipc.ip_req = uap->req;
68 	p->p_flag &= ~SWTED;
69 	while (ipc.ip_req > 0) {
70 		if (p->p_stat==SSTOP)
71 			setrun(p);
72 		sleep((caddr_t)&ipc, IPCPRI);
73 	}
74 	u.u_r.r_val1 = ipc.ip_data;
75 	if (ipc.ip_req < 0)
76 		u.u_error = EIO;
77 	ipc.ip_lock = 0;
78 	wakeup((caddr_t)&ipc);
79 }
80 
81 int ipcreg[] = {R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC};
82 /*
83  * Code that the child process
84  * executes to implement the command
85  * of the parent process in tracing.
86  */
87 procxmt()
88 {
89 	register int i;
90 	register *p;
91 	register struct text *xp;
92 
93 	if (ipc.ip_lock != u.u_procp->p_pid)
94 		return (0);
95 	u.u_procp->p_slptime = 0;
96 	i = ipc.ip_req;
97 	ipc.ip_req = 0;
98 	switch (i) {
99 
100 	/* read user I */
101 	case 1:
102 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
103 			goto error;
104 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
105 		break;
106 
107 	/* read user D */
108 	case 2:
109 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
110 			goto error;
111 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
112 		break;
113 
114 	/* read u */
115 	case 3:
116 		i = (int)ipc.ip_addr;
117 		if (i<0 || i >= ctob(UPAGES))
118 			goto error;
119 		ipc.ip_data = ((physadr)&u)->r[i>>2];
120 		break;
121 
122 	/* write user I */
123 	/* Must set up to allow writing */
124 	case 4:
125 		/*
126 		 * If text, must assure exclusive use
127 		 */
128 		if (xp = u.u_procp->p_textp) {
129 			if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
130 				goto error;
131 			xp->x_iptr->i_flag &= ~ITEXT;
132 		}
133 		i = -1;
134 		if (chgprot((caddr_t)ipc.ip_addr, RW) &&
135 		    chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
136 			i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
137 		(void) chgprot((caddr_t)ipc.ip_addr, RO);
138 		(void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
139 		if (i < 0)
140 			goto error;
141 		if (xp)
142 			xp->x_flag |= XWRIT;
143 		break;
144 
145 	/* write user D */
146 	case 5:
147 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
148 			goto error;
149 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
150 		break;
151 
152 	/* write u */
153 	case 6:
154 		i = (int)ipc.ip_addr;
155 		p = (int *)&((physadr)&u)->r[i>>2];
156 		for (i=0; i<16; i++)
157 			if (p == &u.u_ar0[ipcreg[i]])
158 				goto ok;
159 		if (p == &u.u_ar0[PS]) {
160 			ipc.ip_data |= PSL_CURMOD|PSL_PRVMOD;
161 			ipc.ip_data &=  ~PSL_USERCLR;
162 			goto ok;
163 		}
164 		goto error;
165 
166 	ok:
167 		*p = ipc.ip_data;
168 		break;
169 
170 	/* set signal and continue */
171 	/* one version causes a trace-trap */
172 	case 9:
173 	case 7:
174 		if ((int)ipc.ip_addr != 1)
175 			u.u_ar0[PC] = (int)ipc.ip_addr;
176 		if ((unsigned)ipc.ip_data > NSIG)
177 			goto error;
178 		u.u_procp->p_cursig = ipc.ip_data;	/* see issig */
179 		if (i == 9)
180 			u.u_ar0[PS] |= PSL_T;
181 		wakeup((caddr_t)&ipc);
182 		return (1);
183 
184 	/* force exit */
185 	case 8:
186 		wakeup((caddr_t)&ipc);
187 		exit(u.u_procp->p_cursig);
188 
189 	default:
190 	error:
191 		ipc.ip_req = -1;
192 	}
193 	wakeup((caddr_t)&ipc);
194 	return (0);
195 }
196