Annotation of coherent/b/bin/db/db6.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * db/db6.c
        !             3:  * A debugger.
        !             4:  * Symbol handling.
        !             5:  */
        !             6: 
        !             7: #include <canon.h>
        !             8: #include "db.h"
        !             9: 
        !            10: /*
        !            11:  * In earlier versions of db, a SYM included an id hash, a type and a symbol
        !            12:  * table index, but not did not include the symbol id[] itself.
        !            13:  * This allowed db to handle lots of symbols in a small address space,
        !            14:  * but each symbol lookup required reading the symbol again from
        !            15:  * the symbol table in the program file (i.e. from the disk).
        !            16:  * Since memory is no longer as critical an issue, now db stores the id[]
        !            17:  * as part of the SYM and symbol lookup does not need to access the file.
        !            18:  */
        !            19: 
        !            20: /*
        !            21:  * Given a value 'm' in segment 's', find the closest symbol below.
        !            22:  * Return a pointer to the symbol, or NULL if none.
        !            23:  * In COFF, with a flat address space, the segment can be ignored.
        !            24:  * In l.out, where the same address can represent a code or a data item,
        !            25:  * it had better not be ignored.
        !            26:  */
        !            27: SYM *
        !            28: findsym(s, addr) int s; ADDR_T addr;
        !            29: {
        !            30:        register int n;
        !            31:        register SYM *hp, *sp;
        !            32: 
        !            33:        dbprintf(("findsym(%d, %lX):\n", s, addr));
        !            34:        sp = (SYM *)NULL;
        !            35:        if (sfp == (FILE *)NULL)
        !            36:                return sp;                      /* no symbols */
        !            37:        for (n = 0; n < NHASH; n++) {           /* search all hash buckets */
        !            38:                for (hp = symhash[n]; hp != (SYM *)NULL; hp = hp->s_next) {
        !            39: 
        !            40:                        dbprintf(("findsym: (%d, %lX) id=%s @ (%d, %lX)\n", s, addr, hp->s_id, hp->s_segn, hp->s_addr));
        !            41:                        if (IS_LOUT && hp->s_segn != s)
        !            42:                                continue;       /* segment mismatch */
        !            43: 
        !            44:                        /* If below and better than previous best guess... */
        !            45:                        if (hp->s_addr <= addr
        !            46:                         && (sp==(SYM *)NULL || hp->s_addr > sp->s_addr)) {
        !            47:                                sp = hp;                /* best so far */
        !            48:                                dbprintf((" best so far: %s addr=%lX s=%d\n", sp->s_id, sp->s_addr, sp->s_segn));
        !            49:                                if (sp->s_addr == addr)
        !            50:                                        return sp;      /* gotcha! */
        !            51:                        }
        !            52:                }
        !            53:        }
        !            54:        return sp;                              /* NULL or best guess */
        !            55: }
        !            56: 
        !            57: /*
        !            58:  * Hash a symbol name.
        !            59:  * The '_' character has no effect on the hash, so "foo" and "foo_" hash
        !            60:  * to the same value; this is convenient for l.out symbol lookup,
        !            61:  * where is_symbol() understands "foo" to mean "foo_" if there is no "foo".
        !            62:  */
        !            63: int
        !            64: hash(id) register char *id;
        !            65: {
        !            66:        register int c, h;
        !            67: 
        !            68:        for (h = 0; (c = *id++) != 0; )
        !            69:                if (c != '_')
        !            70:                        h += c;
        !            71:        return h % NHASH;
        !            72: }
        !            73: 
        !            74: /*
        !            75:  * See if the given symbol is a special symbol "d", "i" or "u".
        !            76:  */
        !            77: int
        !            78: is_special(sp) register SYM *sp;
        !            79: {
        !            80:        register int s;
        !            81: 
        !            82:        if (sp->s_id[1] != '\0')
        !            83:                return 0;
        !            84:        switch (sp->s_id[0]) {
        !            85:        case 'd':       s = DSEG;               break;
        !            86:        case 'i':       s = ISEG;               break;
        !            87:        case 'u':       s = USEG;               break;
        !            88:        default:        return 0;
        !            89:        }
        !            90:        sp->s_addr = 0;
        !            91:        sp->s_segn = s;
        !            92:        return 1;
        !            93: }
        !            94: 
        !            95: /*
        !            96:  * Find the value of a symbol.
        !            97:  * Return 1 on success, 0 on failure.
        !            98:  * For l.out, "foo" matches "foo_" if "foo" is not found.
        !            99:  */
        !           100: int
        !           101: is_symbol(sp) SYM *sp;
        !           102: {
        !           103:        register char *cp;
        !           104:        register SYM *hp;
        !           105:        register int len;
        !           106: 
        !           107:        dbprintf(("is_symbol(%s): "));
        !           108:        cp = sp->s_id;
        !           109:        for (hp = symhash[hash(cp)]; hp != (SYM *)NULL; hp = hp->s_next) {
        !           110:                if (strcmp(cp, hp->s_id) == 0) {
        !           111:                        dbprintf(("addr=%lX segn=%d\n", hp->s_addr, hp->s_segn));
        !           112:                        sp->s_addr = hp->s_addr;
        !           113:                        sp->s_segn = hp->s_segn;
        !           114:                        return 1;
        !           115:                }
        !           116:        }
        !           117: 
        !           118:        /* The symbol was not found.  If l.out, try again with trailing '_'. */
        !           119:        if (IS_LOUT) {
        !           120:                len = strlen(cp);
        !           121:                for (hp = symhash[hash(cp)]; hp != (SYM *)NULL; hp = hp->s_next) {
        !           122:                        if (strncmp(cp, hp->s_id, len) == 0
        !           123:                         && hp->s_id[len] == '_'
        !           124:                         && hp->s_id[len+1] == '\0') {
        !           125:                                dbprintf(("(%s) addr=%lX segn=%d\n", hp->s_id, hp->s_addr, hp->s_segn));
        !           126:                                sp->s_addr = hp->s_addr;
        !           127:                                sp->s_segn = hp->s_segn;
        !           128:                                return 1;
        !           129:                        }
        !           130:                }
        !           131:        }
        !           132:        dbprintf((" is_symbol(): %s not found\n", cp));
        !           133:        return 0;
        !           134: }
        !           135: 
        !           136: /*
        !           137:  * Allocate a new SYM with the given id, address and segment.
        !           138:  * Initialize it and link it into the hash chain.
        !           139:  * db.h declares char s_id[1], but the nalloc() call below
        !           140:  * leaves room for the actual id char s_id[len+1].
        !           141:  */
        !           142: void
        !           143: new_sym(id, addr, s) char *id; ADDR_T addr; int s;
        !           144: {
        !           145:        register int len, h;
        !           146:        register SYM *sp;
        !           147: 
        !           148:        h = hash(id);
        !           149:        len = strlen(id);                       /* len+1 is s_id len with NUL */
        !           150:        dbprintf(("new_sym(%s, %x, %lX) len=%d hash=%x\n", id, type, addr, len, h));
        !           151:        sp = (SYM *)nalloc(sizeof(SYM) + len, "symbol");
        !           152:        sp->s_next = symhash[h];
        !           153:        symhash[h] = sp;
        !           154:        sp->s_addr = addr;
        !           155:        sp->s_segn = s;
        !           156:        strcpy(sp->s_id, id);
        !           157: }
        !           158: 
        !           159: /*
        !           160:  * Read COFF symbols.
        !           161:  */
        !           162: int
        !           163: read_coff_sym()
        !           164: {
        !           165:        SYMENT          coffsym;
        !           166:        long            n;
        !           167:        register int    len, segn;
        !           168:        char            *strtab;
        !           169:        SCNHDR          *shp;
        !           170: 
        !           171:        dbprintf(("read_coff_sym()\n"));
        !           172: 
        !           173:        /* Read the COFF string table. */
        !           174:        strtab = read_strtab();
        !           175: 
        !           176:        /* Read the COFF section headers. */
        !           177:        len = coff_hdr.f_nscns * sizeof(SCNHDR);
        !           178:        shp = (SCNHDR *)nalloc(len, "COFF section headers");
        !           179:        if (fseek(sfp, (long)(sizeof(FILEHDR) + coff_hdr.f_opthdr), SEEK_SET) == -1
        !           180:         || fread(shp, len, 1, sfp) != 1)
        !           181:                return printe("Cannot read section headers");
        !           182: 
        !           183:        /* Read symbols. */
        !           184:        if (fseek(sfp, (long)coff_hdr.f_symptr, SEEK_SET) == -1)
        !           185:                return printe("COFF symbol seek failed");
        !           186:        for (nsyms = 0, n = coff_hdr.f_nsyms; n--; ) {
        !           187:                /* Read a COFF symbol. */
        !           188:                if (fread(&coffsym, sizeof(SYMENT), 1, sfp) != 1)
        !           189:                        return printe("Cannot read COFF symbol");
        !           190:                switch (coffsym.n_sclass) {
        !           191:                case C_EXT:
        !           192:                case C_EXTDEF:
        !           193:                        break;
        !           194:                default:
        !           195:                        continue;
        !           196:                }
        !           197:                /* Ignore undefined and absolute symbols. */
        !           198:                if (coffsym.n_scnum == N_UNDEF || coffsym.n_scnum == N_ABS)
        !           199:                        continue;
        !           200: 
        !           201:                switch((int)shp[coffsym.n_scnum-1].s_flags) {
        !           202:                case STYP_TEXT: segn = ISEG;    break;
        !           203:                case STYP_DATA:
        !           204:                case STYP_BSS:  segn = DSEG;    break;
        !           205:                default:
        !           206:                        panic("Unallowed section flags 0x%lX for symbol in section %d",
        !           207:                                shp[coffsym.n_scnum-1].s_flags, coffsym.n_scnum-1);
        !           208:                }
        !           209:                ++nsyms;
        !           210:                new_sym(symName(&coffsym, strtab), coffsym.n_value, segn);
        !           211:        }
        !           212:        dbprintf(("COFF nsyms=%d\n", nsyms));
        !           213:        if (strtab != NULL)
        !           214:                nfree(strtab);
        !           215:        nfree(shp);
        !           216:        return 1;
        !           217: }
        !           218: 
        !           219: /*
        !           220:  * Read l.out symbols.
        !           221:  */
        !           222: int
        !           223: read_lout_sym(symseek) long symseek;
        !           224: {
        !           225:        register int n, segn;
        !           226:        struct ldsym lds;
        !           227:        char id[NCPLN+1];
        !           228: 
        !           229:        if (fseek(sfp, symseek, SEEK_SET) == -1)
        !           230:                return printr("Cannot seek to l.out symbols");
        !           231:        for (n = nsyms; n--; ) {
        !           232:                /* Read an l.out symbol. */
        !           233:                if (fread(&lds, sizeof(struct ldsym), 1, sfp) != 1)
        !           234:                        return printr("Cannot read l.out symbol");
        !           235:                canint(lds.ls_type);
        !           236:                switch(lds.ls_type & LR_SEG) {
        !           237:                case L_ABS:
        !           238:                case L_SHRI:
        !           239:                case L_PRVI:
        !           240:                case L_BSSI:
        !           241:                        segn = ISEG;
        !           242:                        break;
        !           243:                case L_SHRD:
        !           244:                case L_PRVD:
        !           245:                case L_BSSD:
        !           246:                        segn = DSEG;
        !           247:                        break;
        !           248:                default:
        !           249:                        dbprintf(("Unexpected l.out segment %d\n", lds.ls_type & LR_SEG));
        !           250:                        continue;
        !           251:                }
        !           252:                canvaddr(lds.ls_addr);
        !           253:                strncpy(id, lds.ls_id, NCPLN);
        !           254:                id[NCPLN] = '\0';
        !           255:                new_sym(id, (ADDR_T)lds.ls_addr, segn);
        !           256:        }
        !           257:        dbprintf(("l.out nsyms=%d\n", nsyms));
        !           258:        return 1;
        !           259: }
        !           260: 
        !           261: /*
        !           262:  * Read the COFF string table.
        !           263:  * Return a pointer to the allocated table, or NULL if empty.
        !           264:  */
        !           265: char *
        !           266: read_strtab()
        !           267: {
        !           268:        register unsigned int len;
        !           269:        int llen;
        !           270:        char *strtab;
        !           271: 
        !           272:        dbprintf(("read_strtab()\n"));
        !           273:        len = llen = sizeof(SYMENT) * coff_hdr.f_nsyms;
        !           274:        if (len == 0)
        !           275:                return NULL;                    /* no symbols */
        !           276:        if (llen != len)
        !           277:                panic("COFF symbol table too big");
        !           278: 
        !           279:        /* Seek to strtab length. */
        !           280:        if (fseek(sfp, coff_hdr.f_symptr+len, SEEK_SET) == -1
        !           281:         || fread(&llen, sizeof(llen), 1, sfp) != 1)
        !           282:                llen = 0;
        !           283:        if (llen == 0)
        !           284:                return NULL;                    /* no string table */
        !           285:        len = llen -= 4;
        !           286:        if (len != llen)
        !           287:                panic("COFF string table too big");
        !           288:        strtab = nalloc((int)len, "COFF string table");
        !           289:        if (fread(strtab, len, 1, sfp) != 1) {
        !           290:                printe("Cannot read symbol string table");
        !           291:                return NULL;
        !           292:        }
        !           293:        return strtab;
        !           294: }
        !           295: 
        !           296: /*
        !           297:  * Given a COFF symbol table entry, return its NUL-terminated name.
        !           298:  */
        !           299: char *
        !           300: symName(sym, strtab) SYMENT *sym; char *strtab;
        !           301: {
        !           302:        static  char    work[SYMNMLEN+1];
        !           303: 
        !           304:        if (sym->n_zeroes == 0)
        !           305:                return strtab + sym->n_offset - 4;      /* name in string table */
        !           306: 
        !           307:        /* Copy name from n_name to make sure it's NUL-terminated. */
        !           308:        memcpy(work, sym->n_name, SYMNMLEN);
        !           309:        work[SYMNMLEN] = '\0';
        !           310:        return work;
        !           311: }
        !           312: 
        !           313: /*
        !           314:  * Read a symbol and return its value in the given 'VAL' structure.
        !           315:  * The symbol name can contain alphanumeric characters and '_';
        !           316:  * a leading '%' indicates a register name.
        !           317:  */
        !           318: int
        !           319: symval(vp) VAL *vp;
        !           320: {
        !           321:        register int c;
        !           322:        register char *cp;
        !           323:        int regf;
        !           324:        static SYM *sp;
        !           325:        static int sym_len = 128;
        !           326: 
        !           327:        /* Allocate a SYM first time through. */
        !           328:        if (sp == (SYM *)NULL)
        !           329:                sp = (SYM *)nalloc(sizeof(SYM)+sym_len+1, "symbol id buffer");
        !           330: 
        !           331:        /* Read the symbol name into the SYM id[] buffer. */
        !           332:        for (regf = 0, cp = sp->s_id; ; cp++) {
        !           333:                c = getn();
        !           334:                /* Allow leading '%' to indicate register name. */
        !           335:                if (cp==sp->s_id && c=='%') {
        !           336:                        c = getn();
        !           337:                        ++regf;
        !           338:                }
        !           339:                if (!isascii(c) || (!isalnum(c) && c!= '_'))
        !           340:                        break;
        !           341:                if (cp == &sp->s_id[sym_len]) {
        !           342:                        register SYM *sp2;
        !           343: 
        !           344:                        /* Grow the symbol id buffer when required. */
        !           345:                        sp2 = (SYM *)nalloc(sizeof(SYM)+sym_len+sym_len+1, "symbol id buffer");
        !           346:                        strncpy(sp2->s_id, sp->s_id, sym_len);
        !           347:                        cp = &sp2->s_id[sym_len];
        !           348:                        sym_len += sym_len;
        !           349:                        nfree(sp);
        !           350:                        sp = sp2;
        !           351:                }               
        !           352:                *cp = c;
        !           353:        }
        !           354:        *cp = '\0';
        !           355:        ungetn(c);
        !           356:        if (regf) {
        !           357:                if (is_reg(sp) == 0)
        !           358:                        return printe("Register not found");
        !           359:        } else if (!is_special(sp) && !is_symbol(sp) && !is_reg(sp))
        !           360:                return printe("Symbol not found");
        !           361: 
        !           362:        /* Copy the value and segment to vp. */
        !           363:        vp->v_nval = (long)sp->s_addr;
        !           364:        vp->v_segn = sp->s_segn;
        !           365:        vp->v_flag = VSEGN;
        !           366:        return 1;
        !           367: }
        !           368: 
        !           369: /* end of db/db6.c */
        !           370: 

unix.superglobalmegacorp.com

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