xref: /original-bsd/old/sdb/symt.c (revision 0999a820)
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 
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 */
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 *
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 *
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 *
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
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 
292 slookinit() {
293 	clevel = level = fnameflag = comfound = incomm = 0;
294 }
295 
296 long
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
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 *
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 *
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 
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
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  */
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 */
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 *
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 */
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 */
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
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
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 */
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};
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  */
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  */
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  */
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  */
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 */
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