Commit | Line | Data |
---|---|---|
d610219d HK |
1 | #include "head.h" |
2 | #include <a.out.h> | |
3 | #include "cdefs.h" | |
4 | struct user u; | |
5 | BKPTR bkpthead; | |
6 | ||
7 | /* initialize frame pointers to top of call stack */ | |
8 | struct proct * | |
9 | initframe() { | |
10 | argp = *(ADDR *) (((ADDR) &u) + AP); | |
11 | frame = *(ADDR *) (((ADDR) &u) + FP); | |
12 | callpc = *(ADDR *) (((ADDR) &u) + PC); | |
13 | if ((frame == 0) || (frame & 0xf0000000 != 0x70000000)) | |
14 | return(badproc); | |
15 | return(adrtoproc(callpc++)); /* ++ because UNIX backs up instrs */ | |
16 | } | |
17 | ||
18 | ||
19 | struct proct * | |
20 | nextframe() { | |
21 | callpc = get(frame+16, DSP); | |
22 | argp = get(frame+8, DSP); | |
23 | frame = get(frame+12, DSP) & EVEN; | |
24 | if (callpc > 0x70000000) { /* error handler kludge */ | |
25 | callpc = get(argp+12, DSP); | |
26 | argp = get(frame+8, DSP); | |
27 | frame = get(frame+12, DSP) & EVEN; | |
28 | } | |
29 | if ((frame == 0) || (frame & 0xf0000000 != 0x70000000)) | |
30 | return(badproc); | |
31 | return(adrtoproc(callpc-1)); | |
32 | } | |
33 | ||
34 | /* returns core image address for variable */ | |
35 | ADDR | |
36 | formaddr(class, addr) | |
37 | register char class; | |
38 | ADDR addr; { | |
39 | if (debug) printf("formaddr(%o, %d)\n", class & 0377, addr); | |
40 | switch(class & STABMASK) { | |
41 | case N_RSYM: | |
42 | return(stackreg(addr)); | |
43 | case N_GSYM: | |
44 | case N_SSYM: | |
45 | case N_STSYM: | |
46 | case N_LCSYM: | |
47 | return(addr); | |
48 | ||
49 | case N_PSYM: | |
50 | return(argp+addr); | |
51 | ||
52 | case N_LSYM: | |
53 | return(frame+addr); | |
54 | ||
55 | default: | |
56 | printf("Bad class in formaddr: 0%o", | |
57 | class & 0377); | |
58 | return(0); | |
59 | } | |
60 | } | |
61 | ||
62 | char class; | |
63 | ||
64 | /* | |
65 | * stackreg(reg): | |
66 | * If the register for the current frame is somewhere on the stack | |
67 | * then return the address of where it is, otherwise its still in | |
68 | * the register so return the register number. | |
69 | * We distinguish the two by noting that register numbers are less | |
70 | * than 16 and that stack addresses are greater. | |
71 | * | |
72 | * MACHINE DEPENDENT | |
73 | */ | |
74 | ADDR | |
75 | stackreg(reg) { | |
76 | register int curframe, regfl, mask, i; | |
77 | struct proct *procp; | |
78 | ADDR regaddr; | |
79 | ||
80 | curframe = frame; | |
81 | regaddr = reg; | |
82 | regfl = 0x10000 << reg; | |
83 | for (procp=initframe(); frame!=curframe; procp=nextframe()) { | |
84 | if (procp == badproc) { | |
85 | error("Stackreg error: frame"); | |
86 | return(-1); | |
87 | } | |
88 | mask = get(frame+4, DSP); | |
89 | if (mask & regfl) { | |
90 | regaddr = frame + 20; | |
91 | for (i=0; i<reg; i++) { | |
92 | if (mask & 0x10000) | |
93 | regaddr += WORDSIZE; | |
94 | mask = mask >> 1; | |
95 | } | |
96 | if (!(mask & 0x10000)) { | |
97 | error("Stackreg error: contents"); | |
98 | return(-1); | |
99 | } | |
100 | } | |
101 | } | |
102 | return(regaddr); | |
103 | } | |
104 | ||
105 | /* returns address of proc:var. Sets externals class and subflag */ | |
106 | ADDR | |
107 | varaddr(proc, var) | |
108 | char *proc, *var; { | |
109 | return(findvar(proc, var, "", 0)); | |
110 | } | |
111 | ||
112 | /* | |
113 | * displays values of variables matching proc:var, | |
114 | * returns its address | |
115 | */ | |
116 | ADDR | |
117 | dispvar(proc, var, fmt) | |
118 | char *proc, *var, *fmt; { | |
119 | return(findvar(proc, var, fmt, 1)); | |
120 | } | |
121 | ||
122 | /* | |
123 | * Find and print values of all variables matching proc:var | |
124 | * using specified format. | |
125 | * Returns address of last matching variable. | |
126 | * | |
127 | * prvar==0 => no output, | |
128 | * prvar==1 => output value, | |
129 | * prvar==2 => output addr | |
130 | */ | |
131 | ADDR | |
132 | findvar(proc, var, fmt, prvar) | |
133 | char *proc, *var, *fmt; { | |
134 | ADDR addr = -1, a = -1; | |
135 | int metaflag = 0, match=0, nullflag=0, depthcnt = -1; | |
136 | char *comblk; | |
137 | register struct proct *procp; | |
138 | ||
139 | if (var[0] == '\0') { | |
140 | error("Unexpected null variable name"); | |
141 | return(-1); | |
142 | } | |
143 | ||
144 | metaflag = eqany('*', proc) || eqany('?', proc) || | |
145 | eqany('*', var) || eqany('?', var); | |
146 | ||
147 | if (proc[0] == '\0') { | |
148 | nullflag++; | |
149 | proc = curproc()->pname; | |
150 | } | |
151 | ||
152 | comblk = colonflag ? "" : "*"; | |
153 | ||
154 | if (integ && !eqany(var[0], "->.[")) { | |
155 | depthcnt = integ; | |
156 | } | |
157 | if (integ) { | |
158 | if (eqany(var[0], "->.[")) | |
159 | match++; | |
160 | else | |
161 | depthcnt = integ; | |
162 | } | |
163 | ||
164 | procp = initframe(); | |
165 | if (!eqany(var[0], "->.[") && !(nullflag && colonflag)) { | |
166 | do { | |
167 | if (eqpat(proc, procp->pname)) { | |
168 | match++; | |
169 | if (--depthcnt==0 || integ==0) { | |
170 | a = outvar(procp->pname, var, fmt, | |
171 | metaflag, integ, N_GSYM, | |
172 | 0, prname, comblk, prvar); | |
173 | if (a != -1) | |
174 | addr = a; | |
175 | if (depthcnt == 0) | |
176 | break; | |
177 | } | |
178 | } | |
179 | } while ((procp=nextframe()) != badproc); | |
180 | } | |
181 | ||
182 | if ((colonflag || metaflag || a == -1) && | |
183 | (nullflag || eqpat(proc, ""))) { | |
184 | a = outvar("", var, fmt, metaflag, integ, | |
185 | N_GSYM, 0, prname, comblk, prvar); | |
186 | if (a != -1) { | |
187 | addr = a; | |
188 | match++; | |
189 | } | |
190 | } | |
191 | ||
192 | if (match==0 && colonflag) { | |
193 | procp = initframe(); | |
194 | do { | |
195 | if (eqstr(curproc()->pname, procp->pname)) | |
196 | break; | |
197 | } while ((procp=nextframe()) != badproc); | |
198 | a = outvar(curproc()->pname, var, fmt, metaflag, | |
199 | integ, N_GSYM, 0, prname, | |
200 | nullflag ? "_BLNK_" : proc, prvar); | |
201 | if (a != -1) { | |
202 | addr = a; | |
203 | match++; | |
204 | } | |
205 | } | |
206 | ||
207 | if (match == 0) { | |
208 | printf("%s not an active procedure\n", proc); | |
209 | return(-1); | |
210 | } | |
211 | if (addr == -1) { | |
212 | if (var[0] == '.') | |
213 | var++; | |
214 | if (proc[0]) | |
215 | printf("%.8s:%s not found\n", proc, var); | |
216 | else | |
217 | printf("%s not found\n", var); | |
218 | return(-1); | |
219 | } | |
220 | return(addr); | |
221 | } | |
222 | ||
223 | char * | |
224 | typetodesc(type, subflag) | |
225 | short type; { | |
226 | register int ptr, ftn, ary; | |
227 | register char *desc; | |
228 | ||
229 | static char *typedesc[] = { | |
230 | "d", /* undef */ | |
231 | "d", /* farg */ | |
232 | "c", /* char */ | |
233 | "hd", /* short */ | |
234 | "d", /* int */ | |
235 | "ld", /* long */ | |
236 | "f", /* float */ | |
237 | "g", /* double */ | |
238 | "d", /* strty */ | |
239 | "d", /* unionty */ | |
240 | "d", /* enumty */ | |
241 | "d", /* moety */ | |
242 | "bu", /* uchar */ | |
243 | "hu", /* ushort */ | |
244 | "u", /* unsigned */ | |
245 | "lu", /* ulong */ | |
246 | "d" /* ? */ | |
247 | }; | |
248 | ||
249 | ptr = ftn = ary = 0; | |
250 | ||
251 | desc = typedesc[type&BTMASK]; | |
252 | for (; type & TMASK; type = DECREF(type)) { | |
253 | if (ISPTR(type)) ptr++; | |
254 | else if (ISFTN(type)) ftn++; | |
255 | else if (ISARY(type)) ary++; | |
256 | } | |
257 | ||
258 | if ((ptr-subflag == 1 || ary-subflag == 1) && desc[0] == 'c') | |
259 | return("s"); | |
260 | if (debug) | |
261 | printf ("PTR %d; FTN %d; ARY %d; DESC %s\n",ptr,ftn,ary,desc); | |
262 | if (ptr + ary == subflag) | |
263 | return(desc); | |
264 | if (ptr) return("x"); | |
265 | if (ptr==1 && ftn==1) return("p"); | |
266 | return(desc); | |
267 | } | |
268 | ||
269 | typetosize(type, stsize) | |
270 | short type; { | |
271 | register int ptr, ftn, ary; | |
272 | register int size; | |
273 | ||
274 | static char typesize[] = { | |
275 | 4, /* undef */ | |
276 | 4, /* farg */ | |
277 | 1, /* char */ | |
278 | 2, /* short */ | |
279 | WORDSIZE, /* int */ | |
280 | 4, /* long */ | |
281 | 4, /* float */ | |
282 | 8, /* double */ | |
283 | 0, /* strty */ | |
284 | 0, /* unionty */ | |
285 | 4, /* enumty */ | |
286 | 4, /* moety */ | |
287 | 1, /* uchar */ | |
288 | 2, /* ushort */ | |
289 | 4, /* unsigned */ | |
290 | 4, /* ulong */ | |
291 | 4 /* ? */ | |
292 | }; | |
293 | ||
294 | ptr = ftn = ary = 0; | |
295 | ||
296 | size = typesize[type&BTMASK]; | |
297 | for (; type & TMASK; type = DECREF(type)) { | |
298 | if (ISPTR(type)) ptr++; | |
299 | else if (ISFTN(type)) ftn++; | |
300 | else if (ISARY(type)) ary++; | |
301 | } | |
302 | ||
303 | if (debug) | |
304 | printf ("PTR %d; FTN %d; ARY %d; SIZE %d; STSIZE %d\n", | |
305 | ptr,ftn,ary,size,stsize); | |
306 | if (ptr>1) return(4); | |
307 | if (size == 0) return(stsize); | |
308 | else return(size); | |
309 | } | |
310 | ||
311 | ||
312 | /* print breakpoints */ | |
313 | prbkpt() { | |
314 | register BKPTR bkptr; | |
315 | register int cnt; | |
316 | char *cmdp; | |
317 | ||
318 | cnt = 0; | |
319 | ||
320 | for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt) | |
321 | if (bkptr->flag) { | |
322 | cnt++; | |
323 | printbkpt("", adrtoprocp(bkptr->loc)->pname, | |
324 | adrtolineno(bkptr->loc)); | |
325 | cmdp = bkptr->comm; | |
326 | if (*cmdp != '\n') { | |
327 | printf(" <"); | |
328 | while (*cmdp != '\n') | |
329 | printf("%c", *cmdp++); | |
330 | printf(">\n"); | |
331 | } | |
332 | else | |
333 | printf("\n"); | |
334 | } | |
335 | if (cnt == 0) | |
336 | printf("No breakpoints set\n"); | |
337 | } | |
338 | ||
339 | /* interactively delete breakpoints */ | |
340 | ||
341 | idbkpt() { | |
342 | register BKPTR bkptr; | |
343 | register int yesflg, cnt; | |
344 | register char c; | |
345 | ||
346 | cnt = 0; | |
347 | ||
348 | for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt) | |
349 | if (bkptr->flag) { | |
350 | printbkpt(" ? ", adrtoprocp(bkptr->loc)->pname, | |
351 | adrtolineno(bkptr->loc)); | |
352 | yesflg = 0; | |
353 | cnt++; | |
354 | do { | |
355 | c = getchar(); | |
356 | if (c == 'y' || c == 'd') yesflg++; | |
357 | } while (c != '\n'); | |
358 | if (yesflg) | |
359 | bkptr->flag = 0; | |
360 | } | |
361 | if (cnt == 0) | |
362 | printf("No breakpoints set\n"); | |
363 | } | |
364 | ||
365 | /* delete all breakpoints */ | |
366 | ||
367 | dabkpt() { | |
368 | register BKPTR bkptr; | |
369 | ||
370 | for (bkptr = bkpthead; bkptr; bkptr=bkptr->nxtbkpt) | |
371 | bkptr->flag = 0; | |
372 | } | |
373 | printbkpt(s, name, lineno) | |
374 | char *s, *name; { | |
375 | if (name[0] == '_') | |
376 | printf("%.7s:", name+1); | |
377 | else | |
378 | printf("%.8s:", name); | |
379 | ||
380 | if (lineno != -1) | |
381 | printf("%d%s", lineno, s); | |
382 | else | |
383 | printf("%s", s); | |
384 | } | |
385 | ||
386 | /* print call frame */ | |
387 | prframe() { | |
388 | prfrx(0); | |
389 | } | |
390 | ||
391 | /* set top to print just the top procedure */ | |
392 | prfrx(top) { | |
393 | int narg; | |
394 | long offset; | |
395 | register char class; | |
396 | register int endflg; | |
397 | char *p; | |
398 | struct proct *procp; | |
399 | struct nlist stentry; | |
400 | ||
401 | if ((procp = initframe()) == badproc) return; | |
402 | do { | |
403 | if (get(frame+12, DSP) == 0) return; | |
404 | p = procp->pname; | |
405 | if (eqstr("__dbsubc", p)) return; | |
406 | if (p[0] == '_') { | |
407 | endflg = 1; | |
408 | printf("%.7s(", p+1); | |
409 | } | |
410 | else { | |
411 | printf("%.8s(", p); | |
412 | endflg = 0; | |
413 | } | |
414 | if (endflg == 0) { | |
415 | offset = procp->st_offset; | |
416 | blseek(&sbuf, offset, 0); | |
417 | do { | |
418 | if (bread(&sbuf, &stentry, sizeof stentry) < | |
419 | sizeof stentry) { | |
420 | endflg++; | |
421 | break; | |
422 | } | |
423 | class = stentry.n_type & STABMASK; | |
424 | } while (class == N_FUN); | |
425 | while (class != N_PSYM) { | |
426 | if (bread(&sbuf, &stentry, sizeof stentry) < | |
427 | sizeof stentry) { | |
428 | endflg++; | |
429 | break; | |
430 | } | |
431 | class = stentry.n_type & STABMASK; | |
432 | if (class == N_FUN) { | |
433 | endflg++; | |
434 | break; | |
435 | } | |
436 | } | |
437 | } | |
438 | ||
439 | narg = get(argp, DSP); | |
440 | if (narg & ~0xff) narg = 0; | |
441 | argp += WORDSIZE; | |
442 | while (narg) { | |
443 | if (endflg) { | |
444 | printf("%d", get(argp, DSP)); | |
445 | argp += 4; | |
446 | } else { | |
447 | int length; | |
448 | printf("%.8s=", stentry.n_name); | |
449 | dispx(argp, "", N_GSYM, stentry.n_desc, 0, 0); | |
450 | length = typetosize(stentry.n_desc, 0); | |
451 | if (length > WORDSIZE) | |
452 | argp += length; | |
453 | else | |
454 | argp += WORDSIZE; | |
455 | } | |
456 | do { | |
457 | if (endflg) break; | |
458 | if (bread(&sbuf, &stentry, sizeof stentry) < | |
459 | sizeof stentry) { | |
460 | endflg++; | |
461 | break; | |
462 | } | |
463 | class = stentry.n_type & STABMASK; | |
464 | if (class == N_FUN) { | |
465 | endflg++; | |
466 | break; | |
467 | } | |
468 | } while (class != N_PSYM); | |
469 | l1: if (--narg != 0) printf(","); | |
470 | } | |
471 | printf(")"); | |
472 | if (debug) printf(" @ 0x%x ", callpc); | |
473 | if (procp->sfptr != badfile) | |
474 | printf(" [%s:%d]", adrtofilep(callpc-1)->sfilename, | |
475 | adrtolineno(callpc-1)); | |
476 | printf("\n"); | |
477 | } while (((procp = nextframe()) != badproc) && !top); | |
478 | } | |
479 | ||
480 | STRING signals[] = { | |
481 | "", | |
482 | "hangup", | |
483 | "interrupt", | |
484 | "quit", | |
485 | "illegal instruction", | |
486 | "trace/BPT", | |
487 | "IOT", | |
488 | "EMT", | |
489 | "floating exception", | |
490 | "killed", | |
491 | "bus error", | |
492 | "memory fault", | |
493 | "bad system call", | |
494 | "broken pipe", | |
495 | "alarm call", | |
496 | "terminated", | |
497 | }; | |
498 | INT signo; | |
499 | ||
500 | sigprint() { | |
501 | printf("%s", signals[signo]); | |
502 | } | |
503 |