Annotation of 43BSDReno/pgrm/dbx/object.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)object.c   5.4 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: /*
                     25:  * Object code interface, mainly for extraction of symbolic information.
                     26:  */
                     27: 
                     28: #include "defs.h"
                     29: #include "object.h"
                     30: #include "stabstring.h"
                     31: #include "main.h"
                     32: #include "symbols.h"
                     33: #include "names.h"
                     34: #include "languages.h"
                     35: #include "mappings.h"
                     36: #include "lists.h"
                     37: #include <a.out.h>
                     38: #include <stab.h>
                     39: #include <ctype.h>
                     40: 
                     41: #ifndef public
                     42: 
                     43: struct {
                     44:     unsigned int stringsize;   /* size of the dumped string table */
                     45:     unsigned int nsyms;                /* number of symbols */
                     46:     unsigned int nfiles;       /* number of files */
                     47:     unsigned int nlines;       /* number of lines */
                     48: } nlhdr;
                     49: 
                     50: #include "languages.h"
                     51: #include "symbols.h"
                     52: 
                     53: #endif
                     54: 
                     55: #ifndef N_MOD2
                     56: #    define N_MOD2 0x50
                     57: #endif
                     58: 
                     59: public String objname = "a.out";
                     60: public integer objsize;
                     61: 
                     62: public Language curlang;
                     63: public Symbol curmodule;
                     64: public Symbol curparam;
                     65: public Symbol curcomm;
                     66: public Symbol commchain;
                     67: 
                     68: private char *stringtab;
                     69: private struct nlist *curnp;
                     70: private Boolean warned;
                     71: private Boolean strip_ = false;
                     72: 
                     73: private Filetab *filep;
                     74: private Linetab *linep, *prevlinep;
                     75: 
                     76: public String curfilename ()
                     77: {
                     78:     return ((filep-1)->filename);
                     79: }
                     80: 
                     81: /*
                     82:  * Blocks are figured out on the fly while reading the symbol table.
                     83:  */
                     84: 
                     85: #define MAXBLKDEPTH 25
                     86: 
                     87: public Symbol curblock;
                     88: 
                     89: private Symbol blkstack[MAXBLKDEPTH];
                     90: private integer curlevel;
                     91: private integer bnum, nesting;
                     92: private Address addrstk[MAXBLKDEPTH];
                     93: 
                     94: public pushBlock (b)
                     95: Symbol b;
                     96: {
                     97:     if (curlevel >= MAXBLKDEPTH) {
                     98:        fatal("nesting depth too large (%d)", curlevel);
                     99:     }
                    100:     blkstack[curlevel] = curblock;
                    101:     ++curlevel;
                    102:     curblock = b;
                    103:     if (traceblocks) {
                    104:        printf("entering block %s\n", symname(b));
                    105:     }
                    106: }
                    107: 
                    108: /*
                    109:  * Change the current block with saving the previous one,
                    110:  * since it is assumed that the symbol for the current one is to be deleted.
                    111:  */
                    112: 
                    113: public changeBlock (b)
                    114: Symbol b;
                    115: {
                    116:     curblock = b;
                    117: }
                    118: 
                    119: public enterblock (b)
                    120: Symbol b;
                    121: {
                    122:     if (curblock == nil) {
                    123:        b->level = 1;
                    124:     } else {
                    125:        b->level = curblock->level + 1;
                    126:     }
                    127:     b->block = curblock;
                    128:     pushBlock(b);
                    129: }
                    130: 
                    131: public exitblock ()
                    132: {
                    133:     if (curblock->class == FUNC or curblock->class == PROC) {
                    134:        if (prevlinep != linep) {
                    135:            curblock->symvalue.funcv.src = true;
                    136:        }
                    137:     }
                    138:     if (curlevel <= 0) {
                    139:        panic("nesting depth underflow (%d)", curlevel);
                    140:     }
                    141:     --curlevel;
                    142:     if (traceblocks) {
                    143:        printf("exiting block %s\n", symname(curblock));
                    144:     }
                    145:     curblock = blkstack[curlevel];
                    146: }
                    147: 
                    148: /*
                    149:  * Enter a source line or file name reference into the appropriate table.
                    150:  * Expanded inline to reduce procedure calls.
                    151:  *
                    152:  * private enterline (linenumber, address)
                    153:  * Lineno linenumber;
                    154:  * Address address;
                    155:  *  ...
                    156:  */
                    157: 
                    158: #define enterline(linenumber, address) \
                    159: { \
                    160:     register Linetab *lp; \
                    161:  \
                    162:     lp = linep - 1; \
                    163:     if (linenumber != lp->line) { \
                    164:        if (address != lp->addr) { \
                    165:            ++lp; \
                    166:        } \
                    167:        lp->line = linenumber; \
                    168:        lp->addr = address; \
                    169:        linep = lp + 1; \
                    170:     } \
                    171: }
                    172: 
                    173: /*
                    174:  * Read in the namelist from the obj file.
                    175:  *
                    176:  * Reads and seeks are used instead of fread's and fseek's
                    177:  * for efficiency sake; there's a lot of data being read here.
                    178:  */
                    179: 
                    180: public readobj (file)
                    181: String file;
                    182: {
                    183:     Fileid f;
                    184:     struct exec hdr;
                    185:     struct nlist nlist;
                    186: 
                    187:     f = open(file, 0);
                    188:     if (f < 0) {
                    189:        fatal("can't open %s", file);
                    190:     }
                    191:     read(f, &hdr, sizeof(hdr));
                    192:     if (N_BADMAG(hdr)) {
                    193:        objsize = 0;
                    194:        nlhdr.nsyms = 0;
                    195:        nlhdr.nfiles = 0;
                    196:        nlhdr.nlines = 0;
                    197:     } else {
                    198:        objsize = hdr.a_text;
                    199:        nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
                    200:        nlhdr.nfiles = nlhdr.nsyms;
                    201:        nlhdr.nlines = nlhdr.nsyms;
                    202:     }
                    203:     if (nlhdr.nsyms > 0) {
                    204:        lseek(f, (long) N_STROFF(hdr), 0);
                    205:        read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
                    206:        nlhdr.stringsize -= 4;
                    207:        stringtab = newarr(char, nlhdr.stringsize);
                    208:        read(f, stringtab, nlhdr.stringsize);
                    209:        allocmaps(nlhdr.nfiles, nlhdr.nlines);
                    210:        lseek(f, (long) N_SYMOFF(hdr), 0);
                    211:        readsyms(f);
                    212:        ordfunctab();
                    213:        setnlines();
                    214:        setnfiles();
                    215:     } else {
                    216:        initsyms();
                    217:     }
                    218:     close(f);
                    219: }
                    220: 
                    221: /*
                    222:  * Found the beginning of the externals in the object file
                    223:  * (signified by the "-lg" or find an external), close the
                    224:  * block for the last procedure.
                    225:  */
                    226: 
                    227: private foundglobals ()
                    228: {
                    229:     if (curblock->class != PROG) {
                    230:        exitblock();
                    231:        if (curblock->class != PROG) {
                    232:            exitblock();
                    233:        }
                    234:     }
                    235:     enterline(0, (linep-1)->addr + 1);
                    236: }
                    237: 
                    238: /*
                    239:  * Read in symbols from object file.
                    240:  */
                    241: 
                    242: private readsyms (f)
                    243: Fileid f;
                    244: {
                    245:     struct nlist *namelist;
                    246:     register struct nlist *np, *ub;
                    247:     register String name;
                    248:     boolean afterlg, foundstab;
                    249:     integer index;
                    250:     char *lastchar;
                    251: 
                    252:     initsyms();
                    253:     namelist = newarr(struct nlist, nlhdr.nsyms);
                    254:     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
                    255:     afterlg = false;
                    256:     foundstab = false;
                    257:     ub = &namelist[nlhdr.nsyms];
                    258:     curnp = &namelist[0];
                    259:     np = curnp;
                    260:     while (np < ub) {
                    261:        index = np->n_un.n_strx;
                    262:        if (index != 0) {
                    263:            name = &stringtab[index - 4];
                    264:            /*
                    265:              *  If the program contains any .f files a trailing _ is stripped
                    266:                     *  from the name on the assumption it was added by the compiler.
                    267:             *  This only affects names that follow the sdb N_SO entry with
                    268:              *  the .f name. 
                    269:              */
                    270:             if (strip_ and name[0] != '\0' ) {
                    271:                lastchar = &name[strlen(name) - 1];
                    272:                if (*lastchar == '_') {
                    273:                    *lastchar = '\0';
                    274:                }
                    275:             }
                    276:        } else {
                    277:            name = nil;
                    278:        } 
                    279: 
                    280:        /*
                    281:         * Assumptions:
                    282:         *      not an N_STAB   ==> name != nil
                    283:         *      name[0] == '-'  ==> name == "-lg"
                    284:         *      name[0] != '_'  ==> filename or invisible
                    285:         *
                    286:         * The "-lg" signals the beginning of global loader symbols.
                    287:          *
                    288:         */
                    289:        if ((np->n_type&N_STAB) != 0) {
                    290:            foundstab = true;
                    291:            enter_nl(name, np);
                    292:        } else if (name[0] == '-') {
                    293:            afterlg = true;
                    294:            foundglobals();
                    295:        } else if (afterlg) {
                    296:            check_global(name, np);
                    297:        } else if ((np->n_type&N_EXT) == N_EXT) {
                    298:            afterlg = true;
                    299:            foundglobals();
                    300:            check_global(name, np);
                    301:        } else if (name[0] == '_') {
                    302:            check_local(&name[1], np);
                    303:        } else if ((np->n_type&N_TEXT) == N_TEXT) {
                    304:            check_filename(name);
                    305:        }
                    306:        ++curnp;
                    307:        np = curnp;
                    308:     }
                    309:     if (not foundstab) {
                    310:        warning("no source compiled with -g");
                    311:     }
                    312:     dispose(namelist);
                    313: }
                    314: 
                    315: /*
                    316:  * Get a continuation entry from the name list.
                    317:  * Return the beginning of the name.
                    318:  */
                    319: 
                    320: public String getcont ()
                    321: {
                    322:     register integer index;
                    323:     register String name;
                    324: 
                    325:     ++curnp;
                    326:     index = curnp->n_un.n_strx;
                    327:     if (index == 0) {
                    328:        name = "";
                    329:     } else {
                    330:        name = &stringtab[index - 4];
                    331:     }
                    332:     return name;
                    333: }
                    334: 
                    335: /*
                    336:  * Initialize symbol information.
                    337:  */
                    338: 
                    339: private initsyms ()
                    340: {
                    341:     curblock = nil;
                    342:     curlevel = 0;
                    343:     nesting = 0;
                    344:     program = insert(identname("", true));
                    345:     program->class = PROG;
                    346:     program->language = primlang;
                    347:     program->symvalue.funcv.beginaddr = CODESTART;
                    348:     program->symvalue.funcv.inline = false;
                    349:     newfunc(program, codeloc(program));
                    350:     findbeginning(program);
                    351:     enterblock(program);
                    352:     curmodule = program;
                    353: }
                    354: 
                    355: /*
                    356:  * Free all the object file information that's being stored.
                    357:  */
                    358: 
                    359: public objfree ()
                    360: {
                    361:     symbol_free();
                    362:     /* keywords_free(); */
                    363:     /* names_free(); */
                    364:     /* dispose(stringtab); */
                    365:     clrfunctab();
                    366: }
                    367: 
                    368: /*
                    369:  * Enter a namelist entry.
                    370:  */
                    371: 
                    372: private enter_nl (name, np)
                    373: String name;
                    374: register struct nlist *np;
                    375: {
                    376:     register Symbol s;
                    377:     register Name n;
                    378: 
                    379:     s = nil;
                    380:     switch (np->n_type) {
                    381:        /*
                    382:         * Build a symbol for the FORTRAN common area.  All GSYMS that follow
                    383:         * will be chained in a list with the head kept in common.offset, and
                    384:         * the tail in common.chain.
                    385:         */
                    386:        case N_BCOMM:
                    387:            if (curcomm) {
                    388:                curcomm->symvalue.common.chain = commchain;
                    389:            }
                    390:            n = identname(name, true);
                    391:            curcomm = lookup(n);
                    392:            if (curcomm == nil) {
                    393:                curcomm = insert(n);
                    394:                curcomm->class = COMMON;
                    395:                curcomm->block = curblock;
                    396:                curcomm->level = program->level;
                    397:                curcomm->symvalue.common.chain = nil;
                    398:            }
                    399:            commchain = curcomm->symvalue.common.chain;
                    400:            break;
                    401: 
                    402:        case N_ECOMM:
                    403:            if (curcomm) {
                    404:                curcomm->symvalue.common.chain = commchain;
                    405:                curcomm = nil;
                    406:            }
                    407:            break;
                    408: 
                    409:        case N_LBRAC:
                    410:            ++nesting;
                    411:            addrstk[nesting] = (linep - 1)->addr;
                    412:            break;
                    413: 
                    414:        case N_RBRAC:
                    415:            --nesting;
                    416:            if (addrstk[nesting] == NOADDR) {
                    417:                exitblock();
                    418:                newfunc(curblock, (linep - 1)->addr);
                    419:                addrstk[nesting] = (linep - 1)->addr;
                    420:            }
                    421:            break;
                    422: 
                    423:        case N_SLINE:
                    424:            enterline((Lineno) np->n_desc, (Address) np->n_value);
                    425:            break;
                    426: 
                    427:        /*
                    428:         * Source files.
                    429:         */
                    430:        case N_SO:
                    431:            n = identname(name, true);
                    432:            enterSourceModule(n, (Address) np->n_value);
                    433:            break;
                    434: 
                    435:        /*
                    436:         * Textually included files.
                    437:         */
                    438:        case N_SOL:
                    439:            enterfile(name, (Address) np->n_value);
                    440:            break;
                    441: 
                    442:        /*
                    443:         * These symbols are assumed to have non-nil names.
                    444:         */
                    445:        case N_GSYM:
                    446:        case N_FUN:
                    447:        case N_STSYM:
                    448:        case N_LCSYM:
                    449:        case N_RSYM:
                    450:        case N_PSYM:
                    451:        case N_LSYM:
                    452:        case N_SSYM:
                    453:        case N_LENG:
                    454:            if (index(name, ':') == nil) {
                    455:                if (not warned) {
                    456:                    warned = true;
                    457:                    printf("warning: old style symbol information ");
                    458:                    printf("found in \"%s\"\n", curfilename());
                    459:                }
                    460:            } else {
                    461:                entersym(name, np);
                    462:            }
                    463:            break;
                    464: 
                    465:        case N_PC:
                    466:        case N_MOD2:
                    467:            break;
                    468: 
                    469:        default:
                    470:            printf("warning:  stab entry unrecognized: ");
                    471:            if (name != nil) {
                    472:                printf("name %s,", name);
                    473:            }
                    474:            printf("ntype %2x, desc %x, value %x'\n",
                    475:                np->n_type, np->n_desc, np->n_value);
                    476:            break;
                    477:     }
                    478: }
                    479: 
                    480: /*
                    481:  * Try to find the symbol that is referred to by the given name.  Since it's
                    482:  * an external, we need to follow a level or two of indirection.
                    483:  */
                    484: 
                    485: private Symbol findsym (n, var_isextref)
                    486: Name n;
                    487: boolean *var_isextref;
                    488: {
                    489:     register Symbol r, s;
                    490: 
                    491:     *var_isextref = false;
                    492:     find(s, n) where
                    493:        (
                    494:            s->level == program->level and (
                    495:                s->class == EXTREF or s->class == VAR or
                    496:                s->class == PROC or s->class == FUNC
                    497:            )
                    498:        ) or (
                    499:            s->block == program and s->class == MODULE
                    500:        )
                    501:     endfind(s);
                    502:     if (s == nil) {
                    503:        r = nil;
                    504:     } else if (s->class == EXTREF) {
                    505:        *var_isextref = true;
                    506:        r = s->symvalue.extref;
                    507:        delete(s);
                    508: 
                    509:        /*
                    510:         * Now check for another level of indirection that could come from
                    511:         * a forward reference in procedure nesting information.  In this case
                    512:         * the symbol has already been deleted.
                    513:         */
                    514:        if (r != nil and r->class == EXTREF) {
                    515:            r = r->symvalue.extref;
                    516:        }
                    517: /*
                    518:     } else if (s->class == MODULE) {
                    519:        s->class = FUNC;
                    520:        s->level = program->level;
                    521:        r = s;
                    522:  */
                    523:     } else {
                    524:        r = s;
                    525:     }
                    526:     return r;
                    527: }
                    528: 
                    529: /*
                    530:  * Create a symbol for a text symbol with no source information.
                    531:  * We treat it as an assembly language function.
                    532:  */
                    533: 
                    534: private Symbol deffunc (n)
                    535: Name n;
                    536: {
                    537:     Symbol f;
                    538: 
                    539:     f = insert(n);
                    540:     f->language = findlanguage(".s");
                    541:     f->class = FUNC;
                    542:     f->type = t_int;
                    543:     f->block = curblock;
                    544:     f->level = program->level;
                    545:     f->symvalue.funcv.src = false;
                    546:     f->symvalue.funcv.inline = false;
                    547:     if (f->chain != nil) {
                    548:        panic("chain not nil in deffunc");
                    549:     }
                    550:     return f;
                    551: }
                    552: 
                    553: /*
                    554:  * Create a symbol for a data or bss symbol with no source information.
                    555:  * We treat it as an assembly language variable.
                    556:  */
                    557: 
                    558: private Symbol defvar (n)
                    559: Name n;
                    560: {
                    561:     Symbol v;
                    562: 
                    563:     v = insert(n);
                    564:     v->language = findlanguage(".s");
                    565:     v->storage = EXT;
                    566:     v->class = VAR;
                    567:     v->type = t_int;
                    568:     v->level = program->level;
                    569:     v->block = curblock;
                    570:     return v;
                    571: }
                    572: 
                    573: /*
                    574:  * Update a symbol entry with a text address.
                    575:  */
                    576: 
                    577: private updateTextSym (s, name, addr)
                    578: Symbol s;
                    579: char *name;
                    580: Address addr;
                    581: {
                    582:     if (s->class == VAR) {
                    583:        s->symvalue.offset = addr;
                    584:     } else {
                    585:        s->symvalue.funcv.beginaddr = addr;
                    586:        if (name[0] == '_') {
                    587:            newfunc(s, codeloc(s));
                    588:            findbeginning(s);
                    589:        }
                    590:     }
                    591: }
                    592: 
                    593: /*
                    594:  * Avoid seeing Pascal labels as text symbols.
                    595:  */
                    596: 
                    597: private boolean PascalLabel (n)
                    598: Name n;
                    599: {
                    600:     boolean b;
                    601:     register char *p;
                    602: 
                    603:     b = false;
                    604:     if (curlang == findlanguage(".p")) {
                    605:        p = ident(n);
                    606:        while (*p != '\0') {
                    607:            if (*p == '_' and *(p+1) == '$') {
                    608:                b = true;
                    609:                break;
                    610:            }
                    611:            ++p;
                    612:        }
                    613:     }
                    614:     return b;
                    615: }
                    616: 
                    617: /*
                    618:  * Check to see if a global _name is already in the symbol table,
                    619:  * if not then insert it.
                    620:  */
                    621: 
                    622: private check_global (name, np)
                    623: String name;
                    624: register struct nlist *np;
                    625: {
                    626:     register Name n;
                    627:     register Symbol t, u;
                    628:     char buf[4096];
                    629:     boolean isextref;
                    630:     integer count;
                    631: 
                    632:     if (not streq(name, "_end")) {
                    633:        if (name[0] == '_') {
                    634:            n = identname(&name[1], true);
                    635:        } else {
                    636:            n = identname(name, true);
                    637:            if (lookup(n) != nil) {
                    638:                sprintf(buf, "$%s", name);
                    639:                n = identname(buf, false);
                    640:            }
                    641:        }
                    642:        if ((np->n_type&N_TYPE) == N_TEXT) {
                    643:            count = 0;
                    644:            t = findsym(n, &isextref);
                    645:            while (isextref) {
                    646:                ++count;
                    647:                updateTextSym(t, name, np->n_value);
                    648:                t = findsym(n, &isextref);
                    649:            }
                    650:            if (count == 0) {
                    651:                if (t == nil) {
                    652:                    if (not PascalLabel(n)) {
                    653:                        t = deffunc(n);
                    654:                        updateTextSym(t, name, np->n_value);
                    655:                        if (tracesyms) {
                    656:                            printdecl(t);
                    657:                        }
                    658:                    }
                    659:                } else {
                    660:                    if (t->class == MODULE) {
                    661:                        u = t;
                    662:                        t = deffunc(n);
                    663:                        t->block = u;
                    664:                        if (tracesyms) {
                    665:                            printdecl(t);
                    666:                        }
                    667:                    }
                    668:                    updateTextSym(t, name, np->n_value);
                    669:                }
                    670:            }
                    671:        } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) {
                    672:            find(t, n) where
                    673:                t->class == COMMON
                    674:            endfind(t);
                    675:            if (t != nil) {
                    676:                u = (Symbol) t->symvalue.common.offset;
                    677:                while (u != nil) {
                    678:                    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
                    679:                    u = u->symvalue.common.chain;
                    680:                }
                    681:             } else {
                    682:                check_var(np, n);
                    683:            }
                    684:         } else {
                    685:            check_var(np, n);
                    686:        }
                    687:     }
                    688: }
                    689: 
                    690: /*
                    691:  * Check to see if a namelist entry refers to a variable.
                    692:  * If not, create a variable for the entry.  In any case,
                    693:  * set the offset of the variable according to the value field
                    694:  * in the entry.
                    695:  *
                    696:  * If the external name has been referred to by several other symbols,
                    697:  * we must update each of them.
                    698:  */
                    699: 
                    700: private check_var (np, n)
                    701: struct nlist *np;
                    702: register Name n;
                    703: {
                    704:     register Symbol t, u, next;
                    705:     Symbol conflict;
                    706: 
                    707:     t = lookup(n);
                    708:     if (t == nil) {
                    709:        t = defvar(n);
                    710:        t->symvalue.offset = np->n_value;
                    711:        if (tracesyms) {
                    712:            printdecl(t);
                    713:        }
                    714:     } else {
                    715:        conflict = nil;
                    716:        do {
                    717:            next = t->next_sym;
                    718:            if (t->name == n) {
                    719:                if (t->class == MODULE and t->block == program) {
                    720:                    conflict = t;
                    721:                } else if (t->class == EXTREF and t->level == program->level) {
                    722:                    u = t->symvalue.extref;
                    723:                    while (u != nil and u->class == EXTREF) {
                    724:                        u = u->symvalue.extref;
                    725:                    }
                    726:                    u->symvalue.offset = np->n_value;
                    727:                    delete(t);
                    728:                } else if (t->level == program->level and
                    729:                    (t->class == VAR or t->class == PROC or t->class == FUNC)
                    730:                ) {
                    731:                    conflict = nil;
                    732:                    t->symvalue.offset = np->n_value;
                    733:                }
                    734:            }
                    735:            t = next;
                    736:        } while (t != nil);
                    737:        if (conflict != nil) {
                    738:            u = defvar(n);
                    739:            u->block = conflict;
                    740:            u->symvalue.offset = np->n_value;
                    741:        }
                    742:     }
                    743: }
                    744: 
                    745: /*
                    746:  * Check to see if a local _name is known in the current scope.
                    747:  * If not then enter it.
                    748:  */
                    749: 
                    750: private check_local (name, np)
                    751: String name;
                    752: register struct nlist *np;
                    753: {
                    754:     register Name n;
                    755:     register Symbol t, cur;
                    756: 
                    757:     n = identname(name, true);
                    758:     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
                    759:     find(t, n) where t->block == cur endfind(t);
                    760:     if (t == nil) {
                    761:        t = insert(n);
                    762:        t->language = findlanguage(".s");
                    763:        t->type = t_int;
                    764:        t->block = cur;
                    765:        t->storage = EXT;
                    766:        t->level = cur->level;
                    767:        if ((np->n_type&N_TYPE) == N_TEXT) {
                    768:            t->class = FUNC;
                    769:            t->symvalue.funcv.src = false;
                    770:            t->symvalue.funcv.inline = false;
                    771:            t->symvalue.funcv.beginaddr = np->n_value;
                    772:            newfunc(t, codeloc(t));
                    773:            findbeginning(t);
                    774:        } else {
                    775:            t->class = VAR;
                    776:            t->symvalue.offset = np->n_value;
                    777:        }
                    778:     }
                    779: }
                    780: 
                    781: /*
                    782:  * Check to see if a symbol corresponds to a object file name.
                    783:  * For some reason these are listed as in the text segment.
                    784:  */
                    785: 
                    786: private check_filename (name)
                    787: String name;
                    788: {
                    789:     register String mname;
                    790:     register integer i;
                    791:     Name n;
                    792:     Symbol s;
                    793: 
                    794:     mname = strdup(name);
                    795:     i = strlen(mname) - 2;
                    796:     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
                    797:        mname[i] = '\0';
                    798:        --i;
                    799:        while (mname[i] != '/' and i >= 0) {
                    800:            --i;
                    801:        }
                    802:        n = identname(&mname[i+1], true);
                    803:        find(s, n) where s->block == program and s->class == MODULE endfind(s);
                    804:        if (s == nil) {
                    805:            s = insert(n);
                    806:            s->language = findlanguage(".s");
                    807:            s->class = MODULE;
                    808:            s->symvalue.funcv.beginaddr = 0;
                    809:            findbeginning(s);
                    810:        }
                    811:        if (curblock->class != PROG) {
                    812:            exitblock();
                    813:            if (curblock->class != PROG) {
                    814:                exitblock();
                    815:            }
                    816:        }
                    817:        enterblock(s);
                    818:        curmodule = s;
                    819:     }
                    820: }
                    821: 
                    822: /*
                    823:  * Check to see if a symbol is about to be defined within an unnamed block.
                    824:  * If this happens, we create a procedure for the unnamed block, make it
                    825:  * "inline" so that tracebacks don't associate an activation record with it,
                    826:  * and enter it into the function table so that it will be detected
                    827:  * by "whatblock".
                    828:  */
                    829: 
                    830: public chkUnnamedBlock ()
                    831: {
                    832:     register Symbol s;
                    833:     static int bnum = 0;
                    834:     char buf[100];
                    835:     Address startaddr;
                    836: 
                    837:     if (nesting > 0 and addrstk[nesting] != NOADDR) {
                    838:        startaddr = (linep - 1)->addr;
                    839:        ++bnum;
                    840:        sprintf(buf, "$b%d", bnum);
                    841:        s = insert(identname(buf, false));
                    842:        s->language = curlang;
                    843:        s->class = PROC;
                    844:        s->symvalue.funcv.src = false;
                    845:        s->symvalue.funcv.inline = true;
                    846:        s->symvalue.funcv.beginaddr = startaddr;
                    847:        enterblock(s);
                    848:        newfunc(s, startaddr);
                    849:        addrstk[nesting] = NOADDR;
                    850:     }
                    851: }
                    852: 
                    853: /*
                    854:  * Compilation unit.  C associates scope with filenames
                    855:  * so we treat them as "modules".  The filename without
                    856:  * the suffix is used for the module name.
                    857:  *
                    858:  * Because there is no explicit "end-of-block" mark in
                    859:  * the object file, we must exit blocks for the current
                    860:  * procedure and module.
                    861:  */
                    862: 
                    863: private enterSourceModule (n, addr)
                    864: Name n;
                    865: Address addr;
                    866: {
                    867:     register Symbol s;
                    868:     Name nn;
                    869:     String mname, suffix;
                    870: 
                    871:     mname = strdup(ident(n));
                    872:     if (rindex(mname, '/') != nil) {
                    873:        mname = rindex(mname, '/') + 1;
                    874:     }
                    875:     suffix = rindex(mname, '.');
                    876:     if (suffix > mname && *(suffix-1) == '.') {
                    877:        /* special hack for C++ */
                    878:        --suffix;
                    879:     }
                    880:     curlang = findlanguage(suffix);
                    881:     if (curlang == findlanguage(".f")) {
                    882:        strip_ = true;
                    883:     } 
                    884:     if (suffix != nil) {
                    885:        *suffix = '\0';
                    886:     }
                    887:     if (not (*language_op(curlang, L_HASMODULES))()) {
                    888:        if (curblock->class != PROG) {
                    889:            exitblock();
                    890:            if (curblock->class != PROG) {
                    891:                exitblock();
                    892:            }
                    893:        }
                    894:        nn = identname(mname, true);
                    895:        if (curmodule == nil or curmodule->name != nn) {
                    896:            s = insert(nn);
                    897:            s->class = MODULE;
                    898:            s->symvalue.funcv.beginaddr = 0;
                    899:            findbeginning(s);
                    900:        } else {
                    901:            s = curmodule;
                    902:        }
                    903:        s->language = curlang;
                    904:        enterblock(s);
                    905:        curmodule = s;
                    906:     }
                    907:     if (program->language == nil) {
                    908:        program->language = curlang;
                    909:     }
                    910:     warned = false;
                    911:     enterfile(ident(n), addr);
                    912:     initTypeTable();
                    913: }
                    914: 
                    915: /*
                    916:  * Allocate file and line tables and initialize indices.
                    917:  */
                    918: 
                    919: private allocmaps (nf, nl)
                    920: integer nf, nl;
                    921: {
                    922:     if (filetab != nil) {
                    923:        dispose(filetab);
                    924:     }
                    925:     if (linetab != nil) {
                    926:        dispose(linetab);
                    927:     }
                    928:     filetab = newarr(Filetab, nf);
                    929:     linetab = newarr(Linetab, nl);
                    930:     filep = filetab;
                    931:     linep = linetab;
                    932: }
                    933: 
                    934: /*
                    935:  * Add a file to the file table.
                    936:  *
                    937:  * If the new address is the same as the previous file address
                    938:  * this routine used to not enter the file, but this caused some
                    939:  * problems so it has been removed.  It's not clear that this in
                    940:  * turn may not also cause a problem.
                    941:  */
                    942: 
                    943: private enterfile (filename, addr)
                    944: String filename;
                    945: Address addr;
                    946: {
                    947:     filep->addr = addr;
                    948:     filep->filename = filename;
                    949:     filep->lineindex = linep - linetab;
                    950:     ++filep;
                    951: }
                    952: 
                    953: /*
                    954:  * Since we only estimated the number of lines (and it was a poor
                    955:  * estimation) and since we need to know the exact number of lines
                    956:  * to do a binary search, we set it when we're done.
                    957:  */
                    958: 
                    959: private setnlines ()
                    960: {
                    961:     nlhdr.nlines = linep - linetab;
                    962: }
                    963: 
                    964: /*
                    965:  * Similarly for nfiles ...
                    966:  */
                    967: 
                    968: private setnfiles ()
                    969: {
                    970:     nlhdr.nfiles = filep - filetab;
                    971:     setsource(filetab[0].filename);
                    972: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.