19673Slinton /* Copyright (c) 1982 Regents of the University of California */ 29673Slinton 3*18225Slinton static char sccsid[] = "@(#)object.c 1.16 (Berkeley) 03/01/85"; 49673Slinton 5*18225Slinton static char rcsid[] = "$Header: object.c,v 1.6 84/12/26 10:40:51 linton Exp $"; 6*18225Slinton 79673Slinton /* 89673Slinton * Object code interface, mainly for extraction of symbolic information. 99673Slinton */ 109673Slinton 119673Slinton #include "defs.h" 129673Slinton #include "object.h" 1316613Ssam #include "stabstring.h" 149673Slinton #include "main.h" 159673Slinton #include "symbols.h" 169673Slinton #include "names.h" 179673Slinton #include "languages.h" 189673Slinton #include "mappings.h" 199673Slinton #include "lists.h" 209673Slinton #include <a.out.h> 219673Slinton #include <stab.h> 229673Slinton #include <ctype.h> 239673Slinton 249673Slinton #ifndef public 259673Slinton 269673Slinton struct { 279673Slinton unsigned int stringsize; /* size of the dumped string table */ 289673Slinton unsigned int nsyms; /* number of symbols */ 299673Slinton unsigned int nfiles; /* number of files */ 309673Slinton unsigned int nlines; /* number of lines */ 319673Slinton } nlhdr; 329673Slinton 3316613Ssam #include "languages.h" 3416613Ssam #include "symbols.h" 3516613Ssam 369673Slinton #endif 379673Slinton 3816613Ssam #ifndef N_MOD2 3916613Ssam # define N_MOD2 0x50 4016613Ssam #endif 4116613Ssam 429673Slinton public String objname = "a.out"; 4316613Ssam public integer objsize; 449673Slinton 4516613Ssam public Language curlang; 4616613Ssam public Symbol curmodule; 4716613Ssam public Symbol curparam; 4816613Ssam public Symbol curcomm; 4916613Ssam public Symbol commchain; 5016613Ssam 5116613Ssam private char *stringtab; 5216613Ssam private struct nlist *curnp; 539673Slinton private Boolean warned; 5412542Scsvaf private Boolean strip_ = false; 559673Slinton 569673Slinton private Filetab *filep; 5711875Slinton private Linetab *linep, *prevlinep; 589673Slinton 5916613Ssam public String curfilename () 6016613Ssam { 6116613Ssam return ((filep-1)->filename); 6216613Ssam } 639673Slinton 649673Slinton /* 659673Slinton * Blocks are figured out on the fly while reading the symbol table. 669673Slinton */ 679673Slinton 689673Slinton #define MAXBLKDEPTH 25 699673Slinton 7016613Ssam public Symbol curblock; 7116613Ssam 729673Slinton private Symbol blkstack[MAXBLKDEPTH]; 7316613Ssam private integer curlevel; 7416613Ssam private integer bnum, nesting; 7514443Slinton private Address addrstk[MAXBLKDEPTH]; 769673Slinton 7716613Ssam public pushBlock (b) 7816613Ssam Symbol b; 7916613Ssam { 8016613Ssam if (curlevel >= MAXBLKDEPTH) { 8116613Ssam fatal("nesting depth too large (%d)", curlevel); 8216613Ssam } 8316613Ssam blkstack[curlevel] = curblock; 8416613Ssam ++curlevel; 8516613Ssam curblock = b; 8616613Ssam if (traceblocks) { 8716613Ssam printf("entering block %s\n", symname(b)); 8816613Ssam } 899673Slinton } 909673Slinton 91*18225Slinton /* 92*18225Slinton * Change the current block with saving the previous one, 93*18225Slinton * since it is assumed that the symbol for the current one is to be deleted. 94*18225Slinton */ 95*18225Slinton 96*18225Slinton public changeBlock (b) 97*18225Slinton Symbol b; 98*18225Slinton { 99*18225Slinton curblock = b; 100*18225Slinton } 101*18225Slinton 10216613Ssam public enterblock (b) 10316613Ssam Symbol b; 10416613Ssam { 10516613Ssam if (curblock == nil) { 10616613Ssam b->level = 1; 10716613Ssam } else { 10816613Ssam b->level = curblock->level + 1; 10916613Ssam } 11016613Ssam b->block = curblock; 11116613Ssam pushBlock(b); 1129673Slinton } 1139673Slinton 11416613Ssam public exitblock () 11516613Ssam { 11616613Ssam if (curblock->class == FUNC or curblock->class == PROC) { 11716613Ssam if (prevlinep != linep) { 11816613Ssam curblock->symvalue.funcv.src = true; 11916613Ssam } 12016613Ssam } 12116613Ssam if (curlevel <= 0) { 12216613Ssam panic("nesting depth underflow (%d)", curlevel); 12316613Ssam } 12416613Ssam --curlevel; 12516613Ssam if (traceblocks) { 12616613Ssam printf("exiting block %s\n", symname(curblock)); 12716613Ssam } 12816613Ssam curblock = blkstack[curlevel]; 12916613Ssam } 13016613Ssam 1319673Slinton /* 1329673Slinton * Enter a source line or file name reference into the appropriate table. 1339673Slinton * Expanded inline to reduce procedure calls. 1349673Slinton * 13516613Ssam * private enterline (linenumber, address) 1369673Slinton * Lineno linenumber; 1379673Slinton * Address address; 1389673Slinton * ... 1399673Slinton */ 1409673Slinton 1419673Slinton #define enterline(linenumber, address) \ 1429673Slinton { \ 1439673Slinton register Linetab *lp; \ 1449673Slinton \ 1459673Slinton lp = linep - 1; \ 1469673Slinton if (linenumber != lp->line) { \ 1479673Slinton if (address != lp->addr) { \ 1489673Slinton ++lp; \ 1499673Slinton } \ 1509673Slinton lp->line = linenumber; \ 1519673Slinton lp->addr = address; \ 1529673Slinton linep = lp + 1; \ 1539673Slinton } \ 1549673Slinton } 1559673Slinton 1569673Slinton /* 1579673Slinton * Read in the namelist from the obj file. 1589673Slinton * 1599673Slinton * Reads and seeks are used instead of fread's and fseek's 1609673Slinton * for efficiency sake; there's a lot of data being read here. 1619673Slinton */ 1629673Slinton 16316613Ssam public readobj (file) 1649673Slinton String file; 1659673Slinton { 1669673Slinton Fileid f; 1679673Slinton struct exec hdr; 1689673Slinton struct nlist nlist; 1699673Slinton 1709673Slinton f = open(file, 0); 1719673Slinton if (f < 0) { 1729673Slinton fatal("can't open %s", file); 1739673Slinton } 1749673Slinton read(f, &hdr, sizeof(hdr)); 175*18225Slinton if (N_BADMAG(hdr)) { 176*18225Slinton objsize = 0; 177*18225Slinton nlhdr.nsyms = 0; 178*18225Slinton nlhdr.nfiles = 0; 179*18225Slinton nlhdr.nlines = 0; 180*18225Slinton } else { 181*18225Slinton objsize = hdr.a_text; 182*18225Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 183*18225Slinton nlhdr.nfiles = nlhdr.nsyms; 184*18225Slinton nlhdr.nlines = nlhdr.nsyms; 185*18225Slinton } 18614443Slinton if (nlhdr.nsyms > 0) { 18714443Slinton lseek(f, (long) N_STROFF(hdr), 0); 18814443Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 18914443Slinton nlhdr.stringsize -= 4; 19014443Slinton stringtab = newarr(char, nlhdr.stringsize); 19114443Slinton read(f, stringtab, nlhdr.stringsize); 19214443Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 19314443Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 19414443Slinton readsyms(f); 19514443Slinton ordfunctab(); 19614443Slinton setnlines(); 19714443Slinton setnfiles(); 198*18225Slinton } else { 199*18225Slinton initsyms(); 20014443Slinton } 2019673Slinton close(f); 2029673Slinton } 2039673Slinton 2049673Slinton /* 205*18225Slinton * Found the beginning of the externals in the object file 206*18225Slinton * (signified by the "-lg" or find an external), close the 207*18225Slinton * block for the last procedure. 208*18225Slinton */ 209*18225Slinton 210*18225Slinton private foundglobals () 211*18225Slinton { 212*18225Slinton if (curblock->class != PROG) { 213*18225Slinton exitblock(); 214*18225Slinton if (curblock->class != PROG) { 215*18225Slinton exitblock(); 216*18225Slinton } 217*18225Slinton } 218*18225Slinton enterline(0, (linep-1)->addr + 1); 219*18225Slinton } 220*18225Slinton 221*18225Slinton /* 2229673Slinton * Read in symbols from object file. 2239673Slinton */ 2249673Slinton 22516613Ssam private readsyms (f) 2269673Slinton Fileid f; 2279673Slinton { 2289673Slinton struct nlist *namelist; 2299673Slinton register struct nlist *np, *ub; 2309673Slinton register String name; 2319673Slinton register Boolean afterlg; 23216613Ssam integer index; 23316613Ssam char *lastchar; 2349673Slinton 2359673Slinton initsyms(); 2369673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 2379673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 2389673Slinton afterlg = false; 2399673Slinton ub = &namelist[nlhdr.nsyms]; 24016613Ssam curnp = &namelist[0]; 24116613Ssam np = curnp; 24216613Ssam while (np < ub) { 2439673Slinton index = np->n_un.n_strx; 2449673Slinton if (index != 0) { 2459673Slinton name = &stringtab[index - 4]; 24612542Scsvaf /* 24716613Ssam * If the program contains any .f files a trailing _ is stripped 24812542Scsvaf * from the name on the assumption it was added by the compiler. 24912542Scsvaf * This only affects names that follow the sdb N_SO entry with 25012542Scsvaf * the .f name. 25112542Scsvaf */ 25214443Slinton if (strip_ and name[0] != '\0' ) { 25316613Ssam lastchar = &name[strlen(name) - 1]; 25416613Ssam if (*lastchar == '_') { 25516613Ssam *lastchar = '\0'; 25614443Slinton } 25712542Scsvaf } 2589673Slinton } else { 2599673Slinton name = nil; 26012542Scsvaf } 26116613Ssam 2629673Slinton /* 26316613Ssam * Assumptions: 2649673Slinton * not an N_STAB ==> name != nil 2659673Slinton * name[0] == '-' ==> name == "-lg" 2669673Slinton * name[0] != '_' ==> filename or invisible 2679673Slinton * 2689673Slinton * The "-lg" signals the beginning of global loader symbols. 26912542Scsvaf * 2709673Slinton */ 2719673Slinton if ((np->n_type&N_STAB) != 0) { 2729673Slinton enter_nl(name, np); 2739673Slinton } else if (name[0] == '-') { 2749673Slinton afterlg = true; 275*18225Slinton foundglobals(); 27611104Slinton } else if (afterlg) { 277*18225Slinton check_global(name, np); 278*18225Slinton } else if ((np->n_type&N_EXT) == N_EXT) { 279*18225Slinton afterlg = true; 280*18225Slinton foundglobals(); 281*18225Slinton check_global(name, np); 28211104Slinton } else if (name[0] == '_') { 28311104Slinton check_local(&name[1], np); 2849673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 2859673Slinton check_filename(name); 2869673Slinton } 28716613Ssam ++curnp; 28816613Ssam np = curnp; 2899673Slinton } 2909673Slinton dispose(namelist); 2919673Slinton } 2929673Slinton 2939673Slinton /* 29416613Ssam * Get a continuation entry from the name list. 29516613Ssam * Return the beginning of the name. 29616613Ssam */ 29716613Ssam 29816613Ssam public String getcont () 29916613Ssam { 30016613Ssam register integer index; 30116613Ssam register String name; 30216613Ssam 30316613Ssam ++curnp; 30416613Ssam index = curnp->n_un.n_strx; 30516613Ssam if (index == 0) { 30616613Ssam panic("continuation followed by empty stab"); 30716613Ssam } 30816613Ssam name = &stringtab[index - 4]; 30916613Ssam return name; 31016613Ssam } 31116613Ssam 31216613Ssam /* 3139673Slinton * Initialize symbol information. 3149673Slinton */ 3159673Slinton 31616613Ssam private initsyms () 3179673Slinton { 3189673Slinton curblock = nil; 3199673Slinton curlevel = 0; 32014443Slinton nesting = 0; 32116613Ssam program = insert(identname("", true)); 3229673Slinton program->class = PROG; 32311769Slinton program->symvalue.funcv.beginaddr = 0; 32414443Slinton program->symvalue.funcv.inline = false; 32514443Slinton newfunc(program, codeloc(program)); 32611769Slinton findbeginning(program); 3279673Slinton enterblock(program); 3289673Slinton curmodule = program; 3299673Slinton } 3309673Slinton 3319673Slinton /* 3329673Slinton * Free all the object file information that's being stored. 3339673Slinton */ 3349673Slinton 33516613Ssam public objfree () 3369673Slinton { 3379673Slinton symbol_free(); 338*18225Slinton /* keywords_free(); */ 339*18225Slinton /* names_free(); */ 340*18225Slinton /* dispose(stringtab); */ 3419673Slinton clrfunctab(); 3429673Slinton } 3439673Slinton 3449673Slinton /* 3459673Slinton * Enter a namelist entry. 3469673Slinton */ 3479673Slinton 34816613Ssam private enter_nl (name, np) 3499673Slinton String name; 3509673Slinton register struct nlist *np; 3519673Slinton { 3529673Slinton register Symbol s; 35316613Ssam register Name n; 3549673Slinton 3559673Slinton s = nil; 3569673Slinton switch (np->n_type) { 35714443Slinton /* 35814443Slinton * Build a symbol for the FORTRAN common area. All GSYMS that follow 35914443Slinton * will be chained in a list with the head kept in common.offset, and 36014443Slinton * the tail in common.chain. 36114443Slinton */ 36213938Slinton case N_BCOMM: 36313938Slinton if (curcomm) { 36413938Slinton curcomm->symvalue.common.chain = commchain; 36512542Scsvaf } 36616613Ssam n = identname(name, true); 36712542Scsvaf curcomm = lookup(n); 36813938Slinton if (curcomm == nil) { 36913938Slinton curcomm = insert(n); 37013938Slinton curcomm->class = COMMON; 37113938Slinton curcomm->block = curblock; 37213938Slinton curcomm->level = program->level; 37313938Slinton curcomm->symvalue.common.chain = nil; 37412542Scsvaf } 37512542Scsvaf commchain = curcomm->symvalue.common.chain; 37613938Slinton break; 37712542Scsvaf 37812542Scsvaf case N_ECOMM: 37913938Slinton if (curcomm) { 38013938Slinton curcomm->symvalue.common.chain = commchain; 38113938Slinton curcomm = nil; 38212542Scsvaf } 38312542Scsvaf break; 38414443Slinton 3859673Slinton case N_LBRAC: 38614443Slinton ++nesting; 38714443Slinton addrstk[nesting] = (linep - 1)->addr; 3889673Slinton break; 3899673Slinton 3909673Slinton case N_RBRAC: 39116613Ssam --nesting; 39214443Slinton if (addrstk[nesting] == NOADDR) { 39314443Slinton exitblock(); 39414443Slinton newfunc(curblock, (linep - 1)->addr); 39516613Ssam addrstk[nesting] = (linep - 1)->addr; 39614443Slinton } 3979673Slinton break; 3989673Slinton 3999673Slinton case N_SLINE: 4009673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 4019673Slinton break; 4029673Slinton 4039673Slinton /* 40414443Slinton * Source files. 4059673Slinton */ 4069673Slinton case N_SO: 40716613Ssam n = identname(name, true); 40814443Slinton enterSourceModule(n, (Address) np->n_value); 4099673Slinton break; 4109673Slinton 4119673Slinton /* 4129673Slinton * Textually included files. 4139673Slinton */ 4149673Slinton case N_SOL: 4159673Slinton enterfile(name, (Address) np->n_value); 4169673Slinton break; 4179673Slinton 4189673Slinton /* 4199673Slinton * These symbols are assumed to have non-nil names. 4209673Slinton */ 4219673Slinton case N_GSYM: 4229673Slinton case N_FUN: 4239673Slinton case N_STSYM: 4249673Slinton case N_LCSYM: 4259673Slinton case N_RSYM: 4269673Slinton case N_PSYM: 4279673Slinton case N_LSYM: 4289673Slinton case N_SSYM: 42914443Slinton case N_LENG: 4309673Slinton if (index(name, ':') == nil) { 4319673Slinton if (not warned) { 4329673Slinton warned = true; 4339673Slinton warning("old style symbol information found in \"%s\"", 4349673Slinton curfilename()); 4359673Slinton } 4369673Slinton } else { 4379673Slinton entersym(name, np); 4389673Slinton } 4399673Slinton break; 4409673Slinton 4419673Slinton case N_PC: 44216613Ssam case N_MOD2: 4439673Slinton break; 4449673Slinton 44511558Slinton default: 44614443Slinton printf("warning: stab entry unrecognized: "); 4479673Slinton if (name != nil) { 44814443Slinton printf("name %s,", name); 4499673Slinton } 45014443Slinton printf("ntype %2x, desc %x, value %x'\n", 4519673Slinton np->n_type, np->n_desc, np->n_value); 4529673Slinton break; 4539673Slinton } 4549673Slinton } 4559673Slinton 4569673Slinton /* 457*18225Slinton * Try to find the symbol that is referred to by the given name. Since it's 458*18225Slinton * an external, we need to follow a level or two of indirection. 45916613Ssam */ 46016613Ssam 461*18225Slinton private Symbol findsym (n, var_isextref) 46216613Ssam Name n; 463*18225Slinton boolean *var_isextref; 46416613Ssam { 46516613Ssam register Symbol r, s; 46616613Ssam 467*18225Slinton *var_isextref = false; 46816613Ssam find(s, n) where 469*18225Slinton ( 470*18225Slinton s->level == program->level and ( 471*18225Slinton s->class == EXTREF or s->class == VAR or 472*18225Slinton s->class == PROC or s->class == FUNC 473*18225Slinton ) 474*18225Slinton ) or ( 475*18225Slinton s->block == program and s->class == MODULE 476*18225Slinton ) 47716613Ssam endfind(s); 478*18225Slinton if (s == nil) { 479*18225Slinton r = nil; 480*18225Slinton } else if (s->class == EXTREF) { 481*18225Slinton *var_isextref = true; 48216613Ssam r = s->symvalue.extref; 48316613Ssam delete(s); 484*18225Slinton 485*18225Slinton /* 486*18225Slinton * Now check for another level of indirection that could come from 487*18225Slinton * a forward reference in procedure nesting information. In this case 488*18225Slinton * the symbol has already been deleted. 489*18225Slinton */ 490*18225Slinton if (r != nil and r->class == EXTREF) { 491*18225Slinton r = r->symvalue.extref; 492*18225Slinton } 493*18225Slinton /* 494*18225Slinton } else if (s->class == MODULE) { 495*18225Slinton s->class = FUNC; 496*18225Slinton s->level = program->level; 497*18225Slinton r = s; 498*18225Slinton */ 49916613Ssam } else { 50016613Ssam r = s; 50116613Ssam } 50216613Ssam return r; 50316613Ssam } 50416613Ssam 50516613Ssam /* 506*18225Slinton * Create a symbol for a text symbol with no source information. 507*18225Slinton * We treat it as an assembly language function. 508*18225Slinton */ 509*18225Slinton 510*18225Slinton private Symbol deffunc (n) 511*18225Slinton Name n; 512*18225Slinton { 513*18225Slinton Symbol f; 514*18225Slinton 515*18225Slinton f = insert(n); 516*18225Slinton f->language = findlanguage(".s"); 517*18225Slinton f->class = FUNC; 518*18225Slinton f->type = t_int; 519*18225Slinton f->block = curblock; 520*18225Slinton f->level = program->level; 521*18225Slinton f->symvalue.funcv.src = false; 522*18225Slinton f->symvalue.funcv.inline = false; 523*18225Slinton return f; 524*18225Slinton } 525*18225Slinton 526*18225Slinton /* 527*18225Slinton * Create a symbol for a data or bss symbol with no source information. 528*18225Slinton * We treat it as an assembly language variable. 529*18225Slinton */ 530*18225Slinton 531*18225Slinton private Symbol defvar (n) 532*18225Slinton Name n; 533*18225Slinton { 534*18225Slinton Symbol v; 535*18225Slinton 536*18225Slinton v = insert(n); 537*18225Slinton v->language = findlanguage(".s"); 538*18225Slinton v->class = VAR; 539*18225Slinton v->type = t_int; 540*18225Slinton v->level = program->level; 541*18225Slinton v->block = curblock; 542*18225Slinton return v; 543*18225Slinton } 544*18225Slinton 545*18225Slinton /* 546*18225Slinton * Update a symbol entry with a text address. 547*18225Slinton */ 548*18225Slinton 549*18225Slinton private updateTextSym (s, name, addr) 550*18225Slinton Symbol s; 551*18225Slinton char *name; 552*18225Slinton Address addr; 553*18225Slinton { 554*18225Slinton if (s->class == VAR) { 555*18225Slinton s->symvalue.offset = addr; 556*18225Slinton } else { 557*18225Slinton s->symvalue.funcv.beginaddr = addr; 558*18225Slinton if (name[0] == '_') { 559*18225Slinton newfunc(s, codeloc(s)); 560*18225Slinton findbeginning(s); 561*18225Slinton } 562*18225Slinton } 563*18225Slinton } 564*18225Slinton 565*18225Slinton /* 5669673Slinton * Check to see if a global _name is already in the symbol table, 5679673Slinton * if not then insert it. 5689673Slinton */ 5699673Slinton 57016613Ssam private check_global (name, np) 5719673Slinton String name; 5729673Slinton register struct nlist *np; 5739673Slinton { 5749673Slinton register Name n; 57512542Scsvaf register Symbol t, u; 576*18225Slinton char buf[4096]; 577*18225Slinton boolean isextref; 578*18225Slinton integer count; 5799673Slinton 580*18225Slinton if (not streq(name, "_end")) { 581*18225Slinton if (name[0] == '_') { 582*18225Slinton n = identname(&name[1], true); 583*18225Slinton } else { 584*18225Slinton n = identname(name, true); 585*18225Slinton if (lookup(n) != nil) { 586*18225Slinton sprintf(buf, "$%s", name); 587*18225Slinton n = identname(buf, false); 588*18225Slinton } 589*18225Slinton } 5909673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 591*18225Slinton count = 0; 592*18225Slinton t = findsym(n, &isextref); 593*18225Slinton while (isextref) { 594*18225Slinton ++count; 595*18225Slinton updateTextSym(t, name, np->n_value); 596*18225Slinton t = findsym(n, &isextref); 5979673Slinton } 598*18225Slinton if (count == 0) { 599*18225Slinton if (t == nil) { 600*18225Slinton t = deffunc(n); 601*18225Slinton updateTextSym(t, name, np->n_value); 602*18225Slinton if (tracesyms) { 603*18225Slinton printdecl(t); 604*18225Slinton } 605*18225Slinton } else { 606*18225Slinton if (t->class == MODULE) { 607*18225Slinton u = t; 608*18225Slinton t = deffunc(n); 609*18225Slinton t->block = u; 610*18225Slinton if (tracesyms) { 611*18225Slinton printdecl(t); 612*18225Slinton } 613*18225Slinton } 614*18225Slinton updateTextSym(t, name, np->n_value); 615*18225Slinton } 61616613Ssam } 61713938Slinton } else if ((np->n_type&N_TYPE) == N_BSS) { 6189673Slinton find(t, n) where 61913938Slinton t->class == COMMON 62012542Scsvaf endfind(t); 62113938Slinton if (t != nil) { 62213938Slinton u = (Symbol) t->symvalue.common.offset; 62313938Slinton while (u != nil) { 62413938Slinton u->symvalue.offset = u->symvalue.common.offset+np->n_value; 62513938Slinton u = u->symvalue.common.chain; 62613938Slinton } 62713938Slinton } else { 62813938Slinton check_var(np, n); 6299673Slinton } 63013938Slinton } else { 63113938Slinton check_var(np, n); 6329673Slinton } 6339673Slinton } 6349673Slinton } 6359673Slinton 6369673Slinton /* 63713938Slinton * Check to see if a namelist entry refers to a variable. 63813938Slinton * If not, create a variable for the entry. In any case, 63913938Slinton * set the offset of the variable according to the value field 64013938Slinton * in the entry. 641*18225Slinton * 642*18225Slinton * If the external name has been referred to by several other symbols, 643*18225Slinton * we must update each of them. 64413938Slinton */ 64513938Slinton 64616613Ssam private check_var (np, n) 64713938Slinton struct nlist *np; 64813938Slinton register Name n; 64913938Slinton { 650*18225Slinton register Symbol t, u, next; 651*18225Slinton Symbol conflict; 65213938Slinton 653*18225Slinton t = lookup(n); 65413938Slinton if (t == nil) { 655*18225Slinton t = defvar(n); 656*18225Slinton t->symvalue.offset = np->n_value; 657*18225Slinton if (tracesyms) { 658*18225Slinton printdecl(t); 659*18225Slinton } 660*18225Slinton } else { 661*18225Slinton conflict = nil; 662*18225Slinton do { 663*18225Slinton next = t->next_sym; 664*18225Slinton if (t->name == n) { 665*18225Slinton if (t->class == MODULE and t->block == program) { 666*18225Slinton conflict = t; 667*18225Slinton } else if (t->class == EXTREF and t->level == program->level) { 668*18225Slinton u = t->symvalue.extref; 669*18225Slinton while (u != nil and u->class == EXTREF) { 670*18225Slinton u = u->symvalue.extref; 671*18225Slinton } 672*18225Slinton u->symvalue.offset = np->n_value; 673*18225Slinton delete(t); 674*18225Slinton } else if (t->level == program->level and 675*18225Slinton (t->class == VAR or t->class == PROC or t->class == FUNC) 676*18225Slinton ) { 677*18225Slinton conflict = nil; 678*18225Slinton t->symvalue.offset = np->n_value; 679*18225Slinton } 680*18225Slinton } 681*18225Slinton t = next; 682*18225Slinton } while (t != nil); 683*18225Slinton if (conflict != nil) { 684*18225Slinton u = defvar(n); 685*18225Slinton u->block = conflict; 686*18225Slinton u->symvalue.offset = np->n_value; 687*18225Slinton } 68813938Slinton } 68913938Slinton } 69013938Slinton 69113938Slinton /* 6929673Slinton * Check to see if a local _name is known in the current scope. 6939673Slinton * If not then enter it. 6949673Slinton */ 6959673Slinton 69616613Ssam private check_local (name, np) 6979673Slinton String name; 6989673Slinton register struct nlist *np; 6999673Slinton { 7009673Slinton register Name n; 7019673Slinton register Symbol t, cur; 7029673Slinton 7039673Slinton n = identname(name, true); 7049673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 7059673Slinton find(t, n) where t->block == cur endfind(t); 7069673Slinton if (t == nil) { 7079673Slinton t = insert(n); 7089673Slinton t->language = findlanguage(".s"); 7099673Slinton t->type = t_int; 7109673Slinton t->block = cur; 7119673Slinton t->level = cur->level; 7129673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 7139673Slinton t->class = FUNC; 71411875Slinton t->symvalue.funcv.src = false; 71514443Slinton t->symvalue.funcv.inline = false; 7169673Slinton t->symvalue.funcv.beginaddr = np->n_value; 71714443Slinton newfunc(t, codeloc(t)); 7189673Slinton findbeginning(t); 7199673Slinton } else { 7209673Slinton t->class = VAR; 7219673Slinton t->symvalue.offset = np->n_value; 7229673Slinton } 7239673Slinton } 7249673Slinton } 7259673Slinton 7269673Slinton /* 7279673Slinton * Check to see if a symbol corresponds to a object file name. 7289673Slinton * For some reason these are listed as in the text segment. 7299673Slinton */ 7309673Slinton 73116613Ssam private check_filename (name) 7329673Slinton String name; 7339673Slinton { 7349673Slinton register String mname; 73516613Ssam register integer i; 736*18225Slinton Name n; 737*18225Slinton Symbol s; 7389673Slinton 7399673Slinton mname = strdup(name); 7409673Slinton i = strlen(mname) - 2; 7419673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 7429673Slinton mname[i] = '\0'; 7439673Slinton --i; 7449673Slinton while (mname[i] != '/' and i >= 0) { 7459673Slinton --i; 7469673Slinton } 747*18225Slinton n = identname(&mname[i+1], true); 748*18225Slinton find(s, n) where s->block == program and s->class == MODULE endfind(s); 749*18225Slinton if (s == nil) { 750*18225Slinton s = insert(n); 751*18225Slinton s->language = findlanguage(".s"); 752*18225Slinton s->class = MODULE; 753*18225Slinton s->symvalue.funcv.beginaddr = 0; 754*18225Slinton findbeginning(s); 755*18225Slinton } 7569673Slinton if (curblock->class != PROG) { 7579673Slinton exitblock(); 7589673Slinton if (curblock->class != PROG) { 7599673Slinton exitblock(); 7609673Slinton } 7619673Slinton } 7629673Slinton enterblock(s); 7639673Slinton curmodule = s; 7649673Slinton } 7659673Slinton } 7669673Slinton 7679673Slinton /* 76814443Slinton * Check to see if a symbol is about to be defined within an unnamed block. 76914443Slinton * If this happens, we create a procedure for the unnamed block, make it 77014443Slinton * "inline" so that tracebacks don't associate an activation record with it, 77114443Slinton * and enter it into the function table so that it will be detected 77214443Slinton * by "whatblock". 77314443Slinton */ 77414443Slinton 77516613Ssam public chkUnnamedBlock () 77614443Slinton { 77714443Slinton register Symbol s; 77814443Slinton static int bnum = 0; 77914443Slinton char buf[100]; 78016613Ssam Address startaddr; 78114443Slinton 78216613Ssam if (nesting > 0 and addrstk[nesting] != NOADDR) { 78316613Ssam startaddr = (linep - 1)->addr; 78416613Ssam ++bnum; 78516613Ssam sprintf(buf, "$b%d", bnum); 78616613Ssam s = insert(identname(buf, false)); 78716613Ssam s->language = curlang; 78816613Ssam s->class = PROC; 78916613Ssam s->symvalue.funcv.src = false; 79016613Ssam s->symvalue.funcv.inline = true; 79116613Ssam s->symvalue.funcv.beginaddr = startaddr; 79216613Ssam enterblock(s); 79316613Ssam newfunc(s, startaddr); 79416613Ssam addrstk[nesting] = NOADDR; 79516613Ssam } 79614443Slinton } 79714443Slinton 79814443Slinton /* 79914443Slinton * Compilation unit. C associates scope with filenames 80014443Slinton * so we treat them as "modules". The filename without 80114443Slinton * the suffix is used for the module name. 80214443Slinton * 80314443Slinton * Because there is no explicit "end-of-block" mark in 80414443Slinton * the object file, we must exit blocks for the current 80514443Slinton * procedure and module. 80614443Slinton */ 80714443Slinton 80816613Ssam private enterSourceModule (n, addr) 80914443Slinton Name n; 81014443Slinton Address addr; 81114443Slinton { 81214443Slinton register Symbol s; 81314443Slinton Name nn; 81414443Slinton String mname, suffix; 81514443Slinton 81614443Slinton mname = strdup(ident(n)); 81714443Slinton if (rindex(mname, '/') != nil) { 81814443Slinton mname = rindex(mname, '/') + 1; 81914443Slinton } 82014443Slinton suffix = rindex(mname, '.'); 82114443Slinton curlang = findlanguage(suffix); 82214443Slinton if (curlang == findlanguage(".f")) { 82314443Slinton strip_ = true; 82414443Slinton } 82514443Slinton if (suffix != nil) { 82614443Slinton *suffix = '\0'; 82714443Slinton } 82816613Ssam if (not (*language_op(curlang, L_HASMODULES))()) { 82914443Slinton if (curblock->class != PROG) { 83014443Slinton exitblock(); 83116613Ssam if (curblock->class != PROG) { 83216613Ssam exitblock(); 83316613Ssam } 83414443Slinton } 83516613Ssam nn = identname(mname, true); 83616613Ssam if (curmodule == nil or curmodule->name != nn) { 83716613Ssam s = insert(nn); 83816613Ssam s->class = MODULE; 83916613Ssam s->symvalue.funcv.beginaddr = 0; 84016613Ssam findbeginning(s); 84116613Ssam } else { 84216613Ssam s = curmodule; 84316613Ssam } 84416613Ssam s->language = curlang; 84516613Ssam enterblock(s); 84616613Ssam curmodule = s; 84714443Slinton } 84814443Slinton if (program->language == nil) { 84914443Slinton program->language = curlang; 85014443Slinton } 85114443Slinton warned = false; 85214443Slinton enterfile(ident(n), addr); 85316613Ssam initTypeTable(); 85414443Slinton } 85514443Slinton 85614443Slinton /* 8579673Slinton * Allocate file and line tables and initialize indices. 8589673Slinton */ 8599673Slinton 86016613Ssam private allocmaps (nf, nl) 86116613Ssam integer nf, nl; 8629673Slinton { 8639673Slinton if (filetab != nil) { 8649673Slinton dispose(filetab); 8659673Slinton } 8669673Slinton if (linetab != nil) { 8679673Slinton dispose(linetab); 8689673Slinton } 8699673Slinton filetab = newarr(Filetab, nf); 8709673Slinton linetab = newarr(Linetab, nl); 8719673Slinton filep = filetab; 8729673Slinton linep = linetab; 8739673Slinton } 8749673Slinton 8759673Slinton /* 8769673Slinton * Add a file to the file table. 87713938Slinton * 87813938Slinton * If the new address is the same as the previous file address 87913938Slinton * this routine used to not enter the file, but this caused some 88013938Slinton * problems so it has been removed. It's not clear that this in 88113938Slinton * turn may not also cause a problem. 8829673Slinton */ 8839673Slinton 88416613Ssam private enterfile (filename, addr) 8859673Slinton String filename; 8869673Slinton Address addr; 8879673Slinton { 88813938Slinton filep->addr = addr; 88913938Slinton filep->filename = filename; 89013938Slinton filep->lineindex = linep - linetab; 89113938Slinton ++filep; 8929673Slinton } 8939673Slinton 8949673Slinton /* 8959673Slinton * Since we only estimated the number of lines (and it was a poor 8969673Slinton * estimation) and since we need to know the exact number of lines 8979673Slinton * to do a binary search, we set it when we're done. 8989673Slinton */ 8999673Slinton 90016613Ssam private setnlines () 9019673Slinton { 9029673Slinton nlhdr.nlines = linep - linetab; 9039673Slinton } 9049673Slinton 9059673Slinton /* 9069673Slinton * Similarly for nfiles ... 9079673Slinton */ 9089673Slinton 90916613Ssam private setnfiles () 9109673Slinton { 9119673Slinton nlhdr.nfiles = filep - filetab; 9129673Slinton setsource(filetab[0].filename); 9139673Slinton } 914