1 static char sccsid[] = "@(#)symt.c 4.3 08/17/82";
2 #include "head.h"
3 #include <a.out.h>
4 #include <stab.h>
5
6 #ifndef STABTYPES
7 #define STABTYPES N_STAB
8 #endif
9 #include <sys/stat.h>
10
11 struct user u;
12 int compar();
13 char *symfil;
14
15 #ifdef FLEXNAMES
16
17 struct nlist *symtab;
18 char nullname[] = {0,0,0,0,0,0,0,0,0}; /* a few 0 bytes */
19 off_t stoff;
20
21 stread(buff, nbytes)
22 struct nlist *buff;
23 int nbytes;
24 {
25 register int from = stoff;
26
27 stoff += nbytes;
28 if (stoff >= gstart)
29 return (-1);
30 if (nbytes < 0) {
31 from = stoff;
32 buff--;
33 }
34 from = (from - ststart);
35 *buff = symtab[from/sizeof (struct nlist)];
36 return (sizeof (struct nlist));
37 }
38
stseek(off,rel)39 stseek(off, rel)
40 long off;
41 {
42
43 if (rel == 1)
44 stoff += off;
45 else
46 stoff = off;
47 }
48 #define bread(a,b,c) stread(b,c)
49 #define blseek(a,b,c) stseek(b,c)
50 #endif
51
52 /* initialize file and procedure tables */
initfp()53 initfp() {
54 struct nlist stentry;
55 register struct proct *procp;
56 register struct filet *filep;
57 struct stat stbuf;
58
59 long soffset;
60 int i, gflag = 0;
61 u_char class;
62 register char *p, *q;
63
64 #ifdef FLEXNAMES
65 register struct nlist *sp;
66 int malformed = 0;
67 lseek(txtmap.ufd, gstart, 0);
68 if (read(txtmap.ufd, &ssiz, sizeof(ssiz)) != sizeof (ssiz)) {
69 printf("%s: no string table (old format?)\n", symfil);
70 exit(1);
71 }
72 strtab = (char *)malloc(ssiz);
73 if (strtab == 0) {
74 printf("no room for %d bytes of string table\n", ssiz);
75 exit(1);
76 }
77 ssiz -= sizeof (ssiz);
78 if (read(txtmap.ufd, strtab+sizeof (ssiz), ssiz) != ssiz) {
79 printf("%s: error reading string table\n", symfil);
80 exit(1);
81 }
82 i = gstart - ststart;
83 symtab = (struct nlist *)malloc(i);
84 if (symtab == 0) {
85 printf("no room for %d bytes of symbol table\n", i);
86 exit(1);
87 }
88 lseek(txtmap.ufd, ststart, 0);
89 if (read(txtmap.ufd, symtab, i) != i) {
90 printf("%s: error reading symbol table\n", symfil);
91 exit(1);
92 }
93 for (sp = &symtab[i/sizeof (struct nlist)]; --sp >= symtab; )
94 if (sp->n_un.n_strx != 0) {
95 if (sp->n_un.n_strx < sizeof (ssiz) || sp->n_un.n_strx >= ssiz) {
96 if (malformed == 0) {
97 printf("danger: mangled symbol table\n");
98 malformed = 1;
99 }
100 sp->n_un.n_name = nullname;
101 } else
102 sp->n_un.n_name = strtab + sp->n_un.n_strx;
103 } else
104 sp->n_un.n_name = nullname;
105 #endif
106 #ifndef VMUNIX
107 sbuf.fd = txtmap.ufd;
108 #endif
109 firstdata = MAXPOS;
110 soffset = ststart;
111 blseek(&sbuf,ststart,0);
112 filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
113 procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
114
115 for(;;) {
116 if (bread(&sbuf, &stentry, sizeof stentry) <
117 sizeof stentry) break;
118 class = stentry.n_type & STABMASK;
119 switch (class & STABMASK) {
120 case N_SO:
121 case N_SOL:
122 gflag++;
123 if (filep == badfile) {
124 p = sbrk(FILEINCR*sizeof filep[0]);
125 if (p < 0) {
126 perror("sdb");
127 exit(4);
128 }
129 q = p + FILEINCR*sizeof filep[0];
130 while (p > (char *) procs)
131 *--q = *--p;
132 badfile += FILEINCR;
133 procp = (struct proct *)
134 ((char *) procp +
135 FILEINCR*sizeof filep[0]);
136 procs = (struct proct *)
137 ((char *) procs +
138 FILEINCR*sizeof filep[0]);
139 badproc = (struct proct *)
140 ((char *)badproc +
141 FILEINCR*sizeof filep[0]);
142 }
143 filep->faddr = stentry.n_value;
144 filep->lineflag = (class == N_SOL);
145 filep->stf_offset = soffset;
146 #ifndef FLEXNAMES
147 p = filep->sfilename;
148 for (;;) {
149 for (i=0; i<8; i++) *p++ = stentry.n_un.n_name[i];
150 if (*(p-1) == '\0') break;
151 if (bread(&sbuf, &stentry, sizeof stentry)
152 < sizeof stentry)
153 error("Bad N_SO entry (1)");
154 if ((stentry.n_type & STABMASK) != class)
155 error("Bad N_SO entry (2)");
156 soffset += sizeof stentry;
157 }
158 #else
159 filep->sfilename = stentry.n_un.n_name;
160 #endif
161 q = filep->sfilename;
162 for (p=fp; *q; *p++ = *q++) ;
163 *p = 0;
164 if (stat(filework, &stbuf) == -1)
165 printf("Warning: `%s' not found\n",
166 filep->sfilename);
167 else if (stbuf.st_mtime > symtime)
168 printf("Warning: `%s' newer than `%s'\n",
169 filep->sfilename,
170 symfil);
171 filep++;
172 break;
173
174 case N_TEXT:
175 if (stentry.n_un.n_name[0] != '_') break;
176 case N_FUN:
177 case N_ENTRY:
178 if (procp == badproc) {
179 if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
180 perror("sdb");
181 exit(4);
182 }
183 badproc += PROCINCR;
184 }
185 #ifndef FLEXNAMES
186 for(i=0; i<8; i++)
187 procp->pname[i] = stentry.n_un.n_name[i];
188 #else
189 procp->pname = stentry.n_un.n_name;
190 #endif
191 procp->paddr = stentry.n_value;
192 procp->st_offset = soffset;
193 procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
194 procp->lineno = (class != N_TEXT) ? stentry.n_desc : 0;
195 procp->entrypt = (class & STABMASK) == N_ENTRY;
196 procp++;
197 break;
198 }
199 if (stentry.n_type & N_EXT) {
200 if (!extstart)
201 extstart = soffset;
202 if (stentry.n_type == N_DATA | N_EXT ||
203 stentry.n_type == N_BSS | N_EXT ||
204 stentry.n_value < firstdata)
205 firstdata = stentry.n_value;
206 }
207 soffset += sizeof stentry;
208 }
209 qsort(procs, procp-procs, sizeof procs[0], compar);
210 badproc->st_offset = badfile->stf_offset = soffset;
211 badproc->sfptr = procp->sfptr = badfile;
212 #ifndef FLEXNAMES
213 badproc->pname[0] = badfile->sfilename[0]=
214 procp->pname[0] = filep->sfilename[0] = '\0';
215 #else
216 badproc->pname = badfile->sfilename=
217 procp->pname = filep->sfilename = nullname;
218 #endif
219
220 if (!gflag)
221 printf("Warning: `%s' not compiled with -g\n", symfil);
222 setcur(1);
223 }
224
225 /* returns current procedure from state (curfile, fline) */
226 struct proct *
curproc()227 curproc() {
228 register ADDR addr;
229
230 addr = getaddr("", fline ? fline : 1);
231 if (addr == -1) return(badproc);
232 return(adrtoprocp(addr));
233
234 }
235
236 /* returns procedure s, uses curproc() if s == NULL */
237
238 struct proct *
findproc(s)239 findproc(s)
240 char *s; {
241 register struct proct *p, *altproc;
242
243 if (s[0] == '\0') return(curproc());
244 altproc = badproc;
245
246 for (p=procs; p->pname[0]; p++) {
247 if (eqpat(s, p->pname)) return(p);
248 if (p->pname[0] == '_' && eqpatr(s, p->pname+1, 1))
249 altproc = p;
250 }
251 return(altproc);
252 }
253
254 /* returns file s containing filename */
255 struct filet *
findfile(s)256 findfile(s)
257 char *s; {
258 register struct filet *f;
259 if (s == 0 || *s == 0)
260 return(files); /* start at beginning if no cur file */
261 for (f=files; f->sfilename[0]; f++) {
262 if (eqpat(f->sfilename, s)) {
263 for( ; f->lineflag; f--) ;
264 if (f < files) error("Bad file array");
265 return(f);
266 }
267 }
268 return(f);
269 }
270
271 /*
272 * slookup():
273 * looks up variable matching pat starting at (offset + sizeof stentry)
274 * in a.out, searching backwards,
275 * ignoring nested blocks to beginning to procedure.
276 * Returns its offset and symbol table entries decoded in sl_*
277 *
278 * If comblk == "*" then match both within and outside common blocks,
279 * if comblk == "" then match only outside common blocks,
280 * else match only within comblk.
281 */
282
283 long
slookup(pat,poffset,stelt)284 slookup(pat, poffset, stelt)
285 long poffset; char *pat; {
286 slookinit();
287 slooknext(pat, poffset, stelt, "*");
288 }
289
290 int clevel, level, fnameflag, comfound, incomm;
291
slookinit()292 slookinit() {
293 clevel = level = fnameflag = comfound = incomm = 0;
294 }
295
296 long
slooknext(pat,poffset,stelt,comblk)297 slooknext(pat, poffset, stelt, comblk)
298 long poffset; char *pat, *comblk; {
299 register int i;
300 register long offset;
301 char *q;
302 u_char class;
303 struct nlist stentry;
304 struct proct *procp, *p;
305
306 offset = poffset + sizeof stentry;
307 if (debug) printf("slookup(%s,%d)\n",pat,offset);
308 blseek(&sbuf, offset, 0);
309
310 for (;;) {
311 offset -= sizeof stentry;
312 if (offset < ststart) break;
313 if (bread(&sbuf, &stentry+1, -sizeof stentry)
314 < sizeof stentry) break;
315 class = stentry.n_type & STABMASK;
316 switch (class & STABMASK) {
317 case 0:
318 break;
319 case N_FUN:
320 return(-1);
321 case N_RBRAC:
322 level++;
323 break;
324 case N_LBRAC:
325 level--;
326 break;
327 case N_ECOMM:
328 i = 0;
329 #ifndef FLEXNAMES
330 for (q = &stentry.n_un.n_name[7]; q>=stentry.n_un.n_name; q--) {
331 if (*q == '_') {
332 *q = '\0';
333 i++;
334 break;
335 }
336 }
337 #else
338 for (q = stentry.n_un.n_name; *q; q++)
339 continue;
340 if (*--q == '_')
341 *q = 0, i++;
342 #endif
343 if (eqpat(comblk, stentry.n_un.n_name))
344 comfound = 1;
345 if (i)
346 *q = '_';
347 incomm = 1;
348 case N_ECOML:
349 clevel++;
350 break;
351 case N_BCOMM:
352 comfound = incomm = 0;
353 clevel--;
354 break;
355 case N_FNAME:
356 if (fnameflag)
357 break;
358 procp = findproc(stentry.n_un.n_name);
359 for (p=procs; p->pname[0]; p++) {
360 if (p->entrypt == 0 &&
361 p->st_offset > procp->st_offset &&
362 p->st_offset < offset)
363 offset = p->st_offset;
364 }
365 clevel = level = 0;
366 fnameflag++;
367 blseek(&sbuf, offset, 0);
368 break;
369 default:
370 if (level <= 0 && eqpat(pat, stentry.n_un.n_name) &&
371 stentry.n_un.n_name[0] && class & STABTYPES &&
372 (eqstr("*", comblk) ||
373 (comblk[0] == '\0' && incomm == 0) ||
374 comfound) &&
375 (stelt == (class == N_SSYM))) {
376 if (class == N_LENG) {
377 sl_size = stentry.n_value;
378 offset -= sizeof stentry;
379 bread(&sbuf, &stentry+1,
380 -sizeof stentry);
381 if (stentry.n_type&~N_EXT == N_BSS) {
382 bread(&sbuf, &stentry+1,
383 -sizeof stentry);
384 offset -= sizeof stentry;
385 }
386 }
387 else sl_size = 0;
388 sl_class = stentry.n_type & STABMASK;
389 sl_type = stentry.n_desc;
390 sl_addr = stentry.n_value;
391 #ifndef FLEXNAMES
392 for (i=0; i<8; i++) sl_name[i] =
393 stentry.n_un.n_name[i];
394 #else
395 sl_name = stentry.n_un.n_name;
396 #endif
397 if (clevel != 0) docomm(offset);
398 return(offset - sizeof stentry);
399 }
400 }
401 }
402 return(-1);
403 }
404
405 /*
406 * Look up global variable matching pat starting at (filestart+sizeof stentry)
407 * Return its offset and symbol table entries decoded in sl_*
408 */
409 long
globallookup(pat,filestart,stelt)410 globallookup(pat, filestart, stelt)
411 char *pat; long filestart; {
412 register int offset, i;
413 struct nlist stentry;
414 int clevel;
415 u_char class;
416
417 if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
418 blseek(&sbuf, filestart, 0);
419 offset = filestart - sizeof stentry;
420 clevel = 0;
421 do {
422 if (bread(&sbuf, &stentry, sizeof stentry) <
423 sizeof stentry) return(-1);
424 offset += sizeof stentry;
425 } while ((stentry.n_type & STABMASK) == N_SO);
426 for (;;) {
427 class = stentry.n_type & STABMASK;
428 switch (class & STABMASK) {
429 case N_SO:
430 return(-1);
431 case N_ECOMM:
432 clevel--;
433 break;
434 case N_BCOMM:
435 clevel++;
436 break;
437 default:
438 if (eqpat(pat, stentry.n_un.n_name)
439 && stentry.n_un.n_name[0] && class & STABTYPES) {
440 sl_class = stentry.n_type & STABMASK;
441 if (sl_class != N_GSYM && sl_class != N_SSYM &&
442 sl_class != N_STSYM && sl_class != N_LCSYM) goto g1;
443 if (stelt != (sl_class == N_SSYM)) goto g1;
444 sl_size = 0;
445 sl_type = stentry.n_desc;
446 sl_addr = stentry.n_value;
447 #ifndef FLEXNAMES
448 for (i=0; i<8; i++) sl_name[i] = stentry.n_un.n_name[i];
449 #else
450 sl_name = stentry.n_un.n_name;
451 #endif
452 if (clevel != 0) docomm(offset);
453 goto g2;
454 }
455 }
456 g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
457 return(-1);
458 offset += sizeof stentry;
459 }
460 g2: bread(&sbuf, &stentry, sizeof stentry);
461 if (stentry.n_type&~N_EXT==N_BSS) {
462 bread(&sbuf, &stentry, sizeof stentry);
463 offset += sizeof stentry;
464 }
465 if (((stentry.n_type & STABMASK) == N_LENG) &&
466 (eqpat(sl_name, stentry.n_un.n_name)))
467 sl_size = stentry.n_value;
468
469 if (sl_class == N_GSYM && (clevel == 0)) {
470 blseek(&sbuf, extstart, 0);
471 for(;;) {
472 if (bread(&sbuf, &stentry, sizeof stentry)
473 < sizeof stentry)
474 return(-1);
475 if (stentry.n_un.n_name[0] != '_') continue;
476 if (eqpatr(sl_name, stentry.n_un.n_name+1, 1)) {
477 sl_addr = stentry.n_value;
478 break;
479 }
480 }
481 }
482 return(offset + sizeof stentry);
483 }
484
485 /* core address to procedure (pointer to proc array) */
486 struct proct *
adrtoprocp(addr)487 adrtoprocp(addr)
488 ADDR addr; {
489 register struct proct *procp, *lastproc;
490 lastproc = badproc;
491 for (procp=procs; procp->pname[0]; procp++) {
492 if (procp->paddr > addr) break;
493 if (procp->entrypt == 0)
494 lastproc = procp;
495 }
496 return (lastproc);
497 }
498
499
500 /* core address to file (pointer to file array) */
501 struct filet *
adrtofilep(addr)502 adrtofilep(addr)
503 ADDR addr; {
504 register struct filet *filep;
505 for (filep=files; filep->sfilename[0]; filep++) {
506 if (filep->faddr > addr) break;
507 }
508 return (filep != files ? filep-1 : badfile);
509 }
510
511 /*
512 * core address to linenumber
513 * Sets external exactaddr to addr if addr is NOT the first instruction
514 * of a line, set to -1 otherwise.
515 * Sets external lnfaddr to address of first statement in line.
516 */
517 long lastoffset;
518
adrtolineno(addr)519 adrtolineno(addr)
520 ADDR addr; {
521 register int lineno;
522 long offset;
523 struct nlist stentry;
524
525 exactaddr = addr;
526 lineno = lastoffset = -1;
527 offset = adrtoprocp(addr)->st_offset;
528 blseek(&sbuf, offset, 0);
529 for (;;) {
530 if (bread(&sbuf, &stentry, sizeof stentry)
531 < sizeof stentry) break;
532 if (stentry.n_type == N_SO)
533 break;
534 if (stentry.n_type == N_SLINE) {
535 if (stentry.n_value > addr)
536 break;
537 lastoffset = offset;
538 lineno = stentry.n_desc;
539 lnfaddr = stentry.n_value;
540 if (stentry.n_value == addr)
541 exactaddr = -1;
542 }
543 offset += sizeof stentry;
544 }
545 return (lineno);
546 }
547
548
549 /* address to a.out offset */
550 long
adrtostoffset(addr)551 adrtostoffset(addr)
552 ADDR addr; {
553 adrtolineno(addr);
554 return(lastoffset);
555 }
556
557
558 /*
559 * Set (curfile, lineno) from core image.
560 * Returns 1 if there is a core image, 0 otherwise.
561 *
562 * Print the current line iff verbose is set.
563 */
setcur(verbose)564 setcur(verbose) {
565 register struct proct *procp;
566
567 dot = *(ADDR *) (((ADDR) &u) + PC);
568
569 if (dot == 0) {
570 printf("No core image\n");
571 goto setmain;
572 }
573 procp = adrtoprocp(dot);
574 if ((procp->sfptr) != badfile) {
575 finit(adrtofilep(procp->paddr)->sfilename);
576 ffind(adrtolineno(dot));
577 if (verbose) {
578 if (exactaddr != -1)
579 printf("0x%x in ", exactaddr);
580 #ifndef FLEXNAMES
581 printf("%.8s:", procp->pname);
582 #else
583 printf("%s:", procp->pname);
584 #endif
585 fprint();
586 }
587 return(1);
588 }
589 if (verbose) {
590 if (procp->pname[0] == '_')
591 #ifndef FLEXNAMES
592 printf("%.7s: address 0x%x\n", procp->pname+1, dot);
593 #else
594 printf("%s: address 0x%x\n", procp->pname+1, dot);
595 #endif
596 else
597 #ifndef FLEXNAMES
598 printf("%.8s: address %d\n", procp->pname, dot);
599 #else
600 printf("%s: address %d\n", procp->pname, dot);
601 #endif
602 }
603
604 setmain:
605 procp = findproc("MAIN_");
606 if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
607 procp = findproc("main");
608 if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
609 /* printf("main not compiled with debug flag\n"); */
610 return(0);
611 }
612 }
613 finit(procp->sfptr->sfilename);
614 ffind(procp->lineno);
615 return(0);
616 }
617
618 compar(a, b)
619 struct proct *a, *b; {
620 if (a->paddr == b->paddr) {
621 if (a->pname[0] == '_') return(-1);
622 if (b->pname[0] == '_') return(1);
623 return(0);
624 }
625 return(a->paddr < b->paddr ? -1 : 1);
626 }
627
628 /* gets offset of file or procedure named s */
nametooffset(s)629 nametooffset(s)
630 char *s; {
631 register struct filet *f;
632 register struct proct *p;
633
634 if (*s == '\0')
635 return(-1);
636 if (eqany('.', s)) {
637 f = findfile(s);
638 return(f->sfilename[0] ? f->stf_offset : -1);
639 }
640 p = findproc(s);
641 return(p->pname[0] ? p->st_offset : -1);
642 }
643
644 /* returns s if its a filename, its file otherwise */
645 char *
nametofile(s)646 nametofile(s)
647 char *s; {
648 register struct proct *p;
649
650 if (eqany('.', s)) {
651 return(s);
652 }
653 p = findproc(s);
654 return(adrtofilep(p->paddr)->sfilename);
655 }
656
657
658 /* line number to address, starting at offset in a.out */
659 /* assumes that offset is within file */
lntoaddr(lineno,offset,file)660 lntoaddr(lineno, offset, file)
661 long offset; char *file; {
662 struct nlist stentry;
663 register int i, ignore = 0;
664 register int bestln=BIGNUM;
665 ADDR bestaddr;
666 char *p;
667
668 blseek(&sbuf, offset, 0);
669
670 do {
671 if (bread(&sbuf, &stentry, sizeof stentry) <
672 sizeof stentry) return(-1);
673 } while ((stentry.n_type & STABMASK) == N_SO);
674 for (;;) {
675 switch(stentry.n_type & STABMASK) {
676 case N_SLINE:
677 if (!ignore) {
678 if (stentry.n_desc == lineno)
679 return(stentry.n_value);
680 if (stentry.n_desc > lineno &&
681 stentry.n_desc < bestln) {
682 bestln = stentry.n_desc;
683 bestaddr = stentry.n_value;
684 }
685 }
686 break;
687
688 case N_SO:
689 goto ret;
690
691 case N_SOL:
692 p = file;
693 #ifndef FLEXNAMES
694 for (;;) {
695 for (i=0; i<8; i++) {
696 if (*p != stentry.n_un.n_name[i]) goto neq;
697 if (*p++ == '\0') break;
698 }
699 if (stentry.n_un.n_name[7] == '\0')
700 break;
701 if (bread(&sbuf, &stentry, sizeof stentry)
702 < sizeof stentry)
703 error("Bad N_SO entry (1)");
704 if ((stentry.n_type & STABMASK) != (u_char)N_SOL)
705 error("Bad N_SO entry (2)");
706 }
707 #else
708 if (strcmp(file, stentry.n_un.n_name))
709 goto neq;
710 #endif
711 ignore = 0;
712 break;
713
714 neq: ignore++;
715 break;
716 }
717 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
718 break;
719 }
720 ret: return(bestln == BIGNUM ? -1 : bestaddr);
721 }
722
723 /* gets address of proc:number */
getaddr(proc,integ)724 getaddr(proc,integ)
725 char *proc; {
726 register long offset;
727 register char *s, *f;
728 ADDR addr;
729
730 s = proc[0] ? proc : curfile;
731 if (*s == '\0')
732 return(-1);
733 offset = nametooffset(s);
734 f = nametofile(s);
735 if (debug) printf("getaddr() computed offset %d", offset);
736 if (offset == -1) {
737 addr = extaddr(proc);
738 if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
739 if (debug) printf(" extaddr computed %d\n", addr);
740 return(addr);
741 }
742 if (integ)
743 addr = lntoaddr(integ, offset, s);
744 else {
745 ADDR oldaddr;
746 oldaddr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
747 addr = lntoaddr(adrtolineno(addr)+1, offset, f);
748 if (addr == -1)
749 addr = oldaddr;
750 }
751 if (debug) printf(" and addr %d\n", addr);
752 if (addr == -1) return(-1);
753 return(addr);
754 }
755
756 /* returns address of external */
757 ADDR
extaddr(name)758 extaddr(name)
759 char *name; {
760 struct nlist stentry;
761 blseek(&sbuf, extstart, 0);
762
763 for (;;) {
764 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
765 return(-1);
766 if (stentry.n_un.n_name[0] == '_' &&
767 eqpatr(name, stentry.n_un.n_name+1, 1))
768 return(stentry.n_value);
769 }
770 }
771
772
773 /*
774 * Look up external data symbol matching pat starting at
775 * (filestart+sizeof stentry)
776 * Return its address in sl_addr and name in sl_name.
777 */
778 long
extlookup(pat,filestart)779 extlookup(pat, filestart)
780 char *pat; long filestart; {
781 register int offset, i;
782 struct nlist stentry;
783
784 blseek(&sbuf, filestart, 0);
785 offset = filestart - sizeof stentry;
786 do {
787 if (bread(&sbuf, &stentry, sizeof stentry) <
788 sizeof stentry) return(-1);
789 offset += sizeof stentry;
790 } while ((stentry.n_type & STABMASK) == N_SO);
791 for (;;) {
792 if (stentry.n_un.n_name[0] == '_' &&
793 stentry.n_type == (N_DATA | N_EXT) &&
794 eqpatr(pat, stentry.n_un.n_name+1, 1)) {
795 sl_addr = stentry.n_value;
796 #ifndef FLEXNAMES
797 for (i=0; i<7; i++) sl_name[i] = stentry.n_un.n_name[i+1];
798 #else
799 sl_name = stentry.n_un.n_name;
800 #endif
801 return(offset + sizeof stentry);
802 }
803 g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
804 return(-1);
805 offset += sizeof stentry;
806 }
807 }
808
809 /* find enclosing common blocks and fix up addresses */
docomm(offset)810 docomm(offset)
811 long offset; {
812 struct nlist stentry;
813 ADDR addr;
814
815 for (;;) {
816 if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
817 error("Bad common block");
818 return;
819 }
820 sl_class = N_GSYM;
821 if ((stentry.n_type & STABMASK) == N_ECOMM) {
822 addr = extaddr(stentry.n_un.n_name);
823 if (addr == -1)
824 error("Lost common block");
825 sl_addr +=addr;
826 blseek(&sbuf, offset, 0);
827 return;
828 }
829 if ((stentry.n_type & STABMASK) == N_ECOML) {
830 sl_addr += stentry.n_value;
831 blseek(&sbuf, offset, 0);
832 return;
833 }
834 }
835 }
836
837 /* determine if class is that of a variable */
838 char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
839 N_PSYM, 0};
varclass(class)840 varclass(class)
841 u_char class; {
842 char *p;
843
844 for (p=pctypes; *p; p++) {
845 if (class == *p)
846 return(1);
847 }
848 return(0);
849 }
850
851 /*
852 * address to external name
853 * returns difference between addr and address of external
854 * name returned in sl_name
855 */
adrtoext(addr)856 adrtoext(addr)
857 ADDR addr; {
858 struct nlist stentry;
859 register int i, prevdiff = MAXPOS, diff;
860
861 blseek(&sbuf, extstart, 0);
862 for (;;) {
863 if (bread(&sbuf, &stentry, sizeof stentry)
864 < sizeof stentry)
865 return (prevdiff!=MAXPOS ? prevdiff : -1);
866 if (stentry.n_type == (N_DATA | N_EXT) ||
867 stentry.n_type == (N_BSS | N_EXT)) {
868 diff = addr - stentry.n_value;
869 if (diff >= 0 && diff < prevdiff) {
870 #ifndef FLEXNAMES
871 for (i=0; i<7; i++)
872 sl_name[i] = stentry.n_un.n_name[i+1];
873 #else
874 sl_name = stentry.n_un.n_name;
875 #endif
876 if (diff == 0)
877 return(0);
878 prevdiff = diff;
879 }
880 }
881 }
882 }
883
884 /*
885 * address to local name in procp
886 * returns difference between addr and address of local
887 * returned in sl_name
888 */
adrtolocal(addr,procp)889 adrtolocal(addr, procp)
890 ADDR addr; struct proct *procp; {
891 struct nlist stentry;
892 register int i, prevdiff = MAXPOS, diff;
893
894 blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
895 for (;;) {
896 if (bread(&sbuf, &stentry, sizeof stentry)
897 < sizeof stentry)
898 return(prevdiff!=MAXPOS ? prevdiff : -1);
899 if (stentry.n_type == N_FUN)
900 return(prevdiff!=MAXPOS ? prevdiff : -1);
901 if (stentry.n_type == N_LSYM) {
902 diff = addr - stentry.n_value;
903 if (diff >= 0 && diff < prevdiff) {
904 #ifndef FLEXNAMES
905 for (i=0; i<8; i++)
906 sl_name[i] = stentry.n_un.n_name[i];
907 #else
908 sl_name = stentry.n_un.n_name;
909 #endif
910 if (diff == 0)
911 return(0);
912 prevdiff = diff;
913 }
914 }
915 }
916 }
917
918 /*
919 * address to parameter name in procp
920 * returns difference between addr and address of local
921 * returned in sl_name
922 */
adrtoparam(addr,procp)923 adrtoparam(addr, procp)
924 ADDR addr; struct proct *procp; {
925 struct nlist stentry;
926 register int i, prevdiff = MAXPOS, diff;
927
928 blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
929 for (;;) {
930 if (bread(&sbuf, &stentry, sizeof stentry)
931 < sizeof stentry)
932 return(prevdiff!=MAXPOS ? prevdiff : -1);
933 if (stentry.n_type == N_FUN)
934 return(prevdiff!=MAXPOS ? prevdiff : -1);
935 if (stentry.n_type == N_PSYM) {
936 diff = addr - stentry.n_value;
937 if (diff >= 0 && diff < prevdiff) {
938 #ifndef FLEXNAMES
939 for (i=0; i<8; i++)
940 sl_name[i] = stentry.n_un.n_name[i];
941 #else
942 sl_name = stentry.n_un.n_name;
943 #endif
944 if (diff == 0)
945 return(0);
946 prevdiff = diff;
947 }
948 }
949 }
950 }
951
952 /*
953 * register number to register variable name in procp
954 * returned in sl_name
955 */
adrtoregvar(regno,procp)956 adrtoregvar(regno, procp)
957 ADDR regno; struct proct *procp; {
958 struct nlist stentry;
959 register int i;
960
961 blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
962 for (;;) {
963 if (bread(&sbuf, &stentry, sizeof stentry)
964 < sizeof stentry) return(-1);
965 if (stentry.n_type == N_FUN)
966 return(-1);
967 if (stentry.n_type == N_RSYM) {
968 if (stentry.n_value == regno) {
969 #ifndef FLEXNAMES
970 for (i=0; i<8; i++)
971 sl_name[i] = stentry.n_un.n_name[i];
972 #else
973 sl_name = stentry.n_un.n_name;
974 #endif
975 return(0);
976 }
977 }
978 }
979 }
980
981 /* sets file map for M command */
setmap(s)982 setmap(s)
983 char *s; {
984 union {
985 MAP *m;
986 L_INT *mp;
987 } amap;
988 int starflag = 0;
989
990 amap.mp = 0;
991 for (; *s; s++) {
992 switch (*s) {
993 case '/':
994 amap.m = &datmap;
995 break;
996 case '?':
997 amap.m = &txtmap;
998 break;
999 case '*':
1000 starflag++;
1001 break;
1002 default:
1003 goto sout;
1004 }
1005 }
1006
1007 sout: if (amap.mp == 0) {
1008 error("Map `?' or `/' must be specified");
1009 return;
1010 }
1011 if (starflag)
1012 amap.mp += 3;
1013 for (; *s; s++) {
1014 if (*s >= '0' && *s <= '9')
1015 *(amap.mp)++ = readint(&s);
1016 }
1017 }
1018