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