xref: /csrg-svn/old/dbx/object.c (revision 21615)
1*21615Sdist /*
2*21615Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21615Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21615Sdist  * specifies the terms and conditions for redistribution.
5*21615Sdist  */
69673Slinton 
7*21615Sdist #ifndef lint
8*21615Sdist static char sccsid[] = "@(#)object.c	5.1 (Berkeley) 05/31/85";
9*21615Sdist #endif not lint
109673Slinton 
1118225Slinton static char rcsid[] = "$Header: object.c,v 1.6 84/12/26 10:40:51 linton 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;
2379673Slinton     register Boolean afterlg;
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;
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) {
2789673Slinton 	    enter_nl(name, np);
2799673Slinton 	} else if (name[0] == '-') {
2809673Slinton 	    afterlg = true;
28118225Slinton 	    foundglobals();
28211104Slinton 	} else if (afterlg) {
28318225Slinton 	    check_global(name, np);
28418225Slinton 	} else if ((np->n_type&N_EXT) == N_EXT) {
28518225Slinton 	    afterlg = true;
28618225Slinton 	    foundglobals();
28718225Slinton 	    check_global(name, np);
28811104Slinton 	} else if (name[0] == '_') {
28911104Slinton 	    check_local(&name[1], np);
2909673Slinton 	} else if ((np->n_type&N_TEXT) == N_TEXT) {
2919673Slinton 	    check_filename(name);
2929673Slinton 	}
29316613Ssam 	++curnp;
29416613Ssam 	np = curnp;
2959673Slinton     }
2969673Slinton     dispose(namelist);
2979673Slinton }
2989673Slinton 
2999673Slinton /*
30016613Ssam  * Get a continuation entry from the name list.
30116613Ssam  * Return the beginning of the name.
30216613Ssam  */
30316613Ssam 
30416613Ssam public String getcont ()
30516613Ssam {
30616613Ssam     register integer index;
30716613Ssam     register String name;
30816613Ssam 
30916613Ssam     ++curnp;
31016613Ssam     index = curnp->n_un.n_strx;
31116613Ssam     if (index == 0) {
31216613Ssam 	panic("continuation followed by empty stab");
31316613Ssam     }
31416613Ssam     name = &stringtab[index - 4];
31516613Ssam     return name;
31616613Ssam }
31716613Ssam 
31816613Ssam /*
3199673Slinton  * Initialize symbol information.
3209673Slinton  */
3219673Slinton 
32216613Ssam private initsyms ()
3239673Slinton {
3249673Slinton     curblock = nil;
3259673Slinton     curlevel = 0;
32614443Slinton     nesting = 0;
32716613Ssam     program = insert(identname("", true));
3289673Slinton     program->class = PROG;
32911769Slinton     program->symvalue.funcv.beginaddr = 0;
33014443Slinton     program->symvalue.funcv.inline = false;
33114443Slinton     newfunc(program, codeloc(program));
33211769Slinton     findbeginning(program);
3339673Slinton     enterblock(program);
3349673Slinton     curmodule = program;
3359673Slinton }
3369673Slinton 
3379673Slinton /*
3389673Slinton  * Free all the object file information that's being stored.
3399673Slinton  */
3409673Slinton 
34116613Ssam public objfree ()
3429673Slinton {
3439673Slinton     symbol_free();
34418225Slinton     /* keywords_free(); */
34518225Slinton     /* names_free(); */
34618225Slinton     /* dispose(stringtab); */
3479673Slinton     clrfunctab();
3489673Slinton }
3499673Slinton 
3509673Slinton /*
3519673Slinton  * Enter a namelist entry.
3529673Slinton  */
3539673Slinton 
35416613Ssam private enter_nl (name, np)
3559673Slinton String name;
3569673Slinton register struct nlist *np;
3579673Slinton {
3589673Slinton     register Symbol s;
35916613Ssam     register Name n;
3609673Slinton 
3619673Slinton     s = nil;
3629673Slinton     switch (np->n_type) {
36314443Slinton 	/*
36414443Slinton 	 * Build a symbol for the FORTRAN common area.  All GSYMS that follow
36514443Slinton 	 * will be chained in a list with the head kept in common.offset, and
36614443Slinton 	 * the tail in common.chain.
36714443Slinton 	 */
36813938Slinton 	case N_BCOMM:
36913938Slinton  	    if (curcomm) {
37013938Slinton 		curcomm->symvalue.common.chain = commchain;
37112542Scsvaf 	    }
37216613Ssam 	    n = identname(name, true);
37312542Scsvaf 	    curcomm = lookup(n);
37413938Slinton 	    if (curcomm == nil) {
37513938Slinton 		curcomm = insert(n);
37613938Slinton 		curcomm->class = COMMON;
37713938Slinton 		curcomm->block = curblock;
37813938Slinton 		curcomm->level = program->level;
37913938Slinton 		curcomm->symvalue.common.chain = nil;
38012542Scsvaf 	    }
38112542Scsvaf 	    commchain = curcomm->symvalue.common.chain;
38213938Slinton 	    break;
38312542Scsvaf 
38412542Scsvaf 	case N_ECOMM:
38513938Slinton 	    if (curcomm) {
38613938Slinton 		curcomm->symvalue.common.chain = commchain;
38713938Slinton 		curcomm = nil;
38812542Scsvaf 	    }
38912542Scsvaf 	    break;
39014443Slinton 
3919673Slinton 	case N_LBRAC:
39214443Slinton 	    ++nesting;
39314443Slinton 	    addrstk[nesting] = (linep - 1)->addr;
3949673Slinton 	    break;
3959673Slinton 
3969673Slinton 	case N_RBRAC:
39716613Ssam 	    --nesting;
39814443Slinton 	    if (addrstk[nesting] == NOADDR) {
39914443Slinton 		exitblock();
40014443Slinton 		newfunc(curblock, (linep - 1)->addr);
40116613Ssam 		addrstk[nesting] = (linep - 1)->addr;
40214443Slinton 	    }
4039673Slinton 	    break;
4049673Slinton 
4059673Slinton 	case N_SLINE:
4069673Slinton 	    enterline((Lineno) np->n_desc, (Address) np->n_value);
4079673Slinton 	    break;
4089673Slinton 
4099673Slinton 	/*
41014443Slinton 	 * Source files.
4119673Slinton 	 */
4129673Slinton 	case N_SO:
41316613Ssam 	    n = identname(name, true);
41414443Slinton 	    enterSourceModule(n, (Address) np->n_value);
4159673Slinton 	    break;
4169673Slinton 
4179673Slinton 	/*
4189673Slinton 	 * Textually included files.
4199673Slinton 	 */
4209673Slinton 	case N_SOL:
4219673Slinton 	    enterfile(name, (Address) np->n_value);
4229673Slinton 	    break;
4239673Slinton 
4249673Slinton 	/*
4259673Slinton 	 * These symbols are assumed to have non-nil names.
4269673Slinton 	 */
4279673Slinton 	case N_GSYM:
4289673Slinton 	case N_FUN:
4299673Slinton 	case N_STSYM:
4309673Slinton 	case N_LCSYM:
4319673Slinton 	case N_RSYM:
4329673Slinton 	case N_PSYM:
4339673Slinton 	case N_LSYM:
4349673Slinton 	case N_SSYM:
43514443Slinton 	case N_LENG:
4369673Slinton 	    if (index(name, ':') == nil) {
4379673Slinton 		if (not warned) {
4389673Slinton 		    warned = true;
4399673Slinton 		    warning("old style symbol information found in \"%s\"",
4409673Slinton 			curfilename());
4419673Slinton 		}
4429673Slinton 	    } else {
4439673Slinton 		entersym(name, np);
4449673Slinton 	    }
4459673Slinton 	    break;
4469673Slinton 
4479673Slinton 	case N_PC:
44816613Ssam 	case N_MOD2:
4499673Slinton 	    break;
4509673Slinton 
45111558Slinton 	default:
45214443Slinton 	    printf("warning:  stab entry unrecognized: ");
4539673Slinton 	    if (name != nil) {
45414443Slinton 		printf("name %s,", name);
4559673Slinton 	    }
45614443Slinton 	    printf("ntype %2x, desc %x, value %x'\n",
4579673Slinton 		np->n_type, np->n_desc, np->n_value);
4589673Slinton 	    break;
4599673Slinton     }
4609673Slinton }
4619673Slinton 
4629673Slinton /*
46318225Slinton  * Try to find the symbol that is referred to by the given name.  Since it's
46418225Slinton  * an external, we need to follow a level or two of indirection.
46516613Ssam  */
46616613Ssam 
46718225Slinton private Symbol findsym (n, var_isextref)
46816613Ssam Name n;
46918225Slinton boolean *var_isextref;
47016613Ssam {
47116613Ssam     register Symbol r, s;
47216613Ssam 
47318225Slinton     *var_isextref = false;
47416613Ssam     find(s, n) where
47518225Slinton 	(
47618225Slinton 	    s->level == program->level and (
47718225Slinton 		s->class == EXTREF or s->class == VAR or
47818225Slinton 		s->class == PROC or s->class == FUNC
47918225Slinton 	    )
48018225Slinton 	) or (
48118225Slinton 	    s->block == program and s->class == MODULE
48218225Slinton 	)
48316613Ssam     endfind(s);
48418225Slinton     if (s == nil) {
48518225Slinton 	r = nil;
48618225Slinton     } else if (s->class == EXTREF) {
48718225Slinton 	*var_isextref = true;
48816613Ssam 	r = s->symvalue.extref;
48916613Ssam 	delete(s);
49018225Slinton 
49118225Slinton 	/*
49218225Slinton 	 * Now check for another level of indirection that could come from
49318225Slinton 	 * a forward reference in procedure nesting information.  In this case
49418225Slinton 	 * the symbol has already been deleted.
49518225Slinton 	 */
49618225Slinton 	if (r != nil and r->class == EXTREF) {
49718225Slinton 	    r = r->symvalue.extref;
49818225Slinton 	}
49918225Slinton /*
50018225Slinton     } else if (s->class == MODULE) {
50118225Slinton 	s->class = FUNC;
50218225Slinton 	s->level = program->level;
50318225Slinton 	r = s;
50418225Slinton  */
50516613Ssam     } else {
50616613Ssam 	r = s;
50716613Ssam     }
50816613Ssam     return r;
50916613Ssam }
51016613Ssam 
51116613Ssam /*
51218225Slinton  * Create a symbol for a text symbol with no source information.
51318225Slinton  * We treat it as an assembly language function.
51418225Slinton  */
51518225Slinton 
51618225Slinton private Symbol deffunc (n)
51718225Slinton Name n;
51818225Slinton {
51918225Slinton     Symbol f;
52018225Slinton 
52118225Slinton     f = insert(n);
52218225Slinton     f->language = findlanguage(".s");
52318225Slinton     f->class = FUNC;
52418225Slinton     f->type = t_int;
52518225Slinton     f->block = curblock;
52618225Slinton     f->level = program->level;
52718225Slinton     f->symvalue.funcv.src = false;
52818225Slinton     f->symvalue.funcv.inline = false;
52918225Slinton     return f;
53018225Slinton }
53118225Slinton 
53218225Slinton /*
53318225Slinton  * Create a symbol for a data or bss symbol with no source information.
53418225Slinton  * We treat it as an assembly language variable.
53518225Slinton  */
53618225Slinton 
53718225Slinton private Symbol defvar (n)
53818225Slinton Name n;
53918225Slinton {
54018225Slinton     Symbol v;
54118225Slinton 
54218225Slinton     v = insert(n);
54318225Slinton     v->language = findlanguage(".s");
54418225Slinton     v->class = VAR;
54518225Slinton     v->type = t_int;
54618225Slinton     v->level = program->level;
54718225Slinton     v->block = curblock;
54818225Slinton     return v;
54918225Slinton }
55018225Slinton 
55118225Slinton /*
55218225Slinton  * Update a symbol entry with a text address.
55318225Slinton  */
55418225Slinton 
55518225Slinton private updateTextSym (s, name, addr)
55618225Slinton Symbol s;
55718225Slinton char *name;
55818225Slinton Address addr;
55918225Slinton {
56018225Slinton     if (s->class == VAR) {
56118225Slinton 	s->symvalue.offset = addr;
56218225Slinton     } else {
56318225Slinton 	s->symvalue.funcv.beginaddr = addr;
56418225Slinton 	if (name[0] == '_') {
56518225Slinton 	    newfunc(s, codeloc(s));
56618225Slinton 	    findbeginning(s);
56718225Slinton 	}
56818225Slinton     }
56918225Slinton }
57018225Slinton 
57118225Slinton /*
5729673Slinton  * Check to see if a global _name is already in the symbol table,
5739673Slinton  * if not then insert it.
5749673Slinton  */
5759673Slinton 
57616613Ssam private check_global (name, np)
5779673Slinton String name;
5789673Slinton register struct nlist *np;
5799673Slinton {
5809673Slinton     register Name n;
58112542Scsvaf     register Symbol t, u;
58218225Slinton     char buf[4096];
58318225Slinton     boolean isextref;
58418225Slinton     integer count;
5859673Slinton 
58618225Slinton     if (not streq(name, "_end")) {
58718225Slinton 	if (name[0] == '_') {
58818225Slinton 	    n = identname(&name[1], true);
58918225Slinton 	} else {
59018225Slinton 	    n = identname(name, true);
59118225Slinton 	    if (lookup(n) != nil) {
59218225Slinton 		sprintf(buf, "$%s", name);
59318225Slinton 		n = identname(buf, false);
59418225Slinton 	    }
59518225Slinton 	}
5969673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
59718225Slinton 	    count = 0;
59818225Slinton 	    t = findsym(n, &isextref);
59918225Slinton 	    while (isextref) {
60018225Slinton 		++count;
60118225Slinton 		updateTextSym(t, name, np->n_value);
60218225Slinton 		t = findsym(n, &isextref);
6039673Slinton 	    }
60418225Slinton 	    if (count == 0) {
60518225Slinton 		if (t == nil) {
60618225Slinton 		    t = deffunc(n);
60718225Slinton 		    updateTextSym(t, name, np->n_value);
60818225Slinton 		    if (tracesyms) {
60918225Slinton 			printdecl(t);
61018225Slinton 		    }
61118225Slinton 		} else {
61218225Slinton 		    if (t->class == MODULE) {
61318225Slinton 			u = t;
61418225Slinton 			t = deffunc(n);
61518225Slinton 			t->block = u;
61618225Slinton 			if (tracesyms) {
61718225Slinton 			    printdecl(t);
61818225Slinton 			}
61918225Slinton 		    }
62018225Slinton 		    updateTextSym(t, name, np->n_value);
62118225Slinton 		}
62216613Ssam 	    }
62313938Slinton 	} else if ((np->n_type&N_TYPE) == N_BSS) {
6249673Slinton 	    find(t, n) where
62513938Slinton 		t->class == COMMON
62612542Scsvaf 	    endfind(t);
62713938Slinton 	    if (t != nil) {
62813938Slinton 		u = (Symbol) t->symvalue.common.offset;
62913938Slinton 		while (u != nil) {
63013938Slinton 		    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
63113938Slinton 		    u = u->symvalue.common.chain;
63213938Slinton 		}
63313938Slinton             } else {
63413938Slinton 		check_var(np, n);
6359673Slinton 	    }
63613938Slinton         } else {
63713938Slinton 	    check_var(np, n);
6389673Slinton 	}
6399673Slinton     }
6409673Slinton }
6419673Slinton 
6429673Slinton /*
64313938Slinton  * Check to see if a namelist entry refers to a variable.
64413938Slinton  * If not, create a variable for the entry.  In any case,
64513938Slinton  * set the offset of the variable according to the value field
64613938Slinton  * in the entry.
64718225Slinton  *
64818225Slinton  * If the external name has been referred to by several other symbols,
64918225Slinton  * we must update each of them.
65013938Slinton  */
65113938Slinton 
65216613Ssam private check_var (np, n)
65313938Slinton struct nlist *np;
65413938Slinton register Name n;
65513938Slinton {
65618225Slinton     register Symbol t, u, next;
65718225Slinton     Symbol conflict;
65813938Slinton 
65918225Slinton     t = lookup(n);
66013938Slinton     if (t == nil) {
66118225Slinton 	t = defvar(n);
66218225Slinton 	t->symvalue.offset = np->n_value;
66318225Slinton 	if (tracesyms) {
66418225Slinton 	    printdecl(t);
66518225Slinton 	}
66618225Slinton     } else {
66718225Slinton 	conflict = nil;
66818225Slinton 	do {
66918225Slinton 	    next = t->next_sym;
67018225Slinton 	    if (t->name == n) {
67118225Slinton 		if (t->class == MODULE and t->block == program) {
67218225Slinton 		    conflict = t;
67318225Slinton 		} else if (t->class == EXTREF and t->level == program->level) {
67418225Slinton 		    u = t->symvalue.extref;
67518225Slinton 		    while (u != nil and u->class == EXTREF) {
67618225Slinton 			u = u->symvalue.extref;
67718225Slinton 		    }
67818225Slinton 		    u->symvalue.offset = np->n_value;
67918225Slinton 		    delete(t);
68018225Slinton 		} else if (t->level == program->level and
68118225Slinton 		    (t->class == VAR or t->class == PROC or t->class == FUNC)
68218225Slinton 		) {
68318225Slinton 		    conflict = nil;
68418225Slinton 		    t->symvalue.offset = np->n_value;
68518225Slinton 		}
68618225Slinton 	    }
68718225Slinton 	    t = next;
68818225Slinton 	} while (t != nil);
68918225Slinton 	if (conflict != nil) {
69018225Slinton 	    u = defvar(n);
69118225Slinton 	    u->block = conflict;
69218225Slinton 	    u->symvalue.offset = np->n_value;
69318225Slinton 	}
69413938Slinton     }
69513938Slinton }
69613938Slinton 
69713938Slinton /*
6989673Slinton  * Check to see if a local _name is known in the current scope.
6999673Slinton  * If not then enter it.
7009673Slinton  */
7019673Slinton 
70216613Ssam private check_local (name, np)
7039673Slinton String name;
7049673Slinton register struct nlist *np;
7059673Slinton {
7069673Slinton     register Name n;
7079673Slinton     register Symbol t, cur;
7089673Slinton 
7099673Slinton     n = identname(name, true);
7109673Slinton     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
7119673Slinton     find(t, n) where t->block == cur endfind(t);
7129673Slinton     if (t == nil) {
7139673Slinton 	t = insert(n);
7149673Slinton 	t->language = findlanguage(".s");
7159673Slinton 	t->type = t_int;
7169673Slinton 	t->block = cur;
7179673Slinton 	t->level = cur->level;
7189673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
7199673Slinton 	    t->class = FUNC;
72011875Slinton 	    t->symvalue.funcv.src = false;
72114443Slinton 	    t->symvalue.funcv.inline = false;
7229673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
72314443Slinton 	    newfunc(t, codeloc(t));
7249673Slinton 	    findbeginning(t);
7259673Slinton 	} else {
7269673Slinton 	    t->class = VAR;
7279673Slinton 	    t->symvalue.offset = np->n_value;
7289673Slinton 	}
7299673Slinton     }
7309673Slinton }
7319673Slinton 
7329673Slinton /*
7339673Slinton  * Check to see if a symbol corresponds to a object file name.
7349673Slinton  * For some reason these are listed as in the text segment.
7359673Slinton  */
7369673Slinton 
73716613Ssam private check_filename (name)
7389673Slinton String name;
7399673Slinton {
7409673Slinton     register String mname;
74116613Ssam     register integer i;
74218225Slinton     Name n;
74318225Slinton     Symbol s;
7449673Slinton 
7459673Slinton     mname = strdup(name);
7469673Slinton     i = strlen(mname) - 2;
7479673Slinton     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
7489673Slinton 	mname[i] = '\0';
7499673Slinton 	--i;
7509673Slinton 	while (mname[i] != '/' and i >= 0) {
7519673Slinton 	    --i;
7529673Slinton 	}
75318225Slinton 	n = identname(&mname[i+1], true);
75418225Slinton 	find(s, n) where s->block == program and s->class == MODULE endfind(s);
75518225Slinton 	if (s == nil) {
75618225Slinton 	    s = insert(n);
75718225Slinton 	    s->language = findlanguage(".s");
75818225Slinton 	    s->class = MODULE;
75918225Slinton 	    s->symvalue.funcv.beginaddr = 0;
76018225Slinton 	    findbeginning(s);
76118225Slinton 	}
7629673Slinton 	if (curblock->class != PROG) {
7639673Slinton 	    exitblock();
7649673Slinton 	    if (curblock->class != PROG) {
7659673Slinton 		exitblock();
7669673Slinton 	    }
7679673Slinton 	}
7689673Slinton 	enterblock(s);
7699673Slinton 	curmodule = s;
7709673Slinton     }
7719673Slinton }
7729673Slinton 
7739673Slinton /*
77414443Slinton  * Check to see if a symbol is about to be defined within an unnamed block.
77514443Slinton  * If this happens, we create a procedure for the unnamed block, make it
77614443Slinton  * "inline" so that tracebacks don't associate an activation record with it,
77714443Slinton  * and enter it into the function table so that it will be detected
77814443Slinton  * by "whatblock".
77914443Slinton  */
78014443Slinton 
78116613Ssam public chkUnnamedBlock ()
78214443Slinton {
78314443Slinton     register Symbol s;
78414443Slinton     static int bnum = 0;
78514443Slinton     char buf[100];
78616613Ssam     Address startaddr;
78714443Slinton 
78816613Ssam     if (nesting > 0 and addrstk[nesting] != NOADDR) {
78916613Ssam 	startaddr = (linep - 1)->addr;
79016613Ssam 	++bnum;
79116613Ssam 	sprintf(buf, "$b%d", bnum);
79216613Ssam 	s = insert(identname(buf, false));
79316613Ssam 	s->language = curlang;
79416613Ssam 	s->class = PROC;
79516613Ssam 	s->symvalue.funcv.src = false;
79616613Ssam 	s->symvalue.funcv.inline = true;
79716613Ssam 	s->symvalue.funcv.beginaddr = startaddr;
79816613Ssam 	enterblock(s);
79916613Ssam 	newfunc(s, startaddr);
80016613Ssam 	addrstk[nesting] = NOADDR;
80116613Ssam     }
80214443Slinton }
80314443Slinton 
80414443Slinton /*
80514443Slinton  * Compilation unit.  C associates scope with filenames
80614443Slinton  * so we treat them as "modules".  The filename without
80714443Slinton  * the suffix is used for the module name.
80814443Slinton  *
80914443Slinton  * Because there is no explicit "end-of-block" mark in
81014443Slinton  * the object file, we must exit blocks for the current
81114443Slinton  * procedure and module.
81214443Slinton  */
81314443Slinton 
81416613Ssam private enterSourceModule (n, addr)
81514443Slinton Name n;
81614443Slinton Address addr;
81714443Slinton {
81814443Slinton     register Symbol s;
81914443Slinton     Name nn;
82014443Slinton     String mname, suffix;
82114443Slinton 
82214443Slinton     mname = strdup(ident(n));
82314443Slinton     if (rindex(mname, '/') != nil) {
82414443Slinton 	mname = rindex(mname, '/') + 1;
82514443Slinton     }
82614443Slinton     suffix = rindex(mname, '.');
82714443Slinton     curlang = findlanguage(suffix);
82814443Slinton     if (curlang == findlanguage(".f")) {
82914443Slinton 	strip_ = true;
83014443Slinton     }
83114443Slinton     if (suffix != nil) {
83214443Slinton 	*suffix = '\0';
83314443Slinton     }
83416613Ssam     if (not (*language_op(curlang, L_HASMODULES))()) {
83514443Slinton 	if (curblock->class != PROG) {
83614443Slinton 	    exitblock();
83716613Ssam 	    if (curblock->class != PROG) {
83816613Ssam 		exitblock();
83916613Ssam 	    }
84014443Slinton 	}
84116613Ssam 	nn = identname(mname, true);
84216613Ssam 	if (curmodule == nil or curmodule->name != nn) {
84316613Ssam 	    s = insert(nn);
84416613Ssam 	    s->class = MODULE;
84516613Ssam 	    s->symvalue.funcv.beginaddr = 0;
84616613Ssam 	    findbeginning(s);
84716613Ssam 	} else {
84816613Ssam 	    s = curmodule;
84916613Ssam 	}
85016613Ssam 	s->language = curlang;
85116613Ssam 	enterblock(s);
85216613Ssam 	curmodule = s;
85314443Slinton     }
85414443Slinton     if (program->language == nil) {
85514443Slinton 	program->language = curlang;
85614443Slinton     }
85714443Slinton     warned = false;
85814443Slinton     enterfile(ident(n), addr);
85916613Ssam     initTypeTable();
86014443Slinton }
86114443Slinton 
86214443Slinton /*
8639673Slinton  * Allocate file and line tables and initialize indices.
8649673Slinton  */
8659673Slinton 
86616613Ssam private allocmaps (nf, nl)
86716613Ssam integer nf, nl;
8689673Slinton {
8699673Slinton     if (filetab != nil) {
8709673Slinton 	dispose(filetab);
8719673Slinton     }
8729673Slinton     if (linetab != nil) {
8739673Slinton 	dispose(linetab);
8749673Slinton     }
8759673Slinton     filetab = newarr(Filetab, nf);
8769673Slinton     linetab = newarr(Linetab, nl);
8779673Slinton     filep = filetab;
8789673Slinton     linep = linetab;
8799673Slinton }
8809673Slinton 
8819673Slinton /*
8829673Slinton  * Add a file to the file table.
88313938Slinton  *
88413938Slinton  * If the new address is the same as the previous file address
88513938Slinton  * this routine used to not enter the file, but this caused some
88613938Slinton  * problems so it has been removed.  It's not clear that this in
88713938Slinton  * turn may not also cause a problem.
8889673Slinton  */
8899673Slinton 
89016613Ssam private enterfile (filename, addr)
8919673Slinton String filename;
8929673Slinton Address addr;
8939673Slinton {
89413938Slinton     filep->addr = addr;
89513938Slinton     filep->filename = filename;
89613938Slinton     filep->lineindex = linep - linetab;
89713938Slinton     ++filep;
8989673Slinton }
8999673Slinton 
9009673Slinton /*
9019673Slinton  * Since we only estimated the number of lines (and it was a poor
9029673Slinton  * estimation) and since we need to know the exact number of lines
9039673Slinton  * to do a binary search, we set it when we're done.
9049673Slinton  */
9059673Slinton 
90616613Ssam private setnlines ()
9079673Slinton {
9089673Slinton     nlhdr.nlines = linep - linetab;
9099673Slinton }
9109673Slinton 
9119673Slinton /*
9129673Slinton  * Similarly for nfiles ...
9139673Slinton  */
9149673Slinton 
91516613Ssam private setnfiles ()
9169673Slinton {
9179673Slinton     nlhdr.nfiles = filep - filetab;
9189673Slinton     setsource(filetab[0].filename);
9199673Slinton }
920