📄 object.c
字号:
/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)object.c 5.5 (Berkeley) 3/5/91";#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>#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"#endif#ifndef N_MOD2# define N_MOD2 0x50#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;private Boolean strip_ = false;private Filetab *filep;private Linetab *linep, *prevlinep;public String curfilename (){ return ((filep-1)->filename);}/* * Blocks are figured out on the fly while reading the symbol table. */#define MAXBLKDEPTH 25public Symbol curblock;private Symbol blkstack[MAXBLKDEPTH];private integer curlevel;private integer bnum, nesting;private Address addrstk[MAXBLKDEPTH];public pushBlock (b)Symbol b;{ if (curlevel >= MAXBLKDEPTH) { fatal("nesting depth too large (%d)", curlevel); } blkstack[curlevel] = curblock; ++curlevel; curblock = b; if (traceblocks) { printf("entering block %s\n", 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 (curblock->class == FUNC or curblock->class == PROC) { if (prevlinep != linep) { curblock->symvalue.funcv.src = true; } } if (curlevel <= 0) { panic("nesting depth underflow (%d)", curlevel); } --curlevel; if (traceblocks) { printf("exiting block %s\n", 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; \ \ 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; 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; } 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(); 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 (){ if (curblock->class != PROG) { exitblock(); if (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; boolean afterlg, foundstab; integer index; char *lastchar; initsyms(); namelist = newarr(struct nlist, nlhdr.nsyms); read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); afterlg = false; foundstab = 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) { foundstab = true; 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; } if (not foundstab) { warning("no source compiled with -g"); } 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) { name = ""; } else { name = &stringtab[index - 4]; } return name;}/* * Initialize symbol information. */private initsyms (){ curblock = nil; curlevel = 0; nesting = 0; program = insert(identname("", true)); program->class = PROG; program->language = primlang; program->symvalue.funcv.beginaddr = CODESTART; program->symvalue.funcv.inlne = 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; 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); curcomm = lookup(n); if (curcomm == nil) { curcomm = insert(n); curcomm->class = COMMON; curcomm->block = curblock; 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: n = identname(name, true); enterSourceModule(n, (Address) np->n_value); break; /* * Textually included files. */ case N_SOL: enterfile(name, (Address) np->n_value); break; /* * These symbols are assumed to have non-nil names. */ case N_GSYM: case N_FUN: case N_STSYM: case N_LCSYM: case N_RSYM: case N_PSYM: case N_LSYM: case N_SSYM: case N_LENG: if (index(name, ':') == nil) { if (not warned) { warned = true; printf("warning: old style symbol information "); printf("found in \"%s\"\n", curfilename()); } } else { entersym(name, np); } break; case N_PC: case N_MOD2: break; default: printf("warning: stab entry unrecognized: "); if (name != nil) { printf("name %s,", name); } printf("ntype %2x, desc %x, value %x'\n", np->n_type, np->n_desc, np->n_value); break; }}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -