1 #ifndef lint
2 static char sccsid[] = "@(#)runpcs.c 4.6 4/25/85";
3 #endif
4 /*
5 *
6 * UNIX debugger
7 *
8 */
9
10 #include "defs.h"
11 #include <sys/wait.h>
12
13 extern MAP txtmap;
14
15 MSG NOFORK;
16 MSG ENDPCS;
17 MSG BADWAIT;
18
19 CHAR *lp;
20 ADDR sigint;
21 ADDR sigqit;
22
23 /* breakpoints */
24 BKPTR bkpthead;
25
26 extern REGLIST reglist[];
27 extern INT nregs;
28
29 CHAR lastc;
30
31 INT fcor;
32 INT fsym;
33 STRING errflg;
34 int errno;
35 INT signo;
36 INT sigcode;
37
38 L_INT dot;
39 STRING symfil;
40 INT wtflag;
41 INT pid;
42 L_INT expv;
43 INT adrflg;
44 L_INT loopcnt;
45
46
47
48
49
50 /* service routines for sub process control */
51
getsig(sig)52 getsig(sig)
53 { return(expr(0) ? expv : sig);
54 }
55
56 ADDR userpc = 1;
57
runpcs(runmode,execsig)58 runpcs(runmode,execsig)
59 {
60 INT rc;
61 REG BKPTR bkpt;
62 IF adrflg THEN userpc=dot; FI
63 printf("%s: running\n", symfil);
64
65 WHILE --loopcnt>=0
66 DO
67 #ifdef DEBUG
68 printf("\ncontinue %x %d\n",userpc,execsig);
69 #endif
70 IF runmode==SINGLE
71 THEN delbp(); /* hardware handles single-stepping */
72 ELSE /* continuing from a breakpoint is hard */
73 IF bkpt=scanbkpt(userpc)
74 THEN execbkpt(bkpt,execsig); execsig=0;
75 FI
76 setbp();
77 FI
78 ptrace(runmode,pid,userpc,execsig);
79 bpwait(); chkerr(); execsig=0; delbp(); readregs();
80
81 IF signo==0
82 ANDF runmode != SINGLE
83 #ifdef mc68000
84 ANDF (bkpt=scanbkpt(userpc - 2)) /* argh */
85 #else
86 ANDF (bkpt=scanbkpt(userpc))
87 #endif
88 THEN /* stopped by BPT instruction */
89 #ifdef DEBUG
90 printf("\n BPT code; '%s'%o'%o'%d",
91 bkpt->comm,bkpt->comm[0],EOR,bkpt->flag);
92 #endif
93 dot=bkpt->loc;
94 userpc = dot;
95 *(ADDR *)(((ADDR)&u)+PC-getradj(1)) = userpc;
96 IF bkpt->flag==BKPTEXEC
97 ORF ((bkpt->flag=BKPTEXEC)
98 ANDF bkpt->comm[0]!=EOR
99 ANDF command(bkpt->comm,':')
100 ANDF --bkpt->count)
101 THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++;
102 ELSE bkpt->count=bkpt->initcnt; rc=1;
103 FI
104 ELSE execsig=signo; rc=0;
105 FI
106 OD
107 return(rc);
108 }
109
110 #define BPOUT 0
111 #define BPIN 1
112 INT bpstate = BPOUT;
113
endpcs()114 endpcs()
115 {
116 REG BKPTR bkptr;
117 IF pid
118 THEN ptrace(PT_KILL,pid,0,0); pid=0; userpc=1;
119 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
120 DO IF bkptr->flag
121 THEN bkptr->flag=BKPTSET;
122 FI
123 OD
124 FI
125 bpstate=BPOUT;
126 }
127
128 #ifdef VFORK
nullsig()129 nullsig()
130 {
131
132 }
133 #endif
134
setup()135 setup()
136 {
137 close(fsym); fsym = -1;
138 #ifndef VFORK
139 IF (pid = fork()) == 0
140 #else
141 IF (pid = vfork()) == 0
142 #endif
143 THEN ptrace(PT_TRACE_ME,0,0,0);
144 #ifdef VFORK
145 signal(SIGTRAP,nullsig);
146 #endif
147 signal(SIGINT,sigint); signal(SIGQUIT,sigqit);
148 doexec(); exit(0);
149 ELIF pid == -1
150 THEN error(NOFORK);
151 ELSE bpwait(); readregs(); lp[0]=EOR; lp[1]=0;
152 fsym=open(symfil,wtflag);
153 IF errflg
154 THEN printf("%s: cannot execute\n",symfil);
155 endpcs(); error(0);
156 FI
157 FI
158 bpstate=BPOUT;
159 }
160
execbkpt(bkptr,execsig)161 execbkpt(bkptr,execsig)
162 BKPTR bkptr;
163 {
164 #ifdef DEBUG
165 printf("exbkpt: %d\n",bkptr->count);
166 #endif
167 delbp();
168 ptrace(PT_STEP,pid,bkptr->loc,execsig);
169 bkptr->flag=BKPTSET;
170 bpwait(); chkerr(); readregs();
171 }
172
173
doexec()174 doexec()
175 {
176 STRING argl[MAXARG];
177 CHAR args[LINSIZ];
178 STRING p, *ap, filnam;
179 extern STRING environ;
180 ap=argl; p=args;
181 *ap++=symfil;
182 REP IF rdc()==EOR THEN break; FI
183 *ap = p;
184 /*
185 * First thing is to look for direction characters
186 * and get filename. Do not use up the args for filenames.
187 * Then get rid of spaces before next args.
188 */
189 IF lastc=='<'
190 THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE
191 filnam = p;
192 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>'
193 DO *p++=lastc; readchar(); OD
194 *p = 0;
195 close(0);
196 IF open(filnam,0)<0
197 THEN printf("%s: cannot open\n",filnam); _exit(0);
198 FI
199 p = *ap;
200 ELIF lastc=='>'
201 THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE
202 filnam = p;
203 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='<'
204 DO *p++=lastc; readchar(); OD
205 *p = '\0';
206 close(1);
207 IF creat(filnam,0666)<0
208 THEN printf("%s: cannot create\n",filnam); _exit(0);
209 FI
210 p = *ap;
211 ELSE
212 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>' ANDF lastc!='<'
213 DO *p++=lastc; readchar(); OD
214 *p++ = '\0';
215 ap++;
216 FI
217 PER lastc!=EOR DONE
218 *ap++=0;
219 exect(symfil, argl, environ);
220 perror(symfil);
221 }
222
scanbkpt(adr)223 BKPTR scanbkpt(adr)
224 ADDR adr;
225 {
226 REG BKPTR bkptr;
227 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
228 DO IF bkptr->flag ANDF bkptr->loc==adr
229 THEN break;
230 FI
231 OD
232 return(bkptr);
233 }
234
delbp()235 delbp()
236 {
237 REG ADDR a;
238 REG BKPTR bkptr;
239 IF bpstate!=BPOUT
240 THEN
241 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
242 DO IF bkptr->flag
243 THEN a=bkptr->loc;
244 IF a < txtmap.e1 THEN
245 ptrace(PT_WRITE_I,pid,a,bkptr->ins);
246 ELSE
247 ptrace(PT_WRITE_D,pid,a,bkptr->ins);
248 FI
249 FI
250 OD
251 bpstate=BPOUT;
252 FI
253 }
254
255 #ifdef pdp11
256 help -- I left my architecture manual at home
257 #endif
258
259 #ifdef vax
260 #define SETBP(ins) (BPT | ((ins) &~ 0xFF))
261 #endif
262
263 #ifdef mc68000
264 #define SETBP(ins) ((BPT << 16) | ((ins) & 0xFFFF))
265 #endif
266
267 #if !pdp11 && !vax && !mc68000
268
269 edit this file to handle your machines breakpoint indication
270
271 #endif
272
273 setbp()
274 {
275 REG ADDR a;
276 REG BKPTR bkptr;
277
278 IF bpstate!=BPIN
279 THEN
280 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
281 DO IF bkptr->flag
282 THEN a = bkptr->loc;
283 IF a < txtmap.e1 THEN
284 bkptr->ins = ptrace(PT_READ_I, pid, a, 0);
285 ptrace(PT_WRITE_I, pid, a, SETBP(bkptr->ins));
286 ELSE
287 bkptr->ins = ptrace(PT_READ_D, pid, a, 0);
288 ptrace(PT_WRITE_D, pid, a, SETBP(bkptr->ins));
289 FI
290 IF errno
291 THEN prints("cannot set breakpoint: ");
292 psymoff(bkptr->loc,ISYM,"\n");
293 FI
294 FI
295 OD
296 bpstate=BPIN;
297 FI
298 }
299
bpwait()300 bpwait()
301 {
302 REG ADDR w;
303 union wait stat;
304
305 signal(SIGINT, 1);
306 WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE
307 signal(SIGINT,sigint);
308 IF w == -1
309 THEN pid=0;
310 errflg=BADWAIT;
311 ELIF !WIFSTOPPED(stat)
312 THEN sigcode = 0;
313 IF signo = stat.w_termsig
314 THEN sigprint();
315 FI
316 IF stat.w_coredump
317 THEN prints(" - core dumped");
318 close(fcor);
319 setcor();
320 FI
321 pid=0;
322 errflg=ENDPCS;
323 ELSE signo = stat.w_stopsig;
324 sigcode = ptrace(PT_READ_U, pid, &((struct user *)0)->u_code, 0);
325 IF signo!=SIGTRAP
326 THEN sigprint();
327 ELSE signo=0;
328 FI
329 flushbuf();
330 FI
331 }
332
readregs()333 readregs()
334 {
335 /*get REG values from pcs*/
336 REG i;
337 L_INT radj = getradj(1);
338 L_INT offset;
339
340 FOR i=nregs; --i>=0;
341 DO IF (offset = reglist[i].roffs) >= sizeof (struct user)
342 THEN offset -= radj;
343 FI
344 *(ADDR *)(((ADDR)&u) + offset) =
345 ptrace(PT_READ_U, pid, offset, 0);
346 #ifdef hp300
347 /* XXX: 68881/68882 FP regs are 3 longwords */
348 IF reglist[i].rtype == XPFLOAT
349 THEN offset += sizeof (ADDR);
350 *(ADDR *)(((ADDR)&u) + offset) =
351 ptrace(PT_READ_U, pid, offset, 0);
352 offset += sizeof (ADDR);
353 *(ADDR *)(((ADDR)&u) + offset) =
354 ptrace(PT_READ_U, pid, offset, 0);
355 FI
356 #endif
357 OD
358 userpc= *(ADDR *)(((ADDR)&u) + PC - radj);
359 }
360
361 #ifdef hp300
362 L_INT
getradj(running)363 getradj(running)
364 INT running;
365 {
366 L_INT radj;
367
368 /* this code assumes that u_ap always points to u_arg */
369 IF running
370 THEN u.u_ar0 = (int *) ptrace(PT_READ_U, pid,
371 (ADDR)&u.u_ar0 - (ADDR) &u, 0);
372 #if 0
373 u.u_ap = (int *) ptrace(PT_READ_U, pid,
374 (ADDR)&u.u_ap - (ADDR) &u, 0);
375 #endif
376 IF u.u_ar0 == -1
377 #if 0
378 ORF u.u_ap == -1
379 #endif
380 THEN endpcs();
381 error("can't read from running process");
382 return (0);
383 FI
384 FI
385 IF !kcore
386 THEN
387 #if 0
388 radj = (ADDR) &u.u_arg - (ADDR) &u; /* offset of u_arg */
389 radj = (ADDR) u.u_ap - radj; /* address of u */
390 #endif
391 radj = (ADDR) 0xfff00000;
392 radj = (ADDR) u.u_ar0 - radj; /* offset of d0 */
393 radj = D0 - radj; /* difference from expected offset */
394 ELSE
395 radj = 0;
396 FI
397 return (radj);
398 }
399 #endif
400