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