19673Slinton /* Copyright (c) 1982 Regents of the University of California */ 29673Slinton 3*14443Slinton static char sccsid[] = "@(#)object.c 1.11 08/10/83"; 49673Slinton 59673Slinton /* 69673Slinton * Object code interface, mainly for extraction of symbolic information. 79673Slinton */ 89673Slinton 99673Slinton #include "defs.h" 109673Slinton #include "object.h" 119673Slinton #include "main.h" 129673Slinton #include "symbols.h" 139673Slinton #include "names.h" 149673Slinton #include "languages.h" 159673Slinton #include "mappings.h" 169673Slinton #include "lists.h" 179673Slinton #include <a.out.h> 189673Slinton #include <stab.h> 199673Slinton #include <ctype.h> 209673Slinton 219673Slinton #ifndef public 229673Slinton 239673Slinton struct { 249673Slinton unsigned int stringsize; /* size of the dumped string table */ 259673Slinton unsigned int nsyms; /* number of symbols */ 269673Slinton unsigned int nfiles; /* number of files */ 279673Slinton unsigned int nlines; /* number of lines */ 289673Slinton } nlhdr; 299673Slinton 309673Slinton #endif 319673Slinton 329673Slinton public String objname = "a.out"; 339673Slinton public Integer objsize; 349673Slinton public char *stringtab; 359673Slinton 369673Slinton private String progname = nil; 379673Slinton private Language curlang; 389673Slinton private Symbol curmodule; 399673Slinton private Symbol curparam; 409673Slinton private Boolean warned; 4112542Scsvaf private Symbol curcomm; 4212542Scsvaf private Symbol commchain; 4312542Scsvaf private Boolean strip_ = false; 449673Slinton 459673Slinton private Filetab *filep; 4611875Slinton private Linetab *linep, *prevlinep; 479673Slinton 489673Slinton #define curfilename() (filep-1)->filename 499673Slinton 509673Slinton /* 519673Slinton * Blocks are figured out on the fly while reading the symbol table. 529673Slinton */ 539673Slinton 549673Slinton #define MAXBLKDEPTH 25 559673Slinton 569673Slinton private Symbol curblock; 579673Slinton private Symbol blkstack[MAXBLKDEPTH]; 589673Slinton private Integer curlevel; 59*14443Slinton private Integer bnum, nesting; 60*14443Slinton private Address addrstk[MAXBLKDEPTH]; 619673Slinton 629673Slinton #define enterblock(b) { \ 639673Slinton blkstack[curlevel] = curblock; \ 649673Slinton ++curlevel; \ 659673Slinton b->level = curlevel; \ 669673Slinton b->block = curblock; \ 679673Slinton curblock = b; \ 689673Slinton } 699673Slinton 709673Slinton #define exitblock() { \ 7111875Slinton if (curblock->class == FUNC or curblock->class == PROC) { \ 7211875Slinton if (prevlinep != linep) { \ 7311875Slinton curblock->symvalue.funcv.src = true; \ 7411875Slinton } \ 7511875Slinton } \ 769673Slinton --curlevel; \ 779673Slinton curblock = blkstack[curlevel]; \ 789673Slinton } 799673Slinton 809673Slinton /* 819673Slinton * Enter a source line or file name reference into the appropriate table. 829673Slinton * Expanded inline to reduce procedure calls. 839673Slinton * 849673Slinton * private enterline(linenumber, address) 859673Slinton * Lineno linenumber; 869673Slinton * Address address; 879673Slinton * ... 889673Slinton */ 899673Slinton 909673Slinton #define enterline(linenumber, address) \ 919673Slinton { \ 929673Slinton register Linetab *lp; \ 939673Slinton \ 949673Slinton lp = linep - 1; \ 959673Slinton if (linenumber != lp->line) { \ 969673Slinton if (address != lp->addr) { \ 979673Slinton ++lp; \ 989673Slinton } \ 999673Slinton lp->line = linenumber; \ 1009673Slinton lp->addr = address; \ 1019673Slinton linep = lp + 1; \ 1029673Slinton } \ 1039673Slinton } 1049673Slinton 1059673Slinton #define NTYPES 1000 1069673Slinton 1079673Slinton private Symbol typetable[NTYPES]; 1089673Slinton 1099673Slinton /* 1109673Slinton * Read in the namelist from the obj file. 1119673Slinton * 1129673Slinton * Reads and seeks are used instead of fread's and fseek's 1139673Slinton * for efficiency sake; there's a lot of data being read here. 1149673Slinton */ 1159673Slinton 1169673Slinton public readobj(file) 1179673Slinton String file; 1189673Slinton { 1199673Slinton Fileid f; 1209673Slinton struct exec hdr; 1219673Slinton struct nlist nlist; 1229673Slinton 1239673Slinton f = open(file, 0); 1249673Slinton if (f < 0) { 1259673Slinton fatal("can't open %s", file); 1269673Slinton } 1279673Slinton read(f, &hdr, sizeof(hdr)); 1289673Slinton objsize = hdr.a_text; 1299673Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 1309673Slinton nlhdr.nfiles = nlhdr.nsyms; 1319673Slinton nlhdr.nlines = nlhdr.nsyms; 132*14443Slinton if (nlhdr.nsyms > 0) { 133*14443Slinton lseek(f, (long) N_STROFF(hdr), 0); 134*14443Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 135*14443Slinton nlhdr.stringsize -= 4; 136*14443Slinton stringtab = newarr(char, nlhdr.stringsize); 137*14443Slinton read(f, stringtab, nlhdr.stringsize); 138*14443Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 139*14443Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 140*14443Slinton readsyms(f); 141*14443Slinton ordfunctab(); 142*14443Slinton setnlines(); 143*14443Slinton setnfiles(); 144*14443Slinton } 1459673Slinton close(f); 1469673Slinton } 1479673Slinton 1489673Slinton /* 1499673Slinton * Read in symbols from object file. 1509673Slinton */ 1519673Slinton 1529673Slinton private readsyms(f) 1539673Slinton Fileid f; 1549673Slinton { 1559673Slinton struct nlist *namelist; 1569673Slinton register struct nlist *np, *ub; 1579673Slinton register int index; 1589673Slinton register String name; 1599673Slinton register Boolean afterlg; 1609673Slinton 1619673Slinton initsyms(); 1629673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 1639673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 1649673Slinton afterlg = false; 1659673Slinton ub = &namelist[nlhdr.nsyms]; 1669673Slinton for (np = &namelist[0]; np < ub; np++) { 1679673Slinton index = np->n_un.n_strx; 1689673Slinton if (index != 0) { 1699673Slinton name = &stringtab[index - 4]; 17012542Scsvaf /* 17112542Scsvaf * if the program contains any .f files a trailing _ is stripped 17212542Scsvaf * from the name on the assumption it was added by the compiler. 17312542Scsvaf * This only affects names that follow the sdb N_SO entry with 17412542Scsvaf * the .f name. 17512542Scsvaf */ 176*14443Slinton if (strip_ and name[0] != '\0' ) { 177*14443Slinton register char *p; 178*14443Slinton 179*14443Slinton p = name; 180*14443Slinton while (*p != '\0') { 181*14443Slinton ++p; 182*14443Slinton } 183*14443Slinton --p; 184*14443Slinton if (*p == '-') { 185*14443Slinton *p = '\0'; 186*14443Slinton } 18712542Scsvaf } 18812542Scsvaf 1899673Slinton } else { 1909673Slinton name = nil; 19112542Scsvaf } 1929673Slinton /* 1939673Slinton * assumptions: 1949673Slinton * not an N_STAB ==> name != nil 1959673Slinton * name[0] == '-' ==> name == "-lg" 1969673Slinton * name[0] != '_' ==> filename or invisible 1979673Slinton * 1989673Slinton * The "-lg" signals the beginning of global loader symbols. 19912542Scsvaf * 2009673Slinton */ 2019673Slinton if ((np->n_type&N_STAB) != 0) { 2029673Slinton enter_nl(name, np); 2039673Slinton } else if (name[0] == '-') { 2049673Slinton afterlg = true; 2059673Slinton if (curblock->class != PROG) { 2069673Slinton exitblock(); 2079673Slinton if (curblock->class != PROG) { 2089673Slinton exitblock(); 2099673Slinton } 2109673Slinton } 2119673Slinton enterline(0, (linep-1)->addr + 1); 21211104Slinton } else if (afterlg) { 21311104Slinton if (name[0] == '_') { 2149673Slinton check_global(&name[1], np); 2159673Slinton } 21611104Slinton } else if (name[0] == '_') { 21711104Slinton check_local(&name[1], np); 2189673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 2199673Slinton check_filename(name); 2209673Slinton } 2219673Slinton } 222*14443Slinton if (not afterlg) { 223*14443Slinton panic("not linked for debugging, use \"cc -g ...\""); 224*14443Slinton } 2259673Slinton dispose(namelist); 2269673Slinton } 2279673Slinton 2289673Slinton /* 2299673Slinton * Initialize symbol information. 2309673Slinton */ 2319673Slinton 2329673Slinton private initsyms() 2339673Slinton { 2349673Slinton curblock = nil; 2359673Slinton curlevel = 0; 236*14443Slinton nesting = 0; 2379673Slinton if (progname == nil) { 2389673Slinton progname = strdup(objname); 2399673Slinton if (rindex(progname, '/') != nil) { 2409673Slinton progname = rindex(progname, '/') + 1; 2419673Slinton } 2429673Slinton if (index(progname, '.') != nil) { 2439673Slinton *(index(progname, '.')) = '\0'; 2449673Slinton } 2459673Slinton } 2469673Slinton program = insert(identname(progname, true)); 2479673Slinton program->class = PROG; 24811769Slinton program->symvalue.funcv.beginaddr = 0; 249*14443Slinton program->symvalue.funcv.inline = false; 250*14443Slinton newfunc(program, codeloc(program)); 25111769Slinton findbeginning(program); 2529673Slinton enterblock(program); 2539673Slinton curmodule = program; 2549673Slinton t_boolean = maketype("$boolean", 0L, 1L); 2559673Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 2569673Slinton t_char = maketype("$char", 0L, 127L); 25713838Slinton t_real = maketype("$real", 8L, 0L); 2589673Slinton t_nil = maketype("$nil", 0L, 0L); 2599673Slinton } 2609673Slinton 2619673Slinton /* 2629673Slinton * Free all the object file information that's being stored. 2639673Slinton */ 2649673Slinton 2659673Slinton public objfree() 2669673Slinton { 2679673Slinton symbol_free(); 2689673Slinton keywords_free(); 2699673Slinton names_free(); 2709673Slinton dispose(stringtab); 2719673Slinton clrfunctab(); 2729673Slinton } 2739673Slinton 2749673Slinton /* 2759673Slinton * Enter a namelist entry. 2769673Slinton */ 2779673Slinton 2789673Slinton private enter_nl(name, np) 2799673Slinton String name; 2809673Slinton register struct nlist *np; 2819673Slinton { 2829673Slinton register Symbol s; 28311875Slinton register Name n, nn; 284*14443Slinton char buf[100]; 2859673Slinton 2869673Slinton s = nil; 2879673Slinton if (name == nil) { 2889673Slinton n = nil; 2899673Slinton } else { 2909673Slinton n = identname(name, true); 2919673Slinton } 2929673Slinton switch (np->n_type) { 293*14443Slinton /* 294*14443Slinton * Build a symbol for the FORTRAN common area. All GSYMS that follow 295*14443Slinton * will be chained in a list with the head kept in common.offset, and 296*14443Slinton * the tail in common.chain. 297*14443Slinton */ 29813938Slinton case N_BCOMM: 29913938Slinton if (curcomm) { 30013938Slinton curcomm->symvalue.common.chain = commchain; 30112542Scsvaf } 30212542Scsvaf curcomm = lookup(n); 30313938Slinton if (curcomm == nil) { 30413938Slinton curcomm = insert(n); 30513938Slinton curcomm->class = COMMON; 30613938Slinton curcomm->block = curblock; 30713938Slinton curcomm->level = program->level; 30813938Slinton curcomm->symvalue.common.chain = nil; 30912542Scsvaf } 31012542Scsvaf commchain = curcomm->symvalue.common.chain; 31113938Slinton break; 31212542Scsvaf 31312542Scsvaf case N_ECOMM: 31413938Slinton if (curcomm) { 31513938Slinton curcomm->symvalue.common.chain = commchain; 31613938Slinton curcomm = nil; 31712542Scsvaf } 31812542Scsvaf break; 319*14443Slinton 3209673Slinton case N_LBRAC: 321*14443Slinton ++nesting; 322*14443Slinton addrstk[nesting] = (linep - 1)->addr; 3239673Slinton break; 3249673Slinton 3259673Slinton case N_RBRAC: 326*14443Slinton if (addrstk[nesting] == NOADDR) { 327*14443Slinton exitblock(); 328*14443Slinton newfunc(curblock, (linep - 1)->addr); 329*14443Slinton } 330*14443Slinton --nesting; 3319673Slinton break; 3329673Slinton 3339673Slinton case N_SLINE: 3349673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 3359673Slinton break; 3369673Slinton 3379673Slinton /* 338*14443Slinton * Source files. 3399673Slinton */ 3409673Slinton case N_SO: 341*14443Slinton enterSourceModule(n, (Address) np->n_value); 3429673Slinton break; 3439673Slinton 3449673Slinton /* 3459673Slinton * Textually included files. 3469673Slinton */ 3479673Slinton case N_SOL: 3489673Slinton enterfile(name, (Address) np->n_value); 3499673Slinton break; 3509673Slinton 3519673Slinton /* 3529673Slinton * These symbols are assumed to have non-nil names. 3539673Slinton */ 3549673Slinton case N_GSYM: 3559673Slinton case N_FUN: 3569673Slinton case N_STSYM: 3579673Slinton case N_LCSYM: 3589673Slinton case N_RSYM: 3599673Slinton case N_PSYM: 3609673Slinton case N_LSYM: 3619673Slinton case N_SSYM: 362*14443Slinton case N_LENG: 3639673Slinton if (index(name, ':') == nil) { 3649673Slinton if (not warned) { 3659673Slinton warned = true; 3669673Slinton warning("old style symbol information found in \"%s\"", 3679673Slinton curfilename()); 3689673Slinton } 3699673Slinton } else { 3709673Slinton entersym(name, np); 3719673Slinton } 3729673Slinton break; 3739673Slinton 3749673Slinton case N_PC: 3759673Slinton break; 3769673Slinton 37711558Slinton default: 378*14443Slinton printf("warning: stab entry unrecognized: "); 3799673Slinton if (name != nil) { 380*14443Slinton printf("name %s,", name); 3819673Slinton } 382*14443Slinton printf("ntype %2x, desc %x, value %x'\n", 3839673Slinton np->n_type, np->n_desc, np->n_value); 3849673Slinton break; 3859673Slinton } 3869673Slinton } 3879673Slinton 3889673Slinton /* 3899673Slinton * Check to see if a global _name is already in the symbol table, 3909673Slinton * if not then insert it. 3919673Slinton */ 3929673Slinton 3939673Slinton private check_global(name, np) 3949673Slinton String name; 3959673Slinton register struct nlist *np; 3969673Slinton { 3979673Slinton register Name n; 39812542Scsvaf register Symbol t, u; 3999673Slinton 4009673Slinton if (not streq(name, "end")) { 4019673Slinton n = identname(name, true); 4029673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 4039673Slinton find(t, n) where 404*14443Slinton t->level == program->level and 405*14443Slinton (t->class == PROC or t->class == FUNC) 4069673Slinton endfind(t); 4079673Slinton if (t == nil) { 4089673Slinton t = insert(n); 4099673Slinton t->language = findlanguage(".s"); 4109673Slinton t->class = FUNC; 4119673Slinton t->type = t_int; 4129673Slinton t->block = curblock; 4139673Slinton t->level = program->level; 41411875Slinton t->symvalue.funcv.src = false; 415*14443Slinton t->symvalue.funcv.inline = false; 4169673Slinton } 4179673Slinton t->symvalue.funcv.beginaddr = np->n_value; 418*14443Slinton newfunc(t, codeloc(t)); 4199673Slinton findbeginning(t); 42013938Slinton } else if ((np->n_type&N_TYPE) == N_BSS) { 4219673Slinton find(t, n) where 42213938Slinton t->class == COMMON 42312542Scsvaf endfind(t); 42413938Slinton if (t != nil) { 42513938Slinton u = (Symbol) t->symvalue.common.offset; 42613938Slinton while (u != nil) { 42713938Slinton u->symvalue.offset = u->symvalue.common.offset+np->n_value; 42813938Slinton u = u->symvalue.common.chain; 42913938Slinton } 43013938Slinton } else { 43113938Slinton check_var(np, n); 4329673Slinton } 43313938Slinton } else { 43413938Slinton check_var(np, n); 4359673Slinton } 4369673Slinton } 4379673Slinton } 4389673Slinton 4399673Slinton /* 44013938Slinton * Check to see if a namelist entry refers to a variable. 44113938Slinton * If not, create a variable for the entry. In any case, 44213938Slinton * set the offset of the variable according to the value field 44313938Slinton * in the entry. 44413938Slinton */ 44513938Slinton 44613938Slinton private check_var(np, n) 44713938Slinton struct nlist *np; 44813938Slinton register Name n; 44913938Slinton { 45013938Slinton register Symbol t; 45113938Slinton 45213938Slinton find(t, n) where 45313938Slinton t->class == VAR and t->level == program->level 45413938Slinton endfind(t); 45513938Slinton if (t == nil) { 45613938Slinton t = insert(n); 45713938Slinton t->language = findlanguage(".s"); 45813938Slinton t->class = VAR; 45913938Slinton t->type = t_int; 46013938Slinton t->level = program->level; 46113938Slinton } 46213938Slinton t->block = curblock; 46313938Slinton t->symvalue.offset = np->n_value; 46413938Slinton } 46513938Slinton 46613938Slinton /* 4679673Slinton * Check to see if a local _name is known in the current scope. 4689673Slinton * If not then enter it. 4699673Slinton */ 4709673Slinton 4719673Slinton private check_local(name, np) 4729673Slinton String name; 4739673Slinton register struct nlist *np; 4749673Slinton { 4759673Slinton register Name n; 4769673Slinton register Symbol t, cur; 4779673Slinton 4789673Slinton n = identname(name, true); 4799673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 4809673Slinton find(t, n) where t->block == cur endfind(t); 4819673Slinton if (t == nil) { 4829673Slinton t = insert(n); 4839673Slinton t->language = findlanguage(".s"); 4849673Slinton t->type = t_int; 4859673Slinton t->block = cur; 4869673Slinton t->level = cur->level; 4879673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 4889673Slinton t->class = FUNC; 48911875Slinton t->symvalue.funcv.src = false; 490*14443Slinton t->symvalue.funcv.inline = false; 4919673Slinton t->symvalue.funcv.beginaddr = np->n_value; 492*14443Slinton newfunc(t, codeloc(t)); 4939673Slinton findbeginning(t); 4949673Slinton } else { 4959673Slinton t->class = VAR; 4969673Slinton t->symvalue.offset = np->n_value; 4979673Slinton } 4989673Slinton } 4999673Slinton } 5009673Slinton 5019673Slinton /* 5029673Slinton * Check to see if a symbol corresponds to a object file name. 5039673Slinton * For some reason these are listed as in the text segment. 5049673Slinton */ 5059673Slinton 5069673Slinton private check_filename(name) 5079673Slinton String name; 5089673Slinton { 5099673Slinton register String mname; 5109673Slinton register Integer i; 5119673Slinton register Symbol s; 5129673Slinton 5139673Slinton mname = strdup(name); 5149673Slinton i = strlen(mname) - 2; 5159673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 5169673Slinton mname[i] = '\0'; 5179673Slinton --i; 5189673Slinton while (mname[i] != '/' and i >= 0) { 5199673Slinton --i; 5209673Slinton } 5219673Slinton s = insert(identname(&mname[i+1], true)); 5229673Slinton s->language = findlanguage(".s"); 5239673Slinton s->class = MODULE; 52411769Slinton s->symvalue.funcv.beginaddr = 0; 52511769Slinton findbeginning(s); 5269673Slinton if (curblock->class != PROG) { 5279673Slinton exitblock(); 5289673Slinton if (curblock->class != PROG) { 5299673Slinton exitblock(); 5309673Slinton } 5319673Slinton } 5329673Slinton enterblock(s); 5339673Slinton curmodule = s; 5349673Slinton } 5359673Slinton } 5369673Slinton 5379673Slinton /* 538*14443Slinton * Check to see if a symbol is about to be defined within an unnamed block. 539*14443Slinton * If this happens, we create a procedure for the unnamed block, make it 540*14443Slinton * "inline" so that tracebacks don't associate an activation record with it, 541*14443Slinton * and enter it into the function table so that it will be detected 542*14443Slinton * by "whatblock". 543*14443Slinton */ 544*14443Slinton 545*14443Slinton private unnamed_block() 546*14443Slinton { 547*14443Slinton register Symbol s; 548*14443Slinton static int bnum = 0; 549*14443Slinton char buf[100]; 550*14443Slinton 551*14443Slinton ++bnum; 552*14443Slinton sprintf(buf, "$b%d", bnum); 553*14443Slinton s = insert(identname(buf, false)); 554*14443Slinton s->class = PROG; 555*14443Slinton s->symvalue.funcv.src = false; 556*14443Slinton s->symvalue.funcv.inline = true; 557*14443Slinton s->symvalue.funcv.beginaddr = addrstk[nesting]; 558*14443Slinton enterblock(s); 559*14443Slinton newfunc(s, addrstk[nesting]); 560*14443Slinton addrstk[nesting] = NOADDR; 561*14443Slinton } 562*14443Slinton 563*14443Slinton /* 564*14443Slinton * Compilation unit. C associates scope with filenames 565*14443Slinton * so we treat them as "modules". The filename without 566*14443Slinton * the suffix is used for the module name. 567*14443Slinton * 568*14443Slinton * Because there is no explicit "end-of-block" mark in 569*14443Slinton * the object file, we must exit blocks for the current 570*14443Slinton * procedure and module. 571*14443Slinton */ 572*14443Slinton 573*14443Slinton private enterSourceModule(n, addr) 574*14443Slinton Name n; 575*14443Slinton Address addr; 576*14443Slinton { 577*14443Slinton register Symbol s; 578*14443Slinton Name nn; 579*14443Slinton String mname, suffix; 580*14443Slinton 581*14443Slinton mname = strdup(ident(n)); 582*14443Slinton if (rindex(mname, '/') != nil) { 583*14443Slinton mname = rindex(mname, '/') + 1; 584*14443Slinton } 585*14443Slinton suffix = rindex(mname, '.'); 586*14443Slinton curlang = findlanguage(suffix); 587*14443Slinton if (curlang == findlanguage(".f")) { 588*14443Slinton strip_ = true; 589*14443Slinton } 590*14443Slinton if (suffix != nil) { 591*14443Slinton *suffix = '\0'; 592*14443Slinton } 593*14443Slinton if (curblock->class != PROG) { 594*14443Slinton exitblock(); 595*14443Slinton if (curblock->class != PROG) { 596*14443Slinton exitblock(); 597*14443Slinton } 598*14443Slinton } 599*14443Slinton nn = identname(mname, true); 600*14443Slinton if (curmodule == nil or curmodule->name != nn) { 601*14443Slinton s = insert(nn); 602*14443Slinton s->class = MODULE; 603*14443Slinton s->symvalue.funcv.beginaddr = 0; 604*14443Slinton findbeginning(s); 605*14443Slinton } else { 606*14443Slinton s = curmodule; 607*14443Slinton } 608*14443Slinton s->language = curlang; 609*14443Slinton enterblock(s); 610*14443Slinton curmodule = s; 611*14443Slinton if (program->language == nil) { 612*14443Slinton program->language = curlang; 613*14443Slinton } 614*14443Slinton warned = false; 615*14443Slinton enterfile(ident(n), addr); 616*14443Slinton bzero(typetable, sizeof(typetable)); 617*14443Slinton } 618*14443Slinton 619*14443Slinton /* 6209673Slinton * Put an nlist into the symbol table. 6219673Slinton * If it's already there just add the associated information. 6229673Slinton * 6239673Slinton * Type information is encoded in the name following a ":". 6249673Slinton */ 6259673Slinton 6269673Slinton private Symbol constype(); 6279673Slinton private Char *curchar; 6289673Slinton 6299673Slinton #define skipchar(ptr, ch) { \ 6309673Slinton if (*ptr != ch) { \ 6319673Slinton panic("expected char '%c', found char '%c'", ch, *ptr); \ 6329673Slinton } \ 6339673Slinton ++ptr; \ 6349673Slinton } 6359673Slinton 6369673Slinton private entersym(str, np) 6379673Slinton String str; 6389673Slinton struct nlist *np; 6399673Slinton { 6409673Slinton register Symbol s; 6419673Slinton register char *p; 6429673Slinton register int c; 6439673Slinton register Name n; 6449673Slinton register Integer i; 6459673Slinton Boolean knowtype, isnew; 6469673Slinton Symclass class; 6479673Slinton Integer level; 6489673Slinton 6499673Slinton p = index(str, ':'); 6509673Slinton *p = '\0'; 6519673Slinton c = *(p+1); 6529673Slinton n = identname(str, true); 6539673Slinton if (index("FfGV", c) != nil) { 6549673Slinton if (c == 'F' or c == 'f') { 6559673Slinton class = FUNC; 6569673Slinton } else { 6579673Slinton class = VAR; 6589673Slinton } 6599673Slinton level = (c == 'f' ? curmodule->level : program->level); 6609673Slinton find(s, n) where s->level == level and s->class == class endfind(s); 6619673Slinton if (s == nil) { 6629673Slinton isnew = true; 6639673Slinton s = insert(n); 6649673Slinton } else { 6659673Slinton isnew = false; 6669673Slinton } 6679673Slinton } else { 6689673Slinton isnew = true; 6699673Slinton s = insert(n); 6709673Slinton } 6719673Slinton 672*14443Slinton if (nesting > 0 and addrstk[nesting] != NOADDR) { 673*14443Slinton unnamed_block(); 674*14443Slinton } 675*14443Slinton 6769673Slinton /* 6779673Slinton * Default attributes. 6789673Slinton */ 6799673Slinton s->language = curlang; 6809673Slinton s->class = VAR; 6819673Slinton s->block = curblock; 6829673Slinton s->level = curlevel; 6839673Slinton s->symvalue.offset = np->n_value; 6849673Slinton curchar = p + 2; 6859673Slinton knowtype = false; 6869673Slinton switch (c) { 6879673Slinton case 't': /* type name */ 6889673Slinton s->class = TYPE; 6899673Slinton i = getint(); 6909673Slinton if (i == 0) { 6919673Slinton panic("bad input on type \"%s\" at \"%s\"", symname(s), 6929673Slinton curchar); 6939673Slinton } else if (i >= NTYPES) { 6949673Slinton panic("too many types in file \"%s\"", curfilename()); 6959673Slinton } 6969673Slinton /* 6979673Slinton * A hack for C typedefs that don't create new types, 6989673Slinton * e.g. typedef unsigned int Hashvalue; 69911558Slinton * or typedef struct blah BLAH; 7009673Slinton */ 7019673Slinton if (*curchar == '\0') { 7029673Slinton s->type = typetable[i]; 7039673Slinton if (s->type == nil) { 70411558Slinton s->type = symbol_alloc(); 70511558Slinton typetable[i] = s->type; 7069673Slinton } 7079673Slinton knowtype = true; 7089673Slinton } else { 7099673Slinton typetable[i] = s; 7109673Slinton skipchar(curchar, '='); 7119673Slinton } 7129673Slinton break; 7139673Slinton 7149673Slinton case 'T': /* tag */ 7159673Slinton s->class = TAG; 7169673Slinton i = getint(); 7179673Slinton if (i == 0) { 7189673Slinton panic("bad input on tag \"%s\" at \"%s\"", symname(s), 7199673Slinton curchar); 7209673Slinton } else if (i >= NTYPES) { 7219673Slinton panic("too many types in file \"%s\"", curfilename()); 7229673Slinton } 7239673Slinton if (typetable[i] != nil) { 7249673Slinton typetable[i]->language = curlang; 7259673Slinton typetable[i]->class = TYPE; 7269673Slinton typetable[i]->type = s; 7279673Slinton } else { 7289673Slinton typetable[i] = s; 7299673Slinton } 7309673Slinton skipchar(curchar, '='); 7319673Slinton break; 7329673Slinton 7339673Slinton case 'F': /* public function */ 7349673Slinton case 'f': /* private function */ 7359673Slinton s->class = FUNC; 7369673Slinton if (curblock->class == FUNC or curblock->class == PROC) { 7379673Slinton exitblock(); 7389673Slinton } 7399673Slinton enterblock(s); 7409673Slinton if (c == 'F') { 7419673Slinton s->level = program->level; 7429673Slinton isnew = false; 7439673Slinton } 7449673Slinton curparam = s; 7459673Slinton if (isnew) { 74611875Slinton s->symvalue.funcv.src = false; 747*14443Slinton s->symvalue.funcv.inline = false; 7489673Slinton s->symvalue.funcv.beginaddr = np->n_value; 749*14443Slinton newfunc(s, codeloc(s)); 7509673Slinton findbeginning(s); 7519673Slinton } 7529673Slinton break; 7539673Slinton 7549673Slinton case 'G': /* public variable */ 7559673Slinton s->level = program->level; 7569673Slinton break; 7579673Slinton 7589673Slinton case 'S': /* private variable */ 7599673Slinton s->level = curmodule->level; 7609673Slinton s->block = curmodule; 7619673Slinton break; 7629673Slinton 76312542Scsvaf /* 76412542Scsvaf * keep global BSS variables chained so can resolve when get the start 76512542Scsvaf * of common; keep the list in order so f77 can display all vars in a COMMON 76612542Scsvaf */ 7679673Slinton case 'V': /* own variable */ 7689673Slinton s->level = 2; 76912542Scsvaf if (curcomm) { 77012542Scsvaf if (commchain != nil) { 77112542Scsvaf commchain->symvalue.common.chain = s; 77212542Scsvaf } 77312542Scsvaf else { 77412542Scsvaf curcomm->symvalue.common.offset = (int) s; 77512542Scsvaf } 77612542Scsvaf commchain = s; 77712542Scsvaf s->symvalue.common.offset = np->n_value; 77812542Scsvaf s->symvalue.common.chain = nil; 77912542Scsvaf } 7809673Slinton break; 7819673Slinton 7829673Slinton case 'r': /* register variable */ 7839673Slinton s->level = -(s->level); 7849673Slinton break; 7859673Slinton 7869673Slinton case 'p': /* parameter variable */ 7879673Slinton curparam->chain = s; 7889673Slinton curparam = s; 7899673Slinton break; 7909673Slinton 7919673Slinton case 'v': /* varies parameter */ 7929673Slinton s->class = REF; 7939673Slinton s->symvalue.offset = np->n_value; 7949673Slinton curparam->chain = s; 7959673Slinton curparam = s; 7969673Slinton break; 7979673Slinton 7989673Slinton default: /* local variable */ 7999673Slinton --curchar; 8009673Slinton break; 8019673Slinton } 8029673Slinton if (not knowtype) { 8039673Slinton s->type = constype(nil); 8049673Slinton if (s->class == TAG) { 8059673Slinton addtag(s); 8069673Slinton } 8079673Slinton } 8089673Slinton if (tracesyms) { 8099673Slinton printdecl(s); 8109673Slinton fflush(stdout); 8119673Slinton } 8129673Slinton } 8139673Slinton 8149673Slinton /* 8159673Slinton * Construct a type out of a string encoding. 8169673Slinton * 8179673Slinton * The forms of the string are 8189673Slinton * 8199673Slinton * <number> 8209673Slinton * <number>=<type> 8219673Slinton * r<type>;<number>;<number> $ subrange 8229673Slinton * a<type>;<type> $ array[index] of element 8239673Slinton * s{<name>:<type>;<number>;<number>} $ record 8249673Slinton * *<type> $ pointer 8259673Slinton */ 8269673Slinton 8279673Slinton private Symbol constype(type) 8289673Slinton Symbol type; 8299673Slinton { 8309673Slinton register Symbol t, u; 8319673Slinton register Char *p, *cur; 8329673Slinton register Integer n; 8339673Slinton Integer b; 8349673Slinton Name name; 8359673Slinton Char class; 8369673Slinton 8379673Slinton b = curlevel; 8389673Slinton if (isdigit(*curchar)) { 8399673Slinton n = getint(); 8409673Slinton if (n == 0) { 8419673Slinton panic("bad type number at \"%s\"", curchar); 8429673Slinton } else if (n >= NTYPES) { 8439673Slinton panic("too many types in file \"%s\"", curfilename()); 8449673Slinton } 8459673Slinton if (*curchar == '=') { 8469673Slinton if (typetable[n] != nil) { 8479673Slinton t = typetable[n]; 8489673Slinton } else { 8499673Slinton t = symbol_alloc(); 8509673Slinton typetable[n] = t; 8519673Slinton } 8529673Slinton ++curchar; 8539673Slinton constype(t); 8549673Slinton } else { 8559673Slinton t = typetable[n]; 8569673Slinton if (t == nil) { 8579673Slinton t = symbol_alloc(); 8589673Slinton typetable[n] = t; 8599673Slinton } 8609673Slinton } 8619673Slinton } else { 8629673Slinton if (type == nil) { 8639673Slinton t = symbol_alloc(); 8649673Slinton } else { 8659673Slinton t = type; 8669673Slinton } 8679673Slinton t->language = curlang; 8689673Slinton t->level = b; 86912542Scsvaf t->block = curblock; 8709673Slinton class = *curchar++; 8719673Slinton switch (class) { 87212542Scsvaf 8739673Slinton case 'r': 8749673Slinton t->class = RANGE; 8759673Slinton t->type = constype(nil); 8769673Slinton skipchar(curchar, ';'); 87712542Scsvaf /* some letters indicate a dynamic bound, ie what follows 87812542Scsvaf is the offset from the fp which contains the bound; this will 87912542Scsvaf need a different encoding when pc a['A'..'Z'] is 88012542Scsvaf added; J is a special flag to handle fortran a(*) bounds 88112542Scsvaf */ 88212542Scsvaf switch(*curchar) { 88312542Scsvaf case 'A': 88412542Scsvaf t->symvalue.rangev.lowertype = R_ARG; 88512542Scsvaf curchar++; 88612542Scsvaf break; 88712542Scsvaf 88812542Scsvaf case 'T': 88912542Scsvaf t->symvalue.rangev.lowertype = R_TEMP; 89012542Scsvaf curchar++; 89112542Scsvaf break; 89212542Scsvaf 89312542Scsvaf case 'J': 89412542Scsvaf t->symvalue.rangev.lowertype = R_ADJUST; 89512542Scsvaf curchar++; 89612542Scsvaf break; 89712542Scsvaf 89812542Scsvaf default: 89912542Scsvaf t->symvalue.rangev.lowertype = R_CONST; 90012542Scsvaf break; 90112542Scsvaf 90212542Scsvaf } 90312542Scsvaf t->symvalue.rangev.lower = getint(); 9049673Slinton skipchar(curchar, ';'); 90512542Scsvaf switch(*curchar) { 90612542Scsvaf case 'A': 90712542Scsvaf t->symvalue.rangev.uppertype = R_ARG; 90812542Scsvaf curchar++; 90912542Scsvaf break; 91012542Scsvaf 91112542Scsvaf case 'T': 91212542Scsvaf t->symvalue.rangev.uppertype = R_TEMP; 91312542Scsvaf curchar++; 91412542Scsvaf break; 91512542Scsvaf 91612542Scsvaf case 'J': 91712542Scsvaf t->symvalue.rangev.uppertype = R_ADJUST; 91812542Scsvaf curchar++; 91912542Scsvaf break; 92012542Scsvaf 92112542Scsvaf default: 92212542Scsvaf t->symvalue.rangev.uppertype = R_CONST; 92312542Scsvaf break; 92412542Scsvaf 92512542Scsvaf } 9269673Slinton t->symvalue.rangev.upper = getint(); 9279673Slinton break; 9289673Slinton 9299673Slinton case 'a': 9309673Slinton t->class = ARRAY; 9319673Slinton t->chain = constype(nil); 9329673Slinton skipchar(curchar, ';'); 9339673Slinton t->type = constype(nil); 9349673Slinton break; 9359673Slinton 9369673Slinton case 's': 9379673Slinton case 'u': 9389673Slinton t->class = (class == 's') ? RECORD : VARNT; 9399673Slinton t->symvalue.offset = getint(); 9409673Slinton u = t; 9419673Slinton cur = curchar; 9429673Slinton while (*cur != ';' and *cur != '\0') { 9439673Slinton p = index(cur, ':'); 9449673Slinton if (p == nil) { 9459673Slinton panic("index(\"%s\", ':') failed", curchar); 9469673Slinton } 9479673Slinton *p = '\0'; 9489673Slinton name = identname(cur, true); 9499673Slinton u->chain = newSymbol(name, b, FIELD, nil, nil); 9509673Slinton cur = p + 1; 9519673Slinton u = u->chain; 9529673Slinton u->language = curlang; 9539673Slinton curchar = cur; 9549673Slinton u->type = constype(nil); 9559673Slinton skipchar(curchar, ','); 9569673Slinton u->symvalue.field.offset = getint(); 9579673Slinton skipchar(curchar, ','); 9589673Slinton u->symvalue.field.length = getint(); 9599673Slinton skipchar(curchar, ';'); 9609673Slinton cur = curchar; 9619673Slinton } 9629673Slinton if (*cur == ';') { 9639673Slinton ++cur; 9649673Slinton } 9659673Slinton curchar = cur; 9669673Slinton break; 9679673Slinton 9689673Slinton case 'e': 9699673Slinton t->class = SCAL; 9709673Slinton u = t; 9719673Slinton while (*curchar != ';' and *curchar != '\0') { 9729673Slinton p = index(curchar, ':'); 9739673Slinton assert(p != nil); 9749673Slinton *p = '\0'; 9759673Slinton u->chain = insert(identname(curchar, true)); 9769673Slinton curchar = p + 1; 9779673Slinton u = u->chain; 9789673Slinton u->language = curlang; 9799673Slinton u->class = CONST; 9809673Slinton u->level = b; 9819673Slinton u->block = curblock; 9829673Slinton u->type = t; 9839673Slinton u->symvalue.iconval = getint(); 9849673Slinton skipchar(curchar, ','); 9859673Slinton } 9869673Slinton break; 9879673Slinton 9889673Slinton case '*': 9899673Slinton t->class = PTR; 9909673Slinton t->type = constype(nil); 9919673Slinton break; 9929673Slinton 9939673Slinton case 'f': 9949673Slinton t->class = FUNC; 9959673Slinton t->type = constype(nil); 9969673Slinton break; 9979673Slinton 9989673Slinton default: 9999673Slinton badcaseval(class); 10009673Slinton } 10019673Slinton } 10029673Slinton return t; 10039673Slinton } 10049673Slinton 10059673Slinton /* 10069673Slinton * Read an integer from the current position in the type string. 10079673Slinton */ 10089673Slinton 10099673Slinton private Integer getint() 10109673Slinton { 10119673Slinton register Integer n; 10129673Slinton register char *p; 10139673Slinton register Boolean isneg; 10149673Slinton 10159673Slinton n = 0; 10169673Slinton p = curchar; 10179673Slinton if (*p == '-') { 10189673Slinton isneg = true; 10199673Slinton ++p; 10209673Slinton } else { 10219673Slinton isneg = false; 10229673Slinton } 10239673Slinton while (isdigit(*p)) { 10249673Slinton n = 10*n + (*p - '0'); 10259673Slinton ++p; 10269673Slinton } 10279673Slinton curchar = p; 10289673Slinton return isneg ? (-n) : n; 10299673Slinton } 10309673Slinton 10319673Slinton /* 10329673Slinton * Add a tag name. This is a kludge to be able to refer 10339673Slinton * to tags that have the same name as some other symbol 10349673Slinton * in the same block. 10359673Slinton */ 10369673Slinton 10379673Slinton private addtag(s) 10389673Slinton register Symbol s; 10399673Slinton { 10409673Slinton register Symbol t; 10419673Slinton char buf[100]; 10429673Slinton 10439673Slinton sprintf(buf, "$$%.90s", ident(s->name)); 10449673Slinton t = insert(identname(buf, false)); 10459673Slinton t->language = s->language; 10469673Slinton t->class = TAG; 10479673Slinton t->type = s->type; 10489673Slinton t->block = s->block; 10499673Slinton } 10509673Slinton 10519673Slinton /* 10529673Slinton * Allocate file and line tables and initialize indices. 10539673Slinton */ 10549673Slinton 10559673Slinton private allocmaps(nf, nl) 10569673Slinton Integer nf, nl; 10579673Slinton { 10589673Slinton if (filetab != nil) { 10599673Slinton dispose(filetab); 10609673Slinton } 10619673Slinton if (linetab != nil) { 10629673Slinton dispose(linetab); 10639673Slinton } 10649673Slinton filetab = newarr(Filetab, nf); 10659673Slinton linetab = newarr(Linetab, nl); 10669673Slinton filep = filetab; 10679673Slinton linep = linetab; 10689673Slinton } 10699673Slinton 10709673Slinton /* 10719673Slinton * Add a file to the file table. 107213938Slinton * 107313938Slinton * If the new address is the same as the previous file address 107413938Slinton * this routine used to not enter the file, but this caused some 107513938Slinton * problems so it has been removed. It's not clear that this in 107613938Slinton * turn may not also cause a problem. 10779673Slinton */ 10789673Slinton 10799673Slinton private enterfile(filename, addr) 10809673Slinton String filename; 10819673Slinton Address addr; 10829673Slinton { 108313938Slinton filep->addr = addr; 108413938Slinton filep->filename = filename; 108513938Slinton filep->lineindex = linep - linetab; 108613938Slinton ++filep; 10879673Slinton } 10889673Slinton 10899673Slinton /* 10909673Slinton * Since we only estimated the number of lines (and it was a poor 10919673Slinton * estimation) and since we need to know the exact number of lines 10929673Slinton * to do a binary search, we set it when we're done. 10939673Slinton */ 10949673Slinton 10959673Slinton private setnlines() 10969673Slinton { 10979673Slinton nlhdr.nlines = linep - linetab; 10989673Slinton } 10999673Slinton 11009673Slinton /* 11019673Slinton * Similarly for nfiles ... 11029673Slinton */ 11039673Slinton 11049673Slinton private setnfiles() 11059673Slinton { 11069673Slinton nlhdr.nfiles = filep - filetab; 11079673Slinton setsource(filetab[0].filename); 11089673Slinton } 1109