121615Sdist /* 238105Sbostic * Copyright (c) 1983 The Regents of the University of California. 338105Sbostic * All rights reserved. 438105Sbostic * 5*42683Sbostic * %sccs.include.redist.c% 621615Sdist */ 79673Slinton 821615Sdist #ifndef lint 9*42683Sbostic static char sccsid[] = "@(#)object.c 5.4 (Berkeley) 06/01/90"; 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 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 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 10118225Slinton public changeBlock (b) 10218225Slinton Symbol b; 10318225Slinton { 10418225Slinton curblock = b; 10518225Slinton } 10618225Slinton 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 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 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 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 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 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 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; 33614443Slinton program->symvalue.funcv.inline = 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 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 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 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 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; 53418225Slinton f->symvalue.funcv.inline = 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 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 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 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 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 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 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; 75814443Slinton t->symvalue.funcv.inline = 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 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 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; 83316613Ssam s->symvalue.funcv.inline = 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 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 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 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 94716613Ssam private setnlines () 9489673Slinton { 9499673Slinton nlhdr.nlines = linep - linetab; 9509673Slinton } 9519673Slinton 9529673Slinton /* 9539673Slinton * Similarly for nfiles ... 9549673Slinton */ 9559673Slinton 95616613Ssam private setnfiles () 9579673Slinton { 9589673Slinton nlhdr.nfiles = filep - filetab; 9599673Slinton setsource(filetab[0].filename); 9609673Slinton } 961