|
|
1.1 root 1: #include "head.h"
2: #include <a.out.h>
3: #include <sys/stat.h>
4:
5: struct user u;
6: int compar();
7: char *symfil;
8:
9: /* initialize file and procedure tables */
10: initfp() {
11: struct nlist stentry;
12: register struct proct *procp;
13: register struct filet *filep;
14: struct stat stbuf;
15:
16: long soffset;
17: int i;
18: char class;
19: register char *p, *q;
20:
21: sbuf.fd = txtmap.ufd;
22: soffset = ststart;
23: blseek(&sbuf,ststart,0);
24: filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
25: procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
26:
27: for(;;) {
28: if (bread(&sbuf, &stentry, sizeof stentry) <
29: sizeof stentry) break;
30: class = stentry.n_type & STABMASK;
31: switch (class & STABMASK) {
32: case N_SO:
33: case N_SOL:
34: if (filep == badfile) {
35: p = sbrk(FILEINCR*sizeof filep[0]);
36: if (p < 0) {
37: perror("sdb");
38: exit(4);
39: }
40: q = p + FILEINCR*sizeof filep[0];
41: while (p > (char *) procs)
42: *--q = *--p;
43: badfile += FILEINCR;
44: procp = (struct proct *)
45: ((char *) procp +
46: FILEINCR*sizeof filep[0]);
47: procs = (struct proct *)
48: ((char *) procs +
49: FILEINCR*sizeof filep[0]);
50: badproc = (struct proct *)
51: ((char *)badproc +
52: FILEINCR*sizeof filep[0]);
53: }
54: filep->faddr = stentry.n_value;
55: filep->lineflag = (class == N_SOL);
56: filep->stf_offset = soffset;
57: p = filep->sfilename;
58: for (;;) {
59: for (i=0; i<8; i++) *p++ = stentry.n_name[i];
60: if (*(p-1) == '\0') break;
61: if (bread(&sbuf, &stentry, sizeof stentry)
62: < sizeof stentry)
63: error("Bad N_SO entry (1)");
64: if ((stentry.n_type & STABMASK) !=
65: (unsigned char) class)
66: error("Bad N_SO entry (2)");
67: soffset += sizeof stentry;
68: }
69: q = filep->sfilename;
70: for (p=fp; *q; *p++ = *q++) ;
71: *p = 0;
72: if (stat(filework, &stbuf) == -1)
73: printf("Warning: `%s' not found\n",
74: filep->sfilename);
75: else if (stbuf.st_mtime > symtime)
76: printf("Warning: `%s' newer than `%s'\n",
77: filep->sfilename,
78: symfil);
79: filep++;
80: break;
81:
82: case N_TEXT:
83: if (stentry.n_name[0] != '_') break;
84: case N_FUN:
85: case N_ENTRY:
86: if (procp == badproc) {
87: if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
88: perror("sdb");
89: exit(4);
90: }
91: badproc += PROCINCR;
92: }
93: for(i=0; i<8; i++)
94: procp->pname[i] = stentry.n_name[i];
95: procp->paddr = stentry.n_value;
96: procp->st_offset = soffset;
97: procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
98: procp->lineno = (class != N_TEXT) ? stentry.n_desc : 0;
99: procp->entrypt = (class & STABMASK) == N_ENTRY;
100: procp++;
101: break;
102: }
103: if (stentry.n_type & N_EXT && !extstart) {
104: extstart = soffset;
105: }
106: soffset += sizeof stentry;
107: }
108: qsort(procs, procp-procs, sizeof procs[0], compar);
109: badproc->st_offset = soffset;
110: badproc->sfptr = procp->sfptr = badfile;
111: badproc->pname[0] = badfile->sfilename[0]=
112: procp->pname[0] = filep->sfilename[0] = '\0';
113:
114: setcur(1);
115: }
116:
117: /* returns current procedure from state (curfile, fline) */
118: struct proct *
119: curproc() {
120: register ADDR addr;
121:
122: addr = getaddr("", fline);
123: if (addr == -1) return(badproc);
124: return(adrtoprocp(addr));
125:
126: }
127:
128: /* returns procedure s, uses curproc() if s == NULL */
129:
130: struct proct *
131: findproc(s)
132: char *s; {
133: register struct proct *p;
134:
135: if (s[0] == '\0') return(curproc());
136:
137: for(p=procs; p->pname[0]; p++)
138: if (eqstr(p->pname, s)) return(p);
139:
140: if (debug) printf("%s(): unknown name\n", s);
141: return(badproc);
142: }
143:
144: /* returns file s containing filename */
145: struct filet *
146: findfile(s)
147: char *s; {
148: register struct filet *f;
149: for (f=files; f->sfilename[0]; f++) {
150: if (eqstr(f->sfilename, s)) {
151: for( ; f->lineflag; f--) ;
152: if (f < files) error("Bad file array");
153: return(f);
154: }
155: }
156: return(f);
157: }
158:
159: /*
160: * slookup():
161: * looks up variable matching pat starting at offset in a.out, searching
162: * backwards, ignoring nested blocks to beginning to procedure.
163: * Returns its offset and symbol table entries decoded in sl_*
164: *
165: * If comblk == "*" then match both within and outside common blocks,
166: * if comblk == "" then match only outside common blocks,
167: * else match only within comblk.
168: */
169:
170: long
171: slookup(pat, poffset, stelt)
172: long poffset; char *pat; {
173: slookinit();
174: slooknext(pat, poffset, stelt, "*");
175: }
176:
177: int clevel, level, fnameflag, comfound, incomm;
178:
179: slookinit() {
180: clevel = level = fnameflag = comfound = incomm = 0;
181: }
182:
183: long
184: slooknext(pat, poffset, stelt, comblk)
185: long poffset; char *pat, *comblk; {
186: register int i;
187: register long offset;
188: char class, *q;
189: struct nlist stentry;
190: struct proct *procp, *p;
191:
192: offset = poffset + sizeof stentry;
193: if (debug) printf("slookup(%s,%d)\n",pat,offset);
194: blseek(&sbuf, offset, 0);
195:
196: for (;;) {
197: offset -= sizeof stentry;
198: if (offset < ststart) break;
199: if (bread(&sbuf, &stentry+1, -sizeof stentry)
200: < sizeof stentry) break;
201: class = stentry.n_type & STABMASK;
202: switch (class & STABMASK) {
203: case 0:
204: break;
205: case N_FUN:
206: return(-1);
207: case N_RBRAC:
208: level++;
209: break;
210: case N_LBRAC:
211: level--;
212: break;
213: case N_ECOMM:
214: for (q = &stentry.n_name[7]; q>=stentry.n_name; q--) {
215: if (*q == '_') {
216: *q = '\0';
217: break;
218: }
219: }
220: if (eqpat(comblk, stentry.n_name))
221: comfound = 1;
222: incomm = 1;
223: case N_ECOML:
224: clevel++;
225: break;
226: case N_BCOMM:
227: comfound = incomm = 0;
228: clevel--;
229: break;
230: case N_FNAME:
231: if (fnameflag)
232: break;
233: procp = findproc(stentry.n_name);
234: for (p=procs; p->pname[0]; p++) {
235: if (p->entrypt == 0 &&
236: p->st_offset > procp->st_offset &&
237: p->st_offset < offset)
238: offset = p->st_offset;
239: }
240: clevel = level = 0;
241: fnameflag++;
242: blseek(&sbuf, offset, 0);
243: break;
244: default:
245: if (level <= 0 && eqpat(pat, stentry.n_name) &&
246: stentry.n_name[0] && class & STABTYPES &&
247: (eqstr("*", comblk) ||
248: (comblk[0] == '\0' && incomm == 0) ||
249: comfound) &&
250: (stelt == (class == N_SSYM))) {
251: if (class == N_LENG) {
252: sl_size = stentry.n_value;
253: offset -= sizeof stentry;
254: bread(&sbuf, &stentry+1,
255: -sizeof stentry);
256: }
257: else sl_size = 0;
258: sl_class = stentry.n_type & STABMASK;
259: sl_type = stentry.n_desc;
260: sl_addr = stentry.n_value;
261: for (i=0; i<8; i++) sl_name[i] =
262: stentry.n_name[i];
263: if (clevel != 0) docomm(offset);
264: return(offset - sizeof stentry);
265: }
266: }
267: }
268: return(-1);
269: }
270:
271: /*
272: * Look up global variable matching pat
273: * Return its offset and symbol table entries decoded in sl_*
274: */
275: long
276: globallookup(pat, filestart, stelt)
277: char *pat; long filestart; {
278: register int offset, i;
279: struct nlist stentry;
280: int class, clevel;
281:
282: if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
283: blseek(&sbuf, filestart, 0);
284: offset = filestart - sizeof stentry;
285: clevel = 0;
286: do {
287: if (bread(&sbuf, &stentry, sizeof stentry) <
288: sizeof stentry) return(-1);
289: offset += sizeof stentry;
290: } while ((stentry.n_type & STABMASK) == N_SO);
291: for (;;) {
292: class = stentry.n_type & STABMASK;
293: switch (class & STABMASK) {
294: case N_SO:
295: return(-1);
296: case N_ECOMM:
297: clevel--;
298: break;
299: case N_BCOMM:
300: clevel++;
301: break;
302: default:
303: if (eqpat(pat, stentry.n_name)
304: && stentry.n_name[0] && class & STABTYPES) {
305: sl_class = stentry.n_type & STABMASK;
306: if (sl_class != N_GSYM && sl_class != N_SSYM &&
307: sl_class != N_STSYM) goto g1;
308: if (stelt != (sl_class == N_SSYM)) goto g1;
309: sl_size = 0;
310: sl_type = stentry.n_desc;
311: sl_addr = stentry.n_value;
312: for (i=0; i<8; i++) sl_name[i] = stentry.n_name[i];
313: if (clevel != 0) docomm(offset);
314: goto g2;
315: }
316: }
317: g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
318: return(-1);
319: offset += sizeof stentry;
320: }
321: g2: bread(&sbuf, &stentry, sizeof stentry);
322: if (((stentry.n_type & STABMASK) == N_LENG) &&
323: (eqpat(sl_name, stentry.n_name)))
324: sl_size = stentry.n_value;
325:
326: if (sl_class == N_GSYM && (clevel == 0)) {
327: blseek(&sbuf, extstart, 0);
328: for(;;) {
329: if (bread(&sbuf, &stentry, sizeof stentry)
330: < sizeof stentry)
331: return(-1);
332: if (stentry.n_name[0] != '_') continue;
333: if (eqpatr(sl_name, stentry.n_name+1, 1)) {
334: sl_addr = stentry.n_value;
335: break;
336: }
337: }
338: }
339: return(offset + sizeof stentry);
340: }
341:
342: /* core address to procedure (pointer to proc array) */
343: struct proct *
344: adrtoprocp(addr)
345: ADDR addr; {
346: register struct proct *procp, *lastproc;
347: lastproc = badproc;
348: for (procp=procs; procp->pname[0]; procp++) {
349: if (procp->paddr > addr) break;
350: if (procp->entrypt == 0)
351: lastproc = procp;
352: }
353: return (lastproc);
354: }
355:
356:
357: /* core address to file (pointer to file array) */
358: struct filet *
359: adrtofilep(addr)
360: ADDR addr; {
361: register struct filet *filep;
362: for (filep=files; filep->sfilename[0]; filep++) {
363: if (filep->faddr > addr) break;
364: }
365: return (filep != files ? filep-1 : badfile);
366: }
367:
368: /* core address to linenumber */
369: long lastoffset;
370:
371: adrtolineno(addr)
372: ADDR addr; {
373: register int lineno;
374: long offset;
375: struct nlist stentry;
376:
377: lineno = lastoffset = -1;
378: offset = adrtoproc(addr)->st_offset;
379: blseek(&sbuf, offset, 0);
380: for (;;) {
381: if (bread(&sbuf, &stentry, sizeof stentry)
382: < sizeof stentry) break;
383: if (stentry.n_type == N_SLINE) {
384: if (stentry.n_value > addr) break;
385: lastoffset = offset;
386: lineno = stentry.n_desc;
387: }
388: offset += sizeof stentry;
389: }
390: return (lineno);
391: }
392:
393:
394: /* address to a.out offset */
395: long
396: adrtostoffset(addr)
397: ADDR addr; {
398: adrtolineno(addr);
399: return(lastoffset);
400: }
401:
402:
403: /*
404: * Set (curfile, lineno) from core image.
405: * Returns 1 if there is a core image, 0 otherwise.
406: *
407: * Print the current line iff verbose is set.
408: */
409: setcur(verbose) {
410: register struct proct *procp;
411:
412: dot = *(ADDR *) (((ADDR) &u) + PC);
413:
414: if (dot == 0) {
415: printf("No core image\n");
416: goto setmain;
417: }
418: procp = adrtoprocp(dot);
419: if ((procp->sfptr) != badfile) {
420: finit(adrtofilep(procp->paddr)->sfilename);
421: ffind(adrtolineno(dot));
422: if (verbose) {
423: printf("%.8s:", procp->pname);
424: fprint();
425: }
426: return(1);
427: }
428: if (verbose) {
429: if (procp->pname[0] == '_')
430: printf("%.7s: address 0x%x\n", procp->pname+1, dot);
431: else
432: printf("%.8s: address %d\n", procp->pname, dot);
433: }
434:
435: setmain:
436: procp = findproc("MAIN_");
437: if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
438: procp = findproc("main");
439: if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
440: nolines = 1;
441: printf("main not compiled with debug flag\n");
442: return(0);
443: }
444: }
445: finit(procp->sfptr->sfilename);
446: ffind(procp->lineno);
447: return(0);
448: }
449:
450: compar(a, b)
451: struct proct *a, *b; {
452: if (a->paddr == b->paddr) {
453: if (a->pname[0] == '_') return(-1);
454: if (b->pname[0] == '_') return(1);
455: return(0);
456: }
457: return(a->paddr < b->paddr ? -1 : 1);
458: }
459:
460: /* gets offset of file or procedure named s */
461: nametooffset(s)
462: char *s; {
463: register struct filet *f;
464: register struct proct *p;
465:
466: if (*s == '\0')
467: return(-1);
468: if (eqany('.', s)) {
469: f = findfile(s);
470: return(f->sfilename[0] ? f->stf_offset : -1);
471: }
472: p = findproc(s);
473: return(p->pname[0] ? p->st_offset : -1);
474: }
475: /* returns s if its a filename, its file otherwise */
476: char *
477: nametofile(s)
478: char *s; {
479: register struct proct *p;
480:
481: if (eqany('.', s)) {
482: return(s);
483: }
484: p = findproc(s);
485: return(adrtofilep(p->paddr)->sfilename);
486: }
487:
488:
489: /* line number to address, starting at offset in a.out */
490: /* assumes that offset is within file */
491: lntoaddr(lineno, offset, file)
492: long offset; char *file; {
493: struct nlist stentry;
494: register int i, ignore = 0;
495: register int bestln=BIGNUM;
496: ADDR bestaddr;
497: char *p;
498:
499: blseek(&sbuf, offset, 0);
500:
501: do {
502: if (bread(&sbuf, &stentry, sizeof stentry) <
503: sizeof stentry) return(-1);
504: } while ((stentry.n_type & STABMASK) == N_SO);
505: for (;;) {
506: switch(stentry.n_type & STABMASK) {
507: case N_SLINE:
508: if (!ignore) {
509: if (stentry.n_desc == lineno)
510: return(stentry.n_value);
511: if (stentry.n_desc > lineno &&
512: stentry.n_desc < bestln) {
513: bestln = stentry.n_desc;
514: bestaddr = stentry.n_value;
515: }
516: }
517: break;
518:
519: case N_SO:
520: goto ret;
521:
522: case N_SOL:
523: p = file;
524: for (;;) {
525: for (i=0; i<8; i++) {
526: if (*p != stentry.n_name[i]) goto neq;
527: if (*p++ == '\0') break;
528: }
529: if (stentry.n_name[7] == '\0')
530: break;
531: if (bread(&sbuf, &stentry, sizeof stentry)
532: < sizeof stentry)
533: error("Bad N_SO entry (1)");
534: if ((stentry.n_type & STABMASK) !=
535: (unsigned char) N_SOL)
536: error("Bad N_SO entry (2)");
537: }
538: ignore = 0;
539: break;
540:
541: neq: ignore++;
542: break;
543: }
544: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
545: break;
546: }
547: ret: return(bestln == BIGNUM ? -1 : bestaddr);
548: }
549:
550: /* gets address of proc:number */
551: getaddr(proc,integ)
552: char *proc; {
553: register long offset;
554: register char *s, *f;
555: ADDR addr;
556:
557: s = proc[0] ? proc : curfile;
558: if (*s == '\0')
559: return(-1);
560: offset = nametooffset(s);
561: f = nametofile(s);
562: if (debug) printf("getaddr() computed offset %d", offset);
563: if (offset == -1) {
564: addr = extaddr(proc);
565: if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
566: if (debug) printf(" extaddr computed %d\n", addr);
567: return(addr);
568: }
569: if (integ)
570: addr = lntoaddr(integ, offset, s);
571: else {
572: addr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
573: addr = lntoaddr(adrtolineno(addr)+1, offset, f);
574: }
575: if (debug) printf(" and addr %d\n", addr);
576: if (addr == -1) return(-1);
577: return(addr);
578: }
579:
580: /* returns address of external */
581: ADDR
582: extaddr(name)
583: char *name; {
584: struct nlist stentry;
585: blseek(&sbuf, extstart, 0);
586:
587: for (;;) {
588: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
589: return(-1);
590: if (stentry.n_name[0] == '_' &&
591: eqpatr(name, stentry.n_name+1, 1))
592: return(stentry.n_value);
593: }
594: }
595:
596: /* find enclosing common blocks and fix up addresses */
597: docomm(offset)
598: long offset; {
599: struct nlist stentry;
600:
601: for (;;) {
602: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
603: error("Bad common block");
604: return;
605: }
606: sl_class = N_GSYM;
607: if ((stentry.n_type & STABMASK) == N_ECOMM) {
608: sl_addr += extaddr(stentry.n_name);
609: blseek(&sbuf, offset, 0);
610: return;
611: }
612: if ((stentry.n_type & STABMASK) == N_ECOML) {
613: sl_addr += stentry.n_value;
614: blseek(&sbuf, offset, 0);
615: return;
616: }
617: }
618: }
619:
620: /* determine if class is that of a variable */
621: char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
622: N_PSYM, 0};
623: varclass(class)
624: char class; {
625: char *p;
626:
627: for (p=pctypes; *p; p++) {
628: if (class == *p)
629: return(1);
630: }
631: return(0);
632: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.