xref: /csrg-svn/old/dbx/object.c (revision 33328)
121615Sdist /*
221615Sdist  * Copyright (c) 1983 Regents of the University of California.
321615Sdist  * All rights reserved.  The Berkeley software License Agreement
421615Sdist  * specifies the terms and conditions for redistribution.
521615Sdist  */
69673Slinton 
721615Sdist #ifndef lint
8*33328Sdonn static char sccsid[] = "@(#)object.c	5.2 (Berkeley) 01/12/88";
921615Sdist #endif not lint
109673Slinton 
11*33328Sdonn static char rcsid[] = "$Header: object.c,v 1.5 87/03/26 20:24:58 donn Exp $";
1218225Slinton 
139673Slinton /*
149673Slinton  * Object code interface, mainly for extraction of symbolic information.
159673Slinton  */
169673Slinton 
179673Slinton #include "defs.h"
189673Slinton #include "object.h"
1916613Ssam #include "stabstring.h"
209673Slinton #include "main.h"
219673Slinton #include "symbols.h"
229673Slinton #include "names.h"
239673Slinton #include "languages.h"
249673Slinton #include "mappings.h"
259673Slinton #include "lists.h"
269673Slinton #include <a.out.h>
279673Slinton #include <stab.h>
289673Slinton #include <ctype.h>
299673Slinton 
309673Slinton #ifndef public
319673Slinton 
329673Slinton struct {
339673Slinton     unsigned int stringsize;	/* size of the dumped string table */
349673Slinton     unsigned int nsyms;		/* number of symbols */
359673Slinton     unsigned int nfiles;	/* number of files */
369673Slinton     unsigned int nlines;	/* number of lines */
379673Slinton } nlhdr;
389673Slinton 
3916613Ssam #include "languages.h"
4016613Ssam #include "symbols.h"
4116613Ssam 
429673Slinton #endif
439673Slinton 
4416613Ssam #ifndef N_MOD2
4516613Ssam #    define N_MOD2 0x50
4616613Ssam #endif
4716613Ssam 
489673Slinton public String objname = "a.out";
4916613Ssam public integer objsize;
509673Slinton 
5116613Ssam public Language curlang;
5216613Ssam public Symbol curmodule;
5316613Ssam public Symbol curparam;
5416613Ssam public Symbol curcomm;
5516613Ssam public Symbol commchain;
5616613Ssam 
5716613Ssam private char *stringtab;
5816613Ssam private struct nlist *curnp;
599673Slinton private Boolean warned;
6012542Scsvaf private Boolean strip_ = false;
619673Slinton 
629673Slinton private Filetab *filep;
6311875Slinton private Linetab *linep, *prevlinep;
649673Slinton 
6516613Ssam public String curfilename ()
6616613Ssam {
6716613Ssam     return ((filep-1)->filename);
6816613Ssam }
699673Slinton 
709673Slinton /*
719673Slinton  * Blocks are figured out on the fly while reading the symbol table.
729673Slinton  */
739673Slinton 
749673Slinton #define MAXBLKDEPTH 25
759673Slinton 
7616613Ssam public Symbol curblock;
7716613Ssam 
789673Slinton private Symbol blkstack[MAXBLKDEPTH];
7916613Ssam private integer curlevel;
8016613Ssam private integer bnum, nesting;
8114443Slinton private Address addrstk[MAXBLKDEPTH];
829673Slinton 
8316613Ssam public pushBlock (b)
8416613Ssam Symbol b;
8516613Ssam {
8616613Ssam     if (curlevel >= MAXBLKDEPTH) {
8716613Ssam 	fatal("nesting depth too large (%d)", curlevel);
8816613Ssam     }
8916613Ssam     blkstack[curlevel] = curblock;
9016613Ssam     ++curlevel;
9116613Ssam     curblock = b;
9216613Ssam     if (traceblocks) {
9316613Ssam 	printf("entering block %s\n", symname(b));
9416613Ssam     }
959673Slinton }
969673Slinton 
9718225Slinton /*
9818225Slinton  * Change the current block with saving the previous one,
9918225Slinton  * since it is assumed that the symbol for the current one is to be deleted.
10018225Slinton  */
10118225Slinton 
10218225Slinton public changeBlock (b)
10318225Slinton Symbol b;
10418225Slinton {
10518225Slinton     curblock = b;
10618225Slinton }
10718225Slinton 
10816613Ssam public enterblock (b)
10916613Ssam Symbol b;
11016613Ssam {
11116613Ssam     if (curblock == nil) {
11216613Ssam 	b->level = 1;
11316613Ssam     } else {
11416613Ssam 	b->level = curblock->level + 1;
11516613Ssam     }
11616613Ssam     b->block = curblock;
11716613Ssam     pushBlock(b);
1189673Slinton }
1199673Slinton 
12016613Ssam public exitblock ()
12116613Ssam {
12216613Ssam     if (curblock->class == FUNC or curblock->class == PROC) {
12316613Ssam 	if (prevlinep != linep) {
12416613Ssam 	    curblock->symvalue.funcv.src = true;
12516613Ssam 	}
12616613Ssam     }
12716613Ssam     if (curlevel <= 0) {
12816613Ssam 	panic("nesting depth underflow (%d)", curlevel);
12916613Ssam     }
13016613Ssam     --curlevel;
13116613Ssam     if (traceblocks) {
13216613Ssam 	printf("exiting block %s\n", symname(curblock));
13316613Ssam     }
13416613Ssam     curblock = blkstack[curlevel];
13516613Ssam }
13616613Ssam 
1379673Slinton /*
1389673Slinton  * Enter a source line or file name reference into the appropriate table.
1399673Slinton  * Expanded inline to reduce procedure calls.
1409673Slinton  *
14116613Ssam  * private enterline (linenumber, address)
1429673Slinton  * Lineno linenumber;
1439673Slinton  * Address address;
1449673Slinton  *  ...
1459673Slinton  */
1469673Slinton 
1479673Slinton #define enterline(linenumber, address) \
1489673Slinton { \
1499673Slinton     register Linetab *lp; \
1509673Slinton  \
1519673Slinton     lp = linep - 1; \
1529673Slinton     if (linenumber != lp->line) { \
1539673Slinton 	if (address != lp->addr) { \
1549673Slinton 	    ++lp; \
1559673Slinton 	} \
1569673Slinton 	lp->line = linenumber; \
1579673Slinton 	lp->addr = address; \
1589673Slinton 	linep = lp + 1; \
1599673Slinton     } \
1609673Slinton }
1619673Slinton 
1629673Slinton /*
1639673Slinton  * Read in the namelist from the obj file.
1649673Slinton  *
1659673Slinton  * Reads and seeks are used instead of fread's and fseek's
1669673Slinton  * for efficiency sake; there's a lot of data being read here.
1679673Slinton  */
1689673Slinton 
16916613Ssam public readobj (file)
1709673Slinton String file;
1719673Slinton {
1729673Slinton     Fileid f;
1739673Slinton     struct exec hdr;
1749673Slinton     struct nlist nlist;
1759673Slinton 
1769673Slinton     f = open(file, 0);
1779673Slinton     if (f < 0) {
1789673Slinton 	fatal("can't open %s", file);
1799673Slinton     }
1809673Slinton     read(f, &hdr, sizeof(hdr));
18118225Slinton     if (N_BADMAG(hdr)) {
18218225Slinton 	objsize = 0;
18318225Slinton 	nlhdr.nsyms = 0;
18418225Slinton 	nlhdr.nfiles = 0;
18518225Slinton 	nlhdr.nlines = 0;
18618225Slinton     } else {
18718225Slinton 	objsize = hdr.a_text;
18818225Slinton 	nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
18918225Slinton 	nlhdr.nfiles = nlhdr.nsyms;
19018225Slinton 	nlhdr.nlines = nlhdr.nsyms;
19118225Slinton     }
19214443Slinton     if (nlhdr.nsyms > 0) {
19314443Slinton 	lseek(f, (long) N_STROFF(hdr), 0);
19414443Slinton 	read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
19514443Slinton 	nlhdr.stringsize -= 4;
19614443Slinton 	stringtab = newarr(char, nlhdr.stringsize);
19714443Slinton 	read(f, stringtab, nlhdr.stringsize);
19814443Slinton 	allocmaps(nlhdr.nfiles, nlhdr.nlines);
19914443Slinton 	lseek(f, (long) N_SYMOFF(hdr), 0);
20014443Slinton 	readsyms(f);
20114443Slinton 	ordfunctab();
20214443Slinton 	setnlines();
20314443Slinton 	setnfiles();
20418225Slinton     } else {
20518225Slinton 	initsyms();
20614443Slinton     }
2079673Slinton     close(f);
2089673Slinton }
2099673Slinton 
2109673Slinton /*
21118225Slinton  * Found the beginning of the externals in the object file
21218225Slinton  * (signified by the "-lg" or find an external), close the
21318225Slinton  * block for the last procedure.
21418225Slinton  */
21518225Slinton 
21618225Slinton private foundglobals ()
21718225Slinton {
21818225Slinton     if (curblock->class != PROG) {
21918225Slinton 	exitblock();
22018225Slinton 	if (curblock->class != PROG) {
22118225Slinton 	    exitblock();
22218225Slinton 	}
22318225Slinton     }
22418225Slinton     enterline(0, (linep-1)->addr + 1);
22518225Slinton }
22618225Slinton 
22718225Slinton /*
2289673Slinton  * Read in symbols from object file.
2299673Slinton  */
2309673Slinton 
23116613Ssam private readsyms (f)
2329673Slinton Fileid f;
2339673Slinton {
2349673Slinton     struct nlist *namelist;
2359673Slinton     register struct nlist *np, *ub;
2369673Slinton     register String name;
237*33328Sdonn     boolean afterlg, foundstab;
23816613Ssam     integer index;
23916613Ssam     char *lastchar;
2409673Slinton 
2419673Slinton     initsyms();
2429673Slinton     namelist = newarr(struct nlist, nlhdr.nsyms);
2439673Slinton     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
2449673Slinton     afterlg = false;
245*33328Sdonn     foundstab = false;
2469673Slinton     ub = &namelist[nlhdr.nsyms];
24716613Ssam     curnp = &namelist[0];
24816613Ssam     np = curnp;
24916613Ssam     while (np < ub) {
2509673Slinton 	index = np->n_un.n_strx;
2519673Slinton 	if (index != 0) {
2529673Slinton 	    name = &stringtab[index - 4];
25312542Scsvaf 	    /*
25416613Ssam              *  If the program contains any .f files a trailing _ is stripped
25512542Scsvaf        	     *  from the name on the assumption it was added by the compiler.
25612542Scsvaf 	     *  This only affects names that follow the sdb N_SO entry with
25712542Scsvaf              *  the .f name.
25812542Scsvaf              */
25914443Slinton             if (strip_ and name[0] != '\0' ) {
26016613Ssam 		lastchar = &name[strlen(name) - 1];
26116613Ssam 		if (*lastchar == '_') {
26216613Ssam 		    *lastchar = '\0';
26314443Slinton 		}
26412542Scsvaf             }
2659673Slinton 	} else {
2669673Slinton 	    name = nil;
26712542Scsvaf 	}
26816613Ssam 
2699673Slinton 	/*
27016613Ssam 	 * Assumptions:
2719673Slinton 	 *	not an N_STAB	==> name != nil
2729673Slinton 	 *	name[0] == '-'	==> name == "-lg"
2739673Slinton 	 *	name[0] != '_'	==> filename or invisible
2749673Slinton 	 *
2759673Slinton 	 * The "-lg" signals the beginning of global loader symbols.
27612542Scsvaf          *
2779673Slinton 	 */
2789673Slinton 	if ((np->n_type&N_STAB) != 0) {
279*33328Sdonn 	    foundstab = true;
2809673Slinton 	    enter_nl(name, np);
2819673Slinton 	} else if (name[0] == '-') {
2829673Slinton 	    afterlg = true;
28318225Slinton 	    foundglobals();
28411104Slinton 	} else if (afterlg) {
28518225Slinton 	    check_global(name, np);
28618225Slinton 	} else if ((np->n_type&N_EXT) == N_EXT) {
28718225Slinton 	    afterlg = true;
28818225Slinton 	    foundglobals();
28918225Slinton 	    check_global(name, np);
29011104Slinton 	} else if (name[0] == '_') {
29111104Slinton 	    check_local(&name[1], np);
2929673Slinton 	} else if ((np->n_type&N_TEXT) == N_TEXT) {
2939673Slinton 	    check_filename(name);
2949673Slinton 	}
29516613Ssam 	++curnp;
29616613Ssam 	np = curnp;
2979673Slinton     }
298*33328Sdonn     if (not foundstab) {
299*33328Sdonn 	warning("no source compiled with -g");
300*33328Sdonn     }
3019673Slinton     dispose(namelist);
3029673Slinton }
3039673Slinton 
3049673Slinton /*
30516613Ssam  * Get a continuation entry from the name list.
30616613Ssam  * Return the beginning of the name.
30716613Ssam  */
30816613Ssam 
30916613Ssam public String getcont ()
31016613Ssam {
31116613Ssam     register integer index;
31216613Ssam     register String name;
31316613Ssam 
31416613Ssam     ++curnp;
31516613Ssam     index = curnp->n_un.n_strx;
31616613Ssam     if (index == 0) {
317*33328Sdonn 	name = "";
318*33328Sdonn     } else {
319*33328Sdonn 	name = &stringtab[index - 4];
32016613Ssam     }
32116613Ssam     return name;
32216613Ssam }
32316613Ssam 
32416613Ssam /*
3259673Slinton  * Initialize symbol information.
3269673Slinton  */
3279673Slinton 
32816613Ssam private initsyms ()
3299673Slinton {
3309673Slinton     curblock = nil;
3319673Slinton     curlevel = 0;
33214443Slinton     nesting = 0;
33316613Ssam     program = insert(identname("", true));
3349673Slinton     program->class = PROG;
335*33328Sdonn     program->language = primlang;
336*33328Sdonn     program->symvalue.funcv.beginaddr = CODESTART;
33714443Slinton     program->symvalue.funcv.inline = false;
33814443Slinton     newfunc(program, codeloc(program));
33911769Slinton     findbeginning(program);
3409673Slinton     enterblock(program);
3419673Slinton     curmodule = program;
3429673Slinton }
3439673Slinton 
3449673Slinton /*
3459673Slinton  * Free all the object file information that's being stored.
3469673Slinton  */
3479673Slinton 
34816613Ssam public objfree ()
3499673Slinton {
3509673Slinton     symbol_free();
35118225Slinton     /* keywords_free(); */
35218225Slinton     /* names_free(); */
35318225Slinton     /* dispose(stringtab); */
3549673Slinton     clrfunctab();
3559673Slinton }
3569673Slinton 
3579673Slinton /*
3589673Slinton  * Enter a namelist entry.
3599673Slinton  */
3609673Slinton 
36116613Ssam private enter_nl (name, np)
3629673Slinton String name;
3639673Slinton register struct nlist *np;
3649673Slinton {
3659673Slinton     register Symbol s;
36616613Ssam     register Name n;
3679673Slinton 
3689673Slinton     s = nil;
3699673Slinton     switch (np->n_type) {
37014443Slinton 	/*
37114443Slinton 	 * Build a symbol for the FORTRAN common area.  All GSYMS that follow
37214443Slinton 	 * will be chained in a list with the head kept in common.offset, and
37314443Slinton 	 * the tail in common.chain.
37414443Slinton 	 */
37513938Slinton 	case N_BCOMM:
37613938Slinton  	    if (curcomm) {
37713938Slinton 		curcomm->symvalue.common.chain = commchain;
37812542Scsvaf 	    }
37916613Ssam 	    n = identname(name, true);
38012542Scsvaf 	    curcomm = lookup(n);
38113938Slinton 	    if (curcomm == nil) {
38213938Slinton 		curcomm = insert(n);
38313938Slinton 		curcomm->class = COMMON;
38413938Slinton 		curcomm->block = curblock;
38513938Slinton 		curcomm->level = program->level;
38613938Slinton 		curcomm->symvalue.common.chain = nil;
38712542Scsvaf 	    }
38812542Scsvaf 	    commchain = curcomm->symvalue.common.chain;
38913938Slinton 	    break;
39012542Scsvaf 
39112542Scsvaf 	case N_ECOMM:
39213938Slinton 	    if (curcomm) {
39313938Slinton 		curcomm->symvalue.common.chain = commchain;
39413938Slinton 		curcomm = nil;
39512542Scsvaf 	    }
39612542Scsvaf 	    break;
39714443Slinton 
3989673Slinton 	case N_LBRAC:
39914443Slinton 	    ++nesting;
40014443Slinton 	    addrstk[nesting] = (linep - 1)->addr;
4019673Slinton 	    break;
4029673Slinton 
4039673Slinton 	case N_RBRAC:
40416613Ssam 	    --nesting;
40514443Slinton 	    if (addrstk[nesting] == NOADDR) {
40614443Slinton 		exitblock();
40714443Slinton 		newfunc(curblock, (linep - 1)->addr);
40816613Ssam 		addrstk[nesting] = (linep - 1)->addr;
40914443Slinton 	    }
4109673Slinton 	    break;
4119673Slinton 
4129673Slinton 	case N_SLINE:
4139673Slinton 	    enterline((Lineno) np->n_desc, (Address) np->n_value);
4149673Slinton 	    break;
4159673Slinton 
4169673Slinton 	/*
41714443Slinton 	 * Source files.
4189673Slinton 	 */
4199673Slinton 	case N_SO:
42016613Ssam 	    n = identname(name, true);
42114443Slinton 	    enterSourceModule(n, (Address) np->n_value);
4229673Slinton 	    break;
4239673Slinton 
4249673Slinton 	/*
4259673Slinton 	 * Textually included files.
4269673Slinton 	 */
4279673Slinton 	case N_SOL:
4289673Slinton 	    enterfile(name, (Address) np->n_value);
4299673Slinton 	    break;
4309673Slinton 
4319673Slinton 	/*
4329673Slinton 	 * These symbols are assumed to have non-nil names.
4339673Slinton 	 */
4349673Slinton 	case N_GSYM:
4359673Slinton 	case N_FUN:
4369673Slinton 	case N_STSYM:
4379673Slinton 	case N_LCSYM:
4389673Slinton 	case N_RSYM:
4399673Slinton 	case N_PSYM:
4409673Slinton 	case N_LSYM:
4419673Slinton 	case N_SSYM:
44214443Slinton 	case N_LENG:
4439673Slinton 	    if (index(name, ':') == nil) {
4449673Slinton 		if (not warned) {
4459673Slinton 		    warned = true;
446*33328Sdonn 		    printf("warning: old style symbol information ");
447*33328Sdonn 		    printf("found in \"%s\"\n", curfilename());
4489673Slinton 		}
4499673Slinton 	    } else {
4509673Slinton 		entersym(name, np);
4519673Slinton 	    }
4529673Slinton 	    break;
4539673Slinton 
4549673Slinton 	case N_PC:
45516613Ssam 	case N_MOD2:
4569673Slinton 	    break;
4579673Slinton 
45811558Slinton 	default:
45914443Slinton 	    printf("warning:  stab entry unrecognized: ");
4609673Slinton 	    if (name != nil) {
46114443Slinton 		printf("name %s,", name);
4629673Slinton 	    }
46314443Slinton 	    printf("ntype %2x, desc %x, value %x'\n",
4649673Slinton 		np->n_type, np->n_desc, np->n_value);
4659673Slinton 	    break;
4669673Slinton     }
4679673Slinton }
4689673Slinton 
4699673Slinton /*
47018225Slinton  * Try to find the symbol that is referred to by the given name.  Since it's
47118225Slinton  * an external, we need to follow a level or two of indirection.
47216613Ssam  */
47316613Ssam 
47418225Slinton private Symbol findsym (n, var_isextref)
47516613Ssam Name n;
47618225Slinton boolean *var_isextref;
47716613Ssam {
47816613Ssam     register Symbol r, s;
47916613Ssam 
48018225Slinton     *var_isextref = false;
48116613Ssam     find(s, n) where
48218225Slinton 	(
48318225Slinton 	    s->level == program->level and (
48418225Slinton 		s->class == EXTREF or s->class == VAR or
48518225Slinton 		s->class == PROC or s->class == FUNC
48618225Slinton 	    )
48718225Slinton 	) or (
48818225Slinton 	    s->block == program and s->class == MODULE
48918225Slinton 	)
49016613Ssam     endfind(s);
49118225Slinton     if (s == nil) {
49218225Slinton 	r = nil;
49318225Slinton     } else if (s->class == EXTREF) {
49418225Slinton 	*var_isextref = true;
49516613Ssam 	r = s->symvalue.extref;
49616613Ssam 	delete(s);
49718225Slinton 
49818225Slinton 	/*
49918225Slinton 	 * Now check for another level of indirection that could come from
50018225Slinton 	 * a forward reference in procedure nesting information.  In this case
50118225Slinton 	 * the symbol has already been deleted.
50218225Slinton 	 */
50318225Slinton 	if (r != nil and r->class == EXTREF) {
50418225Slinton 	    r = r->symvalue.extref;
50518225Slinton 	}
50618225Slinton /*
50718225Slinton     } else if (s->class == MODULE) {
50818225Slinton 	s->class = FUNC;
50918225Slinton 	s->level = program->level;
51018225Slinton 	r = s;
51118225Slinton  */
51216613Ssam     } else {
51316613Ssam 	r = s;
51416613Ssam     }
51516613Ssam     return r;
51616613Ssam }
51716613Ssam 
51816613Ssam /*
51918225Slinton  * Create a symbol for a text symbol with no source information.
52018225Slinton  * We treat it as an assembly language function.
52118225Slinton  */
52218225Slinton 
52318225Slinton private Symbol deffunc (n)
52418225Slinton Name n;
52518225Slinton {
52618225Slinton     Symbol f;
52718225Slinton 
52818225Slinton     f = insert(n);
52918225Slinton     f->language = findlanguage(".s");
53018225Slinton     f->class = FUNC;
53118225Slinton     f->type = t_int;
53218225Slinton     f->block = curblock;
53318225Slinton     f->level = program->level;
53418225Slinton     f->symvalue.funcv.src = false;
53518225Slinton     f->symvalue.funcv.inline = false;
536*33328Sdonn     if (f->chain != nil) {
537*33328Sdonn 	panic("chain not nil in deffunc");
538*33328Sdonn     }
53918225Slinton     return f;
54018225Slinton }
54118225Slinton 
54218225Slinton /*
54318225Slinton  * Create a symbol for a data or bss symbol with no source information.
54418225Slinton  * We treat it as an assembly language variable.
54518225Slinton  */
54618225Slinton 
54718225Slinton private Symbol defvar (n)
54818225Slinton Name n;
54918225Slinton {
55018225Slinton     Symbol v;
55118225Slinton 
55218225Slinton     v = insert(n);
55318225Slinton     v->language = findlanguage(".s");
554*33328Sdonn     v->storage = EXT;
55518225Slinton     v->class = VAR;
55618225Slinton     v->type = t_int;
55718225Slinton     v->level = program->level;
55818225Slinton     v->block = curblock;
55918225Slinton     return v;
56018225Slinton }
56118225Slinton 
56218225Slinton /*
56318225Slinton  * Update a symbol entry with a text address.
56418225Slinton  */
56518225Slinton 
56618225Slinton private updateTextSym (s, name, addr)
56718225Slinton Symbol s;
56818225Slinton char *name;
56918225Slinton Address addr;
57018225Slinton {
57118225Slinton     if (s->class == VAR) {
57218225Slinton 	s->symvalue.offset = addr;
57318225Slinton     } else {
57418225Slinton 	s->symvalue.funcv.beginaddr = addr;
57518225Slinton 	if (name[0] == '_') {
57618225Slinton 	    newfunc(s, codeloc(s));
57718225Slinton 	    findbeginning(s);
57818225Slinton 	}
57918225Slinton     }
58018225Slinton }
58118225Slinton 
58218225Slinton /*
583*33328Sdonn  * Avoid seeing Pascal labels as text symbols.
584*33328Sdonn  */
585*33328Sdonn 
586*33328Sdonn private boolean PascalLabel (n)
587*33328Sdonn Name n;
588*33328Sdonn {
589*33328Sdonn     boolean b;
590*33328Sdonn     register char *p;
591*33328Sdonn 
592*33328Sdonn     b = false;
593*33328Sdonn     if (curlang == findlanguage(".p")) {
594*33328Sdonn 	p = ident(n);
595*33328Sdonn 	while (*p != '\0') {
596*33328Sdonn 	    if (*p == '_' and *(p+1) == '$') {
597*33328Sdonn 		b = true;
598*33328Sdonn 		break;
599*33328Sdonn 	    }
600*33328Sdonn 	    ++p;
601*33328Sdonn 	}
602*33328Sdonn     }
603*33328Sdonn     return b;
604*33328Sdonn }
605*33328Sdonn 
606*33328Sdonn /*
6079673Slinton  * Check to see if a global _name is already in the symbol table,
6089673Slinton  * if not then insert it.
6099673Slinton  */
6109673Slinton 
61116613Ssam private check_global (name, np)
6129673Slinton String name;
6139673Slinton register struct nlist *np;
6149673Slinton {
6159673Slinton     register Name n;
61612542Scsvaf     register Symbol t, u;
61718225Slinton     char buf[4096];
61818225Slinton     boolean isextref;
61918225Slinton     integer count;
6209673Slinton 
62118225Slinton     if (not streq(name, "_end")) {
62218225Slinton 	if (name[0] == '_') {
62318225Slinton 	    n = identname(&name[1], true);
62418225Slinton 	} else {
62518225Slinton 	    n = identname(name, true);
62618225Slinton 	    if (lookup(n) != nil) {
62718225Slinton 		sprintf(buf, "$%s", name);
62818225Slinton 		n = identname(buf, false);
62918225Slinton 	    }
63018225Slinton 	}
6319673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
63218225Slinton 	    count = 0;
63318225Slinton 	    t = findsym(n, &isextref);
63418225Slinton 	    while (isextref) {
63518225Slinton 		++count;
63618225Slinton 		updateTextSym(t, name, np->n_value);
63718225Slinton 		t = findsym(n, &isextref);
6389673Slinton 	    }
63918225Slinton 	    if (count == 0) {
64018225Slinton 		if (t == nil) {
641*33328Sdonn 		    if (not PascalLabel(n)) {
642*33328Sdonn 			t = deffunc(n);
643*33328Sdonn 			updateTextSym(t, name, np->n_value);
644*33328Sdonn 			if (tracesyms) {
645*33328Sdonn 			    printdecl(t);
646*33328Sdonn 			}
64718225Slinton 		    }
64818225Slinton 		} else {
64918225Slinton 		    if (t->class == MODULE) {
65018225Slinton 			u = t;
65118225Slinton 			t = deffunc(n);
65218225Slinton 			t->block = u;
65318225Slinton 			if (tracesyms) {
65418225Slinton 			    printdecl(t);
65518225Slinton 			}
65618225Slinton 		    }
65718225Slinton 		    updateTextSym(t, name, np->n_value);
65818225Slinton 		}
65916613Ssam 	    }
660*33328Sdonn 	} else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) {
6619673Slinton 	    find(t, n) where
66213938Slinton 		t->class == COMMON
66312542Scsvaf 	    endfind(t);
66413938Slinton 	    if (t != nil) {
66513938Slinton 		u = (Symbol) t->symvalue.common.offset;
66613938Slinton 		while (u != nil) {
66713938Slinton 		    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
66813938Slinton 		    u = u->symvalue.common.chain;
66913938Slinton 		}
67013938Slinton             } else {
67113938Slinton 		check_var(np, n);
6729673Slinton 	    }
67313938Slinton         } else {
67413938Slinton 	    check_var(np, n);
6759673Slinton 	}
6769673Slinton     }
6779673Slinton }
6789673Slinton 
6799673Slinton /*
68013938Slinton  * Check to see if a namelist entry refers to a variable.
68113938Slinton  * If not, create a variable for the entry.  In any case,
68213938Slinton  * set the offset of the variable according to the value field
68313938Slinton  * in the entry.
68418225Slinton  *
68518225Slinton  * If the external name has been referred to by several other symbols,
68618225Slinton  * we must update each of them.
68713938Slinton  */
68813938Slinton 
68916613Ssam private check_var (np, n)
69013938Slinton struct nlist *np;
69113938Slinton register Name n;
69213938Slinton {
69318225Slinton     register Symbol t, u, next;
69418225Slinton     Symbol conflict;
69513938Slinton 
69618225Slinton     t = lookup(n);
69713938Slinton     if (t == nil) {
69818225Slinton 	t = defvar(n);
69918225Slinton 	t->symvalue.offset = np->n_value;
70018225Slinton 	if (tracesyms) {
70118225Slinton 	    printdecl(t);
70218225Slinton 	}
70318225Slinton     } else {
70418225Slinton 	conflict = nil;
70518225Slinton 	do {
70618225Slinton 	    next = t->next_sym;
70718225Slinton 	    if (t->name == n) {
70818225Slinton 		if (t->class == MODULE and t->block == program) {
70918225Slinton 		    conflict = t;
71018225Slinton 		} else if (t->class == EXTREF and t->level == program->level) {
71118225Slinton 		    u = t->symvalue.extref;
71218225Slinton 		    while (u != nil and u->class == EXTREF) {
71318225Slinton 			u = u->symvalue.extref;
71418225Slinton 		    }
71518225Slinton 		    u->symvalue.offset = np->n_value;
71618225Slinton 		    delete(t);
71718225Slinton 		} else if (t->level == program->level and
71818225Slinton 		    (t->class == VAR or t->class == PROC or t->class == FUNC)
71918225Slinton 		) {
72018225Slinton 		    conflict = nil;
72118225Slinton 		    t->symvalue.offset = np->n_value;
72218225Slinton 		}
72318225Slinton 	    }
72418225Slinton 	    t = next;
72518225Slinton 	} while (t != nil);
72618225Slinton 	if (conflict != nil) {
72718225Slinton 	    u = defvar(n);
72818225Slinton 	    u->block = conflict;
72918225Slinton 	    u->symvalue.offset = np->n_value;
73018225Slinton 	}
73113938Slinton     }
73213938Slinton }
73313938Slinton 
73413938Slinton /*
7359673Slinton  * Check to see if a local _name is known in the current scope.
7369673Slinton  * If not then enter it.
7379673Slinton  */
7389673Slinton 
73916613Ssam private check_local (name, np)
7409673Slinton String name;
7419673Slinton register struct nlist *np;
7429673Slinton {
7439673Slinton     register Name n;
7449673Slinton     register Symbol t, cur;
7459673Slinton 
7469673Slinton     n = identname(name, true);
7479673Slinton     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
7489673Slinton     find(t, n) where t->block == cur endfind(t);
7499673Slinton     if (t == nil) {
7509673Slinton 	t = insert(n);
7519673Slinton 	t->language = findlanguage(".s");
7529673Slinton 	t->type = t_int;
7539673Slinton 	t->block = cur;
754*33328Sdonn 	t->storage = EXT;
7559673Slinton 	t->level = cur->level;
7569673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
7579673Slinton 	    t->class = FUNC;
75811875Slinton 	    t->symvalue.funcv.src = false;
75914443Slinton 	    t->symvalue.funcv.inline = false;
7609673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
76114443Slinton 	    newfunc(t, codeloc(t));
7629673Slinton 	    findbeginning(t);
7639673Slinton 	} else {
7649673Slinton 	    t->class = VAR;
7659673Slinton 	    t->symvalue.offset = np->n_value;
7669673Slinton 	}
7679673Slinton     }
7689673Slinton }
7699673Slinton 
7709673Slinton /*
7719673Slinton  * Check to see if a symbol corresponds to a object file name.
7729673Slinton  * For some reason these are listed as in the text segment.
7739673Slinton  */
7749673Slinton 
77516613Ssam private check_filename (name)
7769673Slinton String name;
7779673Slinton {
7789673Slinton     register String mname;
77916613Ssam     register integer i;
78018225Slinton     Name n;
78118225Slinton     Symbol s;
7829673Slinton 
7839673Slinton     mname = strdup(name);
7849673Slinton     i = strlen(mname) - 2;
7859673Slinton     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
7869673Slinton 	mname[i] = '\0';
7879673Slinton 	--i;
7889673Slinton 	while (mname[i] != '/' and i >= 0) {
7899673Slinton 	    --i;
7909673Slinton 	}
79118225Slinton 	n = identname(&mname[i+1], true);
79218225Slinton 	find(s, n) where s->block == program and s->class == MODULE endfind(s);
79318225Slinton 	if (s == nil) {
79418225Slinton 	    s = insert(n);
79518225Slinton 	    s->language = findlanguage(".s");
79618225Slinton 	    s->class = MODULE;
79718225Slinton 	    s->symvalue.funcv.beginaddr = 0;
79818225Slinton 	    findbeginning(s);
79918225Slinton 	}
8009673Slinton 	if (curblock->class != PROG) {
8019673Slinton 	    exitblock();
8029673Slinton 	    if (curblock->class != PROG) {
8039673Slinton 		exitblock();
8049673Slinton 	    }
8059673Slinton 	}
8069673Slinton 	enterblock(s);
8079673Slinton 	curmodule = s;
8089673Slinton     }
8099673Slinton }
8109673Slinton 
8119673Slinton /*
81214443Slinton  * Check to see if a symbol is about to be defined within an unnamed block.
81314443Slinton  * If this happens, we create a procedure for the unnamed block, make it
81414443Slinton  * "inline" so that tracebacks don't associate an activation record with it,
81514443Slinton  * and enter it into the function table so that it will be detected
81614443Slinton  * by "whatblock".
81714443Slinton  */
81814443Slinton 
81916613Ssam public chkUnnamedBlock ()
82014443Slinton {
82114443Slinton     register Symbol s;
82214443Slinton     static int bnum = 0;
82314443Slinton     char buf[100];
82416613Ssam     Address startaddr;
82514443Slinton 
82616613Ssam     if (nesting > 0 and addrstk[nesting] != NOADDR) {
82716613Ssam 	startaddr = (linep - 1)->addr;
82816613Ssam 	++bnum;
82916613Ssam 	sprintf(buf, "$b%d", bnum);
83016613Ssam 	s = insert(identname(buf, false));
83116613Ssam 	s->language = curlang;
83216613Ssam 	s->class = PROC;
83316613Ssam 	s->symvalue.funcv.src = false;
83416613Ssam 	s->symvalue.funcv.inline = true;
83516613Ssam 	s->symvalue.funcv.beginaddr = startaddr;
83616613Ssam 	enterblock(s);
83716613Ssam 	newfunc(s, startaddr);
83816613Ssam 	addrstk[nesting] = NOADDR;
83916613Ssam     }
84014443Slinton }
84114443Slinton 
84214443Slinton /*
84314443Slinton  * Compilation unit.  C associates scope with filenames
84414443Slinton  * so we treat them as "modules".  The filename without
84514443Slinton  * the suffix is used for the module name.
84614443Slinton  *
84714443Slinton  * Because there is no explicit "end-of-block" mark in
84814443Slinton  * the object file, we must exit blocks for the current
84914443Slinton  * procedure and module.
85014443Slinton  */
85114443Slinton 
85216613Ssam private enterSourceModule (n, addr)
85314443Slinton Name n;
85414443Slinton Address addr;
85514443Slinton {
85614443Slinton     register Symbol s;
85714443Slinton     Name nn;
85814443Slinton     String mname, suffix;
85914443Slinton 
86014443Slinton     mname = strdup(ident(n));
86114443Slinton     if (rindex(mname, '/') != nil) {
86214443Slinton 	mname = rindex(mname, '/') + 1;
86314443Slinton     }
86414443Slinton     suffix = rindex(mname, '.');
865*33328Sdonn     if (suffix > mname && *(suffix-1) == '.') {
866*33328Sdonn 	/* special hack for C++ */
867*33328Sdonn 	--suffix;
868*33328Sdonn     }
86914443Slinton     curlang = findlanguage(suffix);
87014443Slinton     if (curlang == findlanguage(".f")) {
87114443Slinton 	strip_ = true;
87214443Slinton     }
87314443Slinton     if (suffix != nil) {
87414443Slinton 	*suffix = '\0';
87514443Slinton     }
87616613Ssam     if (not (*language_op(curlang, L_HASMODULES))()) {
87714443Slinton 	if (curblock->class != PROG) {
87814443Slinton 	    exitblock();
87916613Ssam 	    if (curblock->class != PROG) {
88016613Ssam 		exitblock();
88116613Ssam 	    }
88214443Slinton 	}
88316613Ssam 	nn = identname(mname, true);
88416613Ssam 	if (curmodule == nil or curmodule->name != nn) {
88516613Ssam 	    s = insert(nn);
88616613Ssam 	    s->class = MODULE;
88716613Ssam 	    s->symvalue.funcv.beginaddr = 0;
88816613Ssam 	    findbeginning(s);
88916613Ssam 	} else {
89016613Ssam 	    s = curmodule;
89116613Ssam 	}
89216613Ssam 	s->language = curlang;
89316613Ssam 	enterblock(s);
89416613Ssam 	curmodule = s;
89514443Slinton     }
89614443Slinton     if (program->language == nil) {
89714443Slinton 	program->language = curlang;
89814443Slinton     }
89914443Slinton     warned = false;
90014443Slinton     enterfile(ident(n), addr);
90116613Ssam     initTypeTable();
90214443Slinton }
90314443Slinton 
90414443Slinton /*
9059673Slinton  * Allocate file and line tables and initialize indices.
9069673Slinton  */
9079673Slinton 
90816613Ssam private allocmaps (nf, nl)
90916613Ssam integer nf, nl;
9109673Slinton {
9119673Slinton     if (filetab != nil) {
9129673Slinton 	dispose(filetab);
9139673Slinton     }
9149673Slinton     if (linetab != nil) {
9159673Slinton 	dispose(linetab);
9169673Slinton     }
9179673Slinton     filetab = newarr(Filetab, nf);
9189673Slinton     linetab = newarr(Linetab, nl);
9199673Slinton     filep = filetab;
9209673Slinton     linep = linetab;
9219673Slinton }
9229673Slinton 
9239673Slinton /*
9249673Slinton  * Add a file to the file table.
92513938Slinton  *
92613938Slinton  * If the new address is the same as the previous file address
92713938Slinton  * this routine used to not enter the file, but this caused some
92813938Slinton  * problems so it has been removed.  It's not clear that this in
92913938Slinton  * turn may not also cause a problem.
9309673Slinton  */
9319673Slinton 
93216613Ssam private enterfile (filename, addr)
9339673Slinton String filename;
9349673Slinton Address addr;
9359673Slinton {
93613938Slinton     filep->addr = addr;
93713938Slinton     filep->filename = filename;
93813938Slinton     filep->lineindex = linep - linetab;
93913938Slinton     ++filep;
9409673Slinton }
9419673Slinton 
9429673Slinton /*
9439673Slinton  * Since we only estimated the number of lines (and it was a poor
9449673Slinton  * estimation) and since we need to know the exact number of lines
9459673Slinton  * to do a binary search, we set it when we're done.
9469673Slinton  */
9479673Slinton 
94816613Ssam private setnlines ()
9499673Slinton {
9509673Slinton     nlhdr.nlines = linep - linetab;
9519673Slinton }
9529673Slinton 
9539673Slinton /*
9549673Slinton  * Similarly for nfiles ...
9559673Slinton  */
9569673Slinton 
95716613Ssam private setnfiles ()
9589673Slinton {
9599673Slinton     nlhdr.nfiles = filep - filetab;
9609673Slinton     setsource(filetab[0].filename);
9619673Slinton }
962