xref: /original-bsd/old/adb/adb.tahoe/runpcs.c (revision 2301fdfb)
1 #ifndef lint
2 static	char sccsid[] = "@(#)runpcs.c	1.1 (Berkeley) 02/25/86";
3 #endif
4 /*
5  *
6  *	UNIX debugger
7  *
8  */
9 
10 #include "defs.h"
11 
12 extern	MAP	txtmap;
13 
14 MSG		NOFORK;
15 MSG		ENDPCS;
16 MSG		BADWAIT;
17 
18 CHAR		*lp;
19 SIG		sigint;
20 SIG		sigqit;
21 
22 /* breakpoints */
23 BKPTR		bkpthead;
24 
25 REGLIST		reglist[];
26 
27 CHAR		lastc;
28 
29 INT		fcor;
30 INT		fsym;
31 STRING		errflg;
32 INT		errno;
33 INT		signo;
34 INT		sigcode;
35 
36 L_INT		dot;
37 STRING		symfil;
38 INT		wtflag;
39 L_INT		pid;
40 L_INT		expv;
41 INT		adrflg;
42 L_INT		loopcnt;
43 
44 
45 
46 
47 
48 /* service routines for sub process control */
49 
50 getsig(sig)
51 {	return(expr(0) ? expv : sig);
52 }
53 
54 ADDR userpc = 1;
55 
56 runpcs(runmode,execsig)
57 {
58 	REG		rc;
59 	REG BKPTR	bkpt;
60 	IF adrflg THEN userpc=dot; FI
61 	printf("%s: running\n", symfil);
62 
63 	WHILE --loopcnt>=0
64 	DO
65 #ifdef DEBUG
66 		printf("\ncontinue %X %D loopcnt=%D\n",userpc,execsig, loopcnt);
67 #endif
68 		IF runmode==SINGLE
69 		THEN delbp(); /* hardware handles single-stepping */
70 		ELSE /* continuing from a breakpoint is hard */
71 			IF bkpt=scanbkpt(userpc)
72 			THEN execbkpt(bkpt,execsig); execsig=0;
73 			FI
74 			setbp();
75 		FI
76 		ptrace(runmode,pid,userpc,execsig);
77 		bpwait(); chkerr(); execsig=0; delbp(); readregs();
78 
79 		IF (signo==0) ANDF (bkpt=scanbkpt(userpc))
80 		THEN /* stopped by BPT instruction */
81 #ifdef DEBUG
82 			printf("\n BPT code; '%s'%o'%d",
83 				bkpt->comm,bkpt->comm[0],EOR,bkpt->flag);
84 #endif
85 			dot=bkpt->loc;
86 			IF bkpt->flag==BKPTEXEC
87 			ORF ((bkpt->flag=BKPTEXEC)
88 				ANDF bkpt->comm[0]!=EOR
89 				ANDF command(bkpt->comm,':')
90 				ANDF --bkpt->count)
91 			THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++;
92 			ELSE bkpt->count=bkpt->initcnt; rc=1;
93 			FI
94 		ELSE execsig=signo; rc=0;
95 		FI
96 	OD
97 	return(rc);
98 }
99 
100 #define BPOUT 0
101 #define BPIN 1
102 INT bpstate = BPOUT;
103 
104 endpcs()
105 {
106 	REG BKPTR	bkptr;
107 	IF pid
108 	THEN ptrace(EXIT,pid); pid=0; userpc=1;
109 	     FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
110 	     DO IF bkptr->flag
111 		THEN bkptr->flag=BKPTSET;
112 		FI
113 	     OD
114 	FI
115 	bpstate=BPOUT;
116 }
117 
118 #ifdef VFORK
119 nullsig()
120 {
121 
122 }
123 #endif
124 
125 setup()
126 {
127 	close(fsym); fsym = -1;
128 #ifndef VFORK
129 	IF (pid = fork()) == 0
130 #else
131 	IF (pid = vfork()) == 0
132 #endif
133 	THEN ptrace(SETTRC);
134 #ifdef VFORK
135 	     signal(SIGTRAP,nullsig);
136 #endif
137 	     signal(SIGINT,sigint); signal(SIGQUIT,sigqit);
138 	     doexec(); exit(0);
139 	ELIF pid == -1
140 	THEN error(NOFORK);
141 	ELSE bpwait(); readregs(); lp[0]=EOR; lp[1]=0;
142 	     fsym=open(symfil,wtflag);
143 	     IF errflg
144 	     THEN printf("%s: cannot execute\n",symfil);
145 		  endpcs(); error(0);
146 	     FI
147 	FI
148 	bpstate=BPOUT;
149 }
150 
151 execbkpt(bkptr,execsig)
152 BKPTR	bkptr;
153 {
154 #ifdef DEBUG
155 	printf("exbkpt: %d\n",bkptr->count);
156 #endif
157 	delbp();
158 	ptrace(SINGLE,pid,bkptr->loc,execsig);
159 	bkptr->flag=BKPTSET;
160 	bpwait(); chkerr(); readregs();
161 }
162 
163 
164 doexec()
165 {
166 	STRING		argl[MAXARG];
167 	CHAR		args[LINSIZ];
168 	REG	STRING	p, *ap, filnam;
169 	extern STRING environ;
170 
171 	ap=argl; p=args;
172 	*ap++=symfil;
173 	REP	IF rdc()==EOR THEN break; FI
174 		*ap = p;
175 		WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB DO *p++=lastc; readchar(); OD
176 		*p++=0; filnam = *ap+1;
177 		IF **ap=='<'
178 		THEN	close(0);
179 			IF open(filnam,0)<0
180 			THEN	printf("%s: cannot open\n",filnam); _exit(0);
181 			FI
182 		ELIF **ap=='>'
183 		THEN	close(1);
184 			IF creat(filnam,0666)<0
185 			THEN	printf("%s: cannot create\n",filnam); _exit(0);
186 			FI
187 		ELSE	ap++;
188 		FI
189 	PER lastc!=EOR DONE
190 	*ap++=0;
191 	execve(symfil, argl, environ);
192 	perror(symfil);
193 }
194 
195 BKPTR	scanbkpt(adr)
196 ADDR adr;
197 {
198 	REG BKPTR	bkptr;
199 	FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
200 	DO IF bkptr->flag ANDF bkptr->loc==adr
201 	   THEN break;
202 	   FI
203 	OD
204 	return(bkptr);
205 }
206 
207 delbp()
208 {
209 	REG ADDR	a;
210 	REG BKPTR	bkptr;
211 	IF bpstate!=BPOUT
212 	THEN
213 		FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
214 		DO	IF bkptr->flag
215 			THEN a=bkptr->loc;
216 				IF a < txtmap.e1 THEN
217 				ptrace(WIUSER,pid,a,bkptr->ins);
218 				ELSE
219 				ptrace(WDUSER,pid,a,bkptr->ins);
220 				FI
221 			FI
222 		OD
223 		bpstate=BPOUT;
224 	FI
225 }
226 
227 #if defined(vax)
228 #define	SETBP(ins)	(BPT | ((ins) &~ 0xff))
229 #else
230 #define	SETBP(ins)	((BPT<<24) | ((ins) & 0xffffff))
231 #endif
232 
233 setbp()
234 {
235 	REG ADDR	a;
236 	REG BKPTR	bkptr;
237 
238 	IF bpstate!=BPIN
239 	THEN
240 		FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
241 		DO IF bkptr->flag
242 		   THEN a = bkptr->loc;
243 			IF a < txtmap.e1 THEN
244 				bkptr->ins = ptrace(RIUSER, pid, a);
245 				ptrace(WIUSER, pid, a, SETBP(bkptr->ins));
246 			ELSE
247 				bkptr->ins = ptrace(RDUSER, pid, a);
248 				ptrace(WDUSER, pid, a, SETBP(bkptr->ins));
249 			FI
250 			IF errno
251 			THEN printf("cannot set breakpoint: ");
252 			     psymoff(bkptr->loc,ISYM,"\n");
253 			FI
254 		   FI
255 		OD
256 		bpstate=BPIN;
257 	FI
258 }
259 
260 bpwait()
261 {
262 	REG w;
263 	ADDR stat;
264 
265 	signal(SIGINT, 1);
266 	WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE
267 	signal(SIGINT,sigint);
268 	IF w == -1
269 	THEN pid=0;
270 	     errflg=BADWAIT;
271 	ELIF (stat & 0177) != 0177
272 	THEN sigcode = 0;
273 	     IF signo = stat&0177
274 	     THEN sigprint();
275 	     FI
276 	     IF stat&0200
277 	     THEN printf(" - core dumped");
278 		  close(fcor);
279 		  setcor();
280 	     FI
281 	     pid=0;
282 	     errflg=ENDPCS;
283 	ELSE signo = stat>>8;
284 	     sigcode = ptrace(RUREGS, pid, &((struct user *)0)->u_code, 0);
285 	     IF signo!=SIGTRAP
286 	     THEN sigprint();
287 	     ELSE signo=0;
288 	     FI
289 	     flushbuf();
290 	FI
291 }
292 
293 readregs()
294 {
295 	/*get REG values from pcs*/
296 	REG REGPTR	p;
297 
298 	FOR p=reglist; p->rname; p++
299 	DO *(ADDR *)(((ADDR)&u)+p->roffs) =
300 		    ptrace(RUREGS, pid, p->roffs, 0);
301 	OD
302  	userpc= *(ADDR *)(((ADDR)&u)+PC);
303 }
304