📄 object.c
字号:
/*@(#)object.c 4.3 Ultrix 12/6/90*//************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * * Modification History * * * * 016 - Updated all calls to findlanguage() to call with * * LanguageName constant, rather than with a filename * * suffix. * * (Bob Neff, February 27, 1990) * * * * 015 - Added support for vectors. * * (L Miller, 18JAN90) * * * * 014 - Change "use" so that a user can access source code in a * * logical fashion (i.e. specifiy the dir where the source * * code lives). Care was taken so that dbx will still work * * the same as before. * * (Lee R. Miller Jan 9, 1990) * * * * 013 - Make "strip_" externally visible for stabstring.c so * * C symbols within FORTRAN programs can be found. * * (Jon Reeves, July 14, 1987) * * * * 012 - Fix for spr ICA-02533. Was losing the address of LCSYM * * stab entries. Change to checkvar(). * * (vjh, Nov. 11, 1986) * * * * 011 - 4.3 changes to check_global(), combined with the lack of * * underscores on global VAX/FORTRAN symbol names, proved * * to be a serious problem. Additionally, VAX/FORTRAN * * is indicating the wrong number of functions in the N_NSYM * * record. Added changes to make all this stuff "work" * * again. Also added vmsFileConvert() for Bliss. * * (vjh, July 16, 1986) * * * * 010 - Merged in 4.3 changes. * * (vjh, April 29, 1986) * * * * 009 - Changed check_global() so that address calculation for * * functions is only done for functions not already seen. * * (vjh, Dec. 23, 1985) * * * * 008 - Added case for N_NOMAP in enter_nl(). Takes into account * * a DST record that will not map to a stab entry. * * (vjh, June 26, 1985) * * * * 007 - enterSourceModule() checks for a LanguageName in n_other. * * If not found, then the file extension is still used to * * determine the language of the source file. * * (vjh, June 22, 1985) * * * * 006 - Check for table overflow - function, source line, and * * source file tables. * * (vjh, June 22, 1985) * * * * 005 - Added dynamically allocated function table, and routine * * newfunc(). Added code to handle new N_NSYMS stab entry. * * (vjh, June 16, 1985) * * * * 004 - Assume that any function encountered before loader * * namelist has source information. This way, there are * * fewer restrictions on the placement of N_SLINE entries * * in the symbol table (for the FORTRAN port). Also, speeds * * things up a bit (removed linep/prevlinep comparison in * * exitblock macro). * * (vjh, May 30, 1985) * * * * 003 - Assign curcomm->language so that fortran_printdecl() * * can print the declared type of named common. Used * * to cause an internal error from a nil pointer. * * (vjh, May 8, 1985) * * * * 002 - Fixed bug: dbx would coredump if the name of a * * FORTRAN common block was the same as a source file * * name that was linked into the program. * * (vjh, April 10, 1985) * * * * 001 - Added N_FNAME to case statement in enter_nl(). * * (Victoria Holt, April 5, 1985) * * * ************************************************************************//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic char *sccsid = "@(#)object.c 2.1 ULTRIX 4/24/89";#endif not lint/* * Object code interface, mainly for extraction of symbolic information. */#include "defs.h"#include "object.h"#include "stabstring.h"#include "main.h"#include "symbols.h"#include "names.h"#include "languages.h"#include "mappings.h"#include "lists.h"#include <a.out.h>#include <stab.h>#include <ctype.h>#include <sys/param.h>#ifndef publicstruct { unsigned int stringsize; /* size of the dumped string table */ unsigned int nsyms; /* number of symbols */ unsigned int nfiles; /* number of files */ unsigned int nlines; /* number of lines */} nlhdr;#include "languages.h"#include "symbols.h"#endifpublic String objname = "a.out";public integer objsize;public Language curlang;public Symbol curmodule;public Symbol curparam;public Symbol curcomm;public Symbol commchain;private char *stringtab;private struct nlist *curnp;private Boolean warned;public Boolean strip_ = false;private Filetab *filep;private Linetab *linep;public String curfilename (){ return ((filep-1)->filename);}/* * Blocks are figured out on the fly while reading the symbol table. */#define MAXBLKDEPTH 100public Symbol curblock;private Symbol blkstack[MAXBLKDEPTH];private integer curlevel;private integer bnum, nesting;private Address addrstk[MAXBLKDEPTH];#define isfunc(s) \ (s->class == FUNC || s->class == PROC)public pushBlock (b)Symbol b;{ if (curlevel >= MAXBLKDEPTH) { fatal("nesting depth too large (%d)", curlevel); } blkstack[curlevel] = curblock; ++curlevel; curblock = b; if (traceblocks) { printf("+%d entering block %s\n", curlevel, symname(b)); }}/* * Change the current block with saving the previous one, * since it is assumed that the symbol for the current one is to be deleted. */public changeBlock (b)Symbol b;{ curblock = b;}public enterblock (b)Symbol b;{ if (curblock == nil) { b->level = 1; } else { b->level = curblock->level + 1; } b->block = curblock; pushBlock(b);}public exitblock (){ if (curlevel <= 0) { panic("nesting depth underflow (%d)", curlevel); } --curlevel; if (traceblocks) { printf("-%d exiting block %s\n", curlevel, symname(curblock)); } curblock = blkstack[curlevel];}/* * Enter a source line or file name reference into the appropriate table. * Expanded inline to reduce procedure calls. * * private enterline (linenumber, address) * Lineno linenumber; * Address address; * ... */#define enterline(linenumber, address) \{ \ register Linetab *lp; \ \ assert(linep); \ lp = linep - 1; \ if (linenumber != lp->line) { \ if (address != lp->addr) { \ ++lp; \ } \ lp->line = linenumber; \ lp->addr = address; \ linep = lp + 1; \ } \}/* * Read in the namelist from the obj file. * * Reads and seeks are used instead of fread's and fseek's * for efficiency sake; there's a lot of data being read here. */public readobj (file)String file;{ Fileid f; struct exec hdr; struct nlist nlist; register Filetab *ftp; char *ptr, tmp[MAXPATHLEN]; String dir; Boolean needed; f = open(file, 0); if (f < 0) { fatal("can't open %s", file); } read(f, &hdr, sizeof(hdr)); if (N_BADMAG(hdr)) { objsize = 0; nlhdr.nsyms = 0; nlhdr.nfiles = 0; nlhdr.nlines = 0; } else { objsize = hdr.a_text; nlhdr.nsyms = hdr.a_syms / sizeof(nlist); nlhdr.nfiles = nlhdr.nsyms; nlhdr.nlines = nlhdr.nsyms; } defvar(identname("$symtotal", true), build(O_LCON, nlhdr.nsyms)); if (nlhdr.nsyms > 0) { lseek(f, (long) N_STROFF(hdr), 0); read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); nlhdr.stringsize -= 4; stringtab = newarr(char, nlhdr.stringsize); read(f, stringtab, nlhdr.stringsize); allocmaps(nlhdr.nfiles, nlhdr.nlines); lseek(f, (long) N_SYMOFF(hdr), 0); readsyms(f); ordfunctab(); setnlines(); for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { if(ptr = (char *)strrchr(ftp->filename, '/')) { if(ptr != ftp->filename){ if (rindex(objname, '/') != nil) { strcpy(tmp, objname); *(rindex(tmp, '/')) = '\0'; strcat(tmp, "/"); strncat(tmp, ftp->filename, ptr - ftp->filename); } else { strcpy(tmp, ftp->filename); *(rindex(tmp, '/')) = '\0'; } needed = true; foreach (String, dir, sourcepath) if(strcmp(tmp, dir) == 0) { needed = false; break; } endfor if(needed) { list_append(list_item(strdup(tmp)), nil, sourcepath); } ftp->filename = ++ptr; } } } setnfiles(); } else { initsyms(); } close(f);}/* * Found the beginning of the externals in the object file * (signified by the "-lg" or find an external), close the * block for the last procedure. */private foundglobals (){ while (curblock->class != PROG) exitblock(); enterline(0, (linep-1)->addr + 1);}/* * Read in symbols from object file. */private readsyms (f)Fileid f;{ struct nlist *namelist; register struct nlist *np, *ub; register String name; register Boolean afterlg; integer index; char *lastchar; initsyms(); namelist = newarr(struct nlist, nlhdr.nsyms); read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); afterlg = false; ub = &namelist[nlhdr.nsyms]; curnp = &namelist[0]; np = curnp; while (np < ub) { index = np->n_un.n_strx; if (index != 0) { name = &stringtab[index - 4]; /* * If the program contains any .f files a trailing _ is stripped * from the name on the assumption it was added by the compiler. * This only affects names that follow the sdb N_SO entry with * the .f name. */ if (strip_ and name[0] != '\0' ) { lastchar = &name[strlen(name) - 1]; if (*lastchar == '_') { *lastchar = '\0'; } } } else { name = nil; } /* * Assumptions: * not an N_STAB ==> name != nil * name[0] == '-' ==> name == "-lg" * name[0] != '_' ==> filename or invisible * * The "-lg" signals the beginning of global loader symbols. * */ if ((np->n_type&N_STAB) != 0) { enter_nl(name, np); } else if (name[0] == '-') { afterlg = true; foundglobals(); } else if (afterlg) { check_global(name, np); } else if ((np->n_type&N_EXT) == N_EXT) { afterlg = true; foundglobals(); check_global(name, np); } else if (name[0] == '_') { check_local(&name[1], np); } else if ((np->n_type&N_TEXT) == N_TEXT) { check_filename(name); } ++curnp; np = curnp; } dispose(namelist);}/* * Get a continuation entry from the name list. * Return the beginning of the name. */public String getcont (){ register integer index; register String name; ++curnp; index = curnp->n_un.n_strx; if (index == 0) { panic("continuation followed by empty stab"); } name = &stringtab[index - 4]; return name;}/* * Initialize symbol information. */private initsyms (){ char *progname; curblock = nil; curlevel = 0; nesting = 0; if(rindex(objname, '/') != nil) { progname = rindex(objname, '/') +1; } else { progname = objname; } program = insert(identname(progname, true)); program->class = PROG; program->symvalue.funcv.beginaddr = 0; program->symvalue.funcv.inline = false; newfunc(program, codeloc(program)); findbeginning(program); enterblock(program); curmodule = program;}/* * Free all the object file information that's being stored. */public objfree (){ symbol_free(); /* keywords_free(); */ /* names_free(); */ /* dispose(stringtab); */ clrfunctab();}/* * Enter a namelist entry. */private enter_nl (name, np)String name;register struct nlist *np;{ register Symbol s; register Name n; char *p; s = nil; switch (np->n_type) { /* * Build a symbol for the FORTRAN common area. All GSYMS that follow * will be chained in a list with the head kept in common.offset, and * the tail in common.chain. */ case N_BCOMM: if (curcomm) { curcomm->symvalue.common.chain = commchain; } n = identname(name, true); find(curcomm, n) where curcomm->class == COMMON endfind(curcomm); if (curcomm == nil) { curcomm = insert(n); curcomm->class = COMMON; curcomm->block = curblock; curcomm->language = curlang; /* curlang is fortran */ curcomm->level = program->level; curcomm->symvalue.common.chain = nil; } commchain = curcomm->symvalue.common.chain; break; case N_ECOMM: if (curcomm) { curcomm->symvalue.common.chain = commchain; curcomm = nil; } break; case N_LBRAC: ++nesting; addrstk[nesting] = (linep - 1)->addr; break; case N_RBRAC: --nesting; if (addrstk[nesting] == NOADDR) { exitblock(); newfunc(curblock, (linep - 1)->addr); addrstk[nesting] = (linep - 1)->addr; } break; case N_SLINE: enterline((Lineno) np->n_desc, (Address) np->n_value); break; /* * Source files. */ case N_SO: vmsFileConvert(name); n = identname(name, true); enterSourceModule(n, (Address) np->n_value, (LanguageName) np->n_other); break; /* * Textually included files. */ case N_SOL: enterfile(name, (Address) np->n_value);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -