📄 object.c
字号:
* Try to find the symbol that is referred to by the given name. Since it's * an external, we need to follow a level or two of indirection. */private Symbol findsym (n, var_isextref)Name n;boolean *var_isextref;{ register Symbol r, s; *var_isextref = false; find(s, n) where ( s->level == program->level and ( s->class == EXTREF or s->class == VAR or s->class == PROC or s->class == FUNC ) ) or ( s->block == program and s->class == MODULE ) endfind(s); if (s == nil) { r = nil; } else if (s->class == EXTREF) { *var_isextref = true; r = s->symvalue.extref; delete(s); /* * Now check for another level of indirection that could come from * a forward reference in procedure nesting information. In this case * the symbol has already been deleted. */ if (r != nil and r->class == EXTREF) { r = r->symvalue.extref; }/* } else if (s->class == MODULE) { s->class = FUNC; s->level = program->level; r = s; */ } else { r = s; } return r;}/* * Create a symbol for a text symbol with no source information. * We treat it as an assembly language function. */private Symbol deffunc (n)Name n;{ Symbol f; f = insert(n); f->language = findlanguage(".s"); f->class = FUNC; f->type = t_int; f->block = curblock; f->level = program->level; f->symvalue.funcv.src = false; f->symvalue.funcv.inlne = false; if (f->chain != nil) { panic("chain not nil in deffunc"); } return f;}/* * Create a symbol for a data or bss symbol with no source information. * We treat it as an assembly language variable. */private Symbol defvar (n)Name n;{ Symbol v; v = insert(n); v->language = findlanguage(".s"); v->storage = EXT; v->class = VAR; v->type = t_int; v->level = program->level; v->block = curblock; return v;}/* * Update a symbol entry with a text address. */private updateTextSym (s, name, addr)Symbol s;char *name;Address addr;{ if (s->class == VAR) { s->symvalue.offset = addr; } else { s->symvalue.funcv.beginaddr = addr; if (name[0] == '_') { newfunc(s, codeloc(s)); findbeginning(s); } }}/* * Avoid seeing Pascal labels as text symbols. */private boolean PascalLabel (n)Name n;{ boolean b; register char *p; b = false; if (curlang == findlanguage(".p")) { p = ident(n); while (*p != '\0') { if (*p == '_' and *(p+1) == '$') { b = true; break; } ++p; } } return b;}/* * Check to see if a global _name is already in the symbol table, * if not then insert it. */private check_global (name, np)String name;register struct nlist *np;{ register Name n; register Symbol t, u; char buf[4096]; boolean isextref; integer count; if (not streq(name, "_end")) { if (name[0] == '_') { n = identname(&name[1], true); } else { n = identname(name, true); if (lookup(n) != nil) { sprintf(buf, "$%s", name); n = identname(buf, false); } } if ((np->n_type&N_TYPE) == N_TEXT) { count = 0; t = findsym(n, &isextref); while (isextref) { ++count; updateTextSym(t, name, np->n_value); t = findsym(n, &isextref); } if (count == 0) { if (t == nil) { if (not PascalLabel(n)) { t = deffunc(n); updateTextSym(t, name, np->n_value); if (tracesyms) { printdecl(t); } } } else { if (t->class == MODULE) { u = t; t = deffunc(n); t->block = u; if (tracesyms) { printdecl(t); } } updateTextSym(t, name, np->n_value); } } } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) { find(t, n) where t->class == COMMON endfind(t); if (t != nil) { u = (Symbol) t->symvalue.common.offset; while (u != nil) { u->symvalue.offset = u->symvalue.common.offset+np->n_value; u = u->symvalue.common.chain; } } else { check_var(np, n); } } else { check_var(np, n); } }}/* * Check to see if a namelist entry refers to a variable. * If not, create a variable for the entry. In any case, * set the offset of the variable according to the value field * in the entry. * * If the external name has been referred to by several other symbols, * we must update each of them. */private check_var (np, n)struct nlist *np;register Name n;{ register Symbol t, u, next; Symbol conflict; t = lookup(n); if (t == nil) { t = defvar(n); t->symvalue.offset = np->n_value; if (tracesyms) { printdecl(t); } } else { conflict = nil; do { next = t->next_sym; if (t->name == n) { if (t->class == MODULE and t->block == program) { conflict = t; } else if (t->class == EXTREF and t->level == program->level) { u = t->symvalue.extref; while (u != nil and u->class == EXTREF) { u = u->symvalue.extref; } u->symvalue.offset = np->n_value; delete(t); } else if (t->level == program->level and (t->class == VAR or t->class == PROC or t->class == FUNC) ) { conflict = nil; t->symvalue.offset = np->n_value; } } t = next; } while (t != nil); if (conflict != nil) { u = defvar(n); u->block = conflict; u->symvalue.offset = np->n_value; } }}/* * Check to see if a local _name is known in the current scope. * If not then enter it. */private check_local (name, np)String name;register struct nlist *np;{ register Name n; register Symbol t, cur; n = identname(name, true); cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; find(t, n) where t->block == cur endfind(t); if (t == nil) { t = insert(n); t->language = findlanguage(".s"); t->type = t_int; t->block = cur; t->storage = EXT; t->level = cur->level; if ((np->n_type&N_TYPE) == N_TEXT) { t->class = FUNC; t->symvalue.funcv.src = false; t->symvalue.funcv.inlne = false; t->symvalue.funcv.beginaddr = np->n_value; newfunc(t, codeloc(t)); findbeginning(t); } else { t->class = VAR; t->symvalue.offset = np->n_value; } }}/* * Check to see if a symbol corresponds to a object file name. * For some reason these are listed as in the text segment. */private check_filename (name)String name;{ register String mname; register integer i; Name n; Symbol s; mname = strdup(name); i = strlen(mname) - 2; if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { mname[i] = '\0'; --i; while (mname[i] != '/' and i >= 0) { --i; } n = identname(&mname[i+1], true); find(s, n) where s->block == program and s->class == MODULE endfind(s); if (s == nil) { s = insert(n); s->language = findlanguage(".s"); s->class = MODULE; s->symvalue.funcv.beginaddr = 0; findbeginning(s); } if (curblock->class != PROG) { exitblock(); if (curblock->class != PROG) { exitblock(); } } enterblock(s); curmodule = s; }}/* * Check to see if a symbol is about to be defined within an unnamed block. * If this happens, we create a procedure for the unnamed block, make it * "inline" so that tracebacks don't associate an activation record with it, * and enter it into the function table so that it will be detected * by "whatblock". */public chkUnnamedBlock (){ register Symbol s; static int bnum = 0; char buf[100]; Address startaddr; if (nesting > 0 and addrstk[nesting] != NOADDR) { startaddr = (linep - 1)->addr; ++bnum; sprintf(buf, "$b%d", bnum); s = insert(identname(buf, false)); s->language = curlang; s->class = PROC; s->symvalue.funcv.src = false; s->symvalue.funcv.inlne = true; s->symvalue.funcv.beginaddr = startaddr; enterblock(s); newfunc(s, startaddr); addrstk[nesting] = NOADDR; }}/* * Compilation unit. C associates scope with filenames * so we treat them as "modules". The filename without * the suffix is used for the module name. * * Because there is no explicit "end-of-block" mark in * the object file, we must exit blocks for the current * procedure and module. */private enterSourceModule (n, addr)Name n;Address addr;{ register Symbol s; Name nn; String mname, suffix; mname = strdup(ident(n)); if (rindex(mname, '/') != nil) { mname = rindex(mname, '/') + 1; } suffix = rindex(mname, '.'); if (suffix > mname && *(suffix-1) == '.') { /* special hack for C++ */ --suffix; } curlang = findlanguage(suffix); if (curlang == findlanguage(".f")) { strip_ = true; } if (suffix != nil) { *suffix = '\0'; } if (not (*language_op(curlang, L_HASMODULES))()) { if (curblock->class != PROG) { exitblock(); if (curblock->class != PROG) { exitblock(); } } nn = identname(mname, true); if (curmodule == nil or curmodule->name != nn) { s = insert(nn); s->class = MODULE; s->symvalue.funcv.beginaddr = 0; findbeginning(s); } else { s = curmodule; } s->language = curlang; enterblock(s); curmodule = s; } if (program->language == nil) { program->language = curlang; } warned = false; enterfile(ident(n), addr); initTypeTable();}/* * Allocate file and line tables and initialize indices. */private allocmaps (nf, nl)integer nf, nl;{ if (filetab != nil) { dispose(filetab); } if (linetab != nil) { dispose(linetab); } filetab = newarr(Filetab, nf); linetab = newarr(Linetab, nl); filep = filetab; linep = linetab;}/* * Add a file to the file table. * * If the new address is the same as the previous file address * this routine used to not enter the file, but this caused some * problems so it has been removed. It's not clear that this in * turn may not also cause a problem. */private enterfile (filename, addr)String filename;Address addr;{ filep->addr = addr; filep->filename = filename; filep->lineindex = linep - linetab; ++filep;}/* * Since we only estimated the number of lines (and it was a poor * estimation) and since we need to know the exact number of lines * to do a binary search, we set it when we're done. */private setnlines (){ nlhdr.nlines = linep - linetab;}/* * Similarly for nfiles ... */private setnfiles (){ nlhdr.nfiles = filep - filetab; setsource(filetab[0].filename);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -