121615Sdist /* 221615Sdist * Copyright (c) 1983 Regents of the University of California. 321615Sdist * All rights reserved. The Berkeley software License Agreement 421615Sdist * specifies the terms and conditions for redistribution. 521615Sdist */ 69673Slinton 721615Sdist #ifndef lint 8*33328Sdonn static char sccsid[] = "@(#)object.c 5.2 (Berkeley) 01/12/88"; 921615Sdist #endif not lint 109673Slinton 11*33328Sdonn static char rcsid[] = "$Header: object.c,v 1.5 87/03/26 20:24:58 donn 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; 237*33328Sdonn boolean afterlg, foundstab; 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; 245*33328Sdonn foundstab = false; 2469673Slinton ub = &namelist[nlhdr.nsyms]; 24716613Ssam curnp = &namelist[0]; 24816613Ssam np = curnp; 24916613Ssam while (np < ub) { 2509673Slinton index = np->n_un.n_strx; 2519673Slinton if (index != 0) { 2529673Slinton name = &stringtab[index - 4]; 25312542Scsvaf /* 25416613Ssam * If the program contains any .f files a trailing _ is stripped 25512542Scsvaf * from the name on the assumption it was added by the compiler. 25612542Scsvaf * This only affects names that follow the sdb N_SO entry with 25712542Scsvaf * the .f name. 25812542Scsvaf */ 25914443Slinton if (strip_ and name[0] != '\0' ) { 26016613Ssam lastchar = &name[strlen(name) - 1]; 26116613Ssam if (*lastchar == '_') { 26216613Ssam *lastchar = '\0'; 26314443Slinton } 26412542Scsvaf } 2659673Slinton } else { 2669673Slinton name = nil; 26712542Scsvaf } 26816613Ssam 2699673Slinton /* 27016613Ssam * Assumptions: 2719673Slinton * not an N_STAB ==> name != nil 2729673Slinton * name[0] == '-' ==> name == "-lg" 2739673Slinton * name[0] != '_' ==> filename or invisible 2749673Slinton * 2759673Slinton * The "-lg" signals the beginning of global loader symbols. 27612542Scsvaf * 2779673Slinton */ 2789673Slinton if ((np->n_type&N_STAB) != 0) { 279*33328Sdonn foundstab = true; 2809673Slinton enter_nl(name, np); 2819673Slinton } else if (name[0] == '-') { 2829673Slinton afterlg = true; 28318225Slinton foundglobals(); 28411104Slinton } else if (afterlg) { 28518225Slinton check_global(name, np); 28618225Slinton } else if ((np->n_type&N_EXT) == N_EXT) { 28718225Slinton afterlg = true; 28818225Slinton foundglobals(); 28918225Slinton check_global(name, np); 29011104Slinton } else if (name[0] == '_') { 29111104Slinton check_local(&name[1], np); 2929673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 2939673Slinton check_filename(name); 2949673Slinton } 29516613Ssam ++curnp; 29616613Ssam np = curnp; 2979673Slinton } 298*33328Sdonn if (not foundstab) { 299*33328Sdonn warning("no source compiled with -g"); 300*33328Sdonn } 3019673Slinton dispose(namelist); 3029673Slinton } 3039673Slinton 3049673Slinton /* 30516613Ssam * Get a continuation entry from the name list. 30616613Ssam * Return the beginning of the name. 30716613Ssam */ 30816613Ssam 30916613Ssam public String getcont () 31016613Ssam { 31116613Ssam register integer index; 31216613Ssam register String name; 31316613Ssam 31416613Ssam ++curnp; 31516613Ssam index = curnp->n_un.n_strx; 31616613Ssam if (index == 0) { 317*33328Sdonn name = ""; 318*33328Sdonn } else { 319*33328Sdonn name = &stringtab[index - 4]; 32016613Ssam } 32116613Ssam return name; 32216613Ssam } 32316613Ssam 32416613Ssam /* 3259673Slinton * Initialize symbol information. 3269673Slinton */ 3279673Slinton 32816613Ssam private initsyms () 3299673Slinton { 3309673Slinton curblock = nil; 3319673Slinton curlevel = 0; 33214443Slinton nesting = 0; 33316613Ssam program = insert(identname("", true)); 3349673Slinton program->class = PROG; 335*33328Sdonn program->language = primlang; 336*33328Sdonn program->symvalue.funcv.beginaddr = CODESTART; 33714443Slinton program->symvalue.funcv.inline = false; 33814443Slinton newfunc(program, codeloc(program)); 33911769Slinton findbeginning(program); 3409673Slinton enterblock(program); 3419673Slinton curmodule = program; 3429673Slinton } 3439673Slinton 3449673Slinton /* 3459673Slinton * Free all the object file information that's being stored. 3469673Slinton */ 3479673Slinton 34816613Ssam public objfree () 3499673Slinton { 3509673Slinton symbol_free(); 35118225Slinton /* keywords_free(); */ 35218225Slinton /* names_free(); */ 35318225Slinton /* dispose(stringtab); */ 3549673Slinton clrfunctab(); 3559673Slinton } 3569673Slinton 3579673Slinton /* 3589673Slinton * Enter a namelist entry. 3599673Slinton */ 3609673Slinton 36116613Ssam private enter_nl (name, np) 3629673Slinton String name; 3639673Slinton register struct nlist *np; 3649673Slinton { 3659673Slinton register Symbol s; 36616613Ssam register Name n; 3679673Slinton 3689673Slinton s = nil; 3699673Slinton switch (np->n_type) { 37014443Slinton /* 37114443Slinton * Build a symbol for the FORTRAN common area. All GSYMS that follow 37214443Slinton * will be chained in a list with the head kept in common.offset, and 37314443Slinton * the tail in common.chain. 37414443Slinton */ 37513938Slinton case N_BCOMM: 37613938Slinton if (curcomm) { 37713938Slinton curcomm->symvalue.common.chain = commchain; 37812542Scsvaf } 37916613Ssam n = identname(name, true); 38012542Scsvaf curcomm = lookup(n); 38113938Slinton if (curcomm == nil) { 38213938Slinton curcomm = insert(n); 38313938Slinton curcomm->class = COMMON; 38413938Slinton curcomm->block = curblock; 38513938Slinton curcomm->level = program->level; 38613938Slinton curcomm->symvalue.common.chain = nil; 38712542Scsvaf } 38812542Scsvaf commchain = curcomm->symvalue.common.chain; 38913938Slinton break; 39012542Scsvaf 39112542Scsvaf case N_ECOMM: 39213938Slinton if (curcomm) { 39313938Slinton curcomm->symvalue.common.chain = commchain; 39413938Slinton curcomm = nil; 39512542Scsvaf } 39612542Scsvaf break; 39714443Slinton 3989673Slinton case N_LBRAC: 39914443Slinton ++nesting; 40014443Slinton addrstk[nesting] = (linep - 1)->addr; 4019673Slinton break; 4029673Slinton 4039673Slinton case N_RBRAC: 40416613Ssam --nesting; 40514443Slinton if (addrstk[nesting] == NOADDR) { 40614443Slinton exitblock(); 40714443Slinton newfunc(curblock, (linep - 1)->addr); 40816613Ssam addrstk[nesting] = (linep - 1)->addr; 40914443Slinton } 4109673Slinton break; 4119673Slinton 4129673Slinton case N_SLINE: 4139673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 4149673Slinton break; 4159673Slinton 4169673Slinton /* 41714443Slinton * Source files. 4189673Slinton */ 4199673Slinton case N_SO: 42016613Ssam n = identname(name, true); 42114443Slinton enterSourceModule(n, (Address) np->n_value); 4229673Slinton break; 4239673Slinton 4249673Slinton /* 4259673Slinton * Textually included files. 4269673Slinton */ 4279673Slinton case N_SOL: 4289673Slinton enterfile(name, (Address) np->n_value); 4299673Slinton break; 4309673Slinton 4319673Slinton /* 4329673Slinton * These symbols are assumed to have non-nil names. 4339673Slinton */ 4349673Slinton case N_GSYM: 4359673Slinton case N_FUN: 4369673Slinton case N_STSYM: 4379673Slinton case N_LCSYM: 4389673Slinton case N_RSYM: 4399673Slinton case N_PSYM: 4409673Slinton case N_LSYM: 4419673Slinton case N_SSYM: 44214443Slinton case N_LENG: 4439673Slinton if (index(name, ':') == nil) { 4449673Slinton if (not warned) { 4459673Slinton warned = true; 446*33328Sdonn printf("warning: old style symbol information "); 447*33328Sdonn printf("found in \"%s\"\n", curfilename()); 4489673Slinton } 4499673Slinton } else { 4509673Slinton entersym(name, np); 4519673Slinton } 4529673Slinton break; 4539673Slinton 4549673Slinton case N_PC: 45516613Ssam case N_MOD2: 4569673Slinton break; 4579673Slinton 45811558Slinton default: 45914443Slinton printf("warning: stab entry unrecognized: "); 4609673Slinton if (name != nil) { 46114443Slinton printf("name %s,", name); 4629673Slinton } 46314443Slinton printf("ntype %2x, desc %x, value %x'\n", 4649673Slinton np->n_type, np->n_desc, np->n_value); 4659673Slinton break; 4669673Slinton } 4679673Slinton } 4689673Slinton 4699673Slinton /* 47018225Slinton * Try to find the symbol that is referred to by the given name. Since it's 47118225Slinton * an external, we need to follow a level or two of indirection. 47216613Ssam */ 47316613Ssam 47418225Slinton private Symbol findsym (n, var_isextref) 47516613Ssam Name n; 47618225Slinton boolean *var_isextref; 47716613Ssam { 47816613Ssam register Symbol r, s; 47916613Ssam 48018225Slinton *var_isextref = false; 48116613Ssam find(s, n) where 48218225Slinton ( 48318225Slinton s->level == program->level and ( 48418225Slinton s->class == EXTREF or s->class == VAR or 48518225Slinton s->class == PROC or s->class == FUNC 48618225Slinton ) 48718225Slinton ) or ( 48818225Slinton s->block == program and s->class == MODULE 48918225Slinton ) 49016613Ssam endfind(s); 49118225Slinton if (s == nil) { 49218225Slinton r = nil; 49318225Slinton } else if (s->class == EXTREF) { 49418225Slinton *var_isextref = true; 49516613Ssam r = s->symvalue.extref; 49616613Ssam delete(s); 49718225Slinton 49818225Slinton /* 49918225Slinton * Now check for another level of indirection that could come from 50018225Slinton * a forward reference in procedure nesting information. In this case 50118225Slinton * the symbol has already been deleted. 50218225Slinton */ 50318225Slinton if (r != nil and r->class == EXTREF) { 50418225Slinton r = r->symvalue.extref; 50518225Slinton } 50618225Slinton /* 50718225Slinton } else if (s->class == MODULE) { 50818225Slinton s->class = FUNC; 50918225Slinton s->level = program->level; 51018225Slinton r = s; 51118225Slinton */ 51216613Ssam } else { 51316613Ssam r = s; 51416613Ssam } 51516613Ssam return r; 51616613Ssam } 51716613Ssam 51816613Ssam /* 51918225Slinton * Create a symbol for a text symbol with no source information. 52018225Slinton * We treat it as an assembly language function. 52118225Slinton */ 52218225Slinton 52318225Slinton private Symbol deffunc (n) 52418225Slinton Name n; 52518225Slinton { 52618225Slinton Symbol f; 52718225Slinton 52818225Slinton f = insert(n); 52918225Slinton f->language = findlanguage(".s"); 53018225Slinton f->class = FUNC; 53118225Slinton f->type = t_int; 53218225Slinton f->block = curblock; 53318225Slinton f->level = program->level; 53418225Slinton f->symvalue.funcv.src = false; 53518225Slinton f->symvalue.funcv.inline = false; 536*33328Sdonn if (f->chain != nil) { 537*33328Sdonn panic("chain not nil in deffunc"); 538*33328Sdonn } 53918225Slinton return f; 54018225Slinton } 54118225Slinton 54218225Slinton /* 54318225Slinton * Create a symbol for a data or bss symbol with no source information. 54418225Slinton * We treat it as an assembly language variable. 54518225Slinton */ 54618225Slinton 54718225Slinton private Symbol defvar (n) 54818225Slinton Name n; 54918225Slinton { 55018225Slinton Symbol v; 55118225Slinton 55218225Slinton v = insert(n); 55318225Slinton v->language = findlanguage(".s"); 554*33328Sdonn v->storage = EXT; 55518225Slinton v->class = VAR; 55618225Slinton v->type = t_int; 55718225Slinton v->level = program->level; 55818225Slinton v->block = curblock; 55918225Slinton return v; 56018225Slinton } 56118225Slinton 56218225Slinton /* 56318225Slinton * Update a symbol entry with a text address. 56418225Slinton */ 56518225Slinton 56618225Slinton private updateTextSym (s, name, addr) 56718225Slinton Symbol s; 56818225Slinton char *name; 56918225Slinton Address addr; 57018225Slinton { 57118225Slinton if (s->class == VAR) { 57218225Slinton s->symvalue.offset = addr; 57318225Slinton } else { 57418225Slinton s->symvalue.funcv.beginaddr = addr; 57518225Slinton if (name[0] == '_') { 57618225Slinton newfunc(s, codeloc(s)); 57718225Slinton findbeginning(s); 57818225Slinton } 57918225Slinton } 58018225Slinton } 58118225Slinton 58218225Slinton /* 583*33328Sdonn * Avoid seeing Pascal labels as text symbols. 584*33328Sdonn */ 585*33328Sdonn 586*33328Sdonn private boolean PascalLabel (n) 587*33328Sdonn Name n; 588*33328Sdonn { 589*33328Sdonn boolean b; 590*33328Sdonn register char *p; 591*33328Sdonn 592*33328Sdonn b = false; 593*33328Sdonn if (curlang == findlanguage(".p")) { 594*33328Sdonn p = ident(n); 595*33328Sdonn while (*p != '\0') { 596*33328Sdonn if (*p == '_' and *(p+1) == '$') { 597*33328Sdonn b = true; 598*33328Sdonn break; 599*33328Sdonn } 600*33328Sdonn ++p; 601*33328Sdonn } 602*33328Sdonn } 603*33328Sdonn return b; 604*33328Sdonn } 605*33328Sdonn 606*33328Sdonn /* 6079673Slinton * Check to see if a global _name is already in the symbol table, 6089673Slinton * if not then insert it. 6099673Slinton */ 6109673Slinton 61116613Ssam private check_global (name, np) 6129673Slinton String name; 6139673Slinton register struct nlist *np; 6149673Slinton { 6159673Slinton register Name n; 61612542Scsvaf register Symbol t, u; 61718225Slinton char buf[4096]; 61818225Slinton boolean isextref; 61918225Slinton integer count; 6209673Slinton 62118225Slinton if (not streq(name, "_end")) { 62218225Slinton if (name[0] == '_') { 62318225Slinton n = identname(&name[1], true); 62418225Slinton } else { 62518225Slinton n = identname(name, true); 62618225Slinton if (lookup(n) != nil) { 62718225Slinton sprintf(buf, "$%s", name); 62818225Slinton n = identname(buf, false); 62918225Slinton } 63018225Slinton } 6319673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 63218225Slinton count = 0; 63318225Slinton t = findsym(n, &isextref); 63418225Slinton while (isextref) { 63518225Slinton ++count; 63618225Slinton updateTextSym(t, name, np->n_value); 63718225Slinton t = findsym(n, &isextref); 6389673Slinton } 63918225Slinton if (count == 0) { 64018225Slinton if (t == nil) { 641*33328Sdonn if (not PascalLabel(n)) { 642*33328Sdonn t = deffunc(n); 643*33328Sdonn updateTextSym(t, name, np->n_value); 644*33328Sdonn if (tracesyms) { 645*33328Sdonn printdecl(t); 646*33328Sdonn } 64718225Slinton } 64818225Slinton } else { 64918225Slinton if (t->class == MODULE) { 65018225Slinton u = t; 65118225Slinton t = deffunc(n); 65218225Slinton t->block = u; 65318225Slinton if (tracesyms) { 65418225Slinton printdecl(t); 65518225Slinton } 65618225Slinton } 65718225Slinton updateTextSym(t, name, np->n_value); 65818225Slinton } 65916613Ssam } 660*33328Sdonn } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) { 6619673Slinton find(t, n) where 66213938Slinton t->class == COMMON 66312542Scsvaf endfind(t); 66413938Slinton if (t != nil) { 66513938Slinton u = (Symbol) t->symvalue.common.offset; 66613938Slinton while (u != nil) { 66713938Slinton u->symvalue.offset = u->symvalue.common.offset+np->n_value; 66813938Slinton u = u->symvalue.common.chain; 66913938Slinton } 67013938Slinton } else { 67113938Slinton check_var(np, n); 6729673Slinton } 67313938Slinton } else { 67413938Slinton check_var(np, n); 6759673Slinton } 6769673Slinton } 6779673Slinton } 6789673Slinton 6799673Slinton /* 68013938Slinton * Check to see if a namelist entry refers to a variable. 68113938Slinton * If not, create a variable for the entry. In any case, 68213938Slinton * set the offset of the variable according to the value field 68313938Slinton * in the entry. 68418225Slinton * 68518225Slinton * If the external name has been referred to by several other symbols, 68618225Slinton * we must update each of them. 68713938Slinton */ 68813938Slinton 68916613Ssam private check_var (np, n) 69013938Slinton struct nlist *np; 69113938Slinton register Name n; 69213938Slinton { 69318225Slinton register Symbol t, u, next; 69418225Slinton Symbol conflict; 69513938Slinton 69618225Slinton t = lookup(n); 69713938Slinton if (t == nil) { 69818225Slinton t = defvar(n); 69918225Slinton t->symvalue.offset = np->n_value; 70018225Slinton if (tracesyms) { 70118225Slinton printdecl(t); 70218225Slinton } 70318225Slinton } else { 70418225Slinton conflict = nil; 70518225Slinton do { 70618225Slinton next = t->next_sym; 70718225Slinton if (t->name == n) { 70818225Slinton if (t->class == MODULE and t->block == program) { 70918225Slinton conflict = t; 71018225Slinton } else if (t->class == EXTREF and t->level == program->level) { 71118225Slinton u = t->symvalue.extref; 71218225Slinton while (u != nil and u->class == EXTREF) { 71318225Slinton u = u->symvalue.extref; 71418225Slinton } 71518225Slinton u->symvalue.offset = np->n_value; 71618225Slinton delete(t); 71718225Slinton } else if (t->level == program->level and 71818225Slinton (t->class == VAR or t->class == PROC or t->class == FUNC) 71918225Slinton ) { 72018225Slinton conflict = nil; 72118225Slinton t->symvalue.offset = np->n_value; 72218225Slinton } 72318225Slinton } 72418225Slinton t = next; 72518225Slinton } while (t != nil); 72618225Slinton if (conflict != nil) { 72718225Slinton u = defvar(n); 72818225Slinton u->block = conflict; 72918225Slinton u->symvalue.offset = np->n_value; 73018225Slinton } 73113938Slinton } 73213938Slinton } 73313938Slinton 73413938Slinton /* 7359673Slinton * Check to see if a local _name is known in the current scope. 7369673Slinton * If not then enter it. 7379673Slinton */ 7389673Slinton 73916613Ssam private check_local (name, np) 7409673Slinton String name; 7419673Slinton register struct nlist *np; 7429673Slinton { 7439673Slinton register Name n; 7449673Slinton register Symbol t, cur; 7459673Slinton 7469673Slinton n = identname(name, true); 7479673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 7489673Slinton find(t, n) where t->block == cur endfind(t); 7499673Slinton if (t == nil) { 7509673Slinton t = insert(n); 7519673Slinton t->language = findlanguage(".s"); 7529673Slinton t->type = t_int; 7539673Slinton t->block = cur; 754*33328Sdonn t->storage = EXT; 7559673Slinton t->level = cur->level; 7569673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 7579673Slinton t->class = FUNC; 75811875Slinton t->symvalue.funcv.src = false; 75914443Slinton t->symvalue.funcv.inline = false; 7609673Slinton t->symvalue.funcv.beginaddr = np->n_value; 76114443Slinton newfunc(t, codeloc(t)); 7629673Slinton findbeginning(t); 7639673Slinton } else { 7649673Slinton t->class = VAR; 7659673Slinton t->symvalue.offset = np->n_value; 7669673Slinton } 7679673Slinton } 7689673Slinton } 7699673Slinton 7709673Slinton /* 7719673Slinton * Check to see if a symbol corresponds to a object file name. 7729673Slinton * For some reason these are listed as in the text segment. 7739673Slinton */ 7749673Slinton 77516613Ssam private check_filename (name) 7769673Slinton String name; 7779673Slinton { 7789673Slinton register String mname; 77916613Ssam register integer i; 78018225Slinton Name n; 78118225Slinton Symbol s; 7829673Slinton 7839673Slinton mname = strdup(name); 7849673Slinton i = strlen(mname) - 2; 7859673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 7869673Slinton mname[i] = '\0'; 7879673Slinton --i; 7889673Slinton while (mname[i] != '/' and i >= 0) { 7899673Slinton --i; 7909673Slinton } 79118225Slinton n = identname(&mname[i+1], true); 79218225Slinton find(s, n) where s->block == program and s->class == MODULE endfind(s); 79318225Slinton if (s == nil) { 79418225Slinton s = insert(n); 79518225Slinton s->language = findlanguage(".s"); 79618225Slinton s->class = MODULE; 79718225Slinton s->symvalue.funcv.beginaddr = 0; 79818225Slinton findbeginning(s); 79918225Slinton } 8009673Slinton if (curblock->class != PROG) { 8019673Slinton exitblock(); 8029673Slinton if (curblock->class != PROG) { 8039673Slinton exitblock(); 8049673Slinton } 8059673Slinton } 8069673Slinton enterblock(s); 8079673Slinton curmodule = s; 8089673Slinton } 8099673Slinton } 8109673Slinton 8119673Slinton /* 81214443Slinton * Check to see if a symbol is about to be defined within an unnamed block. 81314443Slinton * If this happens, we create a procedure for the unnamed block, make it 81414443Slinton * "inline" so that tracebacks don't associate an activation record with it, 81514443Slinton * and enter it into the function table so that it will be detected 81614443Slinton * by "whatblock". 81714443Slinton */ 81814443Slinton 81916613Ssam public chkUnnamedBlock () 82014443Slinton { 82114443Slinton register Symbol s; 82214443Slinton static int bnum = 0; 82314443Slinton char buf[100]; 82416613Ssam Address startaddr; 82514443Slinton 82616613Ssam if (nesting > 0 and addrstk[nesting] != NOADDR) { 82716613Ssam startaddr = (linep - 1)->addr; 82816613Ssam ++bnum; 82916613Ssam sprintf(buf, "$b%d", bnum); 83016613Ssam s = insert(identname(buf, false)); 83116613Ssam s->language = curlang; 83216613Ssam s->class = PROC; 83316613Ssam s->symvalue.funcv.src = false; 83416613Ssam s->symvalue.funcv.inline = true; 83516613Ssam s->symvalue.funcv.beginaddr = startaddr; 83616613Ssam enterblock(s); 83716613Ssam newfunc(s, startaddr); 83816613Ssam addrstk[nesting] = NOADDR; 83916613Ssam } 84014443Slinton } 84114443Slinton 84214443Slinton /* 84314443Slinton * Compilation unit. C associates scope with filenames 84414443Slinton * so we treat them as "modules". The filename without 84514443Slinton * the suffix is used for the module name. 84614443Slinton * 84714443Slinton * Because there is no explicit "end-of-block" mark in 84814443Slinton * the object file, we must exit blocks for the current 84914443Slinton * procedure and module. 85014443Slinton */ 85114443Slinton 85216613Ssam private enterSourceModule (n, addr) 85314443Slinton Name n; 85414443Slinton Address addr; 85514443Slinton { 85614443Slinton register Symbol s; 85714443Slinton Name nn; 85814443Slinton String mname, suffix; 85914443Slinton 86014443Slinton mname = strdup(ident(n)); 86114443Slinton if (rindex(mname, '/') != nil) { 86214443Slinton mname = rindex(mname, '/') + 1; 86314443Slinton } 86414443Slinton suffix = rindex(mname, '.'); 865*33328Sdonn if (suffix > mname && *(suffix-1) == '.') { 866*33328Sdonn /* special hack for C++ */ 867*33328Sdonn --suffix; 868*33328Sdonn } 86914443Slinton curlang = findlanguage(suffix); 87014443Slinton if (curlang == findlanguage(".f")) { 87114443Slinton strip_ = true; 87214443Slinton } 87314443Slinton if (suffix != nil) { 87414443Slinton *suffix = '\0'; 87514443Slinton } 87616613Ssam if (not (*language_op(curlang, L_HASMODULES))()) { 87714443Slinton if (curblock->class != PROG) { 87814443Slinton exitblock(); 87916613Ssam if (curblock->class != PROG) { 88016613Ssam exitblock(); 88116613Ssam } 88214443Slinton } 88316613Ssam nn = identname(mname, true); 88416613Ssam if (curmodule == nil or curmodule->name != nn) { 88516613Ssam s = insert(nn); 88616613Ssam s->class = MODULE; 88716613Ssam s->symvalue.funcv.beginaddr = 0; 88816613Ssam findbeginning(s); 88916613Ssam } else { 89016613Ssam s = curmodule; 89116613Ssam } 89216613Ssam s->language = curlang; 89316613Ssam enterblock(s); 89416613Ssam curmodule = s; 89514443Slinton } 89614443Slinton if (program->language == nil) { 89714443Slinton program->language = curlang; 89814443Slinton } 89914443Slinton warned = false; 90014443Slinton enterfile(ident(n), addr); 90116613Ssam initTypeTable(); 90214443Slinton } 90314443Slinton 90414443Slinton /* 9059673Slinton * Allocate file and line tables and initialize indices. 9069673Slinton */ 9079673Slinton 90816613Ssam private allocmaps (nf, nl) 90916613Ssam integer nf, nl; 9109673Slinton { 9119673Slinton if (filetab != nil) { 9129673Slinton dispose(filetab); 9139673Slinton } 9149673Slinton if (linetab != nil) { 9159673Slinton dispose(linetab); 9169673Slinton } 9179673Slinton filetab = newarr(Filetab, nf); 9189673Slinton linetab = newarr(Linetab, nl); 9199673Slinton filep = filetab; 9209673Slinton linep = linetab; 9219673Slinton } 9229673Slinton 9239673Slinton /* 9249673Slinton * Add a file to the file table. 92513938Slinton * 92613938Slinton * If the new address is the same as the previous file address 92713938Slinton * this routine used to not enter the file, but this caused some 92813938Slinton * problems so it has been removed. It's not clear that this in 92913938Slinton * turn may not also cause a problem. 9309673Slinton */ 9319673Slinton 93216613Ssam private enterfile (filename, addr) 9339673Slinton String filename; 9349673Slinton Address addr; 9359673Slinton { 93613938Slinton filep->addr = addr; 93713938Slinton filep->filename = filename; 93813938Slinton filep->lineindex = linep - linetab; 93913938Slinton ++filep; 9409673Slinton } 9419673Slinton 9429673Slinton /* 9439673Slinton * Since we only estimated the number of lines (and it was a poor 9449673Slinton * estimation) and since we need to know the exact number of lines 9459673Slinton * to do a binary search, we set it when we're done. 9469673Slinton */ 9479673Slinton 94816613Ssam private setnlines () 9499673Slinton { 9509673Slinton nlhdr.nlines = linep - linetab; 9519673Slinton } 9529673Slinton 9539673Slinton /* 9549673Slinton * Similarly for nfiles ... 9559673Slinton */ 9569673Slinton 95716613Ssam private setnfiles () 9589673Slinton { 9599673Slinton nlhdr.nfiles = filep - filetab; 9609673Slinton setsource(filetab[0].filename); 9619673Slinton } 962