xref: /csrg-svn/old/dbx/object.c (revision 38105)
121615Sdist /*
2*38105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38105Sbostic  * All rights reserved.
4*38105Sbostic  *
5*38105Sbostic  * Redistribution and use in source and binary forms are permitted
6*38105Sbostic  * provided that the above copyright notice and this paragraph are
7*38105Sbostic  * duplicated in all such forms and that any documentation,
8*38105Sbostic  * advertising materials, and other materials related to such
9*38105Sbostic  * distribution and use acknowledge that the software was developed
10*38105Sbostic  * by the University of California, Berkeley.  The name of the
11*38105Sbostic  * University may not be used to endorse or promote products derived
12*38105Sbostic  * from this software without specific prior written permission.
13*38105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621615Sdist  */
179673Slinton 
1821615Sdist #ifndef lint
19*38105Sbostic static char sccsid[] = "@(#)object.c	5.3 (Berkeley) 05/23/89";
20*38105Sbostic #endif /* not lint */
219673Slinton 
229673Slinton /*
239673Slinton  * Object code interface, mainly for extraction of symbolic information.
249673Slinton  */
259673Slinton 
269673Slinton #include "defs.h"
279673Slinton #include "object.h"
2816613Ssam #include "stabstring.h"
299673Slinton #include "main.h"
309673Slinton #include "symbols.h"
319673Slinton #include "names.h"
329673Slinton #include "languages.h"
339673Slinton #include "mappings.h"
349673Slinton #include "lists.h"
359673Slinton #include <a.out.h>
369673Slinton #include <stab.h>
379673Slinton #include <ctype.h>
389673Slinton 
399673Slinton #ifndef public
409673Slinton 
419673Slinton struct {
429673Slinton     unsigned int stringsize;	/* size of the dumped string table */
439673Slinton     unsigned int nsyms;		/* number of symbols */
449673Slinton     unsigned int nfiles;	/* number of files */
459673Slinton     unsigned int nlines;	/* number of lines */
469673Slinton } nlhdr;
479673Slinton 
4816613Ssam #include "languages.h"
4916613Ssam #include "symbols.h"
5016613Ssam 
519673Slinton #endif
529673Slinton 
5316613Ssam #ifndef N_MOD2
5416613Ssam #    define N_MOD2 0x50
5516613Ssam #endif
5616613Ssam 
579673Slinton public String objname = "a.out";
5816613Ssam public integer objsize;
599673Slinton 
6016613Ssam public Language curlang;
6116613Ssam public Symbol curmodule;
6216613Ssam public Symbol curparam;
6316613Ssam public Symbol curcomm;
6416613Ssam public Symbol commchain;
6516613Ssam 
6616613Ssam private char *stringtab;
6716613Ssam private struct nlist *curnp;
689673Slinton private Boolean warned;
6912542Scsvaf private Boolean strip_ = false;
709673Slinton 
719673Slinton private Filetab *filep;
7211875Slinton private Linetab *linep, *prevlinep;
739673Slinton 
7416613Ssam public String curfilename ()
7516613Ssam {
7616613Ssam     return ((filep-1)->filename);
7716613Ssam }
789673Slinton 
799673Slinton /*
809673Slinton  * Blocks are figured out on the fly while reading the symbol table.
819673Slinton  */
829673Slinton 
839673Slinton #define MAXBLKDEPTH 25
849673Slinton 
8516613Ssam public Symbol curblock;
8616613Ssam 
879673Slinton private Symbol blkstack[MAXBLKDEPTH];
8816613Ssam private integer curlevel;
8916613Ssam private integer bnum, nesting;
9014443Slinton private Address addrstk[MAXBLKDEPTH];
919673Slinton 
9216613Ssam public pushBlock (b)
9316613Ssam Symbol b;
9416613Ssam {
9516613Ssam     if (curlevel >= MAXBLKDEPTH) {
9616613Ssam 	fatal("nesting depth too large (%d)", curlevel);
9716613Ssam     }
9816613Ssam     blkstack[curlevel] = curblock;
9916613Ssam     ++curlevel;
10016613Ssam     curblock = b;
10116613Ssam     if (traceblocks) {
10216613Ssam 	printf("entering block %s\n", symname(b));
10316613Ssam     }
1049673Slinton }
1059673Slinton 
10618225Slinton /*
10718225Slinton  * Change the current block with saving the previous one,
10818225Slinton  * since it is assumed that the symbol for the current one is to be deleted.
10918225Slinton  */
11018225Slinton 
11118225Slinton public changeBlock (b)
11218225Slinton Symbol b;
11318225Slinton {
11418225Slinton     curblock = b;
11518225Slinton }
11618225Slinton 
11716613Ssam public enterblock (b)
11816613Ssam Symbol b;
11916613Ssam {
12016613Ssam     if (curblock == nil) {
12116613Ssam 	b->level = 1;
12216613Ssam     } else {
12316613Ssam 	b->level = curblock->level + 1;
12416613Ssam     }
12516613Ssam     b->block = curblock;
12616613Ssam     pushBlock(b);
1279673Slinton }
1289673Slinton 
12916613Ssam public exitblock ()
13016613Ssam {
13116613Ssam     if (curblock->class == FUNC or curblock->class == PROC) {
13216613Ssam 	if (prevlinep != linep) {
13316613Ssam 	    curblock->symvalue.funcv.src = true;
13416613Ssam 	}
13516613Ssam     }
13616613Ssam     if (curlevel <= 0) {
13716613Ssam 	panic("nesting depth underflow (%d)", curlevel);
13816613Ssam     }
13916613Ssam     --curlevel;
14016613Ssam     if (traceblocks) {
14116613Ssam 	printf("exiting block %s\n", symname(curblock));
14216613Ssam     }
14316613Ssam     curblock = blkstack[curlevel];
14416613Ssam }
14516613Ssam 
1469673Slinton /*
1479673Slinton  * Enter a source line or file name reference into the appropriate table.
1489673Slinton  * Expanded inline to reduce procedure calls.
1499673Slinton  *
15016613Ssam  * private enterline (linenumber, address)
1519673Slinton  * Lineno linenumber;
1529673Slinton  * Address address;
1539673Slinton  *  ...
1549673Slinton  */
1559673Slinton 
1569673Slinton #define enterline(linenumber, address) \
1579673Slinton { \
1589673Slinton     register Linetab *lp; \
1599673Slinton  \
1609673Slinton     lp = linep - 1; \
1619673Slinton     if (linenumber != lp->line) { \
1629673Slinton 	if (address != lp->addr) { \
1639673Slinton 	    ++lp; \
1649673Slinton 	} \
1659673Slinton 	lp->line = linenumber; \
1669673Slinton 	lp->addr = address; \
1679673Slinton 	linep = lp + 1; \
1689673Slinton     } \
1699673Slinton }
1709673Slinton 
1719673Slinton /*
1729673Slinton  * Read in the namelist from the obj file.
1739673Slinton  *
1749673Slinton  * Reads and seeks are used instead of fread's and fseek's
1759673Slinton  * for efficiency sake; there's a lot of data being read here.
1769673Slinton  */
1779673Slinton 
17816613Ssam public readobj (file)
1799673Slinton String file;
1809673Slinton {
1819673Slinton     Fileid f;
1829673Slinton     struct exec hdr;
1839673Slinton     struct nlist nlist;
1849673Slinton 
1859673Slinton     f = open(file, 0);
1869673Slinton     if (f < 0) {
1879673Slinton 	fatal("can't open %s", file);
1889673Slinton     }
1899673Slinton     read(f, &hdr, sizeof(hdr));
19018225Slinton     if (N_BADMAG(hdr)) {
19118225Slinton 	objsize = 0;
19218225Slinton 	nlhdr.nsyms = 0;
19318225Slinton 	nlhdr.nfiles = 0;
19418225Slinton 	nlhdr.nlines = 0;
19518225Slinton     } else {
19618225Slinton 	objsize = hdr.a_text;
19718225Slinton 	nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
19818225Slinton 	nlhdr.nfiles = nlhdr.nsyms;
19918225Slinton 	nlhdr.nlines = nlhdr.nsyms;
20018225Slinton     }
20114443Slinton     if (nlhdr.nsyms > 0) {
20214443Slinton 	lseek(f, (long) N_STROFF(hdr), 0);
20314443Slinton 	read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
20414443Slinton 	nlhdr.stringsize -= 4;
20514443Slinton 	stringtab = newarr(char, nlhdr.stringsize);
20614443Slinton 	read(f, stringtab, nlhdr.stringsize);
20714443Slinton 	allocmaps(nlhdr.nfiles, nlhdr.nlines);
20814443Slinton 	lseek(f, (long) N_SYMOFF(hdr), 0);
20914443Slinton 	readsyms(f);
21014443Slinton 	ordfunctab();
21114443Slinton 	setnlines();
21214443Slinton 	setnfiles();
21318225Slinton     } else {
21418225Slinton 	initsyms();
21514443Slinton     }
2169673Slinton     close(f);
2179673Slinton }
2189673Slinton 
2199673Slinton /*
22018225Slinton  * Found the beginning of the externals in the object file
22118225Slinton  * (signified by the "-lg" or find an external), close the
22218225Slinton  * block for the last procedure.
22318225Slinton  */
22418225Slinton 
22518225Slinton private foundglobals ()
22618225Slinton {
22718225Slinton     if (curblock->class != PROG) {
22818225Slinton 	exitblock();
22918225Slinton 	if (curblock->class != PROG) {
23018225Slinton 	    exitblock();
23118225Slinton 	}
23218225Slinton     }
23318225Slinton     enterline(0, (linep-1)->addr + 1);
23418225Slinton }
23518225Slinton 
23618225Slinton /*
2379673Slinton  * Read in symbols from object file.
2389673Slinton  */
2399673Slinton 
24016613Ssam private readsyms (f)
2419673Slinton Fileid f;
2429673Slinton {
2439673Slinton     struct nlist *namelist;
2449673Slinton     register struct nlist *np, *ub;
2459673Slinton     register String name;
24633328Sdonn     boolean afterlg, foundstab;
24716613Ssam     integer index;
24816613Ssam     char *lastchar;
2499673Slinton 
2509673Slinton     initsyms();
2519673Slinton     namelist = newarr(struct nlist, nlhdr.nsyms);
2529673Slinton     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
2539673Slinton     afterlg = false;
25433328Sdonn     foundstab = false;
2559673Slinton     ub = &namelist[nlhdr.nsyms];
25616613Ssam     curnp = &namelist[0];
25716613Ssam     np = curnp;
25816613Ssam     while (np < ub) {
2599673Slinton 	index = np->n_un.n_strx;
2609673Slinton 	if (index != 0) {
2619673Slinton 	    name = &stringtab[index - 4];
26212542Scsvaf 	    /*
26316613Ssam              *  If the program contains any .f files a trailing _ is stripped
26412542Scsvaf        	     *  from the name on the assumption it was added by the compiler.
26512542Scsvaf 	     *  This only affects names that follow the sdb N_SO entry with
26612542Scsvaf              *  the .f name.
26712542Scsvaf              */
26814443Slinton             if (strip_ and name[0] != '\0' ) {
26916613Ssam 		lastchar = &name[strlen(name) - 1];
27016613Ssam 		if (*lastchar == '_') {
27116613Ssam 		    *lastchar = '\0';
27214443Slinton 		}
27312542Scsvaf             }
2749673Slinton 	} else {
2759673Slinton 	    name = nil;
27612542Scsvaf 	}
27716613Ssam 
2789673Slinton 	/*
27916613Ssam 	 * Assumptions:
2809673Slinton 	 *	not an N_STAB	==> name != nil
2819673Slinton 	 *	name[0] == '-'	==> name == "-lg"
2829673Slinton 	 *	name[0] != '_'	==> filename or invisible
2839673Slinton 	 *
2849673Slinton 	 * The "-lg" signals the beginning of global loader symbols.
28512542Scsvaf          *
2869673Slinton 	 */
2879673Slinton 	if ((np->n_type&N_STAB) != 0) {
28833328Sdonn 	    foundstab = true;
2899673Slinton 	    enter_nl(name, np);
2909673Slinton 	} else if (name[0] == '-') {
2919673Slinton 	    afterlg = true;
29218225Slinton 	    foundglobals();
29311104Slinton 	} else if (afterlg) {
29418225Slinton 	    check_global(name, np);
29518225Slinton 	} else if ((np->n_type&N_EXT) == N_EXT) {
29618225Slinton 	    afterlg = true;
29718225Slinton 	    foundglobals();
29818225Slinton 	    check_global(name, np);
29911104Slinton 	} else if (name[0] == '_') {
30011104Slinton 	    check_local(&name[1], np);
3019673Slinton 	} else if ((np->n_type&N_TEXT) == N_TEXT) {
3029673Slinton 	    check_filename(name);
3039673Slinton 	}
30416613Ssam 	++curnp;
30516613Ssam 	np = curnp;
3069673Slinton     }
30733328Sdonn     if (not foundstab) {
30833328Sdonn 	warning("no source compiled with -g");
30933328Sdonn     }
3109673Slinton     dispose(namelist);
3119673Slinton }
3129673Slinton 
3139673Slinton /*
31416613Ssam  * Get a continuation entry from the name list.
31516613Ssam  * Return the beginning of the name.
31616613Ssam  */
31716613Ssam 
31816613Ssam public String getcont ()
31916613Ssam {
32016613Ssam     register integer index;
32116613Ssam     register String name;
32216613Ssam 
32316613Ssam     ++curnp;
32416613Ssam     index = curnp->n_un.n_strx;
32516613Ssam     if (index == 0) {
32633328Sdonn 	name = "";
32733328Sdonn     } else {
32833328Sdonn 	name = &stringtab[index - 4];
32916613Ssam     }
33016613Ssam     return name;
33116613Ssam }
33216613Ssam 
33316613Ssam /*
3349673Slinton  * Initialize symbol information.
3359673Slinton  */
3369673Slinton 
33716613Ssam private initsyms ()
3389673Slinton {
3399673Slinton     curblock = nil;
3409673Slinton     curlevel = 0;
34114443Slinton     nesting = 0;
34216613Ssam     program = insert(identname("", true));
3439673Slinton     program->class = PROG;
34433328Sdonn     program->language = primlang;
34533328Sdonn     program->symvalue.funcv.beginaddr = CODESTART;
34614443Slinton     program->symvalue.funcv.inline = false;
34714443Slinton     newfunc(program, codeloc(program));
34811769Slinton     findbeginning(program);
3499673Slinton     enterblock(program);
3509673Slinton     curmodule = program;
3519673Slinton }
3529673Slinton 
3539673Slinton /*
3549673Slinton  * Free all the object file information that's being stored.
3559673Slinton  */
3569673Slinton 
35716613Ssam public objfree ()
3589673Slinton {
3599673Slinton     symbol_free();
36018225Slinton     /* keywords_free(); */
36118225Slinton     /* names_free(); */
36218225Slinton     /* dispose(stringtab); */
3639673Slinton     clrfunctab();
3649673Slinton }
3659673Slinton 
3669673Slinton /*
3679673Slinton  * Enter a namelist entry.
3689673Slinton  */
3699673Slinton 
37016613Ssam private enter_nl (name, np)
3719673Slinton String name;
3729673Slinton register struct nlist *np;
3739673Slinton {
3749673Slinton     register Symbol s;
37516613Ssam     register Name n;
3769673Slinton 
3779673Slinton     s = nil;
3789673Slinton     switch (np->n_type) {
37914443Slinton 	/*
38014443Slinton 	 * Build a symbol for the FORTRAN common area.  All GSYMS that follow
38114443Slinton 	 * will be chained in a list with the head kept in common.offset, and
38214443Slinton 	 * the tail in common.chain.
38314443Slinton 	 */
38413938Slinton 	case N_BCOMM:
38513938Slinton  	    if (curcomm) {
38613938Slinton 		curcomm->symvalue.common.chain = commchain;
38712542Scsvaf 	    }
38816613Ssam 	    n = identname(name, true);
38912542Scsvaf 	    curcomm = lookup(n);
39013938Slinton 	    if (curcomm == nil) {
39113938Slinton 		curcomm = insert(n);
39213938Slinton 		curcomm->class = COMMON;
39313938Slinton 		curcomm->block = curblock;
39413938Slinton 		curcomm->level = program->level;
39513938Slinton 		curcomm->symvalue.common.chain = nil;
39612542Scsvaf 	    }
39712542Scsvaf 	    commchain = curcomm->symvalue.common.chain;
39813938Slinton 	    break;
39912542Scsvaf 
40012542Scsvaf 	case N_ECOMM:
40113938Slinton 	    if (curcomm) {
40213938Slinton 		curcomm->symvalue.common.chain = commchain;
40313938Slinton 		curcomm = nil;
40412542Scsvaf 	    }
40512542Scsvaf 	    break;
40614443Slinton 
4079673Slinton 	case N_LBRAC:
40814443Slinton 	    ++nesting;
40914443Slinton 	    addrstk[nesting] = (linep - 1)->addr;
4109673Slinton 	    break;
4119673Slinton 
4129673Slinton 	case N_RBRAC:
41316613Ssam 	    --nesting;
41414443Slinton 	    if (addrstk[nesting] == NOADDR) {
41514443Slinton 		exitblock();
41614443Slinton 		newfunc(curblock, (linep - 1)->addr);
41716613Ssam 		addrstk[nesting] = (linep - 1)->addr;
41814443Slinton 	    }
4199673Slinton 	    break;
4209673Slinton 
4219673Slinton 	case N_SLINE:
4229673Slinton 	    enterline((Lineno) np->n_desc, (Address) np->n_value);
4239673Slinton 	    break;
4249673Slinton 
4259673Slinton 	/*
42614443Slinton 	 * Source files.
4279673Slinton 	 */
4289673Slinton 	case N_SO:
42916613Ssam 	    n = identname(name, true);
43014443Slinton 	    enterSourceModule(n, (Address) np->n_value);
4319673Slinton 	    break;
4329673Slinton 
4339673Slinton 	/*
4349673Slinton 	 * Textually included files.
4359673Slinton 	 */
4369673Slinton 	case N_SOL:
4379673Slinton 	    enterfile(name, (Address) np->n_value);
4389673Slinton 	    break;
4399673Slinton 
4409673Slinton 	/*
4419673Slinton 	 * These symbols are assumed to have non-nil names.
4429673Slinton 	 */
4439673Slinton 	case N_GSYM:
4449673Slinton 	case N_FUN:
4459673Slinton 	case N_STSYM:
4469673Slinton 	case N_LCSYM:
4479673Slinton 	case N_RSYM:
4489673Slinton 	case N_PSYM:
4499673Slinton 	case N_LSYM:
4509673Slinton 	case N_SSYM:
45114443Slinton 	case N_LENG:
4529673Slinton 	    if (index(name, ':') == nil) {
4539673Slinton 		if (not warned) {
4549673Slinton 		    warned = true;
45533328Sdonn 		    printf("warning: old style symbol information ");
45633328Sdonn 		    printf("found in \"%s\"\n", curfilename());
4579673Slinton 		}
4589673Slinton 	    } else {
4599673Slinton 		entersym(name, np);
4609673Slinton 	    }
4619673Slinton 	    break;
4629673Slinton 
4639673Slinton 	case N_PC:
46416613Ssam 	case N_MOD2:
4659673Slinton 	    break;
4669673Slinton 
46711558Slinton 	default:
46814443Slinton 	    printf("warning:  stab entry unrecognized: ");
4699673Slinton 	    if (name != nil) {
47014443Slinton 		printf("name %s,", name);
4719673Slinton 	    }
47214443Slinton 	    printf("ntype %2x, desc %x, value %x'\n",
4739673Slinton 		np->n_type, np->n_desc, np->n_value);
4749673Slinton 	    break;
4759673Slinton     }
4769673Slinton }
4779673Slinton 
4789673Slinton /*
47918225Slinton  * Try to find the symbol that is referred to by the given name.  Since it's
48018225Slinton  * an external, we need to follow a level or two of indirection.
48116613Ssam  */
48216613Ssam 
48318225Slinton private Symbol findsym (n, var_isextref)
48416613Ssam Name n;
48518225Slinton boolean *var_isextref;
48616613Ssam {
48716613Ssam     register Symbol r, s;
48816613Ssam 
48918225Slinton     *var_isextref = false;
49016613Ssam     find(s, n) where
49118225Slinton 	(
49218225Slinton 	    s->level == program->level and (
49318225Slinton 		s->class == EXTREF or s->class == VAR or
49418225Slinton 		s->class == PROC or s->class == FUNC
49518225Slinton 	    )
49618225Slinton 	) or (
49718225Slinton 	    s->block == program and s->class == MODULE
49818225Slinton 	)
49916613Ssam     endfind(s);
50018225Slinton     if (s == nil) {
50118225Slinton 	r = nil;
50218225Slinton     } else if (s->class == EXTREF) {
50318225Slinton 	*var_isextref = true;
50416613Ssam 	r = s->symvalue.extref;
50516613Ssam 	delete(s);
50618225Slinton 
50718225Slinton 	/*
50818225Slinton 	 * Now check for another level of indirection that could come from
50918225Slinton 	 * a forward reference in procedure nesting information.  In this case
51018225Slinton 	 * the symbol has already been deleted.
51118225Slinton 	 */
51218225Slinton 	if (r != nil and r->class == EXTREF) {
51318225Slinton 	    r = r->symvalue.extref;
51418225Slinton 	}
51518225Slinton /*
51618225Slinton     } else if (s->class == MODULE) {
51718225Slinton 	s->class = FUNC;
51818225Slinton 	s->level = program->level;
51918225Slinton 	r = s;
52018225Slinton  */
52116613Ssam     } else {
52216613Ssam 	r = s;
52316613Ssam     }
52416613Ssam     return r;
52516613Ssam }
52616613Ssam 
52716613Ssam /*
52818225Slinton  * Create a symbol for a text symbol with no source information.
52918225Slinton  * We treat it as an assembly language function.
53018225Slinton  */
53118225Slinton 
53218225Slinton private Symbol deffunc (n)
53318225Slinton Name n;
53418225Slinton {
53518225Slinton     Symbol f;
53618225Slinton 
53718225Slinton     f = insert(n);
53818225Slinton     f->language = findlanguage(".s");
53918225Slinton     f->class = FUNC;
54018225Slinton     f->type = t_int;
54118225Slinton     f->block = curblock;
54218225Slinton     f->level = program->level;
54318225Slinton     f->symvalue.funcv.src = false;
54418225Slinton     f->symvalue.funcv.inline = false;
54533328Sdonn     if (f->chain != nil) {
54633328Sdonn 	panic("chain not nil in deffunc");
54733328Sdonn     }
54818225Slinton     return f;
54918225Slinton }
55018225Slinton 
55118225Slinton /*
55218225Slinton  * Create a symbol for a data or bss symbol with no source information.
55318225Slinton  * We treat it as an assembly language variable.
55418225Slinton  */
55518225Slinton 
55618225Slinton private Symbol defvar (n)
55718225Slinton Name n;
55818225Slinton {
55918225Slinton     Symbol v;
56018225Slinton 
56118225Slinton     v = insert(n);
56218225Slinton     v->language = findlanguage(".s");
56333328Sdonn     v->storage = EXT;
56418225Slinton     v->class = VAR;
56518225Slinton     v->type = t_int;
56618225Slinton     v->level = program->level;
56718225Slinton     v->block = curblock;
56818225Slinton     return v;
56918225Slinton }
57018225Slinton 
57118225Slinton /*
57218225Slinton  * Update a symbol entry with a text address.
57318225Slinton  */
57418225Slinton 
57518225Slinton private updateTextSym (s, name, addr)
57618225Slinton Symbol s;
57718225Slinton char *name;
57818225Slinton Address addr;
57918225Slinton {
58018225Slinton     if (s->class == VAR) {
58118225Slinton 	s->symvalue.offset = addr;
58218225Slinton     } else {
58318225Slinton 	s->symvalue.funcv.beginaddr = addr;
58418225Slinton 	if (name[0] == '_') {
58518225Slinton 	    newfunc(s, codeloc(s));
58618225Slinton 	    findbeginning(s);
58718225Slinton 	}
58818225Slinton     }
58918225Slinton }
59018225Slinton 
59118225Slinton /*
59233328Sdonn  * Avoid seeing Pascal labels as text symbols.
59333328Sdonn  */
59433328Sdonn 
59533328Sdonn private boolean PascalLabel (n)
59633328Sdonn Name n;
59733328Sdonn {
59833328Sdonn     boolean b;
59933328Sdonn     register char *p;
60033328Sdonn 
60133328Sdonn     b = false;
60233328Sdonn     if (curlang == findlanguage(".p")) {
60333328Sdonn 	p = ident(n);
60433328Sdonn 	while (*p != '\0') {
60533328Sdonn 	    if (*p == '_' and *(p+1) == '$') {
60633328Sdonn 		b = true;
60733328Sdonn 		break;
60833328Sdonn 	    }
60933328Sdonn 	    ++p;
61033328Sdonn 	}
61133328Sdonn     }
61233328Sdonn     return b;
61333328Sdonn }
61433328Sdonn 
61533328Sdonn /*
6169673Slinton  * Check to see if a global _name is already in the symbol table,
6179673Slinton  * if not then insert it.
6189673Slinton  */
6199673Slinton 
62016613Ssam private check_global (name, np)
6219673Slinton String name;
6229673Slinton register struct nlist *np;
6239673Slinton {
6249673Slinton     register Name n;
62512542Scsvaf     register Symbol t, u;
62618225Slinton     char buf[4096];
62718225Slinton     boolean isextref;
62818225Slinton     integer count;
6299673Slinton 
63018225Slinton     if (not streq(name, "_end")) {
63118225Slinton 	if (name[0] == '_') {
63218225Slinton 	    n = identname(&name[1], true);
63318225Slinton 	} else {
63418225Slinton 	    n = identname(name, true);
63518225Slinton 	    if (lookup(n) != nil) {
63618225Slinton 		sprintf(buf, "$%s", name);
63718225Slinton 		n = identname(buf, false);
63818225Slinton 	    }
63918225Slinton 	}
6409673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
64118225Slinton 	    count = 0;
64218225Slinton 	    t = findsym(n, &isextref);
64318225Slinton 	    while (isextref) {
64418225Slinton 		++count;
64518225Slinton 		updateTextSym(t, name, np->n_value);
64618225Slinton 		t = findsym(n, &isextref);
6479673Slinton 	    }
64818225Slinton 	    if (count == 0) {
64918225Slinton 		if (t == nil) {
65033328Sdonn 		    if (not PascalLabel(n)) {
65133328Sdonn 			t = deffunc(n);
65233328Sdonn 			updateTextSym(t, name, np->n_value);
65333328Sdonn 			if (tracesyms) {
65433328Sdonn 			    printdecl(t);
65533328Sdonn 			}
65618225Slinton 		    }
65718225Slinton 		} else {
65818225Slinton 		    if (t->class == MODULE) {
65918225Slinton 			u = t;
66018225Slinton 			t = deffunc(n);
66118225Slinton 			t->block = u;
66218225Slinton 			if (tracesyms) {
66318225Slinton 			    printdecl(t);
66418225Slinton 			}
66518225Slinton 		    }
66618225Slinton 		    updateTextSym(t, name, np->n_value);
66718225Slinton 		}
66816613Ssam 	    }
66933328Sdonn 	} else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) {
6709673Slinton 	    find(t, n) where
67113938Slinton 		t->class == COMMON
67212542Scsvaf 	    endfind(t);
67313938Slinton 	    if (t != nil) {
67413938Slinton 		u = (Symbol) t->symvalue.common.offset;
67513938Slinton 		while (u != nil) {
67613938Slinton 		    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
67713938Slinton 		    u = u->symvalue.common.chain;
67813938Slinton 		}
67913938Slinton             } else {
68013938Slinton 		check_var(np, n);
6819673Slinton 	    }
68213938Slinton         } else {
68313938Slinton 	    check_var(np, n);
6849673Slinton 	}
6859673Slinton     }
6869673Slinton }
6879673Slinton 
6889673Slinton /*
68913938Slinton  * Check to see if a namelist entry refers to a variable.
69013938Slinton  * If not, create a variable for the entry.  In any case,
69113938Slinton  * set the offset of the variable according to the value field
69213938Slinton  * in the entry.
69318225Slinton  *
69418225Slinton  * If the external name has been referred to by several other symbols,
69518225Slinton  * we must update each of them.
69613938Slinton  */
69713938Slinton 
69816613Ssam private check_var (np, n)
69913938Slinton struct nlist *np;
70013938Slinton register Name n;
70113938Slinton {
70218225Slinton     register Symbol t, u, next;
70318225Slinton     Symbol conflict;
70413938Slinton 
70518225Slinton     t = lookup(n);
70613938Slinton     if (t == nil) {
70718225Slinton 	t = defvar(n);
70818225Slinton 	t->symvalue.offset = np->n_value;
70918225Slinton 	if (tracesyms) {
71018225Slinton 	    printdecl(t);
71118225Slinton 	}
71218225Slinton     } else {
71318225Slinton 	conflict = nil;
71418225Slinton 	do {
71518225Slinton 	    next = t->next_sym;
71618225Slinton 	    if (t->name == n) {
71718225Slinton 		if (t->class == MODULE and t->block == program) {
71818225Slinton 		    conflict = t;
71918225Slinton 		} else if (t->class == EXTREF and t->level == program->level) {
72018225Slinton 		    u = t->symvalue.extref;
72118225Slinton 		    while (u != nil and u->class == EXTREF) {
72218225Slinton 			u = u->symvalue.extref;
72318225Slinton 		    }
72418225Slinton 		    u->symvalue.offset = np->n_value;
72518225Slinton 		    delete(t);
72618225Slinton 		} else if (t->level == program->level and
72718225Slinton 		    (t->class == VAR or t->class == PROC or t->class == FUNC)
72818225Slinton 		) {
72918225Slinton 		    conflict = nil;
73018225Slinton 		    t->symvalue.offset = np->n_value;
73118225Slinton 		}
73218225Slinton 	    }
73318225Slinton 	    t = next;
73418225Slinton 	} while (t != nil);
73518225Slinton 	if (conflict != nil) {
73618225Slinton 	    u = defvar(n);
73718225Slinton 	    u->block = conflict;
73818225Slinton 	    u->symvalue.offset = np->n_value;
73918225Slinton 	}
74013938Slinton     }
74113938Slinton }
74213938Slinton 
74313938Slinton /*
7449673Slinton  * Check to see if a local _name is known in the current scope.
7459673Slinton  * If not then enter it.
7469673Slinton  */
7479673Slinton 
74816613Ssam private check_local (name, np)
7499673Slinton String name;
7509673Slinton register struct nlist *np;
7519673Slinton {
7529673Slinton     register Name n;
7539673Slinton     register Symbol t, cur;
7549673Slinton 
7559673Slinton     n = identname(name, true);
7569673Slinton     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
7579673Slinton     find(t, n) where t->block == cur endfind(t);
7589673Slinton     if (t == nil) {
7599673Slinton 	t = insert(n);
7609673Slinton 	t->language = findlanguage(".s");
7619673Slinton 	t->type = t_int;
7629673Slinton 	t->block = cur;
76333328Sdonn 	t->storage = EXT;
7649673Slinton 	t->level = cur->level;
7659673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
7669673Slinton 	    t->class = FUNC;
76711875Slinton 	    t->symvalue.funcv.src = false;
76814443Slinton 	    t->symvalue.funcv.inline = false;
7699673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
77014443Slinton 	    newfunc(t, codeloc(t));
7719673Slinton 	    findbeginning(t);
7729673Slinton 	} else {
7739673Slinton 	    t->class = VAR;
7749673Slinton 	    t->symvalue.offset = np->n_value;
7759673Slinton 	}
7769673Slinton     }
7779673Slinton }
7789673Slinton 
7799673Slinton /*
7809673Slinton  * Check to see if a symbol corresponds to a object file name.
7819673Slinton  * For some reason these are listed as in the text segment.
7829673Slinton  */
7839673Slinton 
78416613Ssam private check_filename (name)
7859673Slinton String name;
7869673Slinton {
7879673Slinton     register String mname;
78816613Ssam     register integer i;
78918225Slinton     Name n;
79018225Slinton     Symbol s;
7919673Slinton 
7929673Slinton     mname = strdup(name);
7939673Slinton     i = strlen(mname) - 2;
7949673Slinton     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
7959673Slinton 	mname[i] = '\0';
7969673Slinton 	--i;
7979673Slinton 	while (mname[i] != '/' and i >= 0) {
7989673Slinton 	    --i;
7999673Slinton 	}
80018225Slinton 	n = identname(&mname[i+1], true);
80118225Slinton 	find(s, n) where s->block == program and s->class == MODULE endfind(s);
80218225Slinton 	if (s == nil) {
80318225Slinton 	    s = insert(n);
80418225Slinton 	    s->language = findlanguage(".s");
80518225Slinton 	    s->class = MODULE;
80618225Slinton 	    s->symvalue.funcv.beginaddr = 0;
80718225Slinton 	    findbeginning(s);
80818225Slinton 	}
8099673Slinton 	if (curblock->class != PROG) {
8109673Slinton 	    exitblock();
8119673Slinton 	    if (curblock->class != PROG) {
8129673Slinton 		exitblock();
8139673Slinton 	    }
8149673Slinton 	}
8159673Slinton 	enterblock(s);
8169673Slinton 	curmodule = s;
8179673Slinton     }
8189673Slinton }
8199673Slinton 
8209673Slinton /*
82114443Slinton  * Check to see if a symbol is about to be defined within an unnamed block.
82214443Slinton  * If this happens, we create a procedure for the unnamed block, make it
82314443Slinton  * "inline" so that tracebacks don't associate an activation record with it,
82414443Slinton  * and enter it into the function table so that it will be detected
82514443Slinton  * by "whatblock".
82614443Slinton  */
82714443Slinton 
82816613Ssam public chkUnnamedBlock ()
82914443Slinton {
83014443Slinton     register Symbol s;
83114443Slinton     static int bnum = 0;
83214443Slinton     char buf[100];
83316613Ssam     Address startaddr;
83414443Slinton 
83516613Ssam     if (nesting > 0 and addrstk[nesting] != NOADDR) {
83616613Ssam 	startaddr = (linep - 1)->addr;
83716613Ssam 	++bnum;
83816613Ssam 	sprintf(buf, "$b%d", bnum);
83916613Ssam 	s = insert(identname(buf, false));
84016613Ssam 	s->language = curlang;
84116613Ssam 	s->class = PROC;
84216613Ssam 	s->symvalue.funcv.src = false;
84316613Ssam 	s->symvalue.funcv.inline = true;
84416613Ssam 	s->symvalue.funcv.beginaddr = startaddr;
84516613Ssam 	enterblock(s);
84616613Ssam 	newfunc(s, startaddr);
84716613Ssam 	addrstk[nesting] = NOADDR;
84816613Ssam     }
84914443Slinton }
85014443Slinton 
85114443Slinton /*
85214443Slinton  * Compilation unit.  C associates scope with filenames
85314443Slinton  * so we treat them as "modules".  The filename without
85414443Slinton  * the suffix is used for the module name.
85514443Slinton  *
85614443Slinton  * Because there is no explicit "end-of-block" mark in
85714443Slinton  * the object file, we must exit blocks for the current
85814443Slinton  * procedure and module.
85914443Slinton  */
86014443Slinton 
86116613Ssam private enterSourceModule (n, addr)
86214443Slinton Name n;
86314443Slinton Address addr;
86414443Slinton {
86514443Slinton     register Symbol s;
86614443Slinton     Name nn;
86714443Slinton     String mname, suffix;
86814443Slinton 
86914443Slinton     mname = strdup(ident(n));
87014443Slinton     if (rindex(mname, '/') != nil) {
87114443Slinton 	mname = rindex(mname, '/') + 1;
87214443Slinton     }
87314443Slinton     suffix = rindex(mname, '.');
87433328Sdonn     if (suffix > mname && *(suffix-1) == '.') {
87533328Sdonn 	/* special hack for C++ */
87633328Sdonn 	--suffix;
87733328Sdonn     }
87814443Slinton     curlang = findlanguage(suffix);
87914443Slinton     if (curlang == findlanguage(".f")) {
88014443Slinton 	strip_ = true;
88114443Slinton     }
88214443Slinton     if (suffix != nil) {
88314443Slinton 	*suffix = '\0';
88414443Slinton     }
88516613Ssam     if (not (*language_op(curlang, L_HASMODULES))()) {
88614443Slinton 	if (curblock->class != PROG) {
88714443Slinton 	    exitblock();
88816613Ssam 	    if (curblock->class != PROG) {
88916613Ssam 		exitblock();
89016613Ssam 	    }
89114443Slinton 	}
89216613Ssam 	nn = identname(mname, true);
89316613Ssam 	if (curmodule == nil or curmodule->name != nn) {
89416613Ssam 	    s = insert(nn);
89516613Ssam 	    s->class = MODULE;
89616613Ssam 	    s->symvalue.funcv.beginaddr = 0;
89716613Ssam 	    findbeginning(s);
89816613Ssam 	} else {
89916613Ssam 	    s = curmodule;
90016613Ssam 	}
90116613Ssam 	s->language = curlang;
90216613Ssam 	enterblock(s);
90316613Ssam 	curmodule = s;
90414443Slinton     }
90514443Slinton     if (program->language == nil) {
90614443Slinton 	program->language = curlang;
90714443Slinton     }
90814443Slinton     warned = false;
90914443Slinton     enterfile(ident(n), addr);
91016613Ssam     initTypeTable();
91114443Slinton }
91214443Slinton 
91314443Slinton /*
9149673Slinton  * Allocate file and line tables and initialize indices.
9159673Slinton  */
9169673Slinton 
91716613Ssam private allocmaps (nf, nl)
91816613Ssam integer nf, nl;
9199673Slinton {
9209673Slinton     if (filetab != nil) {
9219673Slinton 	dispose(filetab);
9229673Slinton     }
9239673Slinton     if (linetab != nil) {
9249673Slinton 	dispose(linetab);
9259673Slinton     }
9269673Slinton     filetab = newarr(Filetab, nf);
9279673Slinton     linetab = newarr(Linetab, nl);
9289673Slinton     filep = filetab;
9299673Slinton     linep = linetab;
9309673Slinton }
9319673Slinton 
9329673Slinton /*
9339673Slinton  * Add a file to the file table.
93413938Slinton  *
93513938Slinton  * If the new address is the same as the previous file address
93613938Slinton  * this routine used to not enter the file, but this caused some
93713938Slinton  * problems so it has been removed.  It's not clear that this in
93813938Slinton  * turn may not also cause a problem.
9399673Slinton  */
9409673Slinton 
94116613Ssam private enterfile (filename, addr)
9429673Slinton String filename;
9439673Slinton Address addr;
9449673Slinton {
94513938Slinton     filep->addr = addr;
94613938Slinton     filep->filename = filename;
94713938Slinton     filep->lineindex = linep - linetab;
94813938Slinton     ++filep;
9499673Slinton }
9509673Slinton 
9519673Slinton /*
9529673Slinton  * Since we only estimated the number of lines (and it was a poor
9539673Slinton  * estimation) and since we need to know the exact number of lines
9549673Slinton  * to do a binary search, we set it when we're done.
9559673Slinton  */
9569673Slinton 
95716613Ssam private setnlines ()
9589673Slinton {
9599673Slinton     nlhdr.nlines = linep - linetab;
9609673Slinton }
9619673Slinton 
9629673Slinton /*
9639673Slinton  * Similarly for nfiles ...
9649673Slinton  */
9659673Slinton 
96616613Ssam private setnfiles ()
9679673Slinton {
9689673Slinton     nlhdr.nfiles = filep - filetab;
9699673Slinton     setsource(filetab[0].filename);
9709673Slinton }
971