xref: /csrg-svn/old/dbx/object.c (revision 18225)
19673Slinton /* Copyright (c) 1982 Regents of the University of California */
29673Slinton 
3*18225Slinton static	char sccsid[] = "@(#)object.c	1.16 (Berkeley) 03/01/85";
49673Slinton 
5*18225Slinton static char rcsid[] = "$Header: object.c,v 1.6 84/12/26 10:40:51 linton Exp $";
6*18225Slinton 
79673Slinton /*
89673Slinton  * Object code interface, mainly for extraction of symbolic information.
99673Slinton  */
109673Slinton 
119673Slinton #include "defs.h"
129673Slinton #include "object.h"
1316613Ssam #include "stabstring.h"
149673Slinton #include "main.h"
159673Slinton #include "symbols.h"
169673Slinton #include "names.h"
179673Slinton #include "languages.h"
189673Slinton #include "mappings.h"
199673Slinton #include "lists.h"
209673Slinton #include <a.out.h>
219673Slinton #include <stab.h>
229673Slinton #include <ctype.h>
239673Slinton 
249673Slinton #ifndef public
259673Slinton 
269673Slinton struct {
279673Slinton     unsigned int stringsize;	/* size of the dumped string table */
289673Slinton     unsigned int nsyms;		/* number of symbols */
299673Slinton     unsigned int nfiles;	/* number of files */
309673Slinton     unsigned int nlines;	/* number of lines */
319673Slinton } nlhdr;
329673Slinton 
3316613Ssam #include "languages.h"
3416613Ssam #include "symbols.h"
3516613Ssam 
369673Slinton #endif
379673Slinton 
3816613Ssam #ifndef N_MOD2
3916613Ssam #    define N_MOD2 0x50
4016613Ssam #endif
4116613Ssam 
429673Slinton public String objname = "a.out";
4316613Ssam public integer objsize;
449673Slinton 
4516613Ssam public Language curlang;
4616613Ssam public Symbol curmodule;
4716613Ssam public Symbol curparam;
4816613Ssam public Symbol curcomm;
4916613Ssam public Symbol commchain;
5016613Ssam 
5116613Ssam private char *stringtab;
5216613Ssam private struct nlist *curnp;
539673Slinton private Boolean warned;
5412542Scsvaf private Boolean strip_ = false;
559673Slinton 
569673Slinton private Filetab *filep;
5711875Slinton private Linetab *linep, *prevlinep;
589673Slinton 
5916613Ssam public String curfilename ()
6016613Ssam {
6116613Ssam     return ((filep-1)->filename);
6216613Ssam }
639673Slinton 
649673Slinton /*
659673Slinton  * Blocks are figured out on the fly while reading the symbol table.
669673Slinton  */
679673Slinton 
689673Slinton #define MAXBLKDEPTH 25
699673Slinton 
7016613Ssam public Symbol curblock;
7116613Ssam 
729673Slinton private Symbol blkstack[MAXBLKDEPTH];
7316613Ssam private integer curlevel;
7416613Ssam private integer bnum, nesting;
7514443Slinton private Address addrstk[MAXBLKDEPTH];
769673Slinton 
7716613Ssam public pushBlock (b)
7816613Ssam Symbol b;
7916613Ssam {
8016613Ssam     if (curlevel >= MAXBLKDEPTH) {
8116613Ssam 	fatal("nesting depth too large (%d)", curlevel);
8216613Ssam     }
8316613Ssam     blkstack[curlevel] = curblock;
8416613Ssam     ++curlevel;
8516613Ssam     curblock = b;
8616613Ssam     if (traceblocks) {
8716613Ssam 	printf("entering block %s\n", symname(b));
8816613Ssam     }
899673Slinton }
909673Slinton 
91*18225Slinton /*
92*18225Slinton  * Change the current block with saving the previous one,
93*18225Slinton  * since it is assumed that the symbol for the current one is to be deleted.
94*18225Slinton  */
95*18225Slinton 
96*18225Slinton public changeBlock (b)
97*18225Slinton Symbol b;
98*18225Slinton {
99*18225Slinton     curblock = b;
100*18225Slinton }
101*18225Slinton 
10216613Ssam public enterblock (b)
10316613Ssam Symbol b;
10416613Ssam {
10516613Ssam     if (curblock == nil) {
10616613Ssam 	b->level = 1;
10716613Ssam     } else {
10816613Ssam 	b->level = curblock->level + 1;
10916613Ssam     }
11016613Ssam     b->block = curblock;
11116613Ssam     pushBlock(b);
1129673Slinton }
1139673Slinton 
11416613Ssam public exitblock ()
11516613Ssam {
11616613Ssam     if (curblock->class == FUNC or curblock->class == PROC) {
11716613Ssam 	if (prevlinep != linep) {
11816613Ssam 	    curblock->symvalue.funcv.src = true;
11916613Ssam 	}
12016613Ssam     }
12116613Ssam     if (curlevel <= 0) {
12216613Ssam 	panic("nesting depth underflow (%d)", curlevel);
12316613Ssam     }
12416613Ssam     --curlevel;
12516613Ssam     if (traceblocks) {
12616613Ssam 	printf("exiting block %s\n", symname(curblock));
12716613Ssam     }
12816613Ssam     curblock = blkstack[curlevel];
12916613Ssam }
13016613Ssam 
1319673Slinton /*
1329673Slinton  * Enter a source line or file name reference into the appropriate table.
1339673Slinton  * Expanded inline to reduce procedure calls.
1349673Slinton  *
13516613Ssam  * private enterline (linenumber, address)
1369673Slinton  * Lineno linenumber;
1379673Slinton  * Address address;
1389673Slinton  *  ...
1399673Slinton  */
1409673Slinton 
1419673Slinton #define enterline(linenumber, address) \
1429673Slinton { \
1439673Slinton     register Linetab *lp; \
1449673Slinton  \
1459673Slinton     lp = linep - 1; \
1469673Slinton     if (linenumber != lp->line) { \
1479673Slinton 	if (address != lp->addr) { \
1489673Slinton 	    ++lp; \
1499673Slinton 	} \
1509673Slinton 	lp->line = linenumber; \
1519673Slinton 	lp->addr = address; \
1529673Slinton 	linep = lp + 1; \
1539673Slinton     } \
1549673Slinton }
1559673Slinton 
1569673Slinton /*
1579673Slinton  * Read in the namelist from the obj file.
1589673Slinton  *
1599673Slinton  * Reads and seeks are used instead of fread's and fseek's
1609673Slinton  * for efficiency sake; there's a lot of data being read here.
1619673Slinton  */
1629673Slinton 
16316613Ssam public readobj (file)
1649673Slinton String file;
1659673Slinton {
1669673Slinton     Fileid f;
1679673Slinton     struct exec hdr;
1689673Slinton     struct nlist nlist;
1699673Slinton 
1709673Slinton     f = open(file, 0);
1719673Slinton     if (f < 0) {
1729673Slinton 	fatal("can't open %s", file);
1739673Slinton     }
1749673Slinton     read(f, &hdr, sizeof(hdr));
175*18225Slinton     if (N_BADMAG(hdr)) {
176*18225Slinton 	objsize = 0;
177*18225Slinton 	nlhdr.nsyms = 0;
178*18225Slinton 	nlhdr.nfiles = 0;
179*18225Slinton 	nlhdr.nlines = 0;
180*18225Slinton     } else {
181*18225Slinton 	objsize = hdr.a_text;
182*18225Slinton 	nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
183*18225Slinton 	nlhdr.nfiles = nlhdr.nsyms;
184*18225Slinton 	nlhdr.nlines = nlhdr.nsyms;
185*18225Slinton     }
18614443Slinton     if (nlhdr.nsyms > 0) {
18714443Slinton 	lseek(f, (long) N_STROFF(hdr), 0);
18814443Slinton 	read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
18914443Slinton 	nlhdr.stringsize -= 4;
19014443Slinton 	stringtab = newarr(char, nlhdr.stringsize);
19114443Slinton 	read(f, stringtab, nlhdr.stringsize);
19214443Slinton 	allocmaps(nlhdr.nfiles, nlhdr.nlines);
19314443Slinton 	lseek(f, (long) N_SYMOFF(hdr), 0);
19414443Slinton 	readsyms(f);
19514443Slinton 	ordfunctab();
19614443Slinton 	setnlines();
19714443Slinton 	setnfiles();
198*18225Slinton     } else {
199*18225Slinton 	initsyms();
20014443Slinton     }
2019673Slinton     close(f);
2029673Slinton }
2039673Slinton 
2049673Slinton /*
205*18225Slinton  * Found the beginning of the externals in the object file
206*18225Slinton  * (signified by the "-lg" or find an external), close the
207*18225Slinton  * block for the last procedure.
208*18225Slinton  */
209*18225Slinton 
210*18225Slinton private foundglobals ()
211*18225Slinton {
212*18225Slinton     if (curblock->class != PROG) {
213*18225Slinton 	exitblock();
214*18225Slinton 	if (curblock->class != PROG) {
215*18225Slinton 	    exitblock();
216*18225Slinton 	}
217*18225Slinton     }
218*18225Slinton     enterline(0, (linep-1)->addr + 1);
219*18225Slinton }
220*18225Slinton 
221*18225Slinton /*
2229673Slinton  * Read in symbols from object file.
2239673Slinton  */
2249673Slinton 
22516613Ssam private readsyms (f)
2269673Slinton Fileid f;
2279673Slinton {
2289673Slinton     struct nlist *namelist;
2299673Slinton     register struct nlist *np, *ub;
2309673Slinton     register String name;
2319673Slinton     register Boolean afterlg;
23216613Ssam     integer index;
23316613Ssam     char *lastchar;
2349673Slinton 
2359673Slinton     initsyms();
2369673Slinton     namelist = newarr(struct nlist, nlhdr.nsyms);
2379673Slinton     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
2389673Slinton     afterlg = false;
2399673Slinton     ub = &namelist[nlhdr.nsyms];
24016613Ssam     curnp = &namelist[0];
24116613Ssam     np = curnp;
24216613Ssam     while (np < ub) {
2439673Slinton 	index = np->n_un.n_strx;
2449673Slinton 	if (index != 0) {
2459673Slinton 	    name = &stringtab[index - 4];
24612542Scsvaf 	    /*
24716613Ssam              *  If the program contains any .f files a trailing _ is stripped
24812542Scsvaf        	     *  from the name on the assumption it was added by the compiler.
24912542Scsvaf 	     *  This only affects names that follow the sdb N_SO entry with
25012542Scsvaf              *  the .f name.
25112542Scsvaf              */
25214443Slinton             if (strip_ and name[0] != '\0' ) {
25316613Ssam 		lastchar = &name[strlen(name) - 1];
25416613Ssam 		if (*lastchar == '_') {
25516613Ssam 		    *lastchar = '\0';
25614443Slinton 		}
25712542Scsvaf             }
2589673Slinton 	} else {
2599673Slinton 	    name = nil;
26012542Scsvaf 	}
26116613Ssam 
2629673Slinton 	/*
26316613Ssam 	 * Assumptions:
2649673Slinton 	 *	not an N_STAB	==> name != nil
2659673Slinton 	 *	name[0] == '-'	==> name == "-lg"
2669673Slinton 	 *	name[0] != '_'	==> filename or invisible
2679673Slinton 	 *
2689673Slinton 	 * The "-lg" signals the beginning of global loader symbols.
26912542Scsvaf          *
2709673Slinton 	 */
2719673Slinton 	if ((np->n_type&N_STAB) != 0) {
2729673Slinton 	    enter_nl(name, np);
2739673Slinton 	} else if (name[0] == '-') {
2749673Slinton 	    afterlg = true;
275*18225Slinton 	    foundglobals();
27611104Slinton 	} else if (afterlg) {
277*18225Slinton 	    check_global(name, np);
278*18225Slinton 	} else if ((np->n_type&N_EXT) == N_EXT) {
279*18225Slinton 	    afterlg = true;
280*18225Slinton 	    foundglobals();
281*18225Slinton 	    check_global(name, np);
28211104Slinton 	} else if (name[0] == '_') {
28311104Slinton 	    check_local(&name[1], np);
2849673Slinton 	} else if ((np->n_type&N_TEXT) == N_TEXT) {
2859673Slinton 	    check_filename(name);
2869673Slinton 	}
28716613Ssam 	++curnp;
28816613Ssam 	np = curnp;
2899673Slinton     }
2909673Slinton     dispose(namelist);
2919673Slinton }
2929673Slinton 
2939673Slinton /*
29416613Ssam  * Get a continuation entry from the name list.
29516613Ssam  * Return the beginning of the name.
29616613Ssam  */
29716613Ssam 
29816613Ssam public String getcont ()
29916613Ssam {
30016613Ssam     register integer index;
30116613Ssam     register String name;
30216613Ssam 
30316613Ssam     ++curnp;
30416613Ssam     index = curnp->n_un.n_strx;
30516613Ssam     if (index == 0) {
30616613Ssam 	panic("continuation followed by empty stab");
30716613Ssam     }
30816613Ssam     name = &stringtab[index - 4];
30916613Ssam     return name;
31016613Ssam }
31116613Ssam 
31216613Ssam /*
3139673Slinton  * Initialize symbol information.
3149673Slinton  */
3159673Slinton 
31616613Ssam private initsyms ()
3179673Slinton {
3189673Slinton     curblock = nil;
3199673Slinton     curlevel = 0;
32014443Slinton     nesting = 0;
32116613Ssam     program = insert(identname("", true));
3229673Slinton     program->class = PROG;
32311769Slinton     program->symvalue.funcv.beginaddr = 0;
32414443Slinton     program->symvalue.funcv.inline = false;
32514443Slinton     newfunc(program, codeloc(program));
32611769Slinton     findbeginning(program);
3279673Slinton     enterblock(program);
3289673Slinton     curmodule = program;
3299673Slinton }
3309673Slinton 
3319673Slinton /*
3329673Slinton  * Free all the object file information that's being stored.
3339673Slinton  */
3349673Slinton 
33516613Ssam public objfree ()
3369673Slinton {
3379673Slinton     symbol_free();
338*18225Slinton     /* keywords_free(); */
339*18225Slinton     /* names_free(); */
340*18225Slinton     /* dispose(stringtab); */
3419673Slinton     clrfunctab();
3429673Slinton }
3439673Slinton 
3449673Slinton /*
3459673Slinton  * Enter a namelist entry.
3469673Slinton  */
3479673Slinton 
34816613Ssam private enter_nl (name, np)
3499673Slinton String name;
3509673Slinton register struct nlist *np;
3519673Slinton {
3529673Slinton     register Symbol s;
35316613Ssam     register Name n;
3549673Slinton 
3559673Slinton     s = nil;
3569673Slinton     switch (np->n_type) {
35714443Slinton 	/*
35814443Slinton 	 * Build a symbol for the FORTRAN common area.  All GSYMS that follow
35914443Slinton 	 * will be chained in a list with the head kept in common.offset, and
36014443Slinton 	 * the tail in common.chain.
36114443Slinton 	 */
36213938Slinton 	case N_BCOMM:
36313938Slinton  	    if (curcomm) {
36413938Slinton 		curcomm->symvalue.common.chain = commchain;
36512542Scsvaf 	    }
36616613Ssam 	    n = identname(name, true);
36712542Scsvaf 	    curcomm = lookup(n);
36813938Slinton 	    if (curcomm == nil) {
36913938Slinton 		curcomm = insert(n);
37013938Slinton 		curcomm->class = COMMON;
37113938Slinton 		curcomm->block = curblock;
37213938Slinton 		curcomm->level = program->level;
37313938Slinton 		curcomm->symvalue.common.chain = nil;
37412542Scsvaf 	    }
37512542Scsvaf 	    commchain = curcomm->symvalue.common.chain;
37613938Slinton 	    break;
37712542Scsvaf 
37812542Scsvaf 	case N_ECOMM:
37913938Slinton 	    if (curcomm) {
38013938Slinton 		curcomm->symvalue.common.chain = commchain;
38113938Slinton 		curcomm = nil;
38212542Scsvaf 	    }
38312542Scsvaf 	    break;
38414443Slinton 
3859673Slinton 	case N_LBRAC:
38614443Slinton 	    ++nesting;
38714443Slinton 	    addrstk[nesting] = (linep - 1)->addr;
3889673Slinton 	    break;
3899673Slinton 
3909673Slinton 	case N_RBRAC:
39116613Ssam 	    --nesting;
39214443Slinton 	    if (addrstk[nesting] == NOADDR) {
39314443Slinton 		exitblock();
39414443Slinton 		newfunc(curblock, (linep - 1)->addr);
39516613Ssam 		addrstk[nesting] = (linep - 1)->addr;
39614443Slinton 	    }
3979673Slinton 	    break;
3989673Slinton 
3999673Slinton 	case N_SLINE:
4009673Slinton 	    enterline((Lineno) np->n_desc, (Address) np->n_value);
4019673Slinton 	    break;
4029673Slinton 
4039673Slinton 	/*
40414443Slinton 	 * Source files.
4059673Slinton 	 */
4069673Slinton 	case N_SO:
40716613Ssam 	    n = identname(name, true);
40814443Slinton 	    enterSourceModule(n, (Address) np->n_value);
4099673Slinton 	    break;
4109673Slinton 
4119673Slinton 	/*
4129673Slinton 	 * Textually included files.
4139673Slinton 	 */
4149673Slinton 	case N_SOL:
4159673Slinton 	    enterfile(name, (Address) np->n_value);
4169673Slinton 	    break;
4179673Slinton 
4189673Slinton 	/*
4199673Slinton 	 * These symbols are assumed to have non-nil names.
4209673Slinton 	 */
4219673Slinton 	case N_GSYM:
4229673Slinton 	case N_FUN:
4239673Slinton 	case N_STSYM:
4249673Slinton 	case N_LCSYM:
4259673Slinton 	case N_RSYM:
4269673Slinton 	case N_PSYM:
4279673Slinton 	case N_LSYM:
4289673Slinton 	case N_SSYM:
42914443Slinton 	case N_LENG:
4309673Slinton 	    if (index(name, ':') == nil) {
4319673Slinton 		if (not warned) {
4329673Slinton 		    warned = true;
4339673Slinton 		    warning("old style symbol information found in \"%s\"",
4349673Slinton 			curfilename());
4359673Slinton 		}
4369673Slinton 	    } else {
4379673Slinton 		entersym(name, np);
4389673Slinton 	    }
4399673Slinton 	    break;
4409673Slinton 
4419673Slinton 	case N_PC:
44216613Ssam 	case N_MOD2:
4439673Slinton 	    break;
4449673Slinton 
44511558Slinton 	default:
44614443Slinton 	    printf("warning:  stab entry unrecognized: ");
4479673Slinton 	    if (name != nil) {
44814443Slinton 		printf("name %s,", name);
4499673Slinton 	    }
45014443Slinton 	    printf("ntype %2x, desc %x, value %x'\n",
4519673Slinton 		np->n_type, np->n_desc, np->n_value);
4529673Slinton 	    break;
4539673Slinton     }
4549673Slinton }
4559673Slinton 
4569673Slinton /*
457*18225Slinton  * Try to find the symbol that is referred to by the given name.  Since it's
458*18225Slinton  * an external, we need to follow a level or two of indirection.
45916613Ssam  */
46016613Ssam 
461*18225Slinton private Symbol findsym (n, var_isextref)
46216613Ssam Name n;
463*18225Slinton boolean *var_isextref;
46416613Ssam {
46516613Ssam     register Symbol r, s;
46616613Ssam 
467*18225Slinton     *var_isextref = false;
46816613Ssam     find(s, n) where
469*18225Slinton 	(
470*18225Slinton 	    s->level == program->level and (
471*18225Slinton 		s->class == EXTREF or s->class == VAR or
472*18225Slinton 		s->class == PROC or s->class == FUNC
473*18225Slinton 	    )
474*18225Slinton 	) or (
475*18225Slinton 	    s->block == program and s->class == MODULE
476*18225Slinton 	)
47716613Ssam     endfind(s);
478*18225Slinton     if (s == nil) {
479*18225Slinton 	r = nil;
480*18225Slinton     } else if (s->class == EXTREF) {
481*18225Slinton 	*var_isextref = true;
48216613Ssam 	r = s->symvalue.extref;
48316613Ssam 	delete(s);
484*18225Slinton 
485*18225Slinton 	/*
486*18225Slinton 	 * Now check for another level of indirection that could come from
487*18225Slinton 	 * a forward reference in procedure nesting information.  In this case
488*18225Slinton 	 * the symbol has already been deleted.
489*18225Slinton 	 */
490*18225Slinton 	if (r != nil and r->class == EXTREF) {
491*18225Slinton 	    r = r->symvalue.extref;
492*18225Slinton 	}
493*18225Slinton /*
494*18225Slinton     } else if (s->class == MODULE) {
495*18225Slinton 	s->class = FUNC;
496*18225Slinton 	s->level = program->level;
497*18225Slinton 	r = s;
498*18225Slinton  */
49916613Ssam     } else {
50016613Ssam 	r = s;
50116613Ssam     }
50216613Ssam     return r;
50316613Ssam }
50416613Ssam 
50516613Ssam /*
506*18225Slinton  * Create a symbol for a text symbol with no source information.
507*18225Slinton  * We treat it as an assembly language function.
508*18225Slinton  */
509*18225Slinton 
510*18225Slinton private Symbol deffunc (n)
511*18225Slinton Name n;
512*18225Slinton {
513*18225Slinton     Symbol f;
514*18225Slinton 
515*18225Slinton     f = insert(n);
516*18225Slinton     f->language = findlanguage(".s");
517*18225Slinton     f->class = FUNC;
518*18225Slinton     f->type = t_int;
519*18225Slinton     f->block = curblock;
520*18225Slinton     f->level = program->level;
521*18225Slinton     f->symvalue.funcv.src = false;
522*18225Slinton     f->symvalue.funcv.inline = false;
523*18225Slinton     return f;
524*18225Slinton }
525*18225Slinton 
526*18225Slinton /*
527*18225Slinton  * Create a symbol for a data or bss symbol with no source information.
528*18225Slinton  * We treat it as an assembly language variable.
529*18225Slinton  */
530*18225Slinton 
531*18225Slinton private Symbol defvar (n)
532*18225Slinton Name n;
533*18225Slinton {
534*18225Slinton     Symbol v;
535*18225Slinton 
536*18225Slinton     v = insert(n);
537*18225Slinton     v->language = findlanguage(".s");
538*18225Slinton     v->class = VAR;
539*18225Slinton     v->type = t_int;
540*18225Slinton     v->level = program->level;
541*18225Slinton     v->block = curblock;
542*18225Slinton     return v;
543*18225Slinton }
544*18225Slinton 
545*18225Slinton /*
546*18225Slinton  * Update a symbol entry with a text address.
547*18225Slinton  */
548*18225Slinton 
549*18225Slinton private updateTextSym (s, name, addr)
550*18225Slinton Symbol s;
551*18225Slinton char *name;
552*18225Slinton Address addr;
553*18225Slinton {
554*18225Slinton     if (s->class == VAR) {
555*18225Slinton 	s->symvalue.offset = addr;
556*18225Slinton     } else {
557*18225Slinton 	s->symvalue.funcv.beginaddr = addr;
558*18225Slinton 	if (name[0] == '_') {
559*18225Slinton 	    newfunc(s, codeloc(s));
560*18225Slinton 	    findbeginning(s);
561*18225Slinton 	}
562*18225Slinton     }
563*18225Slinton }
564*18225Slinton 
565*18225Slinton /*
5669673Slinton  * Check to see if a global _name is already in the symbol table,
5679673Slinton  * if not then insert it.
5689673Slinton  */
5699673Slinton 
57016613Ssam private check_global (name, np)
5719673Slinton String name;
5729673Slinton register struct nlist *np;
5739673Slinton {
5749673Slinton     register Name n;
57512542Scsvaf     register Symbol t, u;
576*18225Slinton     char buf[4096];
577*18225Slinton     boolean isextref;
578*18225Slinton     integer count;
5799673Slinton 
580*18225Slinton     if (not streq(name, "_end")) {
581*18225Slinton 	if (name[0] == '_') {
582*18225Slinton 	    n = identname(&name[1], true);
583*18225Slinton 	} else {
584*18225Slinton 	    n = identname(name, true);
585*18225Slinton 	    if (lookup(n) != nil) {
586*18225Slinton 		sprintf(buf, "$%s", name);
587*18225Slinton 		n = identname(buf, false);
588*18225Slinton 	    }
589*18225Slinton 	}
5909673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
591*18225Slinton 	    count = 0;
592*18225Slinton 	    t = findsym(n, &isextref);
593*18225Slinton 	    while (isextref) {
594*18225Slinton 		++count;
595*18225Slinton 		updateTextSym(t, name, np->n_value);
596*18225Slinton 		t = findsym(n, &isextref);
5979673Slinton 	    }
598*18225Slinton 	    if (count == 0) {
599*18225Slinton 		if (t == nil) {
600*18225Slinton 		    t = deffunc(n);
601*18225Slinton 		    updateTextSym(t, name, np->n_value);
602*18225Slinton 		    if (tracesyms) {
603*18225Slinton 			printdecl(t);
604*18225Slinton 		    }
605*18225Slinton 		} else {
606*18225Slinton 		    if (t->class == MODULE) {
607*18225Slinton 			u = t;
608*18225Slinton 			t = deffunc(n);
609*18225Slinton 			t->block = u;
610*18225Slinton 			if (tracesyms) {
611*18225Slinton 			    printdecl(t);
612*18225Slinton 			}
613*18225Slinton 		    }
614*18225Slinton 		    updateTextSym(t, name, np->n_value);
615*18225Slinton 		}
61616613Ssam 	    }
61713938Slinton 	} else if ((np->n_type&N_TYPE) == N_BSS) {
6189673Slinton 	    find(t, n) where
61913938Slinton 		t->class == COMMON
62012542Scsvaf 	    endfind(t);
62113938Slinton 	    if (t != nil) {
62213938Slinton 		u = (Symbol) t->symvalue.common.offset;
62313938Slinton 		while (u != nil) {
62413938Slinton 		    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
62513938Slinton 		    u = u->symvalue.common.chain;
62613938Slinton 		}
62713938Slinton             } else {
62813938Slinton 		check_var(np, n);
6299673Slinton 	    }
63013938Slinton         } else {
63113938Slinton 	    check_var(np, n);
6329673Slinton 	}
6339673Slinton     }
6349673Slinton }
6359673Slinton 
6369673Slinton /*
63713938Slinton  * Check to see if a namelist entry refers to a variable.
63813938Slinton  * If not, create a variable for the entry.  In any case,
63913938Slinton  * set the offset of the variable according to the value field
64013938Slinton  * in the entry.
641*18225Slinton  *
642*18225Slinton  * If the external name has been referred to by several other symbols,
643*18225Slinton  * we must update each of them.
64413938Slinton  */
64513938Slinton 
64616613Ssam private check_var (np, n)
64713938Slinton struct nlist *np;
64813938Slinton register Name n;
64913938Slinton {
650*18225Slinton     register Symbol t, u, next;
651*18225Slinton     Symbol conflict;
65213938Slinton 
653*18225Slinton     t = lookup(n);
65413938Slinton     if (t == nil) {
655*18225Slinton 	t = defvar(n);
656*18225Slinton 	t->symvalue.offset = np->n_value;
657*18225Slinton 	if (tracesyms) {
658*18225Slinton 	    printdecl(t);
659*18225Slinton 	}
660*18225Slinton     } else {
661*18225Slinton 	conflict = nil;
662*18225Slinton 	do {
663*18225Slinton 	    next = t->next_sym;
664*18225Slinton 	    if (t->name == n) {
665*18225Slinton 		if (t->class == MODULE and t->block == program) {
666*18225Slinton 		    conflict = t;
667*18225Slinton 		} else if (t->class == EXTREF and t->level == program->level) {
668*18225Slinton 		    u = t->symvalue.extref;
669*18225Slinton 		    while (u != nil and u->class == EXTREF) {
670*18225Slinton 			u = u->symvalue.extref;
671*18225Slinton 		    }
672*18225Slinton 		    u->symvalue.offset = np->n_value;
673*18225Slinton 		    delete(t);
674*18225Slinton 		} else if (t->level == program->level and
675*18225Slinton 		    (t->class == VAR or t->class == PROC or t->class == FUNC)
676*18225Slinton 		) {
677*18225Slinton 		    conflict = nil;
678*18225Slinton 		    t->symvalue.offset = np->n_value;
679*18225Slinton 		}
680*18225Slinton 	    }
681*18225Slinton 	    t = next;
682*18225Slinton 	} while (t != nil);
683*18225Slinton 	if (conflict != nil) {
684*18225Slinton 	    u = defvar(n);
685*18225Slinton 	    u->block = conflict;
686*18225Slinton 	    u->symvalue.offset = np->n_value;
687*18225Slinton 	}
68813938Slinton     }
68913938Slinton }
69013938Slinton 
69113938Slinton /*
6929673Slinton  * Check to see if a local _name is known in the current scope.
6939673Slinton  * If not then enter it.
6949673Slinton  */
6959673Slinton 
69616613Ssam private check_local (name, np)
6979673Slinton String name;
6989673Slinton register struct nlist *np;
6999673Slinton {
7009673Slinton     register Name n;
7019673Slinton     register Symbol t, cur;
7029673Slinton 
7039673Slinton     n = identname(name, true);
7049673Slinton     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
7059673Slinton     find(t, n) where t->block == cur endfind(t);
7069673Slinton     if (t == nil) {
7079673Slinton 	t = insert(n);
7089673Slinton 	t->language = findlanguage(".s");
7099673Slinton 	t->type = t_int;
7109673Slinton 	t->block = cur;
7119673Slinton 	t->level = cur->level;
7129673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
7139673Slinton 	    t->class = FUNC;
71411875Slinton 	    t->symvalue.funcv.src = false;
71514443Slinton 	    t->symvalue.funcv.inline = false;
7169673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
71714443Slinton 	    newfunc(t, codeloc(t));
7189673Slinton 	    findbeginning(t);
7199673Slinton 	} else {
7209673Slinton 	    t->class = VAR;
7219673Slinton 	    t->symvalue.offset = np->n_value;
7229673Slinton 	}
7239673Slinton     }
7249673Slinton }
7259673Slinton 
7269673Slinton /*
7279673Slinton  * Check to see if a symbol corresponds to a object file name.
7289673Slinton  * For some reason these are listed as in the text segment.
7299673Slinton  */
7309673Slinton 
73116613Ssam private check_filename (name)
7329673Slinton String name;
7339673Slinton {
7349673Slinton     register String mname;
73516613Ssam     register integer i;
736*18225Slinton     Name n;
737*18225Slinton     Symbol s;
7389673Slinton 
7399673Slinton     mname = strdup(name);
7409673Slinton     i = strlen(mname) - 2;
7419673Slinton     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
7429673Slinton 	mname[i] = '\0';
7439673Slinton 	--i;
7449673Slinton 	while (mname[i] != '/' and i >= 0) {
7459673Slinton 	    --i;
7469673Slinton 	}
747*18225Slinton 	n = identname(&mname[i+1], true);
748*18225Slinton 	find(s, n) where s->block == program and s->class == MODULE endfind(s);
749*18225Slinton 	if (s == nil) {
750*18225Slinton 	    s = insert(n);
751*18225Slinton 	    s->language = findlanguage(".s");
752*18225Slinton 	    s->class = MODULE;
753*18225Slinton 	    s->symvalue.funcv.beginaddr = 0;
754*18225Slinton 	    findbeginning(s);
755*18225Slinton 	}
7569673Slinton 	if (curblock->class != PROG) {
7579673Slinton 	    exitblock();
7589673Slinton 	    if (curblock->class != PROG) {
7599673Slinton 		exitblock();
7609673Slinton 	    }
7619673Slinton 	}
7629673Slinton 	enterblock(s);
7639673Slinton 	curmodule = s;
7649673Slinton     }
7659673Slinton }
7669673Slinton 
7679673Slinton /*
76814443Slinton  * Check to see if a symbol is about to be defined within an unnamed block.
76914443Slinton  * If this happens, we create a procedure for the unnamed block, make it
77014443Slinton  * "inline" so that tracebacks don't associate an activation record with it,
77114443Slinton  * and enter it into the function table so that it will be detected
77214443Slinton  * by "whatblock".
77314443Slinton  */
77414443Slinton 
77516613Ssam public chkUnnamedBlock ()
77614443Slinton {
77714443Slinton     register Symbol s;
77814443Slinton     static int bnum = 0;
77914443Slinton     char buf[100];
78016613Ssam     Address startaddr;
78114443Slinton 
78216613Ssam     if (nesting > 0 and addrstk[nesting] != NOADDR) {
78316613Ssam 	startaddr = (linep - 1)->addr;
78416613Ssam 	++bnum;
78516613Ssam 	sprintf(buf, "$b%d", bnum);
78616613Ssam 	s = insert(identname(buf, false));
78716613Ssam 	s->language = curlang;
78816613Ssam 	s->class = PROC;
78916613Ssam 	s->symvalue.funcv.src = false;
79016613Ssam 	s->symvalue.funcv.inline = true;
79116613Ssam 	s->symvalue.funcv.beginaddr = startaddr;
79216613Ssam 	enterblock(s);
79316613Ssam 	newfunc(s, startaddr);
79416613Ssam 	addrstk[nesting] = NOADDR;
79516613Ssam     }
79614443Slinton }
79714443Slinton 
79814443Slinton /*
79914443Slinton  * Compilation unit.  C associates scope with filenames
80014443Slinton  * so we treat them as "modules".  The filename without
80114443Slinton  * the suffix is used for the module name.
80214443Slinton  *
80314443Slinton  * Because there is no explicit "end-of-block" mark in
80414443Slinton  * the object file, we must exit blocks for the current
80514443Slinton  * procedure and module.
80614443Slinton  */
80714443Slinton 
80816613Ssam private enterSourceModule (n, addr)
80914443Slinton Name n;
81014443Slinton Address addr;
81114443Slinton {
81214443Slinton     register Symbol s;
81314443Slinton     Name nn;
81414443Slinton     String mname, suffix;
81514443Slinton 
81614443Slinton     mname = strdup(ident(n));
81714443Slinton     if (rindex(mname, '/') != nil) {
81814443Slinton 	mname = rindex(mname, '/') + 1;
81914443Slinton     }
82014443Slinton     suffix = rindex(mname, '.');
82114443Slinton     curlang = findlanguage(suffix);
82214443Slinton     if (curlang == findlanguage(".f")) {
82314443Slinton 	strip_ = true;
82414443Slinton     }
82514443Slinton     if (suffix != nil) {
82614443Slinton 	*suffix = '\0';
82714443Slinton     }
82816613Ssam     if (not (*language_op(curlang, L_HASMODULES))()) {
82914443Slinton 	if (curblock->class != PROG) {
83014443Slinton 	    exitblock();
83116613Ssam 	    if (curblock->class != PROG) {
83216613Ssam 		exitblock();
83316613Ssam 	    }
83414443Slinton 	}
83516613Ssam 	nn = identname(mname, true);
83616613Ssam 	if (curmodule == nil or curmodule->name != nn) {
83716613Ssam 	    s = insert(nn);
83816613Ssam 	    s->class = MODULE;
83916613Ssam 	    s->symvalue.funcv.beginaddr = 0;
84016613Ssam 	    findbeginning(s);
84116613Ssam 	} else {
84216613Ssam 	    s = curmodule;
84316613Ssam 	}
84416613Ssam 	s->language = curlang;
84516613Ssam 	enterblock(s);
84616613Ssam 	curmodule = s;
84714443Slinton     }
84814443Slinton     if (program->language == nil) {
84914443Slinton 	program->language = curlang;
85014443Slinton     }
85114443Slinton     warned = false;
85214443Slinton     enterfile(ident(n), addr);
85316613Ssam     initTypeTable();
85414443Slinton }
85514443Slinton 
85614443Slinton /*
8579673Slinton  * Allocate file and line tables and initialize indices.
8589673Slinton  */
8599673Slinton 
86016613Ssam private allocmaps (nf, nl)
86116613Ssam integer nf, nl;
8629673Slinton {
8639673Slinton     if (filetab != nil) {
8649673Slinton 	dispose(filetab);
8659673Slinton     }
8669673Slinton     if (linetab != nil) {
8679673Slinton 	dispose(linetab);
8689673Slinton     }
8699673Slinton     filetab = newarr(Filetab, nf);
8709673Slinton     linetab = newarr(Linetab, nl);
8719673Slinton     filep = filetab;
8729673Slinton     linep = linetab;
8739673Slinton }
8749673Slinton 
8759673Slinton /*
8769673Slinton  * Add a file to the file table.
87713938Slinton  *
87813938Slinton  * If the new address is the same as the previous file address
87913938Slinton  * this routine used to not enter the file, but this caused some
88013938Slinton  * problems so it has been removed.  It's not clear that this in
88113938Slinton  * turn may not also cause a problem.
8829673Slinton  */
8839673Slinton 
88416613Ssam private enterfile (filename, addr)
8859673Slinton String filename;
8869673Slinton Address addr;
8879673Slinton {
88813938Slinton     filep->addr = addr;
88913938Slinton     filep->filename = filename;
89013938Slinton     filep->lineindex = linep - linetab;
89113938Slinton     ++filep;
8929673Slinton }
8939673Slinton 
8949673Slinton /*
8959673Slinton  * Since we only estimated the number of lines (and it was a poor
8969673Slinton  * estimation) and since we need to know the exact number of lines
8979673Slinton  * to do a binary search, we set it when we're done.
8989673Slinton  */
8999673Slinton 
90016613Ssam private setnlines ()
9019673Slinton {
9029673Slinton     nlhdr.nlines = linep - linetab;
9039673Slinton }
9049673Slinton 
9059673Slinton /*
9069673Slinton  * Similarly for nfiles ...
9079673Slinton  */
9089673Slinton 
90916613Ssam private setnfiles ()
9109673Slinton {
9119673Slinton     nlhdr.nfiles = filep - filetab;
9129673Slinton     setsource(filetab[0].filename);
9139673Slinton }
914