Annotation of coherent/b/bin/db/db6.c, revision 1.1.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.