xref: /csrg-svn/old/sdb/symt.c (revision 7776)
1*7776Srrh static	char sccsid[] = "@(#)symt.c 4.3 08/17/82";
21352Sbill #include "head.h"
31352Sbill #include <a.out.h>
41352Sbill #include <stab.h>
51352Sbill 
61352Sbill #ifndef STABTYPES
71352Sbill #define	STABTYPES N_STAB
81352Sbill #endif
91352Sbill #include <sys/stat.h>
101352Sbill 
111352Sbill struct user u;
121352Sbill int compar();
131352Sbill char *symfil;
141352Sbill 
151352Sbill #ifdef FLEXNAMES
161352Sbill 
171352Sbill struct	nlist *symtab;
181352Sbill char	nullname[] = {0,0,0,0,0,0,0,0,0};	/* a few 0 bytes */
191352Sbill off_t	stoff;
201352Sbill 
211352Sbill stread(buff, nbytes)
221352Sbill struct nlist *buff;
231352Sbill int nbytes;
241352Sbill {
251352Sbill 	register int from = stoff;
261352Sbill 
271352Sbill 	stoff += nbytes;
281352Sbill 	if (stoff >= gstart)
291352Sbill 		return (-1);
301352Sbill 	if (nbytes < 0) {
311352Sbill 		from = stoff;
321352Sbill 		buff--;
331352Sbill 	}
341352Sbill 	from = (from - ststart);
351352Sbill 	*buff = symtab[from/sizeof (struct nlist)];
361352Sbill 	return (sizeof (struct nlist));
371352Sbill }
381352Sbill 
stseek(off,rel)391352Sbill stseek(off, rel)
401352Sbill long off;
411352Sbill {
421352Sbill 
431352Sbill 	if (rel == 1)
441352Sbill 		stoff += off;
451352Sbill 	else
461352Sbill 		stoff = off;
471352Sbill }
481352Sbill #define	bread(a,b,c)	stread(b,c)
491352Sbill #define	blseek(a,b,c)	stseek(b,c)
501352Sbill #endif
511352Sbill 
521352Sbill /* initialize file and procedure tables */
initfp()531352Sbill initfp() {
541352Sbill 	struct nlist stentry;
551352Sbill 	register struct proct *procp;
561352Sbill 	register struct filet *filep;
571352Sbill 	struct stat stbuf;
581352Sbill 
591352Sbill 	long soffset;
601352Sbill 	int i, gflag = 0;
61*7776Srrh 	u_char class;
621352Sbill 	register char *p, *q;
631352Sbill 
641352Sbill #ifdef FLEXNAMES
651352Sbill 	register struct nlist *sp;
661352Sbill 	int malformed = 0;
671352Sbill 	lseek(txtmap.ufd, gstart, 0);
681352Sbill 	if (read(txtmap.ufd, &ssiz, sizeof(ssiz)) != sizeof (ssiz)) {
691352Sbill 		printf("%s: no string table (old format?)\n", symfil);
701352Sbill 		exit(1);
711352Sbill 	}
721352Sbill 	strtab = (char *)malloc(ssiz);
731352Sbill 	if (strtab == 0) {
741352Sbill 		printf("no room for %d bytes of string table\n", ssiz);
751352Sbill 		exit(1);
761352Sbill 	}
771352Sbill 	ssiz -= sizeof (ssiz);
781352Sbill 	if (read(txtmap.ufd, strtab+sizeof (ssiz), ssiz) != ssiz) {
791352Sbill 		printf("%s: error reading string table\n", symfil);
801352Sbill 		exit(1);
811352Sbill 	}
821352Sbill 	i = gstart - ststart;
831352Sbill 	symtab = (struct nlist *)malloc(i);
841352Sbill 	if (symtab == 0) {
851352Sbill 		printf("no room for %d bytes of symbol table\n", i);
861352Sbill 		exit(1);
871352Sbill 	}
881352Sbill 	lseek(txtmap.ufd, ststart, 0);
891352Sbill 	if (read(txtmap.ufd, symtab, i) != i) {
901352Sbill 		printf("%s: error reading symbol table\n", symfil);
911352Sbill 		exit(1);
921352Sbill 	}
931352Sbill 	for (sp = &symtab[i/sizeof (struct nlist)]; --sp >= symtab; )
941352Sbill 	if (sp->n_un.n_strx != 0) {
951352Sbill 		if (sp->n_un.n_strx < sizeof (ssiz) || sp->n_un.n_strx >= ssiz) {
961352Sbill 			if (malformed == 0) {
971352Sbill 				printf("danger: mangled symbol table\n");
981352Sbill 				malformed = 1;
991352Sbill 			}
1001352Sbill 			sp->n_un.n_name = nullname;
1011352Sbill 		} else
1021352Sbill 			sp->n_un.n_name = strtab + sp->n_un.n_strx;
1031352Sbill 	} else
1041352Sbill 		sp->n_un.n_name = nullname;
1051352Sbill #endif
1061352Sbill #ifndef VMUNIX
1071352Sbill 	sbuf.fd = txtmap.ufd;
1081352Sbill #endif
1091352Sbill 	firstdata = MAXPOS;
1101352Sbill 	soffset = ststart;
1111352Sbill 	blseek(&sbuf,ststart,0);
1121352Sbill 	filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
1131352Sbill 	procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
1141352Sbill 
1151352Sbill 	for(;;) {
1161352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) <
1171352Sbill 				sizeof stentry) break;
1181352Sbill 		class = stentry.n_type & STABMASK;
1191352Sbill 		switch (class & STABMASK) {
1201352Sbill 		case N_SO:
1211352Sbill 		case N_SOL:
1221352Sbill 			gflag++;
1231352Sbill 			if (filep == badfile) {
1241352Sbill 				p = sbrk(FILEINCR*sizeof filep[0]);
1251352Sbill 				if (p < 0) {
1261352Sbill 					perror("sdb");
1271352Sbill 					exit(4);
1281352Sbill 				}
1291352Sbill 				q = p + FILEINCR*sizeof filep[0];
1301352Sbill 				while (p > (char *) procs)
1311352Sbill 					*--q = *--p;
1321352Sbill 				badfile += FILEINCR;
1331352Sbill 				procp = (struct proct *)
1341352Sbill 				    ((char *) procp +
1351352Sbill 						FILEINCR*sizeof filep[0]);
1361352Sbill 				procs = (struct proct *)
1371352Sbill 				    ((char *) procs +
1381352Sbill 						FILEINCR*sizeof filep[0]);
1391352Sbill 				badproc = (struct proct *)
1401352Sbill 				    ((char *)badproc +
1411352Sbill 						FILEINCR*sizeof filep[0]);
1421352Sbill 			}
1431352Sbill 			filep->faddr = stentry.n_value;
1441352Sbill 			filep->lineflag = (class == N_SOL);
1451352Sbill 			filep->stf_offset = soffset;
1461352Sbill #ifndef FLEXNAMES
1471352Sbill 			p = filep->sfilename;
1481352Sbill 			for (;;) {
1491352Sbill 				for (i=0; i<8; i++) *p++ = stentry.n_un.n_name[i];
1501352Sbill 				if (*(p-1) == '\0') break;
1511352Sbill 				if (bread(&sbuf, &stentry, sizeof stentry)
1521352Sbill 						< sizeof stentry)
1531352Sbill 					error("Bad N_SO entry (1)");
154*7776Srrh 				if ((stentry.n_type & STABMASK) != class)
1551352Sbill 					error("Bad N_SO entry (2)");
1561352Sbill 				soffset += sizeof stentry;
1571352Sbill 			}
1581352Sbill #else
1591352Sbill 			filep->sfilename = stentry.n_un.n_name;
1601352Sbill #endif
1611352Sbill 			q = filep->sfilename;
1621352Sbill 			for (p=fp; *q; *p++ = *q++) ;
1631352Sbill 			*p = 0;
1641352Sbill 			if (stat(filework, &stbuf) == -1)
1651352Sbill 				printf("Warning: `%s' not found\n",
1661352Sbill 					filep->sfilename);
1671352Sbill 			else if (stbuf.st_mtime > symtime)
1681352Sbill 				printf("Warning: `%s' newer than `%s'\n",
1691352Sbill 					filep->sfilename,
1701352Sbill 					symfil);
1711352Sbill 			filep++;
1721352Sbill 			break;
1731352Sbill 
1741352Sbill 		case N_TEXT:
1751352Sbill 			if (stentry.n_un.n_name[0] != '_') break;
1761352Sbill 		case N_FUN:
1771352Sbill 		case N_ENTRY:
1781352Sbill 			if (procp == badproc) {
1791352Sbill 				if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
1801352Sbill 					perror("sdb");
1811352Sbill 					exit(4);
1821352Sbill 				}
1831352Sbill 				badproc += PROCINCR;
1841352Sbill 			}
1851352Sbill #ifndef FLEXNAMES
1861352Sbill 			for(i=0; i<8; i++)
1871352Sbill 				procp->pname[i] = stentry.n_un.n_name[i];
1881352Sbill #else
1891352Sbill 			procp->pname = stentry.n_un.n_name;
1901352Sbill #endif
1911352Sbill 			procp->paddr = stentry.n_value;
1921352Sbill 			procp->st_offset = soffset;
1931352Sbill 			procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
1941352Sbill 			procp->lineno = (class != N_TEXT) ? stentry.n_desc : 0;
1951352Sbill 			procp->entrypt = (class & STABMASK) == N_ENTRY;
1961352Sbill 			procp++;
1971352Sbill 			break;
1981352Sbill 		}
1991352Sbill 		if (stentry.n_type & N_EXT) {
2001352Sbill 			if (!extstart)
2011352Sbill 				extstart = soffset;
2021352Sbill 			if (stentry.n_type == N_DATA | N_EXT ||
2031352Sbill 					stentry.n_type == N_BSS | N_EXT ||
2041352Sbill 					stentry.n_value < firstdata)
2051352Sbill 				firstdata = stentry.n_value;
2061352Sbill 		}
2071352Sbill 		soffset += sizeof stentry;
2081352Sbill 	}
2091352Sbill 	qsort(procs, procp-procs, sizeof procs[0], compar);
2101352Sbill 	badproc->st_offset = badfile->stf_offset = soffset;
2111352Sbill 	badproc->sfptr = procp->sfptr = badfile;
2121352Sbill #ifndef FLEXNAMES
2131352Sbill 	badproc->pname[0] = badfile->sfilename[0]=
2141352Sbill 		procp->pname[0] = filep->sfilename[0] = '\0';
2151352Sbill #else
2161352Sbill 	badproc->pname = badfile->sfilename=
2171352Sbill 		procp->pname = filep->sfilename = nullname;
2181352Sbill #endif
2191352Sbill 
2201352Sbill 	if (!gflag)
2211352Sbill 		printf("Warning: `%s' not compiled with -g\n", symfil);
2221352Sbill 	setcur(1);
2231352Sbill }
2241352Sbill 
2251352Sbill /* returns current procedure from state (curfile, fline) */
2261352Sbill struct proct *
curproc()2271352Sbill curproc() {
2281352Sbill 	register ADDR addr;
2291352Sbill 
2303946Sroot 	addr = getaddr("", fline ? fline : 1);
2311352Sbill 	if (addr == -1) return(badproc);
2321352Sbill 	return(adrtoprocp(addr));
2331352Sbill 
2341352Sbill }
2351352Sbill 
2361352Sbill /* returns procedure s, uses curproc() if s == NULL */
2371352Sbill 
2381352Sbill struct proct *
findproc(s)2391352Sbill findproc(s)
2401352Sbill char *s; {
2411352Sbill 	register struct proct *p, *altproc;
2421352Sbill 
2431352Sbill 	if (s[0] == '\0') return(curproc());
2441352Sbill 	altproc = badproc;
2451352Sbill 
2461352Sbill 	for (p=procs; p->pname[0]; p++) {
2471352Sbill 		if (eqpat(s, p->pname)) return(p);
2481352Sbill 		if (p->pname[0] == '_' && eqpatr(s, p->pname+1, 1))
2491352Sbill 			altproc = p;
2501352Sbill 	}
2511352Sbill 	return(altproc);
2521352Sbill }
2531352Sbill 
2541352Sbill /* returns file s containing filename */
2551352Sbill struct filet *
findfile(s)2561352Sbill findfile(s)
2571352Sbill char *s; {
2581352Sbill 	register struct filet *f;
2593946Sroot 	if (s == 0 || *s == 0)
2603946Sroot 		return(files);		/* start at beginning if no cur file */
2611352Sbill 	for (f=files; f->sfilename[0]; f++) {
2621352Sbill 		if (eqpat(f->sfilename, s)) {
2631352Sbill 			for( ; f->lineflag; f--) ;
2641352Sbill 			if (f < files) error("Bad file array");
2651352Sbill 			return(f);
2661352Sbill 		}
2671352Sbill 	}
2681352Sbill 	return(f);
2691352Sbill }
2701352Sbill 
2711352Sbill /*
2721352Sbill  * slookup():
2731352Sbill  * looks up variable matching pat starting at (offset + sizeof stentry)
2741352Sbill  * in a.out, searching backwards,
2751352Sbill  * ignoring nested blocks to beginning to procedure.
2761352Sbill  * Returns its offset and symbol table entries decoded in sl_*
2771352Sbill  *
2781352Sbill  * If comblk == "*" then match both within and outside common blocks,
2791352Sbill  * if comblk == ""  then match only outside common blocks,
2801352Sbill  *                  else match only within comblk.
2811352Sbill  */
2821352Sbill 
2831352Sbill long
slookup(pat,poffset,stelt)2841352Sbill slookup(pat, poffset, stelt)
2851352Sbill long poffset; char *pat; {
2861352Sbill 	slookinit();
2871352Sbill 	slooknext(pat, poffset, stelt, "*");
2881352Sbill }
2891352Sbill 
2901352Sbill int clevel, level, fnameflag, comfound, incomm;
2911352Sbill 
slookinit()2921352Sbill slookinit() {
2931352Sbill 	clevel = level = fnameflag = comfound = incomm = 0;
2941352Sbill }
2951352Sbill 
2961352Sbill long
slooknext(pat,poffset,stelt,comblk)2971352Sbill slooknext(pat, poffset, stelt, comblk)
2981352Sbill long poffset; char *pat, *comblk; {
2991352Sbill 	register int i;
3001352Sbill 	register long offset;
301*7776Srrh 	char	*q;
302*7776Srrh 	u_char	class;
3031352Sbill 	struct nlist stentry;
3041352Sbill 	struct proct *procp, *p;
3051352Sbill 
3061352Sbill 	offset = poffset + sizeof stentry;
3071352Sbill 	if (debug) printf("slookup(%s,%d)\n",pat,offset);
3081352Sbill 	blseek(&sbuf, offset, 0);
3091352Sbill 
3101352Sbill 	for (;;) {
3111352Sbill 		offset -= sizeof stentry;
3121352Sbill 		if (offset < ststart) break;
3131352Sbill 		if (bread(&sbuf, &stentry+1, -sizeof stentry)
3141352Sbill 			< sizeof stentry) break;
3151352Sbill 		class = stentry.n_type & STABMASK;
3161352Sbill 		switch (class & STABMASK) {
3171352Sbill 		case 0:
3181352Sbill 			break;
3191352Sbill 		case N_FUN:
3201352Sbill 			return(-1);
3211352Sbill 		case N_RBRAC:
3221352Sbill 			level++;
3231352Sbill 			break;
3241352Sbill 		case N_LBRAC:
3251352Sbill 			level--;
3261352Sbill 			break;
3271352Sbill 		case N_ECOMM:
3283946Sroot 			i = 0;
3291352Sbill #ifndef FLEXNAMES
3301352Sbill 			for (q = &stentry.n_un.n_name[7]; q>=stentry.n_un.n_name; q--) {
3311352Sbill 				if (*q == '_') {
3321352Sbill 					*q = '\0';
3333946Sroot 					i++;
3341352Sbill 					break;
3351352Sbill 				}
3361352Sbill 			}
3371352Sbill #else
3381352Sbill 			for (q = stentry.n_un.n_name; *q; q++)
3391352Sbill 				continue;
3401352Sbill 			if (*--q == '_')
3413946Sroot 				*q = 0, i++;
3421352Sbill #endif
3431352Sbill 			if (eqpat(comblk, stentry.n_un.n_name))
3441352Sbill 				comfound = 1;
3453946Sroot 			if (i)
3463946Sroot 				*q = '_';
3471352Sbill 			incomm = 1;
3481352Sbill 		case N_ECOML:
3491352Sbill 			clevel++;
3501352Sbill 			break;
3511352Sbill 		case N_BCOMM:
3521352Sbill 			comfound = incomm = 0;
3531352Sbill 			clevel--;
3541352Sbill 			break;
3551352Sbill 		case N_FNAME:
3561352Sbill 			if (fnameflag)
3571352Sbill 				break;
3581352Sbill 			procp = findproc(stentry.n_un.n_name);
3591352Sbill 			for (p=procs; p->pname[0]; p++) {
3601352Sbill 				if (p->entrypt == 0 &&
3611352Sbill 					p->st_offset > procp->st_offset &&
3621352Sbill 					p->st_offset < offset)
3631352Sbill 						offset = p->st_offset;
3641352Sbill 			}
3651352Sbill 			clevel = level = 0;
3661352Sbill 			fnameflag++;
3671352Sbill 			blseek(&sbuf, offset, 0);
3681352Sbill 			break;
3691352Sbill 		default:
3701352Sbill 			if (level <= 0  &&  eqpat(pat, stentry.n_un.n_name) &&
3711352Sbill 				stentry.n_un.n_name[0] && class & STABTYPES &&
3721352Sbill 				(eqstr("*", comblk) ||
3731352Sbill 				 (comblk[0] == '\0' && incomm == 0) ||
3741352Sbill 				 comfound) &&
3751352Sbill 				(stelt == (class == N_SSYM))) {
3761352Sbill 				if (class == N_LENG) {
3771352Sbill 					sl_size = stentry.n_value;
3781352Sbill 					offset -= sizeof stentry;
3791352Sbill 					bread(&sbuf, &stentry+1,
3801352Sbill 							-sizeof stentry);
3811352Sbill 					if (stentry.n_type&~N_EXT == N_BSS) {
3821352Sbill 						bread(&sbuf, &stentry+1,
3831352Sbill 						    -sizeof stentry);
3841352Sbill 						offset -= sizeof stentry;
3851352Sbill 					}
3861352Sbill 				}
3871352Sbill 				else sl_size = 0;
3881352Sbill 				sl_class = stentry.n_type & STABMASK;
3891352Sbill 				sl_type = stentry.n_desc;
3901352Sbill 				sl_addr = stentry.n_value;
3911352Sbill #ifndef FLEXNAMES
3921352Sbill 				for (i=0; i<8; i++) sl_name[i] =
3931352Sbill 						stentry.n_un.n_name[i];
3941352Sbill #else
3951352Sbill 				sl_name = stentry.n_un.n_name;
3961352Sbill #endif
3971352Sbill 				if (clevel != 0) docomm(offset);
3981352Sbill 				return(offset - sizeof stentry);
3991352Sbill 			}
4001352Sbill 		}
4011352Sbill 	}
4021352Sbill 	return(-1);
4031352Sbill }
4041352Sbill 
4051352Sbill /*
4061352Sbill  * Look up global variable matching pat starting at (filestart+sizeof stentry)
4071352Sbill  * Return its offset and symbol table entries decoded in sl_*
4081352Sbill  */
4091352Sbill long
globallookup(pat,filestart,stelt)4101352Sbill globallookup(pat, filestart, stelt)
4111352Sbill char *pat; long filestart; {
4121352Sbill 	register int offset, i;
4131352Sbill 	struct nlist stentry;
414*7776Srrh 	int	clevel;
415*7776Srrh 	u_char	class;
4161352Sbill 
4171352Sbill 	if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
4181352Sbill 	blseek(&sbuf, filestart, 0);
4191352Sbill 	offset = filestart - sizeof stentry;
4201352Sbill 	clevel = 0;
4211352Sbill 	do {
4221352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) <
4231352Sbill 				sizeof stentry) return(-1);
4241352Sbill 		offset += sizeof stentry;
4251352Sbill 	} while ((stentry.n_type & STABMASK) == N_SO);
4261352Sbill 	for (;;) {
4271352Sbill 		class = stentry.n_type & STABMASK;
4281352Sbill 		switch (class & STABMASK) {
4291352Sbill 		case N_SO:
4301352Sbill 			return(-1);
4311352Sbill 		case N_ECOMM:
4321352Sbill 			clevel--;
4331352Sbill 			break;
4341352Sbill 		case N_BCOMM:
4351352Sbill 			clevel++;
4361352Sbill 			break;
4371352Sbill 		default:
4381352Sbill 		if (eqpat(pat, stentry.n_un.n_name)
4391352Sbill 				&& stentry.n_un.n_name[0] && class & STABTYPES) {
4401352Sbill 			sl_class = stentry.n_type & STABMASK;
4411352Sbill 			if (sl_class != N_GSYM && sl_class != N_SSYM &&
4421352Sbill 				sl_class != N_STSYM && sl_class != N_LCSYM) goto g1;
4431352Sbill 			if (stelt != (sl_class == N_SSYM)) goto g1;
4441352Sbill 			sl_size = 0;
4451352Sbill 			sl_type = stentry.n_desc;
4461352Sbill 			sl_addr = stentry.n_value;
4471352Sbill #ifndef FLEXNAMES
4481352Sbill 			for (i=0; i<8; i++) sl_name[i] = stentry.n_un.n_name[i];
4491352Sbill #else
4501352Sbill 			sl_name = stentry.n_un.n_name;
4511352Sbill #endif
4521352Sbill 			if (clevel != 0) docomm(offset);
4531352Sbill 			goto g2;
4541352Sbill 		}
4551352Sbill 		}
4561352Sbill g1:		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
4571352Sbill 			return(-1);
4581352Sbill 		offset += sizeof stentry;
4591352Sbill 	}
4601352Sbill g2:	bread(&sbuf, &stentry, sizeof stentry);
4611352Sbill 	if (stentry.n_type&~N_EXT==N_BSS) {
4621352Sbill 		bread(&sbuf, &stentry, sizeof stentry);
4631352Sbill 		offset += sizeof stentry;
4641352Sbill 	}
4651352Sbill 	if (((stentry.n_type & STABMASK) == N_LENG) &&
4661352Sbill 			(eqpat(sl_name, stentry.n_un.n_name)))
4671352Sbill 		sl_size = stentry.n_value;
4681352Sbill 
4691352Sbill 	if (sl_class == N_GSYM && (clevel == 0)) {
4701352Sbill 		blseek(&sbuf, extstart, 0);
4711352Sbill 		for(;;) {
4721352Sbill 			if (bread(&sbuf, &stentry, sizeof stentry)
4731352Sbill 					< sizeof stentry)
4741352Sbill 				return(-1);
4751352Sbill 			if (stentry.n_un.n_name[0] != '_') continue;
4761352Sbill 			if (eqpatr(sl_name, stentry.n_un.n_name+1, 1)) {
4771352Sbill 				sl_addr = stentry.n_value;
4781352Sbill 				break;
4791352Sbill 			}
4801352Sbill 		}
4811352Sbill 	}
4821352Sbill 	return(offset + sizeof stentry);
4831352Sbill }
4841352Sbill 
4851352Sbill /* core address to procedure (pointer to proc array) */
4861352Sbill struct proct *
adrtoprocp(addr)4871352Sbill adrtoprocp(addr)
4881352Sbill ADDR addr; {
4891352Sbill 	register struct proct *procp, *lastproc;
4901352Sbill 	lastproc = badproc;
4911352Sbill 	for (procp=procs; procp->pname[0]; procp++) {
4921352Sbill 		if (procp->paddr > addr) break;
4931352Sbill 		if (procp->entrypt == 0)
4941352Sbill 			lastproc = procp;
4951352Sbill 	}
4961352Sbill 	return (lastproc);
4971352Sbill }
4981352Sbill 
4991352Sbill 
5001352Sbill /* core address to file (pointer to file array) */
5011352Sbill struct filet *
adrtofilep(addr)5021352Sbill adrtofilep(addr)
5031352Sbill ADDR addr; {
5041352Sbill 	register struct filet *filep;
5051352Sbill 	for (filep=files; filep->sfilename[0]; filep++) {
5061352Sbill 		if (filep->faddr > addr) break;
5071352Sbill 	}
5081352Sbill 	return (filep != files ? filep-1 : badfile);
5091352Sbill }
5101352Sbill 
5111352Sbill /*
5121352Sbill  * core address to linenumber
5131352Sbill  *  Sets external exactaddr to addr if addr is NOT the first instruction
5141352Sbill  * of a line, set to -1 otherwise.
5151352Sbill  *  Sets external lnfaddr to address of first statement in line.
5161352Sbill  */
5171352Sbill long lastoffset;
5181352Sbill 
adrtolineno(addr)5191352Sbill adrtolineno(addr)
5201352Sbill ADDR addr; {
5211352Sbill 	register int lineno;
5221352Sbill 	long offset;
5231352Sbill 	struct nlist stentry;
5241352Sbill 
5251352Sbill 	exactaddr = addr;
5261352Sbill 	lineno = lastoffset = -1;
5271352Sbill 	offset = adrtoprocp(addr)->st_offset;
5281352Sbill 	blseek(&sbuf, offset, 0);
5291352Sbill 	for (;;) {
5301352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry)
5311352Sbill 				< sizeof stentry) break;
5321352Sbill 		if (stentry.n_type == N_SO)
5331352Sbill 			break;
5341352Sbill 		if (stentry.n_type == N_SLINE) {
5351352Sbill 			if (stentry.n_value > addr)
5361352Sbill 				break;
5371352Sbill 			lastoffset = offset;
5381352Sbill 			lineno = stentry.n_desc;
5391352Sbill 			lnfaddr = stentry.n_value;
5401352Sbill 			if (stentry.n_value == addr)
5411352Sbill 				exactaddr = -1;
5421352Sbill 		}
5431352Sbill 		offset += sizeof stentry;
5441352Sbill 	}
5451352Sbill 	return (lineno);
5461352Sbill }
5471352Sbill 
5481352Sbill 
5491352Sbill /* address to a.out offset */
5501352Sbill long
adrtostoffset(addr)5511352Sbill adrtostoffset(addr)
5521352Sbill ADDR addr; {
5531352Sbill 	adrtolineno(addr);
5541352Sbill 	return(lastoffset);
5551352Sbill }
5561352Sbill 
5571352Sbill 
5581352Sbill /*
5591352Sbill  * Set (curfile, lineno) from core image.
5601352Sbill  * Returns 1 if there is a core image, 0 otherwise.
5611352Sbill  *
5621352Sbill  * Print the current line iff verbose is set.
5631352Sbill  */
setcur(verbose)5641352Sbill setcur(verbose) {
5651352Sbill 	register struct proct *procp;
5661352Sbill 
5671352Sbill 	dot = *(ADDR *) (((ADDR) &u) + PC);
5681352Sbill 
5691352Sbill 	if (dot == 0) {
5701352Sbill 		printf("No core image\n");
5711352Sbill 		goto setmain;
5721352Sbill 	}
5731352Sbill 	procp = adrtoprocp(dot);
5741352Sbill 	if ((procp->sfptr) != badfile) {
5751352Sbill 		finit(adrtofilep(procp->paddr)->sfilename);
5761352Sbill 		ffind(adrtolineno(dot));
5771352Sbill 		if (verbose) {
5781352Sbill 			if (exactaddr != -1)
5791352Sbill 				printf("0x%x in ", exactaddr);
5801352Sbill #ifndef FLEXNAMES
5811352Sbill 			printf("%.8s:", procp->pname);
5821352Sbill #else
5831352Sbill 			printf("%s:", procp->pname);
5841352Sbill #endif
5851352Sbill 			fprint();
5861352Sbill 		}
5871352Sbill 		return(1);
5881352Sbill 	}
5891352Sbill 	if (verbose) {
5901352Sbill 		if (procp->pname[0] == '_')
5911352Sbill #ifndef FLEXNAMES
5921352Sbill 			printf("%.7s: address 0x%x\n", procp->pname+1, dot);
5931352Sbill #else
5941352Sbill 			printf("%s: address 0x%x\n", procp->pname+1, dot);
5951352Sbill #endif
5961352Sbill 		else
5971352Sbill #ifndef FLEXNAMES
5981352Sbill 			printf("%.8s: address %d\n", procp->pname, dot);
5991352Sbill #else
6001352Sbill 			printf("%s: address %d\n", procp->pname, dot);
6011352Sbill #endif
6021352Sbill 	}
6031352Sbill 
6041352Sbill setmain:
6051352Sbill 	procp = findproc("MAIN_");
6061352Sbill 	if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
6071352Sbill 		procp = findproc("main");
6081352Sbill 		if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
6091352Sbill 			/* printf("main not compiled with debug flag\n"); */
6101352Sbill 			return(0);
6111352Sbill 		}
6121352Sbill 	}
6131352Sbill 	finit(procp->sfptr->sfilename);
6141352Sbill 	ffind(procp->lineno);
6151352Sbill 	return(0);
6161352Sbill }
6171352Sbill 
6181352Sbill compar(a, b)
6191352Sbill struct proct *a, *b; {
6201352Sbill 	if (a->paddr == b->paddr) {
6211352Sbill 		if (a->pname[0] == '_') return(-1);
6221352Sbill 		if (b->pname[0] == '_') return(1);
6231352Sbill 		return(0);
6241352Sbill 	}
6251352Sbill 	return(a->paddr < b->paddr ? -1 : 1);
6261352Sbill }
6271352Sbill 
6281352Sbill /* gets offset of file or procedure named s */
nametooffset(s)6291352Sbill nametooffset(s)
6301352Sbill char *s; {
6311352Sbill 	register struct filet *f;
6321352Sbill 	register struct proct *p;
6331352Sbill 
6341352Sbill 	if (*s == '\0')
6351352Sbill 		return(-1);
6361352Sbill 	if (eqany('.', s)) {
6371352Sbill 		f = findfile(s);
6381352Sbill 		return(f->sfilename[0] ? f->stf_offset : -1);
6391352Sbill 	}
6401352Sbill 	p = findproc(s);
6411352Sbill 	return(p->pname[0] ? p->st_offset : -1);
6421352Sbill }
6431352Sbill 
6441352Sbill /* returns s if its a filename, its file otherwise */
6451352Sbill char *
nametofile(s)6461352Sbill nametofile(s)
6471352Sbill char *s; {
6481352Sbill 	register struct proct *p;
6491352Sbill 
6501352Sbill 	if (eqany('.', s)) {
6511352Sbill 		return(s);
6521352Sbill 	}
6531352Sbill 	p = findproc(s);
6541352Sbill 	return(adrtofilep(p->paddr)->sfilename);
6551352Sbill }
6561352Sbill 
6571352Sbill 
6581352Sbill /* line number to address, starting at offset in a.out */
6591352Sbill /* assumes that offset is within file */
lntoaddr(lineno,offset,file)6601352Sbill lntoaddr(lineno, offset, file)
6611352Sbill long offset; char *file; {
6621352Sbill 	struct nlist stentry;
6631352Sbill 	register int i, ignore = 0;
6641352Sbill 	register int bestln=BIGNUM;
6651352Sbill 	ADDR bestaddr;
6661352Sbill 	char *p;
6671352Sbill 
6681352Sbill 	blseek(&sbuf, offset, 0);
6691352Sbill 
6701352Sbill 	do {
6711352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) <
6721352Sbill 				sizeof stentry) return(-1);
6731352Sbill 	} while ((stentry.n_type & STABMASK) == N_SO);
6741352Sbill 	for (;;) {
6751352Sbill 		switch(stentry.n_type & STABMASK) {
6761352Sbill 		case N_SLINE:
6771352Sbill 			if (!ignore) {
6781352Sbill 				if (stentry.n_desc == lineno)
6791352Sbill 					return(stentry.n_value);
6801352Sbill 				if (stentry.n_desc > lineno &&
6811352Sbill 					stentry.n_desc < bestln) {
6821352Sbill 					bestln = stentry.n_desc;
6831352Sbill 					bestaddr = stentry.n_value;
6841352Sbill 				}
6851352Sbill 			}
6861352Sbill 			break;
6871352Sbill 
6881352Sbill 		case N_SO:
6891352Sbill 			goto ret;
6901352Sbill 
6911352Sbill 		case N_SOL:
6921352Sbill 			p = file;
6931352Sbill #ifndef FLEXNAMES
6941352Sbill 			for (;;) {
6951352Sbill 				for (i=0; i<8; i++) {
6961352Sbill 					if (*p != stentry.n_un.n_name[i]) goto neq;
6971352Sbill 					if (*p++ == '\0') break;
6981352Sbill 				}
6991352Sbill 				if (stentry.n_un.n_name[7] == '\0')
7001352Sbill 					break;
7011352Sbill 				if (bread(&sbuf, &stentry, sizeof stentry)
7021352Sbill 						< sizeof stentry)
7031352Sbill 					error("Bad N_SO entry (1)");
704*7776Srrh 				if ((stentry.n_type & STABMASK) != (u_char)N_SOL)
7051352Sbill 					error("Bad N_SO entry (2)");
7061352Sbill 			}
7071352Sbill #else
7081352Sbill 			if (strcmp(file, stentry.n_un.n_name))
7091352Sbill 				goto neq;
7101352Sbill #endif
7111352Sbill 			ignore = 0;
7121352Sbill 			break;
7131352Sbill 
7141352Sbill neq:			ignore++;
7151352Sbill 			break;
7161352Sbill 		}
7171352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
7181352Sbill 			break;
7191352Sbill 	}
7201352Sbill ret:	return(bestln == BIGNUM ? -1 : bestaddr);
7211352Sbill }
7221352Sbill 
7231352Sbill /* gets address of proc:number */
getaddr(proc,integ)7241352Sbill getaddr(proc,integ)
7251352Sbill char *proc; {
7261352Sbill 	register long offset;
7271352Sbill 	register char *s, *f;
7281352Sbill 	ADDR addr;
7291352Sbill 
7301352Sbill 	s = proc[0] ? proc : curfile;
7311352Sbill 	if (*s == '\0')
7321352Sbill 		return(-1);
7331352Sbill 	offset = nametooffset(s);
7341352Sbill 	f = nametofile(s);
7351352Sbill 	if (debug) printf("getaddr() computed offset %d", offset);
7361352Sbill 	if (offset == -1) {
7371352Sbill 		addr = extaddr(proc);
7381352Sbill 		if (addr != -1) addr += 2;  /* MACHINE DEPENDENT */
7391352Sbill 		if (debug) printf(" extaddr computed %d\n", addr);
7401352Sbill 		return(addr);
7411352Sbill 	}
7421352Sbill 	if (integ)
7431352Sbill 		addr = lntoaddr(integ, offset, s);
7441352Sbill 	else {
7451352Sbill 		ADDR oldaddr;
7461352Sbill 		oldaddr = findproc(proc)->paddr + 2;  /* MACHINE DEPENDENT */
7471352Sbill 		addr = lntoaddr(adrtolineno(addr)+1, offset, f);
7481352Sbill 		if (addr == -1)
7491352Sbill 			addr = oldaddr;
7501352Sbill 	}
7511352Sbill 	if (debug) printf(" and addr %d\n", addr);
7521352Sbill 	if (addr == -1) return(-1);
7531352Sbill 	return(addr);
7541352Sbill }
7551352Sbill 
7561352Sbill /* returns address of external */
7571352Sbill ADDR
extaddr(name)7581352Sbill extaddr(name)
7591352Sbill char *name; {
7601352Sbill 	struct nlist stentry;
7611352Sbill 	blseek(&sbuf, extstart, 0);
7621352Sbill 
7631352Sbill 	for (;;) {
7641352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
7651352Sbill 			return(-1);
7661352Sbill 		if (stentry.n_un.n_name[0] == '_' &&
7671352Sbill 			    eqpatr(name, stentry.n_un.n_name+1, 1))
7681352Sbill 			return(stentry.n_value);
7691352Sbill 	}
7701352Sbill }
7711352Sbill 
7721352Sbill 
7731352Sbill /*
7741352Sbill  * Look up external data symbol matching pat starting at
7751352Sbill  *  (filestart+sizeof stentry)
7761352Sbill  * Return its address in sl_addr and name in sl_name.
7771352Sbill  */
7781352Sbill long
extlookup(pat,filestart)7791352Sbill extlookup(pat, filestart)
7801352Sbill char *pat; long filestart; {
7811352Sbill 	register int offset, i;
7821352Sbill 	struct nlist stentry;
7831352Sbill 
7841352Sbill 	blseek(&sbuf, filestart, 0);
7851352Sbill 	offset = filestart - sizeof stentry;
7861352Sbill 	do {
7871352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) <
7881352Sbill 				sizeof stentry) return(-1);
7891352Sbill 		offset += sizeof stentry;
7901352Sbill 	} while ((stentry.n_type & STABMASK) == N_SO);
7911352Sbill 	for (;;) {
7921352Sbill 		if (stentry.n_un.n_name[0] == '_' &&
7931352Sbill 			    stentry.n_type == (N_DATA | N_EXT) &&
7941352Sbill 			    eqpatr(pat, stentry.n_un.n_name+1, 1)) {
7951352Sbill 			sl_addr = stentry.n_value;
7961352Sbill #ifndef FLEXNAMES
7971352Sbill 			for (i=0; i<7; i++) sl_name[i] = stentry.n_un.n_name[i+1];
7981352Sbill #else
7991352Sbill 			sl_name = stentry.n_un.n_name;
8001352Sbill #endif
8011352Sbill 			return(offset + sizeof stentry);
8021352Sbill 		}
8031352Sbill g1:		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
8041352Sbill 			return(-1);
8051352Sbill 		offset += sizeof stentry;
8061352Sbill 	}
8071352Sbill }
8081352Sbill 
8091352Sbill /* find enclosing common blocks and fix up addresses */
docomm(offset)8101352Sbill docomm(offset)
8111352Sbill long offset; {
8121352Sbill 	struct nlist stentry;
8133946Sroot 	ADDR addr;
8141352Sbill 
8151352Sbill 	for (;;) {
8161352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
8171352Sbill 			error("Bad common block");
8181352Sbill 			return;
8191352Sbill 		}
8201352Sbill 		sl_class = N_GSYM;
8211352Sbill 		if ((stentry.n_type & STABMASK) == N_ECOMM) {
8223946Sroot 			addr = extaddr(stentry.n_un.n_name);
8233946Sroot 			if (addr == -1)
8243946Sroot 				error("Lost common block");
8253946Sroot 			sl_addr +=addr;
8261352Sbill 			blseek(&sbuf, offset, 0);
8271352Sbill 			return;
8281352Sbill 		}
8291352Sbill 		if ((stentry.n_type & STABMASK) == N_ECOML) {
8301352Sbill 			sl_addr += stentry.n_value;
8311352Sbill 			blseek(&sbuf, offset, 0);
8321352Sbill 			return;
8331352Sbill 		}
8341352Sbill 	}
8351352Sbill }
8361352Sbill 
8371352Sbill /* determine if class is that of a variable */
8381352Sbill char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
8391352Sbill 			N_PSYM, 0};
varclass(class)8401352Sbill varclass(class)
841*7776Srrh u_char class; {
8421352Sbill 	char *p;
8431352Sbill 
8441352Sbill 	for (p=pctypes; *p; p++) {
8451352Sbill 		if (class == *p)
8461352Sbill 			return(1);
8471352Sbill 	}
8481352Sbill 	return(0);
8491352Sbill }
8501352Sbill 
8511352Sbill /*
8521352Sbill  * address to external name
8531352Sbill  * returns difference between addr and address of external
8541352Sbill  * name returned in sl_name
8551352Sbill  */
adrtoext(addr)8561352Sbill adrtoext(addr)
8571352Sbill ADDR addr; {
8581352Sbill 	struct nlist stentry;
8591352Sbill 	register int i, prevdiff = MAXPOS, diff;
8601352Sbill 
8611352Sbill 	blseek(&sbuf, extstart, 0);
8621352Sbill 	for (;;) {
8631352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry)
8641352Sbill 				< sizeof stentry)
8651352Sbill 			return (prevdiff!=MAXPOS ? prevdiff : -1);
8661352Sbill 		if (stentry.n_type == (N_DATA | N_EXT) ||
8671352Sbill 		    stentry.n_type == (N_BSS | N_EXT)) {
8681352Sbill 			diff = addr - stentry.n_value;
8691352Sbill 			if (diff >= 0 && diff < prevdiff) {
8701352Sbill #ifndef FLEXNAMES
8711352Sbill 				for (i=0; i<7; i++)
8721352Sbill 					sl_name[i] = stentry.n_un.n_name[i+1];
8731352Sbill #else
8741352Sbill 				sl_name = stentry.n_un.n_name;
8751352Sbill #endif
8761352Sbill 				if (diff == 0)
8771352Sbill 					return(0);
8781352Sbill 				prevdiff = diff;
8791352Sbill 			}
8801352Sbill 		}
8811352Sbill 	}
8821352Sbill }
8831352Sbill 
8841352Sbill /*
8851352Sbill  * address to local name in procp
8861352Sbill  * returns difference between addr and address of local
8871352Sbill  * returned in sl_name
8881352Sbill  */
adrtolocal(addr,procp)8891352Sbill adrtolocal(addr, procp)
8901352Sbill ADDR addr; struct proct *procp; {
8911352Sbill 	struct nlist stentry;
8921352Sbill 	register int i, prevdiff = MAXPOS, diff;
8931352Sbill 
8941352Sbill 	blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
8951352Sbill 	for (;;) {
8961352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry)
8971352Sbill 				< sizeof stentry)
8981352Sbill 			return(prevdiff!=MAXPOS ? prevdiff : -1);
8991352Sbill 		if (stentry.n_type == N_FUN)
9001352Sbill 			return(prevdiff!=MAXPOS ? prevdiff : -1);
9011352Sbill 		if (stentry.n_type == N_LSYM) {
9021352Sbill 			diff = addr - stentry.n_value;
9031352Sbill 			if (diff >= 0 && diff < prevdiff) {
9041352Sbill #ifndef FLEXNAMES
9051352Sbill 				for (i=0; i<8; i++)
9061352Sbill 					sl_name[i] = stentry.n_un.n_name[i];
9071352Sbill #else
9081352Sbill 				sl_name = stentry.n_un.n_name;
9091352Sbill #endif
9101352Sbill 				if (diff == 0)
9111352Sbill 					return(0);
9121352Sbill 				prevdiff = diff;
9131352Sbill 			}
9141352Sbill 		}
9151352Sbill 	}
9161352Sbill }
9171352Sbill 
9181352Sbill /*
9191352Sbill  * address to parameter name in procp
9201352Sbill  * returns difference between addr and address of local
9211352Sbill  * returned in sl_name
9221352Sbill  */
adrtoparam(addr,procp)9231352Sbill adrtoparam(addr, procp)
9241352Sbill ADDR addr; struct proct *procp; {
9251352Sbill 	struct nlist stentry;
9261352Sbill 	register int i, prevdiff = MAXPOS, diff;
9271352Sbill 
9281352Sbill 	blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
9291352Sbill 	for (;;) {
9301352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry)
9311352Sbill 				< sizeof stentry)
9321352Sbill 			return(prevdiff!=MAXPOS ? prevdiff : -1);
9331352Sbill 		if (stentry.n_type == N_FUN)
9341352Sbill 			return(prevdiff!=MAXPOS ? prevdiff : -1);
9351352Sbill 		if (stentry.n_type == N_PSYM) {
9361352Sbill 			diff = addr - stentry.n_value;
9371352Sbill 			if (diff >= 0 && diff < prevdiff) {
9381352Sbill #ifndef FLEXNAMES
9391352Sbill 				for (i=0; i<8; i++)
9401352Sbill 					sl_name[i] = stentry.n_un.n_name[i];
9411352Sbill #else
9421352Sbill 				sl_name = stentry.n_un.n_name;
9431352Sbill #endif
9441352Sbill 				if (diff == 0)
9451352Sbill 					return(0);
9461352Sbill 				prevdiff = diff;
9471352Sbill 			}
9481352Sbill 		}
9491352Sbill 	}
9501352Sbill }
9511352Sbill 
9521352Sbill /*
9531352Sbill  * register number to register variable name in procp
9541352Sbill  * returned in sl_name
9551352Sbill  */
adrtoregvar(regno,procp)9561352Sbill adrtoregvar(regno, procp)
9571352Sbill ADDR regno; struct proct *procp; {
9581352Sbill 	struct nlist stentry;
9591352Sbill 	register int i;
9601352Sbill 
9611352Sbill 	blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
9621352Sbill 	for (;;) {
9631352Sbill 		if (bread(&sbuf, &stentry, sizeof stentry)
9641352Sbill 				< sizeof stentry) return(-1);
9651352Sbill 		if (stentry.n_type == N_FUN)
9661352Sbill 			return(-1);
9671352Sbill 		if (stentry.n_type == N_RSYM) {
9681352Sbill 			if (stentry.n_value == regno) {
9691352Sbill #ifndef FLEXNAMES
9701352Sbill 				for (i=0; i<8; i++)
9711352Sbill 					sl_name[i] = stentry.n_un.n_name[i];
9721352Sbill #else
9731352Sbill 				sl_name = stentry.n_un.n_name;
9741352Sbill #endif
9751352Sbill 				return(0);
9761352Sbill 			}
9771352Sbill 		}
9781352Sbill 	}
9791352Sbill }
9801352Sbill 
9811352Sbill /* sets file map for M command */
setmap(s)9821352Sbill setmap(s)
9831352Sbill char *s; {
9841352Sbill 	union {
9851352Sbill 		MAP *m;
9861352Sbill 		L_INT *mp;
9871352Sbill 	} amap;
9881352Sbill 	int starflag = 0;
9891352Sbill 
9901352Sbill 	amap.mp = 0;
9911352Sbill 	for (; *s; s++) {
9921352Sbill 		switch (*s) {
9931352Sbill 		case '/':
9941352Sbill 			amap.m = &datmap;
9951352Sbill 			break;
9961352Sbill 		case '?':
9971352Sbill 			amap.m = &txtmap;
9981352Sbill 			break;
9991352Sbill 		case '*':
10001352Sbill 			starflag++;
10011352Sbill 			break;
10021352Sbill 		default:
10031352Sbill 			goto sout;
10041352Sbill 		}
10051352Sbill 	}
10061352Sbill 
10071352Sbill sout:	if (amap.mp == 0) {
10081352Sbill 		error("Map `?' or `/' must be specified");
10091352Sbill 		return;
10101352Sbill 	}
10111352Sbill 	if (starflag)
10121352Sbill 		amap.mp += 3;
10131352Sbill 	for (; *s; s++) {
10141352Sbill 		if (*s >= '0' && *s <= '9')
10151352Sbill 			*(amap.mp)++ = readint(&s);
10161352Sbill 	}
10171352Sbill }
1018