xref: /csrg-svn/old/dbx/object.c (revision 46994)
121615Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
542683Sbostic  * %sccs.include.redist.c%
621615Sdist  */
79673Slinton 
821615Sdist #ifndef lint
9*46994Sbostic static char sccsid[] = "@(#)object.c	5.5 (Berkeley) 03/05/91";
1038105Sbostic #endif /* not lint */
119673Slinton 
129673Slinton /*
139673Slinton  * Object code interface, mainly for extraction of symbolic information.
149673Slinton  */
159673Slinton 
169673Slinton #include "defs.h"
179673Slinton #include "object.h"
1816613Ssam #include "stabstring.h"
199673Slinton #include "main.h"
209673Slinton #include "symbols.h"
219673Slinton #include "names.h"
229673Slinton #include "languages.h"
239673Slinton #include "mappings.h"
249673Slinton #include "lists.h"
259673Slinton #include <a.out.h>
269673Slinton #include <stab.h>
279673Slinton #include <ctype.h>
289673Slinton 
299673Slinton #ifndef public
309673Slinton 
319673Slinton struct {
329673Slinton     unsigned int stringsize;	/* size of the dumped string table */
339673Slinton     unsigned int nsyms;		/* number of symbols */
349673Slinton     unsigned int nfiles;	/* number of files */
359673Slinton     unsigned int nlines;	/* number of lines */
369673Slinton } nlhdr;
379673Slinton 
3816613Ssam #include "languages.h"
3916613Ssam #include "symbols.h"
4016613Ssam 
419673Slinton #endif
429673Slinton 
4316613Ssam #ifndef N_MOD2
4416613Ssam #    define N_MOD2 0x50
4516613Ssam #endif
4616613Ssam 
479673Slinton public String objname = "a.out";
4816613Ssam public integer objsize;
499673Slinton 
5016613Ssam public Language curlang;
5116613Ssam public Symbol curmodule;
5216613Ssam public Symbol curparam;
5316613Ssam public Symbol curcomm;
5416613Ssam public Symbol commchain;
5516613Ssam 
5616613Ssam private char *stringtab;
5716613Ssam private struct nlist *curnp;
589673Slinton private Boolean warned;
5912542Scsvaf private Boolean strip_ = false;
609673Slinton 
619673Slinton private Filetab *filep;
6211875Slinton private Linetab *linep, *prevlinep;
639673Slinton 
curfilename()6416613Ssam public String curfilename ()
6516613Ssam {
6616613Ssam     return ((filep-1)->filename);
6716613Ssam }
689673Slinton 
699673Slinton /*
709673Slinton  * Blocks are figured out on the fly while reading the symbol table.
719673Slinton  */
729673Slinton 
739673Slinton #define MAXBLKDEPTH 25
749673Slinton 
7516613Ssam public Symbol curblock;
7616613Ssam 
779673Slinton private Symbol blkstack[MAXBLKDEPTH];
7816613Ssam private integer curlevel;
7916613Ssam private integer bnum, nesting;
8014443Slinton private Address addrstk[MAXBLKDEPTH];
819673Slinton 
pushBlock(b)8216613Ssam public pushBlock (b)
8316613Ssam Symbol b;
8416613Ssam {
8516613Ssam     if (curlevel >= MAXBLKDEPTH) {
8616613Ssam 	fatal("nesting depth too large (%d)", curlevel);
8716613Ssam     }
8816613Ssam     blkstack[curlevel] = curblock;
8916613Ssam     ++curlevel;
9016613Ssam     curblock = b;
9116613Ssam     if (traceblocks) {
9216613Ssam 	printf("entering block %s\n", symname(b));
9316613Ssam     }
949673Slinton }
959673Slinton 
9618225Slinton /*
9718225Slinton  * Change the current block with saving the previous one,
9818225Slinton  * since it is assumed that the symbol for the current one is to be deleted.
9918225Slinton  */
10018225Slinton 
changeBlock(b)10118225Slinton public changeBlock (b)
10218225Slinton Symbol b;
10318225Slinton {
10418225Slinton     curblock = b;
10518225Slinton }
10618225Slinton 
enterblock(b)10716613Ssam public enterblock (b)
10816613Ssam Symbol b;
10916613Ssam {
11016613Ssam     if (curblock == nil) {
11116613Ssam 	b->level = 1;
11216613Ssam     } else {
11316613Ssam 	b->level = curblock->level + 1;
11416613Ssam     }
11516613Ssam     b->block = curblock;
11616613Ssam     pushBlock(b);
1179673Slinton }
1189673Slinton 
exitblock()11916613Ssam public exitblock ()
12016613Ssam {
12116613Ssam     if (curblock->class == FUNC or curblock->class == PROC) {
12216613Ssam 	if (prevlinep != linep) {
12316613Ssam 	    curblock->symvalue.funcv.src = true;
12416613Ssam 	}
12516613Ssam     }
12616613Ssam     if (curlevel <= 0) {
12716613Ssam 	panic("nesting depth underflow (%d)", curlevel);
12816613Ssam     }
12916613Ssam     --curlevel;
13016613Ssam     if (traceblocks) {
13116613Ssam 	printf("exiting block %s\n", symname(curblock));
13216613Ssam     }
13316613Ssam     curblock = blkstack[curlevel];
13416613Ssam }
13516613Ssam 
1369673Slinton /*
1379673Slinton  * Enter a source line or file name reference into the appropriate table.
1389673Slinton  * Expanded inline to reduce procedure calls.
1399673Slinton  *
14016613Ssam  * private enterline (linenumber, address)
1419673Slinton  * Lineno linenumber;
1429673Slinton  * Address address;
1439673Slinton  *  ...
1449673Slinton  */
1459673Slinton 
1469673Slinton #define enterline(linenumber, address) \
1479673Slinton { \
1489673Slinton     register Linetab *lp; \
1499673Slinton  \
1509673Slinton     lp = linep - 1; \
1519673Slinton     if (linenumber != lp->line) { \
1529673Slinton 	if (address != lp->addr) { \
1539673Slinton 	    ++lp; \
1549673Slinton 	} \
1559673Slinton 	lp->line = linenumber; \
1569673Slinton 	lp->addr = address; \
1579673Slinton 	linep = lp + 1; \
1589673Slinton     } \
1599673Slinton }
1609673Slinton 
1619673Slinton /*
1629673Slinton  * Read in the namelist from the obj file.
1639673Slinton  *
1649673Slinton  * Reads and seeks are used instead of fread's and fseek's
1659673Slinton  * for efficiency sake; there's a lot of data being read here.
1669673Slinton  */
1679673Slinton 
readobj(file)16816613Ssam public readobj (file)
1699673Slinton String file;
1709673Slinton {
1719673Slinton     Fileid f;
1729673Slinton     struct exec hdr;
1739673Slinton     struct nlist nlist;
1749673Slinton 
1759673Slinton     f = open(file, 0);
1769673Slinton     if (f < 0) {
1779673Slinton 	fatal("can't open %s", file);
1789673Slinton     }
1799673Slinton     read(f, &hdr, sizeof(hdr));
18018225Slinton     if (N_BADMAG(hdr)) {
18118225Slinton 	objsize = 0;
18218225Slinton 	nlhdr.nsyms = 0;
18318225Slinton 	nlhdr.nfiles = 0;
18418225Slinton 	nlhdr.nlines = 0;
18518225Slinton     } else {
18618225Slinton 	objsize = hdr.a_text;
18718225Slinton 	nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
18818225Slinton 	nlhdr.nfiles = nlhdr.nsyms;
18918225Slinton 	nlhdr.nlines = nlhdr.nsyms;
19018225Slinton     }
19114443Slinton     if (nlhdr.nsyms > 0) {
19214443Slinton 	lseek(f, (long) N_STROFF(hdr), 0);
19314443Slinton 	read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
19414443Slinton 	nlhdr.stringsize -= 4;
19514443Slinton 	stringtab = newarr(char, nlhdr.stringsize);
19614443Slinton 	read(f, stringtab, nlhdr.stringsize);
19714443Slinton 	allocmaps(nlhdr.nfiles, nlhdr.nlines);
19814443Slinton 	lseek(f, (long) N_SYMOFF(hdr), 0);
19914443Slinton 	readsyms(f);
20014443Slinton 	ordfunctab();
20114443Slinton 	setnlines();
20214443Slinton 	setnfiles();
20318225Slinton     } else {
20418225Slinton 	initsyms();
20514443Slinton     }
2069673Slinton     close(f);
2079673Slinton }
2089673Slinton 
2099673Slinton /*
21018225Slinton  * Found the beginning of the externals in the object file
21118225Slinton  * (signified by the "-lg" or find an external), close the
21218225Slinton  * block for the last procedure.
21318225Slinton  */
21418225Slinton 
foundglobals()21518225Slinton private foundglobals ()
21618225Slinton {
21718225Slinton     if (curblock->class != PROG) {
21818225Slinton 	exitblock();
21918225Slinton 	if (curblock->class != PROG) {
22018225Slinton 	    exitblock();
22118225Slinton 	}
22218225Slinton     }
22318225Slinton     enterline(0, (linep-1)->addr + 1);
22418225Slinton }
22518225Slinton 
22618225Slinton /*
2279673Slinton  * Read in symbols from object file.
2289673Slinton  */
2299673Slinton 
readsyms(f)23016613Ssam private readsyms (f)
2319673Slinton Fileid f;
2329673Slinton {
2339673Slinton     struct nlist *namelist;
2349673Slinton     register struct nlist *np, *ub;
2359673Slinton     register String name;
23633328Sdonn     boolean afterlg, foundstab;
23716613Ssam     integer index;
23816613Ssam     char *lastchar;
2399673Slinton 
2409673Slinton     initsyms();
2419673Slinton     namelist = newarr(struct nlist, nlhdr.nsyms);
2429673Slinton     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
2439673Slinton     afterlg = false;
24433328Sdonn     foundstab = false;
2459673Slinton     ub = &namelist[nlhdr.nsyms];
24616613Ssam     curnp = &namelist[0];
24716613Ssam     np = curnp;
24816613Ssam     while (np < ub) {
2499673Slinton 	index = np->n_un.n_strx;
2509673Slinton 	if (index != 0) {
2519673Slinton 	    name = &stringtab[index - 4];
25212542Scsvaf 	    /*
25316613Ssam              *  If the program contains any .f files a trailing _ is stripped
25412542Scsvaf        	     *  from the name on the assumption it was added by the compiler.
25512542Scsvaf 	     *  This only affects names that follow the sdb N_SO entry with
25612542Scsvaf              *  the .f name.
25712542Scsvaf              */
25814443Slinton             if (strip_ and name[0] != '\0' ) {
25916613Ssam 		lastchar = &name[strlen(name) - 1];
26016613Ssam 		if (*lastchar == '_') {
26116613Ssam 		    *lastchar = '\0';
26214443Slinton 		}
26312542Scsvaf             }
2649673Slinton 	} else {
2659673Slinton 	    name = nil;
26612542Scsvaf 	}
26716613Ssam 
2689673Slinton 	/*
26916613Ssam 	 * Assumptions:
2709673Slinton 	 *	not an N_STAB	==> name != nil
2719673Slinton 	 *	name[0] == '-'	==> name == "-lg"
2729673Slinton 	 *	name[0] != '_'	==> filename or invisible
2739673Slinton 	 *
2749673Slinton 	 * The "-lg" signals the beginning of global loader symbols.
27512542Scsvaf          *
2769673Slinton 	 */
2779673Slinton 	if ((np->n_type&N_STAB) != 0) {
27833328Sdonn 	    foundstab = true;
2799673Slinton 	    enter_nl(name, np);
2809673Slinton 	} else if (name[0] == '-') {
2819673Slinton 	    afterlg = true;
28218225Slinton 	    foundglobals();
28311104Slinton 	} else if (afterlg) {
28418225Slinton 	    check_global(name, np);
28518225Slinton 	} else if ((np->n_type&N_EXT) == N_EXT) {
28618225Slinton 	    afterlg = true;
28718225Slinton 	    foundglobals();
28818225Slinton 	    check_global(name, np);
28911104Slinton 	} else if (name[0] == '_') {
29011104Slinton 	    check_local(&name[1], np);
2919673Slinton 	} else if ((np->n_type&N_TEXT) == N_TEXT) {
2929673Slinton 	    check_filename(name);
2939673Slinton 	}
29416613Ssam 	++curnp;
29516613Ssam 	np = curnp;
2969673Slinton     }
29733328Sdonn     if (not foundstab) {
29833328Sdonn 	warning("no source compiled with -g");
29933328Sdonn     }
3009673Slinton     dispose(namelist);
3019673Slinton }
3029673Slinton 
3039673Slinton /*
30416613Ssam  * Get a continuation entry from the name list.
30516613Ssam  * Return the beginning of the name.
30616613Ssam  */
30716613Ssam 
getcont()30816613Ssam public String getcont ()
30916613Ssam {
31016613Ssam     register integer index;
31116613Ssam     register String name;
31216613Ssam 
31316613Ssam     ++curnp;
31416613Ssam     index = curnp->n_un.n_strx;
31516613Ssam     if (index == 0) {
31633328Sdonn 	name = "";
31733328Sdonn     } else {
31833328Sdonn 	name = &stringtab[index - 4];
31916613Ssam     }
32016613Ssam     return name;
32116613Ssam }
32216613Ssam 
32316613Ssam /*
3249673Slinton  * Initialize symbol information.
3259673Slinton  */
3269673Slinton 
initsyms()32716613Ssam private initsyms ()
3289673Slinton {
3299673Slinton     curblock = nil;
3309673Slinton     curlevel = 0;
33114443Slinton     nesting = 0;
33216613Ssam     program = insert(identname("", true));
3339673Slinton     program->class = PROG;
33433328Sdonn     program->language = primlang;
33533328Sdonn     program->symvalue.funcv.beginaddr = CODESTART;
336*46994Sbostic     program->symvalue.funcv.inlne = false;
33714443Slinton     newfunc(program, codeloc(program));
33811769Slinton     findbeginning(program);
3399673Slinton     enterblock(program);
3409673Slinton     curmodule = program;
3419673Slinton }
3429673Slinton 
3439673Slinton /*
3449673Slinton  * Free all the object file information that's being stored.
3459673Slinton  */
3469673Slinton 
objfree()34716613Ssam public objfree ()
3489673Slinton {
3499673Slinton     symbol_free();
35018225Slinton     /* keywords_free(); */
35118225Slinton     /* names_free(); */
35218225Slinton     /* dispose(stringtab); */
3539673Slinton     clrfunctab();
3549673Slinton }
3559673Slinton 
3569673Slinton /*
3579673Slinton  * Enter a namelist entry.
3589673Slinton  */
3599673Slinton 
enter_nl(name,np)36016613Ssam private enter_nl (name, np)
3619673Slinton String name;
3629673Slinton register struct nlist *np;
3639673Slinton {
3649673Slinton     register Symbol s;
36516613Ssam     register Name n;
3669673Slinton 
3679673Slinton     s = nil;
3689673Slinton     switch (np->n_type) {
36914443Slinton 	/*
37014443Slinton 	 * Build a symbol for the FORTRAN common area.  All GSYMS that follow
37114443Slinton 	 * will be chained in a list with the head kept in common.offset, and
37214443Slinton 	 * the tail in common.chain.
37314443Slinton 	 */
37413938Slinton 	case N_BCOMM:
37513938Slinton  	    if (curcomm) {
37613938Slinton 		curcomm->symvalue.common.chain = commchain;
37712542Scsvaf 	    }
37816613Ssam 	    n = identname(name, true);
37912542Scsvaf 	    curcomm = lookup(n);
38013938Slinton 	    if (curcomm == nil) {
38113938Slinton 		curcomm = insert(n);
38213938Slinton 		curcomm->class = COMMON;
38313938Slinton 		curcomm->block = curblock;
38413938Slinton 		curcomm->level = program->level;
38513938Slinton 		curcomm->symvalue.common.chain = nil;
38612542Scsvaf 	    }
38712542Scsvaf 	    commchain = curcomm->symvalue.common.chain;
38813938Slinton 	    break;
38912542Scsvaf 
39012542Scsvaf 	case N_ECOMM:
39113938Slinton 	    if (curcomm) {
39213938Slinton 		curcomm->symvalue.common.chain = commchain;
39313938Slinton 		curcomm = nil;
39412542Scsvaf 	    }
39512542Scsvaf 	    break;
39614443Slinton 
3979673Slinton 	case N_LBRAC:
39814443Slinton 	    ++nesting;
39914443Slinton 	    addrstk[nesting] = (linep - 1)->addr;
4009673Slinton 	    break;
4019673Slinton 
4029673Slinton 	case N_RBRAC:
40316613Ssam 	    --nesting;
40414443Slinton 	    if (addrstk[nesting] == NOADDR) {
40514443Slinton 		exitblock();
40614443Slinton 		newfunc(curblock, (linep - 1)->addr);
40716613Ssam 		addrstk[nesting] = (linep - 1)->addr;
40814443Slinton 	    }
4099673Slinton 	    break;
4109673Slinton 
4119673Slinton 	case N_SLINE:
4129673Slinton 	    enterline((Lineno) np->n_desc, (Address) np->n_value);
4139673Slinton 	    break;
4149673Slinton 
4159673Slinton 	/*
41614443Slinton 	 * Source files.
4179673Slinton 	 */
4189673Slinton 	case N_SO:
41916613Ssam 	    n = identname(name, true);
42014443Slinton 	    enterSourceModule(n, (Address) np->n_value);
4219673Slinton 	    break;
4229673Slinton 
4239673Slinton 	/*
4249673Slinton 	 * Textually included files.
4259673Slinton 	 */
4269673Slinton 	case N_SOL:
4279673Slinton 	    enterfile(name, (Address) np->n_value);
4289673Slinton 	    break;
4299673Slinton 
4309673Slinton 	/*
4319673Slinton 	 * These symbols are assumed to have non-nil names.
4329673Slinton 	 */
4339673Slinton 	case N_GSYM:
4349673Slinton 	case N_FUN:
4359673Slinton 	case N_STSYM:
4369673Slinton 	case N_LCSYM:
4379673Slinton 	case N_RSYM:
4389673Slinton 	case N_PSYM:
4399673Slinton 	case N_LSYM:
4409673Slinton 	case N_SSYM:
44114443Slinton 	case N_LENG:
4429673Slinton 	    if (index(name, ':') == nil) {
4439673Slinton 		if (not warned) {
4449673Slinton 		    warned = true;
44533328Sdonn 		    printf("warning: old style symbol information ");
44633328Sdonn 		    printf("found in \"%s\"\n", curfilename());
4479673Slinton 		}
4489673Slinton 	    } else {
4499673Slinton 		entersym(name, np);
4509673Slinton 	    }
4519673Slinton 	    break;
4529673Slinton 
4539673Slinton 	case N_PC:
45416613Ssam 	case N_MOD2:
4559673Slinton 	    break;
4569673Slinton 
45711558Slinton 	default:
45814443Slinton 	    printf("warning:  stab entry unrecognized: ");
4599673Slinton 	    if (name != nil) {
46014443Slinton 		printf("name %s,", name);
4619673Slinton 	    }
46214443Slinton 	    printf("ntype %2x, desc %x, value %x'\n",
4639673Slinton 		np->n_type, np->n_desc, np->n_value);
4649673Slinton 	    break;
4659673Slinton     }
4669673Slinton }
4679673Slinton 
4689673Slinton /*
46918225Slinton  * Try to find the symbol that is referred to by the given name.  Since it's
47018225Slinton  * an external, we need to follow a level or two of indirection.
47116613Ssam  */
47216613Ssam 
findsym(n,var_isextref)47318225Slinton private Symbol findsym (n, var_isextref)
47416613Ssam Name n;
47518225Slinton boolean *var_isextref;
47616613Ssam {
47716613Ssam     register Symbol r, s;
47816613Ssam 
47918225Slinton     *var_isextref = false;
48016613Ssam     find(s, n) where
48118225Slinton 	(
48218225Slinton 	    s->level == program->level and (
48318225Slinton 		s->class == EXTREF or s->class == VAR or
48418225Slinton 		s->class == PROC or s->class == FUNC
48518225Slinton 	    )
48618225Slinton 	) or (
48718225Slinton 	    s->block == program and s->class == MODULE
48818225Slinton 	)
48916613Ssam     endfind(s);
49018225Slinton     if (s == nil) {
49118225Slinton 	r = nil;
49218225Slinton     } else if (s->class == EXTREF) {
49318225Slinton 	*var_isextref = true;
49416613Ssam 	r = s->symvalue.extref;
49516613Ssam 	delete(s);
49618225Slinton 
49718225Slinton 	/*
49818225Slinton 	 * Now check for another level of indirection that could come from
49918225Slinton 	 * a forward reference in procedure nesting information.  In this case
50018225Slinton 	 * the symbol has already been deleted.
50118225Slinton 	 */
50218225Slinton 	if (r != nil and r->class == EXTREF) {
50318225Slinton 	    r = r->symvalue.extref;
50418225Slinton 	}
50518225Slinton /*
50618225Slinton     } else if (s->class == MODULE) {
50718225Slinton 	s->class = FUNC;
50818225Slinton 	s->level = program->level;
50918225Slinton 	r = s;
51018225Slinton  */
51116613Ssam     } else {
51216613Ssam 	r = s;
51316613Ssam     }
51416613Ssam     return r;
51516613Ssam }
51616613Ssam 
51716613Ssam /*
51818225Slinton  * Create a symbol for a text symbol with no source information.
51918225Slinton  * We treat it as an assembly language function.
52018225Slinton  */
52118225Slinton 
deffunc(n)52218225Slinton private Symbol deffunc (n)
52318225Slinton Name n;
52418225Slinton {
52518225Slinton     Symbol f;
52618225Slinton 
52718225Slinton     f = insert(n);
52818225Slinton     f->language = findlanguage(".s");
52918225Slinton     f->class = FUNC;
53018225Slinton     f->type = t_int;
53118225Slinton     f->block = curblock;
53218225Slinton     f->level = program->level;
53318225Slinton     f->symvalue.funcv.src = false;
534*46994Sbostic     f->symvalue.funcv.inlne = false;
53533328Sdonn     if (f->chain != nil) {
53633328Sdonn 	panic("chain not nil in deffunc");
53733328Sdonn     }
53818225Slinton     return f;
53918225Slinton }
54018225Slinton 
54118225Slinton /*
54218225Slinton  * Create a symbol for a data or bss symbol with no source information.
54318225Slinton  * We treat it as an assembly language variable.
54418225Slinton  */
54518225Slinton 
defvar(n)54618225Slinton private Symbol defvar (n)
54718225Slinton Name n;
54818225Slinton {
54918225Slinton     Symbol v;
55018225Slinton 
55118225Slinton     v = insert(n);
55218225Slinton     v->language = findlanguage(".s");
55333328Sdonn     v->storage = EXT;
55418225Slinton     v->class = VAR;
55518225Slinton     v->type = t_int;
55618225Slinton     v->level = program->level;
55718225Slinton     v->block = curblock;
55818225Slinton     return v;
55918225Slinton }
56018225Slinton 
56118225Slinton /*
56218225Slinton  * Update a symbol entry with a text address.
56318225Slinton  */
56418225Slinton 
updateTextSym(s,name,addr)56518225Slinton private updateTextSym (s, name, addr)
56618225Slinton Symbol s;
56718225Slinton char *name;
56818225Slinton Address addr;
56918225Slinton {
57018225Slinton     if (s->class == VAR) {
57118225Slinton 	s->symvalue.offset = addr;
57218225Slinton     } else {
57318225Slinton 	s->symvalue.funcv.beginaddr = addr;
57418225Slinton 	if (name[0] == '_') {
57518225Slinton 	    newfunc(s, codeloc(s));
57618225Slinton 	    findbeginning(s);
57718225Slinton 	}
57818225Slinton     }
57918225Slinton }
58018225Slinton 
58118225Slinton /*
58233328Sdonn  * Avoid seeing Pascal labels as text symbols.
58333328Sdonn  */
58433328Sdonn 
PascalLabel(n)58533328Sdonn private boolean PascalLabel (n)
58633328Sdonn Name n;
58733328Sdonn {
58833328Sdonn     boolean b;
58933328Sdonn     register char *p;
59033328Sdonn 
59133328Sdonn     b = false;
59233328Sdonn     if (curlang == findlanguage(".p")) {
59333328Sdonn 	p = ident(n);
59433328Sdonn 	while (*p != '\0') {
59533328Sdonn 	    if (*p == '_' and *(p+1) == '$') {
59633328Sdonn 		b = true;
59733328Sdonn 		break;
59833328Sdonn 	    }
59933328Sdonn 	    ++p;
60033328Sdonn 	}
60133328Sdonn     }
60233328Sdonn     return b;
60333328Sdonn }
60433328Sdonn 
60533328Sdonn /*
6069673Slinton  * Check to see if a global _name is already in the symbol table,
6079673Slinton  * if not then insert it.
6089673Slinton  */
6099673Slinton 
check_global(name,np)61016613Ssam private check_global (name, np)
6119673Slinton String name;
6129673Slinton register struct nlist *np;
6139673Slinton {
6149673Slinton     register Name n;
61512542Scsvaf     register Symbol t, u;
61618225Slinton     char buf[4096];
61718225Slinton     boolean isextref;
61818225Slinton     integer count;
6199673Slinton 
62018225Slinton     if (not streq(name, "_end")) {
62118225Slinton 	if (name[0] == '_') {
62218225Slinton 	    n = identname(&name[1], true);
62318225Slinton 	} else {
62418225Slinton 	    n = identname(name, true);
62518225Slinton 	    if (lookup(n) != nil) {
62618225Slinton 		sprintf(buf, "$%s", name);
62718225Slinton 		n = identname(buf, false);
62818225Slinton 	    }
62918225Slinton 	}
6309673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
63118225Slinton 	    count = 0;
63218225Slinton 	    t = findsym(n, &isextref);
63318225Slinton 	    while (isextref) {
63418225Slinton 		++count;
63518225Slinton 		updateTextSym(t, name, np->n_value);
63618225Slinton 		t = findsym(n, &isextref);
6379673Slinton 	    }
63818225Slinton 	    if (count == 0) {
63918225Slinton 		if (t == nil) {
64033328Sdonn 		    if (not PascalLabel(n)) {
64133328Sdonn 			t = deffunc(n);
64233328Sdonn 			updateTextSym(t, name, np->n_value);
64333328Sdonn 			if (tracesyms) {
64433328Sdonn 			    printdecl(t);
64533328Sdonn 			}
64618225Slinton 		    }
64718225Slinton 		} else {
64818225Slinton 		    if (t->class == MODULE) {
64918225Slinton 			u = t;
65018225Slinton 			t = deffunc(n);
65118225Slinton 			t->block = u;
65218225Slinton 			if (tracesyms) {
65318225Slinton 			    printdecl(t);
65418225Slinton 			}
65518225Slinton 		    }
65618225Slinton 		    updateTextSym(t, name, np->n_value);
65718225Slinton 		}
65816613Ssam 	    }
65933328Sdonn 	} else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) {
6609673Slinton 	    find(t, n) where
66113938Slinton 		t->class == COMMON
66212542Scsvaf 	    endfind(t);
66313938Slinton 	    if (t != nil) {
66413938Slinton 		u = (Symbol) t->symvalue.common.offset;
66513938Slinton 		while (u != nil) {
66613938Slinton 		    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
66713938Slinton 		    u = u->symvalue.common.chain;
66813938Slinton 		}
66913938Slinton             } else {
67013938Slinton 		check_var(np, n);
6719673Slinton 	    }
67213938Slinton         } else {
67313938Slinton 	    check_var(np, n);
6749673Slinton 	}
6759673Slinton     }
6769673Slinton }
6779673Slinton 
6789673Slinton /*
67913938Slinton  * Check to see if a namelist entry refers to a variable.
68013938Slinton  * If not, create a variable for the entry.  In any case,
68113938Slinton  * set the offset of the variable according to the value field
68213938Slinton  * in the entry.
68318225Slinton  *
68418225Slinton  * If the external name has been referred to by several other symbols,
68518225Slinton  * we must update each of them.
68613938Slinton  */
68713938Slinton 
check_var(np,n)68816613Ssam private check_var (np, n)
68913938Slinton struct nlist *np;
69013938Slinton register Name n;
69113938Slinton {
69218225Slinton     register Symbol t, u, next;
69318225Slinton     Symbol conflict;
69413938Slinton 
69518225Slinton     t = lookup(n);
69613938Slinton     if (t == nil) {
69718225Slinton 	t = defvar(n);
69818225Slinton 	t->symvalue.offset = np->n_value;
69918225Slinton 	if (tracesyms) {
70018225Slinton 	    printdecl(t);
70118225Slinton 	}
70218225Slinton     } else {
70318225Slinton 	conflict = nil;
70418225Slinton 	do {
70518225Slinton 	    next = t->next_sym;
70618225Slinton 	    if (t->name == n) {
70718225Slinton 		if (t->class == MODULE and t->block == program) {
70818225Slinton 		    conflict = t;
70918225Slinton 		} else if (t->class == EXTREF and t->level == program->level) {
71018225Slinton 		    u = t->symvalue.extref;
71118225Slinton 		    while (u != nil and u->class == EXTREF) {
71218225Slinton 			u = u->symvalue.extref;
71318225Slinton 		    }
71418225Slinton 		    u->symvalue.offset = np->n_value;
71518225Slinton 		    delete(t);
71618225Slinton 		} else if (t->level == program->level and
71718225Slinton 		    (t->class == VAR or t->class == PROC or t->class == FUNC)
71818225Slinton 		) {
71918225Slinton 		    conflict = nil;
72018225Slinton 		    t->symvalue.offset = np->n_value;
72118225Slinton 		}
72218225Slinton 	    }
72318225Slinton 	    t = next;
72418225Slinton 	} while (t != nil);
72518225Slinton 	if (conflict != nil) {
72618225Slinton 	    u = defvar(n);
72718225Slinton 	    u->block = conflict;
72818225Slinton 	    u->symvalue.offset = np->n_value;
72918225Slinton 	}
73013938Slinton     }
73113938Slinton }
73213938Slinton 
73313938Slinton /*
7349673Slinton  * Check to see if a local _name is known in the current scope.
7359673Slinton  * If not then enter it.
7369673Slinton  */
7379673Slinton 
check_local(name,np)73816613Ssam private check_local (name, np)
7399673Slinton String name;
7409673Slinton register struct nlist *np;
7419673Slinton {
7429673Slinton     register Name n;
7439673Slinton     register Symbol t, cur;
7449673Slinton 
7459673Slinton     n = identname(name, true);
7469673Slinton     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
7479673Slinton     find(t, n) where t->block == cur endfind(t);
7489673Slinton     if (t == nil) {
7499673Slinton 	t = insert(n);
7509673Slinton 	t->language = findlanguage(".s");
7519673Slinton 	t->type = t_int;
7529673Slinton 	t->block = cur;
75333328Sdonn 	t->storage = EXT;
7549673Slinton 	t->level = cur->level;
7559673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
7569673Slinton 	    t->class = FUNC;
75711875Slinton 	    t->symvalue.funcv.src = false;
758*46994Sbostic 	    t->symvalue.funcv.inlne = false;
7599673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
76014443Slinton 	    newfunc(t, codeloc(t));
7619673Slinton 	    findbeginning(t);
7629673Slinton 	} else {
7639673Slinton 	    t->class = VAR;
7649673Slinton 	    t->symvalue.offset = np->n_value;
7659673Slinton 	}
7669673Slinton     }
7679673Slinton }
7689673Slinton 
7699673Slinton /*
7709673Slinton  * Check to see if a symbol corresponds to a object file name.
7719673Slinton  * For some reason these are listed as in the text segment.
7729673Slinton  */
7739673Slinton 
check_filename(name)77416613Ssam private check_filename (name)
7759673Slinton String name;
7769673Slinton {
7779673Slinton     register String mname;
77816613Ssam     register integer i;
77918225Slinton     Name n;
78018225Slinton     Symbol s;
7819673Slinton 
7829673Slinton     mname = strdup(name);
7839673Slinton     i = strlen(mname) - 2;
7849673Slinton     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
7859673Slinton 	mname[i] = '\0';
7869673Slinton 	--i;
7879673Slinton 	while (mname[i] != '/' and i >= 0) {
7889673Slinton 	    --i;
7899673Slinton 	}
79018225Slinton 	n = identname(&mname[i+1], true);
79118225Slinton 	find(s, n) where s->block == program and s->class == MODULE endfind(s);
79218225Slinton 	if (s == nil) {
79318225Slinton 	    s = insert(n);
79418225Slinton 	    s->language = findlanguage(".s");
79518225Slinton 	    s->class = MODULE;
79618225Slinton 	    s->symvalue.funcv.beginaddr = 0;
79718225Slinton 	    findbeginning(s);
79818225Slinton 	}
7999673Slinton 	if (curblock->class != PROG) {
8009673Slinton 	    exitblock();
8019673Slinton 	    if (curblock->class != PROG) {
8029673Slinton 		exitblock();
8039673Slinton 	    }
8049673Slinton 	}
8059673Slinton 	enterblock(s);
8069673Slinton 	curmodule = s;
8079673Slinton     }
8089673Slinton }
8099673Slinton 
8109673Slinton /*
81114443Slinton  * Check to see if a symbol is about to be defined within an unnamed block.
81214443Slinton  * If this happens, we create a procedure for the unnamed block, make it
81314443Slinton  * "inline" so that tracebacks don't associate an activation record with it,
81414443Slinton  * and enter it into the function table so that it will be detected
81514443Slinton  * by "whatblock".
81614443Slinton  */
81714443Slinton 
chkUnnamedBlock()81816613Ssam public chkUnnamedBlock ()
81914443Slinton {
82014443Slinton     register Symbol s;
82114443Slinton     static int bnum = 0;
82214443Slinton     char buf[100];
82316613Ssam     Address startaddr;
82414443Slinton 
82516613Ssam     if (nesting > 0 and addrstk[nesting] != NOADDR) {
82616613Ssam 	startaddr = (linep - 1)->addr;
82716613Ssam 	++bnum;
82816613Ssam 	sprintf(buf, "$b%d", bnum);
82916613Ssam 	s = insert(identname(buf, false));
83016613Ssam 	s->language = curlang;
83116613Ssam 	s->class = PROC;
83216613Ssam 	s->symvalue.funcv.src = false;
833*46994Sbostic 	s->symvalue.funcv.inlne = true;
83416613Ssam 	s->symvalue.funcv.beginaddr = startaddr;
83516613Ssam 	enterblock(s);
83616613Ssam 	newfunc(s, startaddr);
83716613Ssam 	addrstk[nesting] = NOADDR;
83816613Ssam     }
83914443Slinton }
84014443Slinton 
84114443Slinton /*
84214443Slinton  * Compilation unit.  C associates scope with filenames
84314443Slinton  * so we treat them as "modules".  The filename without
84414443Slinton  * the suffix is used for the module name.
84514443Slinton  *
84614443Slinton  * Because there is no explicit "end-of-block" mark in
84714443Slinton  * the object file, we must exit blocks for the current
84814443Slinton  * procedure and module.
84914443Slinton  */
85014443Slinton 
enterSourceModule(n,addr)85116613Ssam private enterSourceModule (n, addr)
85214443Slinton Name n;
85314443Slinton Address addr;
85414443Slinton {
85514443Slinton     register Symbol s;
85614443Slinton     Name nn;
85714443Slinton     String mname, suffix;
85814443Slinton 
85914443Slinton     mname = strdup(ident(n));
86014443Slinton     if (rindex(mname, '/') != nil) {
86114443Slinton 	mname = rindex(mname, '/') + 1;
86214443Slinton     }
86314443Slinton     suffix = rindex(mname, '.');
86433328Sdonn     if (suffix > mname && *(suffix-1) == '.') {
86533328Sdonn 	/* special hack for C++ */
86633328Sdonn 	--suffix;
86733328Sdonn     }
86814443Slinton     curlang = findlanguage(suffix);
86914443Slinton     if (curlang == findlanguage(".f")) {
87014443Slinton 	strip_ = true;
87114443Slinton     }
87214443Slinton     if (suffix != nil) {
87314443Slinton 	*suffix = '\0';
87414443Slinton     }
87516613Ssam     if (not (*language_op(curlang, L_HASMODULES))()) {
87614443Slinton 	if (curblock->class != PROG) {
87714443Slinton 	    exitblock();
87816613Ssam 	    if (curblock->class != PROG) {
87916613Ssam 		exitblock();
88016613Ssam 	    }
88114443Slinton 	}
88216613Ssam 	nn = identname(mname, true);
88316613Ssam 	if (curmodule == nil or curmodule->name != nn) {
88416613Ssam 	    s = insert(nn);
88516613Ssam 	    s->class = MODULE;
88616613Ssam 	    s->symvalue.funcv.beginaddr = 0;
88716613Ssam 	    findbeginning(s);
88816613Ssam 	} else {
88916613Ssam 	    s = curmodule;
89016613Ssam 	}
89116613Ssam 	s->language = curlang;
89216613Ssam 	enterblock(s);
89316613Ssam 	curmodule = s;
89414443Slinton     }
89514443Slinton     if (program->language == nil) {
89614443Slinton 	program->language = curlang;
89714443Slinton     }
89814443Slinton     warned = false;
89914443Slinton     enterfile(ident(n), addr);
90016613Ssam     initTypeTable();
90114443Slinton }
90214443Slinton 
90314443Slinton /*
9049673Slinton  * Allocate file and line tables and initialize indices.
9059673Slinton  */
9069673Slinton 
allocmaps(nf,nl)90716613Ssam private allocmaps (nf, nl)
90816613Ssam integer nf, nl;
9099673Slinton {
9109673Slinton     if (filetab != nil) {
9119673Slinton 	dispose(filetab);
9129673Slinton     }
9139673Slinton     if (linetab != nil) {
9149673Slinton 	dispose(linetab);
9159673Slinton     }
9169673Slinton     filetab = newarr(Filetab, nf);
9179673Slinton     linetab = newarr(Linetab, nl);
9189673Slinton     filep = filetab;
9199673Slinton     linep = linetab;
9209673Slinton }
9219673Slinton 
9229673Slinton /*
9239673Slinton  * Add a file to the file table.
92413938Slinton  *
92513938Slinton  * If the new address is the same as the previous file address
92613938Slinton  * this routine used to not enter the file, but this caused some
92713938Slinton  * problems so it has been removed.  It's not clear that this in
92813938Slinton  * turn may not also cause a problem.
9299673Slinton  */
9309673Slinton 
enterfile(filename,addr)93116613Ssam private enterfile (filename, addr)
9329673Slinton String filename;
9339673Slinton Address addr;
9349673Slinton {
93513938Slinton     filep->addr = addr;
93613938Slinton     filep->filename = filename;
93713938Slinton     filep->lineindex = linep - linetab;
93813938Slinton     ++filep;
9399673Slinton }
9409673Slinton 
9419673Slinton /*
9429673Slinton  * Since we only estimated the number of lines (and it was a poor
9439673Slinton  * estimation) and since we need to know the exact number of lines
9449673Slinton  * to do a binary search, we set it when we're done.
9459673Slinton  */
9469673Slinton 
setnlines()94716613Ssam private setnlines ()
9489673Slinton {
9499673Slinton     nlhdr.nlines = linep - linetab;
9509673Slinton }
9519673Slinton 
9529673Slinton /*
9539673Slinton  * Similarly for nfiles ...
9549673Slinton  */
9559673Slinton 
setnfiles()95616613Ssam private setnfiles ()
9579673Slinton {
9589673Slinton     nlhdr.nfiles = filep - filetab;
9599673Slinton     setsource(filetab[0].filename);
9609673Slinton }
961