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