xref: /original-bsd/old/sdb/symt.c (revision ba72ef4c)
1 static	char sccsid[] = "@(#)symt.c 4.1 10/09/80";
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 	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) */
227 struct proct *
228 curproc() {
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 
239 struct proct *
240 findproc(s)
241 char *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 */
256 struct filet *
257 findfile(s)
258 char *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 
282 long
283 slookup(pat, poffset, stelt)
284 long poffset; char *pat; {
285 	slookinit();
286 	slooknext(pat, poffset, stelt, "*");
287 }
288 
289 int clevel, level, fnameflag, comfound, incomm;
290 
291 slookinit() {
292 	clevel = level = fnameflag = comfound = incomm = 0;
293 }
294 
295 long
296 slooknext(pat, poffset, stelt, comblk)
297 long 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  */
403 long
404 globallookup(pat, filestart, stelt)
405 char *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 		}
449 g1:		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
450 			return(-1);
451 		offset += sizeof stentry;
452 	}
453 g2:	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) */
479 struct proct *
480 adrtoprocp(addr)
481 ADDR 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) */
494 struct filet *
495 adrtofilep(addr)
496 ADDR 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  */
510 long lastoffset;
511 
512 adrtolineno(addr)
513 ADDR 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 */
543 long
544 adrtostoffset(addr)
545 ADDR 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  */
557 setcur(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 
597 setmain:
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 
611 compar(a, b)
612 struct 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 */
622 nametooffset(s)
623 char *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 */
638 char *
639 nametofile(s)
640 char *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 */
653 lntoaddr(lineno, offset, file)
654 long 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 
708 neq:			ignore++;
709 			break;
710 		}
711 		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
712 			break;
713 	}
714 ret:	return(bestln == BIGNUM ? -1 : bestaddr);
715 }
716 
717 /* gets address of proc:number */
718 getaddr(proc,integ)
719 char *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 */
751 ADDR
752 extaddr(name)
753 char *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  */
772 long
773 extlookup(pat, filestart)
774 char *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 		}
797 g1:		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 */
804 docomm(offset)
805 long 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 */
828 char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
829 			N_PSYM, 0};
830 varclass(class)
831 char 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  */
846 adrtoext(addr)
847 ADDR 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  */
879 adrtolocal(addr, procp)
880 ADDR 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  */
913 adrtoparam(addr, procp)
914 ADDR 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  */
946 adrtoregvar(regno, procp)
947 ADDR 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 */
972 setmap(s)
973 char *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 
997 sout:	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 }
1008