1*21615Sdist /* 2*21615Sdist * Copyright (c) 1983 Regents of the University of California. 3*21615Sdist * All rights reserved. The Berkeley software License Agreement 4*21615Sdist * specifies the terms and conditions for redistribution. 5*21615Sdist */ 69673Slinton 7*21615Sdist #ifndef lint 8*21615Sdist static char sccsid[] = "@(#)object.c 5.1 (Berkeley) 05/31/85"; 9*21615Sdist #endif not lint 109673Slinton 1118225Slinton static char rcsid[] = "$Header: object.c,v 1.6 84/12/26 10:40:51 linton Exp $"; 1218225Slinton 139673Slinton /* 149673Slinton * Object code interface, mainly for extraction of symbolic information. 159673Slinton */ 169673Slinton 179673Slinton #include "defs.h" 189673Slinton #include "object.h" 1916613Ssam #include "stabstring.h" 209673Slinton #include "main.h" 219673Slinton #include "symbols.h" 229673Slinton #include "names.h" 239673Slinton #include "languages.h" 249673Slinton #include "mappings.h" 259673Slinton #include "lists.h" 269673Slinton #include <a.out.h> 279673Slinton #include <stab.h> 289673Slinton #include <ctype.h> 299673Slinton 309673Slinton #ifndef public 319673Slinton 329673Slinton struct { 339673Slinton unsigned int stringsize; /* size of the dumped string table */ 349673Slinton unsigned int nsyms; /* number of symbols */ 359673Slinton unsigned int nfiles; /* number of files */ 369673Slinton unsigned int nlines; /* number of lines */ 379673Slinton } nlhdr; 389673Slinton 3916613Ssam #include "languages.h" 4016613Ssam #include "symbols.h" 4116613Ssam 429673Slinton #endif 439673Slinton 4416613Ssam #ifndef N_MOD2 4516613Ssam # define N_MOD2 0x50 4616613Ssam #endif 4716613Ssam 489673Slinton public String objname = "a.out"; 4916613Ssam public integer objsize; 509673Slinton 5116613Ssam public Language curlang; 5216613Ssam public Symbol curmodule; 5316613Ssam public Symbol curparam; 5416613Ssam public Symbol curcomm; 5516613Ssam public Symbol commchain; 5616613Ssam 5716613Ssam private char *stringtab; 5816613Ssam private struct nlist *curnp; 599673Slinton private Boolean warned; 6012542Scsvaf private Boolean strip_ = false; 619673Slinton 629673Slinton private Filetab *filep; 6311875Slinton private Linetab *linep, *prevlinep; 649673Slinton 6516613Ssam public String curfilename () 6616613Ssam { 6716613Ssam return ((filep-1)->filename); 6816613Ssam } 699673Slinton 709673Slinton /* 719673Slinton * Blocks are figured out on the fly while reading the symbol table. 729673Slinton */ 739673Slinton 749673Slinton #define MAXBLKDEPTH 25 759673Slinton 7616613Ssam public Symbol curblock; 7716613Ssam 789673Slinton private Symbol blkstack[MAXBLKDEPTH]; 7916613Ssam private integer curlevel; 8016613Ssam private integer bnum, nesting; 8114443Slinton private Address addrstk[MAXBLKDEPTH]; 829673Slinton 8316613Ssam public pushBlock (b) 8416613Ssam Symbol b; 8516613Ssam { 8616613Ssam if (curlevel >= MAXBLKDEPTH) { 8716613Ssam fatal("nesting depth too large (%d)", curlevel); 8816613Ssam } 8916613Ssam blkstack[curlevel] = curblock; 9016613Ssam ++curlevel; 9116613Ssam curblock = b; 9216613Ssam if (traceblocks) { 9316613Ssam printf("entering block %s\n", symname(b)); 9416613Ssam } 959673Slinton } 969673Slinton 9718225Slinton /* 9818225Slinton * Change the current block with saving the previous one, 9918225Slinton * since it is assumed that the symbol for the current one is to be deleted. 10018225Slinton */ 10118225Slinton 10218225Slinton public changeBlock (b) 10318225Slinton Symbol b; 10418225Slinton { 10518225Slinton curblock = b; 10618225Slinton } 10718225Slinton 10816613Ssam public enterblock (b) 10916613Ssam Symbol b; 11016613Ssam { 11116613Ssam if (curblock == nil) { 11216613Ssam b->level = 1; 11316613Ssam } else { 11416613Ssam b->level = curblock->level + 1; 11516613Ssam } 11616613Ssam b->block = curblock; 11716613Ssam pushBlock(b); 1189673Slinton } 1199673Slinton 12016613Ssam public exitblock () 12116613Ssam { 12216613Ssam if (curblock->class == FUNC or curblock->class == PROC) { 12316613Ssam if (prevlinep != linep) { 12416613Ssam curblock->symvalue.funcv.src = true; 12516613Ssam } 12616613Ssam } 12716613Ssam if (curlevel <= 0) { 12816613Ssam panic("nesting depth underflow (%d)", curlevel); 12916613Ssam } 13016613Ssam --curlevel; 13116613Ssam if (traceblocks) { 13216613Ssam printf("exiting block %s\n", symname(curblock)); 13316613Ssam } 13416613Ssam curblock = blkstack[curlevel]; 13516613Ssam } 13616613Ssam 1379673Slinton /* 1389673Slinton * Enter a source line or file name reference into the appropriate table. 1399673Slinton * Expanded inline to reduce procedure calls. 1409673Slinton * 14116613Ssam * private enterline (linenumber, address) 1429673Slinton * Lineno linenumber; 1439673Slinton * Address address; 1449673Slinton * ... 1459673Slinton */ 1469673Slinton 1479673Slinton #define enterline(linenumber, address) \ 1489673Slinton { \ 1499673Slinton register Linetab *lp; \ 1509673Slinton \ 1519673Slinton lp = linep - 1; \ 1529673Slinton if (linenumber != lp->line) { \ 1539673Slinton if (address != lp->addr) { \ 1549673Slinton ++lp; \ 1559673Slinton } \ 1569673Slinton lp->line = linenumber; \ 1579673Slinton lp->addr = address; \ 1589673Slinton linep = lp + 1; \ 1599673Slinton } \ 1609673Slinton } 1619673Slinton 1629673Slinton /* 1639673Slinton * Read in the namelist from the obj file. 1649673Slinton * 1659673Slinton * Reads and seeks are used instead of fread's and fseek's 1669673Slinton * for efficiency sake; there's a lot of data being read here. 1679673Slinton */ 1689673Slinton 16916613Ssam public readobj (file) 1709673Slinton String file; 1719673Slinton { 1729673Slinton Fileid f; 1739673Slinton struct exec hdr; 1749673Slinton struct nlist nlist; 1759673Slinton 1769673Slinton f = open(file, 0); 1779673Slinton if (f < 0) { 1789673Slinton fatal("can't open %s", file); 1799673Slinton } 1809673Slinton read(f, &hdr, sizeof(hdr)); 18118225Slinton if (N_BADMAG(hdr)) { 18218225Slinton objsize = 0; 18318225Slinton nlhdr.nsyms = 0; 18418225Slinton nlhdr.nfiles = 0; 18518225Slinton nlhdr.nlines = 0; 18618225Slinton } else { 18718225Slinton objsize = hdr.a_text; 18818225Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 18918225Slinton nlhdr.nfiles = nlhdr.nsyms; 19018225Slinton nlhdr.nlines = nlhdr.nsyms; 19118225Slinton } 19214443Slinton if (nlhdr.nsyms > 0) { 19314443Slinton lseek(f, (long) N_STROFF(hdr), 0); 19414443Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 19514443Slinton nlhdr.stringsize -= 4; 19614443Slinton stringtab = newarr(char, nlhdr.stringsize); 19714443Slinton read(f, stringtab, nlhdr.stringsize); 19814443Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 19914443Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 20014443Slinton readsyms(f); 20114443Slinton ordfunctab(); 20214443Slinton setnlines(); 20314443Slinton setnfiles(); 20418225Slinton } else { 20518225Slinton initsyms(); 20614443Slinton } 2079673Slinton close(f); 2089673Slinton } 2099673Slinton 2109673Slinton /* 21118225Slinton * Found the beginning of the externals in the object file 21218225Slinton * (signified by the "-lg" or find an external), close the 21318225Slinton * block for the last procedure. 21418225Slinton */ 21518225Slinton 21618225Slinton private foundglobals () 21718225Slinton { 21818225Slinton if (curblock->class != PROG) { 21918225Slinton exitblock(); 22018225Slinton if (curblock->class != PROG) { 22118225Slinton exitblock(); 22218225Slinton } 22318225Slinton } 22418225Slinton enterline(0, (linep-1)->addr + 1); 22518225Slinton } 22618225Slinton 22718225Slinton /* 2289673Slinton * Read in symbols from object file. 2299673Slinton */ 2309673Slinton 23116613Ssam private readsyms (f) 2329673Slinton Fileid f; 2339673Slinton { 2349673Slinton struct nlist *namelist; 2359673Slinton register struct nlist *np, *ub; 2369673Slinton register String name; 2379673Slinton register Boolean afterlg; 23816613Ssam integer index; 23916613Ssam char *lastchar; 2409673Slinton 2419673Slinton initsyms(); 2429673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 2439673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 2449673Slinton afterlg = false; 2459673Slinton ub = &namelist[nlhdr.nsyms]; 24616613Ssam curnp = &namelist[0]; 24716613Ssam np = curnp; 24816613Ssam while (np < ub) { 2499673Slinton index = np->n_un.n_strx; 2509673Slinton if (index != 0) { 2519673Slinton name = &stringtab[index - 4]; 25212542Scsvaf /* 25316613Ssam * If the program contains any .f files a trailing _ is stripped 25412542Scsvaf * from the name on the assumption it was added by the compiler. 25512542Scsvaf * This only affects names that follow the sdb N_SO entry with 25612542Scsvaf * the .f name. 25712542Scsvaf */ 25814443Slinton if (strip_ and name[0] != '\0' ) { 25916613Ssam lastchar = &name[strlen(name) - 1]; 26016613Ssam if (*lastchar == '_') { 26116613Ssam *lastchar = '\0'; 26214443Slinton } 26312542Scsvaf } 2649673Slinton } else { 2659673Slinton name = nil; 26612542Scsvaf } 26716613Ssam 2689673Slinton /* 26916613Ssam * Assumptions: 2709673Slinton * not an N_STAB ==> name != nil 2719673Slinton * name[0] == '-' ==> name == "-lg" 2729673Slinton * name[0] != '_' ==> filename or invisible 2739673Slinton * 2749673Slinton * The "-lg" signals the beginning of global loader symbols. 27512542Scsvaf * 2769673Slinton */ 2779673Slinton if ((np->n_type&N_STAB) != 0) { 2789673Slinton enter_nl(name, np); 2799673Slinton } else if (name[0] == '-') { 2809673Slinton afterlg = true; 28118225Slinton foundglobals(); 28211104Slinton } else if (afterlg) { 28318225Slinton check_global(name, np); 28418225Slinton } else if ((np->n_type&N_EXT) == N_EXT) { 28518225Slinton afterlg = true; 28618225Slinton foundglobals(); 28718225Slinton check_global(name, np); 28811104Slinton } else if (name[0] == '_') { 28911104Slinton check_local(&name[1], np); 2909673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 2919673Slinton check_filename(name); 2929673Slinton } 29316613Ssam ++curnp; 29416613Ssam np = curnp; 2959673Slinton } 2969673Slinton dispose(namelist); 2979673Slinton } 2989673Slinton 2999673Slinton /* 30016613Ssam * Get a continuation entry from the name list. 30116613Ssam * Return the beginning of the name. 30216613Ssam */ 30316613Ssam 30416613Ssam public String getcont () 30516613Ssam { 30616613Ssam register integer index; 30716613Ssam register String name; 30816613Ssam 30916613Ssam ++curnp; 31016613Ssam index = curnp->n_un.n_strx; 31116613Ssam if (index == 0) { 31216613Ssam panic("continuation followed by empty stab"); 31316613Ssam } 31416613Ssam name = &stringtab[index - 4]; 31516613Ssam return name; 31616613Ssam } 31716613Ssam 31816613Ssam /* 3199673Slinton * Initialize symbol information. 3209673Slinton */ 3219673Slinton 32216613Ssam private initsyms () 3239673Slinton { 3249673Slinton curblock = nil; 3259673Slinton curlevel = 0; 32614443Slinton nesting = 0; 32716613Ssam program = insert(identname("", true)); 3289673Slinton program->class = PROG; 32911769Slinton program->symvalue.funcv.beginaddr = 0; 33014443Slinton program->symvalue.funcv.inline = false; 33114443Slinton newfunc(program, codeloc(program)); 33211769Slinton findbeginning(program); 3339673Slinton enterblock(program); 3349673Slinton curmodule = program; 3359673Slinton } 3369673Slinton 3379673Slinton /* 3389673Slinton * Free all the object file information that's being stored. 3399673Slinton */ 3409673Slinton 34116613Ssam public objfree () 3429673Slinton { 3439673Slinton symbol_free(); 34418225Slinton /* keywords_free(); */ 34518225Slinton /* names_free(); */ 34618225Slinton /* dispose(stringtab); */ 3479673Slinton clrfunctab(); 3489673Slinton } 3499673Slinton 3509673Slinton /* 3519673Slinton * Enter a namelist entry. 3529673Slinton */ 3539673Slinton 35416613Ssam private enter_nl (name, np) 3559673Slinton String name; 3569673Slinton register struct nlist *np; 3579673Slinton { 3589673Slinton register Symbol s; 35916613Ssam register Name n; 3609673Slinton 3619673Slinton s = nil; 3629673Slinton switch (np->n_type) { 36314443Slinton /* 36414443Slinton * Build a symbol for the FORTRAN common area. All GSYMS that follow 36514443Slinton * will be chained in a list with the head kept in common.offset, and 36614443Slinton * the tail in common.chain. 36714443Slinton */ 36813938Slinton case N_BCOMM: 36913938Slinton if (curcomm) { 37013938Slinton curcomm->symvalue.common.chain = commchain; 37112542Scsvaf } 37216613Ssam n = identname(name, true); 37312542Scsvaf curcomm = lookup(n); 37413938Slinton if (curcomm == nil) { 37513938Slinton curcomm = insert(n); 37613938Slinton curcomm->class = COMMON; 37713938Slinton curcomm->block = curblock; 37813938Slinton curcomm->level = program->level; 37913938Slinton curcomm->symvalue.common.chain = nil; 38012542Scsvaf } 38112542Scsvaf commchain = curcomm->symvalue.common.chain; 38213938Slinton break; 38312542Scsvaf 38412542Scsvaf case N_ECOMM: 38513938Slinton if (curcomm) { 38613938Slinton curcomm->symvalue.common.chain = commchain; 38713938Slinton curcomm = nil; 38812542Scsvaf } 38912542Scsvaf break; 39014443Slinton 3919673Slinton case N_LBRAC: 39214443Slinton ++nesting; 39314443Slinton addrstk[nesting] = (linep - 1)->addr; 3949673Slinton break; 3959673Slinton 3969673Slinton case N_RBRAC: 39716613Ssam --nesting; 39814443Slinton if (addrstk[nesting] == NOADDR) { 39914443Slinton exitblock(); 40014443Slinton newfunc(curblock, (linep - 1)->addr); 40116613Ssam addrstk[nesting] = (linep - 1)->addr; 40214443Slinton } 4039673Slinton break; 4049673Slinton 4059673Slinton case N_SLINE: 4069673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 4079673Slinton break; 4089673Slinton 4099673Slinton /* 41014443Slinton * Source files. 4119673Slinton */ 4129673Slinton case N_SO: 41316613Ssam n = identname(name, true); 41414443Slinton enterSourceModule(n, (Address) np->n_value); 4159673Slinton break; 4169673Slinton 4179673Slinton /* 4189673Slinton * Textually included files. 4199673Slinton */ 4209673Slinton case N_SOL: 4219673Slinton enterfile(name, (Address) np->n_value); 4229673Slinton break; 4239673Slinton 4249673Slinton /* 4259673Slinton * These symbols are assumed to have non-nil names. 4269673Slinton */ 4279673Slinton case N_GSYM: 4289673Slinton case N_FUN: 4299673Slinton case N_STSYM: 4309673Slinton case N_LCSYM: 4319673Slinton case N_RSYM: 4329673Slinton case N_PSYM: 4339673Slinton case N_LSYM: 4349673Slinton case N_SSYM: 43514443Slinton case N_LENG: 4369673Slinton if (index(name, ':') == nil) { 4379673Slinton if (not warned) { 4389673Slinton warned = true; 4399673Slinton warning("old style symbol information found in \"%s\"", 4409673Slinton curfilename()); 4419673Slinton } 4429673Slinton } else { 4439673Slinton entersym(name, np); 4449673Slinton } 4459673Slinton break; 4469673Slinton 4479673Slinton case N_PC: 44816613Ssam case N_MOD2: 4499673Slinton break; 4509673Slinton 45111558Slinton default: 45214443Slinton printf("warning: stab entry unrecognized: "); 4539673Slinton if (name != nil) { 45414443Slinton printf("name %s,", name); 4559673Slinton } 45614443Slinton printf("ntype %2x, desc %x, value %x'\n", 4579673Slinton np->n_type, np->n_desc, np->n_value); 4589673Slinton break; 4599673Slinton } 4609673Slinton } 4619673Slinton 4629673Slinton /* 46318225Slinton * Try to find the symbol that is referred to by the given name. Since it's 46418225Slinton * an external, we need to follow a level or two of indirection. 46516613Ssam */ 46616613Ssam 46718225Slinton private Symbol findsym (n, var_isextref) 46816613Ssam Name n; 46918225Slinton boolean *var_isextref; 47016613Ssam { 47116613Ssam register Symbol r, s; 47216613Ssam 47318225Slinton *var_isextref = false; 47416613Ssam find(s, n) where 47518225Slinton ( 47618225Slinton s->level == program->level and ( 47718225Slinton s->class == EXTREF or s->class == VAR or 47818225Slinton s->class == PROC or s->class == FUNC 47918225Slinton ) 48018225Slinton ) or ( 48118225Slinton s->block == program and s->class == MODULE 48218225Slinton ) 48316613Ssam endfind(s); 48418225Slinton if (s == nil) { 48518225Slinton r = nil; 48618225Slinton } else if (s->class == EXTREF) { 48718225Slinton *var_isextref = true; 48816613Ssam r = s->symvalue.extref; 48916613Ssam delete(s); 49018225Slinton 49118225Slinton /* 49218225Slinton * Now check for another level of indirection that could come from 49318225Slinton * a forward reference in procedure nesting information. In this case 49418225Slinton * the symbol has already been deleted. 49518225Slinton */ 49618225Slinton if (r != nil and r->class == EXTREF) { 49718225Slinton r = r->symvalue.extref; 49818225Slinton } 49918225Slinton /* 50018225Slinton } else if (s->class == MODULE) { 50118225Slinton s->class = FUNC; 50218225Slinton s->level = program->level; 50318225Slinton r = s; 50418225Slinton */ 50516613Ssam } else { 50616613Ssam r = s; 50716613Ssam } 50816613Ssam return r; 50916613Ssam } 51016613Ssam 51116613Ssam /* 51218225Slinton * Create a symbol for a text symbol with no source information. 51318225Slinton * We treat it as an assembly language function. 51418225Slinton */ 51518225Slinton 51618225Slinton private Symbol deffunc (n) 51718225Slinton Name n; 51818225Slinton { 51918225Slinton Symbol f; 52018225Slinton 52118225Slinton f = insert(n); 52218225Slinton f->language = findlanguage(".s"); 52318225Slinton f->class = FUNC; 52418225Slinton f->type = t_int; 52518225Slinton f->block = curblock; 52618225Slinton f->level = program->level; 52718225Slinton f->symvalue.funcv.src = false; 52818225Slinton f->symvalue.funcv.inline = false; 52918225Slinton return f; 53018225Slinton } 53118225Slinton 53218225Slinton /* 53318225Slinton * Create a symbol for a data or bss symbol with no source information. 53418225Slinton * We treat it as an assembly language variable. 53518225Slinton */ 53618225Slinton 53718225Slinton private Symbol defvar (n) 53818225Slinton Name n; 53918225Slinton { 54018225Slinton Symbol v; 54118225Slinton 54218225Slinton v = insert(n); 54318225Slinton v->language = findlanguage(".s"); 54418225Slinton v->class = VAR; 54518225Slinton v->type = t_int; 54618225Slinton v->level = program->level; 54718225Slinton v->block = curblock; 54818225Slinton return v; 54918225Slinton } 55018225Slinton 55118225Slinton /* 55218225Slinton * Update a symbol entry with a text address. 55318225Slinton */ 55418225Slinton 55518225Slinton private updateTextSym (s, name, addr) 55618225Slinton Symbol s; 55718225Slinton char *name; 55818225Slinton Address addr; 55918225Slinton { 56018225Slinton if (s->class == VAR) { 56118225Slinton s->symvalue.offset = addr; 56218225Slinton } else { 56318225Slinton s->symvalue.funcv.beginaddr = addr; 56418225Slinton if (name[0] == '_') { 56518225Slinton newfunc(s, codeloc(s)); 56618225Slinton findbeginning(s); 56718225Slinton } 56818225Slinton } 56918225Slinton } 57018225Slinton 57118225Slinton /* 5729673Slinton * Check to see if a global _name is already in the symbol table, 5739673Slinton * if not then insert it. 5749673Slinton */ 5759673Slinton 57616613Ssam private check_global (name, np) 5779673Slinton String name; 5789673Slinton register struct nlist *np; 5799673Slinton { 5809673Slinton register Name n; 58112542Scsvaf register Symbol t, u; 58218225Slinton char buf[4096]; 58318225Slinton boolean isextref; 58418225Slinton integer count; 5859673Slinton 58618225Slinton if (not streq(name, "_end")) { 58718225Slinton if (name[0] == '_') { 58818225Slinton n = identname(&name[1], true); 58918225Slinton } else { 59018225Slinton n = identname(name, true); 59118225Slinton if (lookup(n) != nil) { 59218225Slinton sprintf(buf, "$%s", name); 59318225Slinton n = identname(buf, false); 59418225Slinton } 59518225Slinton } 5969673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 59718225Slinton count = 0; 59818225Slinton t = findsym(n, &isextref); 59918225Slinton while (isextref) { 60018225Slinton ++count; 60118225Slinton updateTextSym(t, name, np->n_value); 60218225Slinton t = findsym(n, &isextref); 6039673Slinton } 60418225Slinton if (count == 0) { 60518225Slinton if (t == nil) { 60618225Slinton t = deffunc(n); 60718225Slinton updateTextSym(t, name, np->n_value); 60818225Slinton if (tracesyms) { 60918225Slinton printdecl(t); 61018225Slinton } 61118225Slinton } else { 61218225Slinton if (t->class == MODULE) { 61318225Slinton u = t; 61418225Slinton t = deffunc(n); 61518225Slinton t->block = u; 61618225Slinton if (tracesyms) { 61718225Slinton printdecl(t); 61818225Slinton } 61918225Slinton } 62018225Slinton updateTextSym(t, name, np->n_value); 62118225Slinton } 62216613Ssam } 62313938Slinton } else if ((np->n_type&N_TYPE) == N_BSS) { 6249673Slinton find(t, n) where 62513938Slinton t->class == COMMON 62612542Scsvaf endfind(t); 62713938Slinton if (t != nil) { 62813938Slinton u = (Symbol) t->symvalue.common.offset; 62913938Slinton while (u != nil) { 63013938Slinton u->symvalue.offset = u->symvalue.common.offset+np->n_value; 63113938Slinton u = u->symvalue.common.chain; 63213938Slinton } 63313938Slinton } else { 63413938Slinton check_var(np, n); 6359673Slinton } 63613938Slinton } else { 63713938Slinton check_var(np, n); 6389673Slinton } 6399673Slinton } 6409673Slinton } 6419673Slinton 6429673Slinton /* 64313938Slinton * Check to see if a namelist entry refers to a variable. 64413938Slinton * If not, create a variable for the entry. In any case, 64513938Slinton * set the offset of the variable according to the value field 64613938Slinton * in the entry. 64718225Slinton * 64818225Slinton * If the external name has been referred to by several other symbols, 64918225Slinton * we must update each of them. 65013938Slinton */ 65113938Slinton 65216613Ssam private check_var (np, n) 65313938Slinton struct nlist *np; 65413938Slinton register Name n; 65513938Slinton { 65618225Slinton register Symbol t, u, next; 65718225Slinton Symbol conflict; 65813938Slinton 65918225Slinton t = lookup(n); 66013938Slinton if (t == nil) { 66118225Slinton t = defvar(n); 66218225Slinton t->symvalue.offset = np->n_value; 66318225Slinton if (tracesyms) { 66418225Slinton printdecl(t); 66518225Slinton } 66618225Slinton } else { 66718225Slinton conflict = nil; 66818225Slinton do { 66918225Slinton next = t->next_sym; 67018225Slinton if (t->name == n) { 67118225Slinton if (t->class == MODULE and t->block == program) { 67218225Slinton conflict = t; 67318225Slinton } else if (t->class == EXTREF and t->level == program->level) { 67418225Slinton u = t->symvalue.extref; 67518225Slinton while (u != nil and u->class == EXTREF) { 67618225Slinton u = u->symvalue.extref; 67718225Slinton } 67818225Slinton u->symvalue.offset = np->n_value; 67918225Slinton delete(t); 68018225Slinton } else if (t->level == program->level and 68118225Slinton (t->class == VAR or t->class == PROC or t->class == FUNC) 68218225Slinton ) { 68318225Slinton conflict = nil; 68418225Slinton t->symvalue.offset = np->n_value; 68518225Slinton } 68618225Slinton } 68718225Slinton t = next; 68818225Slinton } while (t != nil); 68918225Slinton if (conflict != nil) { 69018225Slinton u = defvar(n); 69118225Slinton u->block = conflict; 69218225Slinton u->symvalue.offset = np->n_value; 69318225Slinton } 69413938Slinton } 69513938Slinton } 69613938Slinton 69713938Slinton /* 6989673Slinton * Check to see if a local _name is known in the current scope. 6999673Slinton * If not then enter it. 7009673Slinton */ 7019673Slinton 70216613Ssam private check_local (name, np) 7039673Slinton String name; 7049673Slinton register struct nlist *np; 7059673Slinton { 7069673Slinton register Name n; 7079673Slinton register Symbol t, cur; 7089673Slinton 7099673Slinton n = identname(name, true); 7109673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 7119673Slinton find(t, n) where t->block == cur endfind(t); 7129673Slinton if (t == nil) { 7139673Slinton t = insert(n); 7149673Slinton t->language = findlanguage(".s"); 7159673Slinton t->type = t_int; 7169673Slinton t->block = cur; 7179673Slinton t->level = cur->level; 7189673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 7199673Slinton t->class = FUNC; 72011875Slinton t->symvalue.funcv.src = false; 72114443Slinton t->symvalue.funcv.inline = false; 7229673Slinton t->symvalue.funcv.beginaddr = np->n_value; 72314443Slinton newfunc(t, codeloc(t)); 7249673Slinton findbeginning(t); 7259673Slinton } else { 7269673Slinton t->class = VAR; 7279673Slinton t->symvalue.offset = np->n_value; 7289673Slinton } 7299673Slinton } 7309673Slinton } 7319673Slinton 7329673Slinton /* 7339673Slinton * Check to see if a symbol corresponds to a object file name. 7349673Slinton * For some reason these are listed as in the text segment. 7359673Slinton */ 7369673Slinton 73716613Ssam private check_filename (name) 7389673Slinton String name; 7399673Slinton { 7409673Slinton register String mname; 74116613Ssam register integer i; 74218225Slinton Name n; 74318225Slinton Symbol s; 7449673Slinton 7459673Slinton mname = strdup(name); 7469673Slinton i = strlen(mname) - 2; 7479673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 7489673Slinton mname[i] = '\0'; 7499673Slinton --i; 7509673Slinton while (mname[i] != '/' and i >= 0) { 7519673Slinton --i; 7529673Slinton } 75318225Slinton n = identname(&mname[i+1], true); 75418225Slinton find(s, n) where s->block == program and s->class == MODULE endfind(s); 75518225Slinton if (s == nil) { 75618225Slinton s = insert(n); 75718225Slinton s->language = findlanguage(".s"); 75818225Slinton s->class = MODULE; 75918225Slinton s->symvalue.funcv.beginaddr = 0; 76018225Slinton findbeginning(s); 76118225Slinton } 7629673Slinton if (curblock->class != PROG) { 7639673Slinton exitblock(); 7649673Slinton if (curblock->class != PROG) { 7659673Slinton exitblock(); 7669673Slinton } 7679673Slinton } 7689673Slinton enterblock(s); 7699673Slinton curmodule = s; 7709673Slinton } 7719673Slinton } 7729673Slinton 7739673Slinton /* 77414443Slinton * Check to see if a symbol is about to be defined within an unnamed block. 77514443Slinton * If this happens, we create a procedure for the unnamed block, make it 77614443Slinton * "inline" so that tracebacks don't associate an activation record with it, 77714443Slinton * and enter it into the function table so that it will be detected 77814443Slinton * by "whatblock". 77914443Slinton */ 78014443Slinton 78116613Ssam public chkUnnamedBlock () 78214443Slinton { 78314443Slinton register Symbol s; 78414443Slinton static int bnum = 0; 78514443Slinton char buf[100]; 78616613Ssam Address startaddr; 78714443Slinton 78816613Ssam if (nesting > 0 and addrstk[nesting] != NOADDR) { 78916613Ssam startaddr = (linep - 1)->addr; 79016613Ssam ++bnum; 79116613Ssam sprintf(buf, "$b%d", bnum); 79216613Ssam s = insert(identname(buf, false)); 79316613Ssam s->language = curlang; 79416613Ssam s->class = PROC; 79516613Ssam s->symvalue.funcv.src = false; 79616613Ssam s->symvalue.funcv.inline = true; 79716613Ssam s->symvalue.funcv.beginaddr = startaddr; 79816613Ssam enterblock(s); 79916613Ssam newfunc(s, startaddr); 80016613Ssam addrstk[nesting] = NOADDR; 80116613Ssam } 80214443Slinton } 80314443Slinton 80414443Slinton /* 80514443Slinton * Compilation unit. C associates scope with filenames 80614443Slinton * so we treat them as "modules". The filename without 80714443Slinton * the suffix is used for the module name. 80814443Slinton * 80914443Slinton * Because there is no explicit "end-of-block" mark in 81014443Slinton * the object file, we must exit blocks for the current 81114443Slinton * procedure and module. 81214443Slinton */ 81314443Slinton 81416613Ssam private enterSourceModule (n, addr) 81514443Slinton Name n; 81614443Slinton Address addr; 81714443Slinton { 81814443Slinton register Symbol s; 81914443Slinton Name nn; 82014443Slinton String mname, suffix; 82114443Slinton 82214443Slinton mname = strdup(ident(n)); 82314443Slinton if (rindex(mname, '/') != nil) { 82414443Slinton mname = rindex(mname, '/') + 1; 82514443Slinton } 82614443Slinton suffix = rindex(mname, '.'); 82714443Slinton curlang = findlanguage(suffix); 82814443Slinton if (curlang == findlanguage(".f")) { 82914443Slinton strip_ = true; 83014443Slinton } 83114443Slinton if (suffix != nil) { 83214443Slinton *suffix = '\0'; 83314443Slinton } 83416613Ssam if (not (*language_op(curlang, L_HASMODULES))()) { 83514443Slinton if (curblock->class != PROG) { 83614443Slinton exitblock(); 83716613Ssam if (curblock->class != PROG) { 83816613Ssam exitblock(); 83916613Ssam } 84014443Slinton } 84116613Ssam nn = identname(mname, true); 84216613Ssam if (curmodule == nil or curmodule->name != nn) { 84316613Ssam s = insert(nn); 84416613Ssam s->class = MODULE; 84516613Ssam s->symvalue.funcv.beginaddr = 0; 84616613Ssam findbeginning(s); 84716613Ssam } else { 84816613Ssam s = curmodule; 84916613Ssam } 85016613Ssam s->language = curlang; 85116613Ssam enterblock(s); 85216613Ssam curmodule = s; 85314443Slinton } 85414443Slinton if (program->language == nil) { 85514443Slinton program->language = curlang; 85614443Slinton } 85714443Slinton warned = false; 85814443Slinton enterfile(ident(n), addr); 85916613Ssam initTypeTable(); 86014443Slinton } 86114443Slinton 86214443Slinton /* 8639673Slinton * Allocate file and line tables and initialize indices. 8649673Slinton */ 8659673Slinton 86616613Ssam private allocmaps (nf, nl) 86716613Ssam integer nf, nl; 8689673Slinton { 8699673Slinton if (filetab != nil) { 8709673Slinton dispose(filetab); 8719673Slinton } 8729673Slinton if (linetab != nil) { 8739673Slinton dispose(linetab); 8749673Slinton } 8759673Slinton filetab = newarr(Filetab, nf); 8769673Slinton linetab = newarr(Linetab, nl); 8779673Slinton filep = filetab; 8789673Slinton linep = linetab; 8799673Slinton } 8809673Slinton 8819673Slinton /* 8829673Slinton * Add a file to the file table. 88313938Slinton * 88413938Slinton * If the new address is the same as the previous file address 88513938Slinton * this routine used to not enter the file, but this caused some 88613938Slinton * problems so it has been removed. It's not clear that this in 88713938Slinton * turn may not also cause a problem. 8889673Slinton */ 8899673Slinton 89016613Ssam private enterfile (filename, addr) 8919673Slinton String filename; 8929673Slinton Address addr; 8939673Slinton { 89413938Slinton filep->addr = addr; 89513938Slinton filep->filename = filename; 89613938Slinton filep->lineindex = linep - linetab; 89713938Slinton ++filep; 8989673Slinton } 8999673Slinton 9009673Slinton /* 9019673Slinton * Since we only estimated the number of lines (and it was a poor 9029673Slinton * estimation) and since we need to know the exact number of lines 9039673Slinton * to do a binary search, we set it when we're done. 9049673Slinton */ 9059673Slinton 90616613Ssam private setnlines () 9079673Slinton { 9089673Slinton nlhdr.nlines = linep - linetab; 9099673Slinton } 9109673Slinton 9119673Slinton /* 9129673Slinton * Similarly for nfiles ... 9139673Slinton */ 9149673Slinton 91516613Ssam private setnfiles () 9169673Slinton { 9179673Slinton nlhdr.nfiles = filep - filetab; 9189673Slinton setsource(filetab[0].filename); 9199673Slinton } 920