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