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