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