121615Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621615Sdist */ 179673Slinton 1821615Sdist #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)object.c 5.3 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 219673Slinton 229673Slinton /* 239673Slinton * Object code interface, mainly for extraction of symbolic information. 249673Slinton */ 259673Slinton 269673Slinton #include "defs.h" 279673Slinton #include "object.h" 2816613Ssam #include "stabstring.h" 299673Slinton #include "main.h" 309673Slinton #include "symbols.h" 319673Slinton #include "names.h" 329673Slinton #include "languages.h" 339673Slinton #include "mappings.h" 349673Slinton #include "lists.h" 359673Slinton #include <a.out.h> 369673Slinton #include <stab.h> 379673Slinton #include <ctype.h> 389673Slinton 399673Slinton #ifndef public 409673Slinton 419673Slinton struct { 429673Slinton unsigned int stringsize; /* size of the dumped string table */ 439673Slinton unsigned int nsyms; /* number of symbols */ 449673Slinton unsigned int nfiles; /* number of files */ 459673Slinton unsigned int nlines; /* number of lines */ 469673Slinton } nlhdr; 479673Slinton 4816613Ssam #include "languages.h" 4916613Ssam #include "symbols.h" 5016613Ssam 519673Slinton #endif 529673Slinton 5316613Ssam #ifndef N_MOD2 5416613Ssam # define N_MOD2 0x50 5516613Ssam #endif 5616613Ssam 579673Slinton public String objname = "a.out"; 5816613Ssam public integer objsize; 599673Slinton 6016613Ssam public Language curlang; 6116613Ssam public Symbol curmodule; 6216613Ssam public Symbol curparam; 6316613Ssam public Symbol curcomm; 6416613Ssam public Symbol commchain; 6516613Ssam 6616613Ssam private char *stringtab; 6716613Ssam private struct nlist *curnp; 689673Slinton private Boolean warned; 6912542Scsvaf private Boolean strip_ = false; 709673Slinton 719673Slinton private Filetab *filep; 7211875Slinton private Linetab *linep, *prevlinep; 739673Slinton 7416613Ssam public String curfilename () 7516613Ssam { 7616613Ssam return ((filep-1)->filename); 7716613Ssam } 789673Slinton 799673Slinton /* 809673Slinton * Blocks are figured out on the fly while reading the symbol table. 819673Slinton */ 829673Slinton 839673Slinton #define MAXBLKDEPTH 25 849673Slinton 8516613Ssam public Symbol curblock; 8616613Ssam 879673Slinton private Symbol blkstack[MAXBLKDEPTH]; 8816613Ssam private integer curlevel; 8916613Ssam private integer bnum, nesting; 9014443Slinton private Address addrstk[MAXBLKDEPTH]; 919673Slinton 9216613Ssam public pushBlock (b) 9316613Ssam Symbol b; 9416613Ssam { 9516613Ssam if (curlevel >= MAXBLKDEPTH) { 9616613Ssam fatal("nesting depth too large (%d)", curlevel); 9716613Ssam } 9816613Ssam blkstack[curlevel] = curblock; 9916613Ssam ++curlevel; 10016613Ssam curblock = b; 10116613Ssam if (traceblocks) { 10216613Ssam printf("entering block %s\n", symname(b)); 10316613Ssam } 1049673Slinton } 1059673Slinton 10618225Slinton /* 10718225Slinton * Change the current block with saving the previous one, 10818225Slinton * since it is assumed that the symbol for the current one is to be deleted. 10918225Slinton */ 11018225Slinton 11118225Slinton public changeBlock (b) 11218225Slinton Symbol b; 11318225Slinton { 11418225Slinton curblock = b; 11518225Slinton } 11618225Slinton 11716613Ssam public enterblock (b) 11816613Ssam Symbol b; 11916613Ssam { 12016613Ssam if (curblock == nil) { 12116613Ssam b->level = 1; 12216613Ssam } else { 12316613Ssam b->level = curblock->level + 1; 12416613Ssam } 12516613Ssam b->block = curblock; 12616613Ssam pushBlock(b); 1279673Slinton } 1289673Slinton 12916613Ssam public exitblock () 13016613Ssam { 13116613Ssam if (curblock->class == FUNC or curblock->class == PROC) { 13216613Ssam if (prevlinep != linep) { 13316613Ssam curblock->symvalue.funcv.src = true; 13416613Ssam } 13516613Ssam } 13616613Ssam if (curlevel <= 0) { 13716613Ssam panic("nesting depth underflow (%d)", curlevel); 13816613Ssam } 13916613Ssam --curlevel; 14016613Ssam if (traceblocks) { 14116613Ssam printf("exiting block %s\n", symname(curblock)); 14216613Ssam } 14316613Ssam curblock = blkstack[curlevel]; 14416613Ssam } 14516613Ssam 1469673Slinton /* 1479673Slinton * Enter a source line or file name reference into the appropriate table. 1489673Slinton * Expanded inline to reduce procedure calls. 1499673Slinton * 15016613Ssam * private enterline (linenumber, address) 1519673Slinton * Lineno linenumber; 1529673Slinton * Address address; 1539673Slinton * ... 1549673Slinton */ 1559673Slinton 1569673Slinton #define enterline(linenumber, address) \ 1579673Slinton { \ 1589673Slinton register Linetab *lp; \ 1599673Slinton \ 1609673Slinton lp = linep - 1; \ 1619673Slinton if (linenumber != lp->line) { \ 1629673Slinton if (address != lp->addr) { \ 1639673Slinton ++lp; \ 1649673Slinton } \ 1659673Slinton lp->line = linenumber; \ 1669673Slinton lp->addr = address; \ 1679673Slinton linep = lp + 1; \ 1689673Slinton } \ 1699673Slinton } 1709673Slinton 1719673Slinton /* 1729673Slinton * Read in the namelist from the obj file. 1739673Slinton * 1749673Slinton * Reads and seeks are used instead of fread's and fseek's 1759673Slinton * for efficiency sake; there's a lot of data being read here. 1769673Slinton */ 1779673Slinton 17816613Ssam public readobj (file) 1799673Slinton String file; 1809673Slinton { 1819673Slinton Fileid f; 1829673Slinton struct exec hdr; 1839673Slinton struct nlist nlist; 1849673Slinton 1859673Slinton f = open(file, 0); 1869673Slinton if (f < 0) { 1879673Slinton fatal("can't open %s", file); 1889673Slinton } 1899673Slinton read(f, &hdr, sizeof(hdr)); 19018225Slinton if (N_BADMAG(hdr)) { 19118225Slinton objsize = 0; 19218225Slinton nlhdr.nsyms = 0; 19318225Slinton nlhdr.nfiles = 0; 19418225Slinton nlhdr.nlines = 0; 19518225Slinton } else { 19618225Slinton objsize = hdr.a_text; 19718225Slinton nlhdr.nsyms = hdr.a_syms / sizeof(nlist); 19818225Slinton nlhdr.nfiles = nlhdr.nsyms; 19918225Slinton nlhdr.nlines = nlhdr.nsyms; 20018225Slinton } 20114443Slinton if (nlhdr.nsyms > 0) { 20214443Slinton lseek(f, (long) N_STROFF(hdr), 0); 20314443Slinton read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); 20414443Slinton nlhdr.stringsize -= 4; 20514443Slinton stringtab = newarr(char, nlhdr.stringsize); 20614443Slinton read(f, stringtab, nlhdr.stringsize); 20714443Slinton allocmaps(nlhdr.nfiles, nlhdr.nlines); 20814443Slinton lseek(f, (long) N_SYMOFF(hdr), 0); 20914443Slinton readsyms(f); 21014443Slinton ordfunctab(); 21114443Slinton setnlines(); 21214443Slinton setnfiles(); 21318225Slinton } else { 21418225Slinton initsyms(); 21514443Slinton } 2169673Slinton close(f); 2179673Slinton } 2189673Slinton 2199673Slinton /* 22018225Slinton * Found the beginning of the externals in the object file 22118225Slinton * (signified by the "-lg" or find an external), close the 22218225Slinton * block for the last procedure. 22318225Slinton */ 22418225Slinton 22518225Slinton private foundglobals () 22618225Slinton { 22718225Slinton if (curblock->class != PROG) { 22818225Slinton exitblock(); 22918225Slinton if (curblock->class != PROG) { 23018225Slinton exitblock(); 23118225Slinton } 23218225Slinton } 23318225Slinton enterline(0, (linep-1)->addr + 1); 23418225Slinton } 23518225Slinton 23618225Slinton /* 2379673Slinton * Read in symbols from object file. 2389673Slinton */ 2399673Slinton 24016613Ssam private readsyms (f) 2419673Slinton Fileid f; 2429673Slinton { 2439673Slinton struct nlist *namelist; 2449673Slinton register struct nlist *np, *ub; 2459673Slinton register String name; 24633328Sdonn boolean afterlg, foundstab; 24716613Ssam integer index; 24816613Ssam char *lastchar; 2499673Slinton 2509673Slinton initsyms(); 2519673Slinton namelist = newarr(struct nlist, nlhdr.nsyms); 2529673Slinton read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); 2539673Slinton afterlg = false; 25433328Sdonn foundstab = false; 2559673Slinton ub = &namelist[nlhdr.nsyms]; 25616613Ssam curnp = &namelist[0]; 25716613Ssam np = curnp; 25816613Ssam while (np < ub) { 2599673Slinton index = np->n_un.n_strx; 2609673Slinton if (index != 0) { 2619673Slinton name = &stringtab[index - 4]; 26212542Scsvaf /* 26316613Ssam * If the program contains any .f files a trailing _ is stripped 26412542Scsvaf * from the name on the assumption it was added by the compiler. 26512542Scsvaf * This only affects names that follow the sdb N_SO entry with 26612542Scsvaf * the .f name. 26712542Scsvaf */ 26814443Slinton if (strip_ and name[0] != '\0' ) { 26916613Ssam lastchar = &name[strlen(name) - 1]; 27016613Ssam if (*lastchar == '_') { 27116613Ssam *lastchar = '\0'; 27214443Slinton } 27312542Scsvaf } 2749673Slinton } else { 2759673Slinton name = nil; 27612542Scsvaf } 27716613Ssam 2789673Slinton /* 27916613Ssam * Assumptions: 2809673Slinton * not an N_STAB ==> name != nil 2819673Slinton * name[0] == '-' ==> name == "-lg" 2829673Slinton * name[0] != '_' ==> filename or invisible 2839673Slinton * 2849673Slinton * The "-lg" signals the beginning of global loader symbols. 28512542Scsvaf * 2869673Slinton */ 2879673Slinton if ((np->n_type&N_STAB) != 0) { 28833328Sdonn foundstab = true; 2899673Slinton enter_nl(name, np); 2909673Slinton } else if (name[0] == '-') { 2919673Slinton afterlg = true; 29218225Slinton foundglobals(); 29311104Slinton } else if (afterlg) { 29418225Slinton check_global(name, np); 29518225Slinton } else if ((np->n_type&N_EXT) == N_EXT) { 29618225Slinton afterlg = true; 29718225Slinton foundglobals(); 29818225Slinton check_global(name, np); 29911104Slinton } else if (name[0] == '_') { 30011104Slinton check_local(&name[1], np); 3019673Slinton } else if ((np->n_type&N_TEXT) == N_TEXT) { 3029673Slinton check_filename(name); 3039673Slinton } 30416613Ssam ++curnp; 30516613Ssam np = curnp; 3069673Slinton } 30733328Sdonn if (not foundstab) { 30833328Sdonn warning("no source compiled with -g"); 30933328Sdonn } 3109673Slinton dispose(namelist); 3119673Slinton } 3129673Slinton 3139673Slinton /* 31416613Ssam * Get a continuation entry from the name list. 31516613Ssam * Return the beginning of the name. 31616613Ssam */ 31716613Ssam 31816613Ssam public String getcont () 31916613Ssam { 32016613Ssam register integer index; 32116613Ssam register String name; 32216613Ssam 32316613Ssam ++curnp; 32416613Ssam index = curnp->n_un.n_strx; 32516613Ssam if (index == 0) { 32633328Sdonn name = ""; 32733328Sdonn } else { 32833328Sdonn name = &stringtab[index - 4]; 32916613Ssam } 33016613Ssam return name; 33116613Ssam } 33216613Ssam 33316613Ssam /* 3349673Slinton * Initialize symbol information. 3359673Slinton */ 3369673Slinton 33716613Ssam private initsyms () 3389673Slinton { 3399673Slinton curblock = nil; 3409673Slinton curlevel = 0; 34114443Slinton nesting = 0; 34216613Ssam program = insert(identname("", true)); 3439673Slinton program->class = PROG; 34433328Sdonn program->language = primlang; 34533328Sdonn program->symvalue.funcv.beginaddr = CODESTART; 34614443Slinton program->symvalue.funcv.inline = false; 34714443Slinton newfunc(program, codeloc(program)); 34811769Slinton findbeginning(program); 3499673Slinton enterblock(program); 3509673Slinton curmodule = program; 3519673Slinton } 3529673Slinton 3539673Slinton /* 3549673Slinton * Free all the object file information that's being stored. 3559673Slinton */ 3569673Slinton 35716613Ssam public objfree () 3589673Slinton { 3599673Slinton symbol_free(); 36018225Slinton /* keywords_free(); */ 36118225Slinton /* names_free(); */ 36218225Slinton /* dispose(stringtab); */ 3639673Slinton clrfunctab(); 3649673Slinton } 3659673Slinton 3669673Slinton /* 3679673Slinton * Enter a namelist entry. 3689673Slinton */ 3699673Slinton 37016613Ssam private enter_nl (name, np) 3719673Slinton String name; 3729673Slinton register struct nlist *np; 3739673Slinton { 3749673Slinton register Symbol s; 37516613Ssam register Name n; 3769673Slinton 3779673Slinton s = nil; 3789673Slinton switch (np->n_type) { 37914443Slinton /* 38014443Slinton * Build a symbol for the FORTRAN common area. All GSYMS that follow 38114443Slinton * will be chained in a list with the head kept in common.offset, and 38214443Slinton * the tail in common.chain. 38314443Slinton */ 38413938Slinton case N_BCOMM: 38513938Slinton if (curcomm) { 38613938Slinton curcomm->symvalue.common.chain = commchain; 38712542Scsvaf } 38816613Ssam n = identname(name, true); 38912542Scsvaf curcomm = lookup(n); 39013938Slinton if (curcomm == nil) { 39113938Slinton curcomm = insert(n); 39213938Slinton curcomm->class = COMMON; 39313938Slinton curcomm->block = curblock; 39413938Slinton curcomm->level = program->level; 39513938Slinton curcomm->symvalue.common.chain = nil; 39612542Scsvaf } 39712542Scsvaf commchain = curcomm->symvalue.common.chain; 39813938Slinton break; 39912542Scsvaf 40012542Scsvaf case N_ECOMM: 40113938Slinton if (curcomm) { 40213938Slinton curcomm->symvalue.common.chain = commchain; 40313938Slinton curcomm = nil; 40412542Scsvaf } 40512542Scsvaf break; 40614443Slinton 4079673Slinton case N_LBRAC: 40814443Slinton ++nesting; 40914443Slinton addrstk[nesting] = (linep - 1)->addr; 4109673Slinton break; 4119673Slinton 4129673Slinton case N_RBRAC: 41316613Ssam --nesting; 41414443Slinton if (addrstk[nesting] == NOADDR) { 41514443Slinton exitblock(); 41614443Slinton newfunc(curblock, (linep - 1)->addr); 41716613Ssam addrstk[nesting] = (linep - 1)->addr; 41814443Slinton } 4199673Slinton break; 4209673Slinton 4219673Slinton case N_SLINE: 4229673Slinton enterline((Lineno) np->n_desc, (Address) np->n_value); 4239673Slinton break; 4249673Slinton 4259673Slinton /* 42614443Slinton * Source files. 4279673Slinton */ 4289673Slinton case N_SO: 42916613Ssam n = identname(name, true); 43014443Slinton enterSourceModule(n, (Address) np->n_value); 4319673Slinton break; 4329673Slinton 4339673Slinton /* 4349673Slinton * Textually included files. 4359673Slinton */ 4369673Slinton case N_SOL: 4379673Slinton enterfile(name, (Address) np->n_value); 4389673Slinton break; 4399673Slinton 4409673Slinton /* 4419673Slinton * These symbols are assumed to have non-nil names. 4429673Slinton */ 4439673Slinton case N_GSYM: 4449673Slinton case N_FUN: 4459673Slinton case N_STSYM: 4469673Slinton case N_LCSYM: 4479673Slinton case N_RSYM: 4489673Slinton case N_PSYM: 4499673Slinton case N_LSYM: 4509673Slinton case N_SSYM: 45114443Slinton case N_LENG: 4529673Slinton if (index(name, ':') == nil) { 4539673Slinton if (not warned) { 4549673Slinton warned = true; 45533328Sdonn printf("warning: old style symbol information "); 45633328Sdonn printf("found in \"%s\"\n", curfilename()); 4579673Slinton } 4589673Slinton } else { 4599673Slinton entersym(name, np); 4609673Slinton } 4619673Slinton break; 4629673Slinton 4639673Slinton case N_PC: 46416613Ssam case N_MOD2: 4659673Slinton break; 4669673Slinton 46711558Slinton default: 46814443Slinton printf("warning: stab entry unrecognized: "); 4699673Slinton if (name != nil) { 47014443Slinton printf("name %s,", name); 4719673Slinton } 47214443Slinton printf("ntype %2x, desc %x, value %x'\n", 4739673Slinton np->n_type, np->n_desc, np->n_value); 4749673Slinton break; 4759673Slinton } 4769673Slinton } 4779673Slinton 4789673Slinton /* 47918225Slinton * Try to find the symbol that is referred to by the given name. Since it's 48018225Slinton * an external, we need to follow a level or two of indirection. 48116613Ssam */ 48216613Ssam 48318225Slinton private Symbol findsym (n, var_isextref) 48416613Ssam Name n; 48518225Slinton boolean *var_isextref; 48616613Ssam { 48716613Ssam register Symbol r, s; 48816613Ssam 48918225Slinton *var_isextref = false; 49016613Ssam find(s, n) where 49118225Slinton ( 49218225Slinton s->level == program->level and ( 49318225Slinton s->class == EXTREF or s->class == VAR or 49418225Slinton s->class == PROC or s->class == FUNC 49518225Slinton ) 49618225Slinton ) or ( 49718225Slinton s->block == program and s->class == MODULE 49818225Slinton ) 49916613Ssam endfind(s); 50018225Slinton if (s == nil) { 50118225Slinton r = nil; 50218225Slinton } else if (s->class == EXTREF) { 50318225Slinton *var_isextref = true; 50416613Ssam r = s->symvalue.extref; 50516613Ssam delete(s); 50618225Slinton 50718225Slinton /* 50818225Slinton * Now check for another level of indirection that could come from 50918225Slinton * a forward reference in procedure nesting information. In this case 51018225Slinton * the symbol has already been deleted. 51118225Slinton */ 51218225Slinton if (r != nil and r->class == EXTREF) { 51318225Slinton r = r->symvalue.extref; 51418225Slinton } 51518225Slinton /* 51618225Slinton } else if (s->class == MODULE) { 51718225Slinton s->class = FUNC; 51818225Slinton s->level = program->level; 51918225Slinton r = s; 52018225Slinton */ 52116613Ssam } else { 52216613Ssam r = s; 52316613Ssam } 52416613Ssam return r; 52516613Ssam } 52616613Ssam 52716613Ssam /* 52818225Slinton * Create a symbol for a text symbol with no source information. 52918225Slinton * We treat it as an assembly language function. 53018225Slinton */ 53118225Slinton 53218225Slinton private Symbol deffunc (n) 53318225Slinton Name n; 53418225Slinton { 53518225Slinton Symbol f; 53618225Slinton 53718225Slinton f = insert(n); 53818225Slinton f->language = findlanguage(".s"); 53918225Slinton f->class = FUNC; 54018225Slinton f->type = t_int; 54118225Slinton f->block = curblock; 54218225Slinton f->level = program->level; 54318225Slinton f->symvalue.funcv.src = false; 54418225Slinton f->symvalue.funcv.inline = false; 54533328Sdonn if (f->chain != nil) { 54633328Sdonn panic("chain not nil in deffunc"); 54733328Sdonn } 54818225Slinton return f; 54918225Slinton } 55018225Slinton 55118225Slinton /* 55218225Slinton * Create a symbol for a data or bss symbol with no source information. 55318225Slinton * We treat it as an assembly language variable. 55418225Slinton */ 55518225Slinton 55618225Slinton private Symbol defvar (n) 55718225Slinton Name n; 55818225Slinton { 55918225Slinton Symbol v; 56018225Slinton 56118225Slinton v = insert(n); 56218225Slinton v->language = findlanguage(".s"); 56333328Sdonn v->storage = EXT; 56418225Slinton v->class = VAR; 56518225Slinton v->type = t_int; 56618225Slinton v->level = program->level; 56718225Slinton v->block = curblock; 56818225Slinton return v; 56918225Slinton } 57018225Slinton 57118225Slinton /* 57218225Slinton * Update a symbol entry with a text address. 57318225Slinton */ 57418225Slinton 57518225Slinton private updateTextSym (s, name, addr) 57618225Slinton Symbol s; 57718225Slinton char *name; 57818225Slinton Address addr; 57918225Slinton { 58018225Slinton if (s->class == VAR) { 58118225Slinton s->symvalue.offset = addr; 58218225Slinton } else { 58318225Slinton s->symvalue.funcv.beginaddr = addr; 58418225Slinton if (name[0] == '_') { 58518225Slinton newfunc(s, codeloc(s)); 58618225Slinton findbeginning(s); 58718225Slinton } 58818225Slinton } 58918225Slinton } 59018225Slinton 59118225Slinton /* 59233328Sdonn * Avoid seeing Pascal labels as text symbols. 59333328Sdonn */ 59433328Sdonn 59533328Sdonn private boolean PascalLabel (n) 59633328Sdonn Name n; 59733328Sdonn { 59833328Sdonn boolean b; 59933328Sdonn register char *p; 60033328Sdonn 60133328Sdonn b = false; 60233328Sdonn if (curlang == findlanguage(".p")) { 60333328Sdonn p = ident(n); 60433328Sdonn while (*p != '\0') { 60533328Sdonn if (*p == '_' and *(p+1) == '$') { 60633328Sdonn b = true; 60733328Sdonn break; 60833328Sdonn } 60933328Sdonn ++p; 61033328Sdonn } 61133328Sdonn } 61233328Sdonn return b; 61333328Sdonn } 61433328Sdonn 61533328Sdonn /* 6169673Slinton * Check to see if a global _name is already in the symbol table, 6179673Slinton * if not then insert it. 6189673Slinton */ 6199673Slinton 62016613Ssam private check_global (name, np) 6219673Slinton String name; 6229673Slinton register struct nlist *np; 6239673Slinton { 6249673Slinton register Name n; 62512542Scsvaf register Symbol t, u; 62618225Slinton char buf[4096]; 62718225Slinton boolean isextref; 62818225Slinton integer count; 6299673Slinton 63018225Slinton if (not streq(name, "_end")) { 63118225Slinton if (name[0] == '_') { 63218225Slinton n = identname(&name[1], true); 63318225Slinton } else { 63418225Slinton n = identname(name, true); 63518225Slinton if (lookup(n) != nil) { 63618225Slinton sprintf(buf, "$%s", name); 63718225Slinton n = identname(buf, false); 63818225Slinton } 63918225Slinton } 6409673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 64118225Slinton count = 0; 64218225Slinton t = findsym(n, &isextref); 64318225Slinton while (isextref) { 64418225Slinton ++count; 64518225Slinton updateTextSym(t, name, np->n_value); 64618225Slinton t = findsym(n, &isextref); 6479673Slinton } 64818225Slinton if (count == 0) { 64918225Slinton if (t == nil) { 65033328Sdonn if (not PascalLabel(n)) { 65133328Sdonn t = deffunc(n); 65233328Sdonn updateTextSym(t, name, np->n_value); 65333328Sdonn if (tracesyms) { 65433328Sdonn printdecl(t); 65533328Sdonn } 65618225Slinton } 65718225Slinton } else { 65818225Slinton if (t->class == MODULE) { 65918225Slinton u = t; 66018225Slinton t = deffunc(n); 66118225Slinton t->block = u; 66218225Slinton if (tracesyms) { 66318225Slinton printdecl(t); 66418225Slinton } 66518225Slinton } 66618225Slinton updateTextSym(t, name, np->n_value); 66718225Slinton } 66816613Ssam } 66933328Sdonn } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) { 6709673Slinton find(t, n) where 67113938Slinton t->class == COMMON 67212542Scsvaf endfind(t); 67313938Slinton if (t != nil) { 67413938Slinton u = (Symbol) t->symvalue.common.offset; 67513938Slinton while (u != nil) { 67613938Slinton u->symvalue.offset = u->symvalue.common.offset+np->n_value; 67713938Slinton u = u->symvalue.common.chain; 67813938Slinton } 67913938Slinton } else { 68013938Slinton check_var(np, n); 6819673Slinton } 68213938Slinton } else { 68313938Slinton check_var(np, n); 6849673Slinton } 6859673Slinton } 6869673Slinton } 6879673Slinton 6889673Slinton /* 68913938Slinton * Check to see if a namelist entry refers to a variable. 69013938Slinton * If not, create a variable for the entry. In any case, 69113938Slinton * set the offset of the variable according to the value field 69213938Slinton * in the entry. 69318225Slinton * 69418225Slinton * If the external name has been referred to by several other symbols, 69518225Slinton * we must update each of them. 69613938Slinton */ 69713938Slinton 69816613Ssam private check_var (np, n) 69913938Slinton struct nlist *np; 70013938Slinton register Name n; 70113938Slinton { 70218225Slinton register Symbol t, u, next; 70318225Slinton Symbol conflict; 70413938Slinton 70518225Slinton t = lookup(n); 70613938Slinton if (t == nil) { 70718225Slinton t = defvar(n); 70818225Slinton t->symvalue.offset = np->n_value; 70918225Slinton if (tracesyms) { 71018225Slinton printdecl(t); 71118225Slinton } 71218225Slinton } else { 71318225Slinton conflict = nil; 71418225Slinton do { 71518225Slinton next = t->next_sym; 71618225Slinton if (t->name == n) { 71718225Slinton if (t->class == MODULE and t->block == program) { 71818225Slinton conflict = t; 71918225Slinton } else if (t->class == EXTREF and t->level == program->level) { 72018225Slinton u = t->symvalue.extref; 72118225Slinton while (u != nil and u->class == EXTREF) { 72218225Slinton u = u->symvalue.extref; 72318225Slinton } 72418225Slinton u->symvalue.offset = np->n_value; 72518225Slinton delete(t); 72618225Slinton } else if (t->level == program->level and 72718225Slinton (t->class == VAR or t->class == PROC or t->class == FUNC) 72818225Slinton ) { 72918225Slinton conflict = nil; 73018225Slinton t->symvalue.offset = np->n_value; 73118225Slinton } 73218225Slinton } 73318225Slinton t = next; 73418225Slinton } while (t != nil); 73518225Slinton if (conflict != nil) { 73618225Slinton u = defvar(n); 73718225Slinton u->block = conflict; 73818225Slinton u->symvalue.offset = np->n_value; 73918225Slinton } 74013938Slinton } 74113938Slinton } 74213938Slinton 74313938Slinton /* 7449673Slinton * Check to see if a local _name is known in the current scope. 7459673Slinton * If not then enter it. 7469673Slinton */ 7479673Slinton 74816613Ssam private check_local (name, np) 7499673Slinton String name; 7509673Slinton register struct nlist *np; 7519673Slinton { 7529673Slinton register Name n; 7539673Slinton register Symbol t, cur; 7549673Slinton 7559673Slinton n = identname(name, true); 7569673Slinton cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; 7579673Slinton find(t, n) where t->block == cur endfind(t); 7589673Slinton if (t == nil) { 7599673Slinton t = insert(n); 7609673Slinton t->language = findlanguage(".s"); 7619673Slinton t->type = t_int; 7629673Slinton t->block = cur; 76333328Sdonn t->storage = EXT; 7649673Slinton t->level = cur->level; 7659673Slinton if ((np->n_type&N_TYPE) == N_TEXT) { 7669673Slinton t->class = FUNC; 76711875Slinton t->symvalue.funcv.src = false; 76814443Slinton t->symvalue.funcv.inline = false; 7699673Slinton t->symvalue.funcv.beginaddr = np->n_value; 77014443Slinton newfunc(t, codeloc(t)); 7719673Slinton findbeginning(t); 7729673Slinton } else { 7739673Slinton t->class = VAR; 7749673Slinton t->symvalue.offset = np->n_value; 7759673Slinton } 7769673Slinton } 7779673Slinton } 7789673Slinton 7799673Slinton /* 7809673Slinton * Check to see if a symbol corresponds to a object file name. 7819673Slinton * For some reason these are listed as in the text segment. 7829673Slinton */ 7839673Slinton 78416613Ssam private check_filename (name) 7859673Slinton String name; 7869673Slinton { 7879673Slinton register String mname; 78816613Ssam register integer i; 78918225Slinton Name n; 79018225Slinton Symbol s; 7919673Slinton 7929673Slinton mname = strdup(name); 7939673Slinton i = strlen(mname) - 2; 7949673Slinton if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { 7959673Slinton mname[i] = '\0'; 7969673Slinton --i; 7979673Slinton while (mname[i] != '/' and i >= 0) { 7989673Slinton --i; 7999673Slinton } 80018225Slinton n = identname(&mname[i+1], true); 80118225Slinton find(s, n) where s->block == program and s->class == MODULE endfind(s); 80218225Slinton if (s == nil) { 80318225Slinton s = insert(n); 80418225Slinton s->language = findlanguage(".s"); 80518225Slinton s->class = MODULE; 80618225Slinton s->symvalue.funcv.beginaddr = 0; 80718225Slinton findbeginning(s); 80818225Slinton } 8099673Slinton if (curblock->class != PROG) { 8109673Slinton exitblock(); 8119673Slinton if (curblock->class != PROG) { 8129673Slinton exitblock(); 8139673Slinton } 8149673Slinton } 8159673Slinton enterblock(s); 8169673Slinton curmodule = s; 8179673Slinton } 8189673Slinton } 8199673Slinton 8209673Slinton /* 82114443Slinton * Check to see if a symbol is about to be defined within an unnamed block. 82214443Slinton * If this happens, we create a procedure for the unnamed block, make it 82314443Slinton * "inline" so that tracebacks don't associate an activation record with it, 82414443Slinton * and enter it into the function table so that it will be detected 82514443Slinton * by "whatblock". 82614443Slinton */ 82714443Slinton 82816613Ssam public chkUnnamedBlock () 82914443Slinton { 83014443Slinton register Symbol s; 83114443Slinton static int bnum = 0; 83214443Slinton char buf[100]; 83316613Ssam Address startaddr; 83414443Slinton 83516613Ssam if (nesting > 0 and addrstk[nesting] != NOADDR) { 83616613Ssam startaddr = (linep - 1)->addr; 83716613Ssam ++bnum; 83816613Ssam sprintf(buf, "$b%d", bnum); 83916613Ssam s = insert(identname(buf, false)); 84016613Ssam s->language = curlang; 84116613Ssam s->class = PROC; 84216613Ssam s->symvalue.funcv.src = false; 84316613Ssam s->symvalue.funcv.inline = true; 84416613Ssam s->symvalue.funcv.beginaddr = startaddr; 84516613Ssam enterblock(s); 84616613Ssam newfunc(s, startaddr); 84716613Ssam addrstk[nesting] = NOADDR; 84816613Ssam } 84914443Slinton } 85014443Slinton 85114443Slinton /* 85214443Slinton * Compilation unit. C associates scope with filenames 85314443Slinton * so we treat them as "modules". The filename without 85414443Slinton * the suffix is used for the module name. 85514443Slinton * 85614443Slinton * Because there is no explicit "end-of-block" mark in 85714443Slinton * the object file, we must exit blocks for the current 85814443Slinton * procedure and module. 85914443Slinton */ 86014443Slinton 86116613Ssam private enterSourceModule (n, addr) 86214443Slinton Name n; 86314443Slinton Address addr; 86414443Slinton { 86514443Slinton register Symbol s; 86614443Slinton Name nn; 86714443Slinton String mname, suffix; 86814443Slinton 86914443Slinton mname = strdup(ident(n)); 87014443Slinton if (rindex(mname, '/') != nil) { 87114443Slinton mname = rindex(mname, '/') + 1; 87214443Slinton } 87314443Slinton suffix = rindex(mname, '.'); 87433328Sdonn if (suffix > mname && *(suffix-1) == '.') { 87533328Sdonn /* special hack for C++ */ 87633328Sdonn --suffix; 87733328Sdonn } 87814443Slinton curlang = findlanguage(suffix); 87914443Slinton if (curlang == findlanguage(".f")) { 88014443Slinton strip_ = true; 88114443Slinton } 88214443Slinton if (suffix != nil) { 88314443Slinton *suffix = '\0'; 88414443Slinton } 88516613Ssam if (not (*language_op(curlang, L_HASMODULES))()) { 88614443Slinton if (curblock->class != PROG) { 88714443Slinton exitblock(); 88816613Ssam if (curblock->class != PROG) { 88916613Ssam exitblock(); 89016613Ssam } 89114443Slinton } 89216613Ssam nn = identname(mname, true); 89316613Ssam if (curmodule == nil or curmodule->name != nn) { 89416613Ssam s = insert(nn); 89516613Ssam s->class = MODULE; 89616613Ssam s->symvalue.funcv.beginaddr = 0; 89716613Ssam findbeginning(s); 89816613Ssam } else { 89916613Ssam s = curmodule; 90016613Ssam } 90116613Ssam s->language = curlang; 90216613Ssam enterblock(s); 90316613Ssam curmodule = s; 90414443Slinton } 90514443Slinton if (program->language == nil) { 90614443Slinton program->language = curlang; 90714443Slinton } 90814443Slinton warned = false; 90914443Slinton enterfile(ident(n), addr); 91016613Ssam initTypeTable(); 91114443Slinton } 91214443Slinton 91314443Slinton /* 9149673Slinton * Allocate file and line tables and initialize indices. 9159673Slinton */ 9169673Slinton 91716613Ssam private allocmaps (nf, nl) 91816613Ssam integer nf, nl; 9199673Slinton { 9209673Slinton if (filetab != nil) { 9219673Slinton dispose(filetab); 9229673Slinton } 9239673Slinton if (linetab != nil) { 9249673Slinton dispose(linetab); 9259673Slinton } 9269673Slinton filetab = newarr(Filetab, nf); 9279673Slinton linetab = newarr(Linetab, nl); 9289673Slinton filep = filetab; 9299673Slinton linep = linetab; 9309673Slinton } 9319673Slinton 9329673Slinton /* 9339673Slinton * Add a file to the file table. 93413938Slinton * 93513938Slinton * If the new address is the same as the previous file address 93613938Slinton * this routine used to not enter the file, but this caused some 93713938Slinton * problems so it has been removed. It's not clear that this in 93813938Slinton * turn may not also cause a problem. 9399673Slinton */ 9409673Slinton 94116613Ssam private enterfile (filename, addr) 9429673Slinton String filename; 9439673Slinton Address addr; 9449673Slinton { 94513938Slinton filep->addr = addr; 94613938Slinton filep->filename = filename; 94713938Slinton filep->lineindex = linep - linetab; 94813938Slinton ++filep; 9499673Slinton } 9509673Slinton 9519673Slinton /* 9529673Slinton * Since we only estimated the number of lines (and it was a poor 9539673Slinton * estimation) and since we need to know the exact number of lines 9549673Slinton * to do a binary search, we set it when we're done. 9559673Slinton */ 9569673Slinton 95716613Ssam private setnlines () 9589673Slinton { 9599673Slinton nlhdr.nlines = linep - linetab; 9609673Slinton } 9619673Slinton 9629673Slinton /* 9639673Slinton * Similarly for nfiles ... 9649673Slinton */ 9659673Slinton 96616613Ssam private setnfiles () 9679673Slinton { 9689673Slinton nlhdr.nfiles = filep - filetab; 9699673Slinton setsource(filetab[0].filename); 9709673Slinton } 971