Annotation of lucent/sys/src/libmach/sym.c, revision 1.1.1.1

1.1       root        1: #include <u.h>
                      2: #include <libc.h>
                      3: #include <bio.h>
                      4: #include <mach.h>
                      5: 
                      6: #define        HUGEINT 0x7fffffff
                      7: #define        NNAME   20              /* a relic of the past */
                      8: 
                      9: typedef        struct txtsym Txtsym;
                     10: typedef        struct file File;
                     11: typedef        struct hist Hist;
                     12: 
                     13: struct txtsym {                                /* Text Symbol table */
                     14:        int     n;                      /* number of local vars */
                     15:        Sym     **locals;               /* array of ptrs to autos */
                     16:        Sym     *sym;                   /* function symbol entry */
                     17: };
                     18: 
                     19: struct hist {          /* Stack of include files & #line directives */
                     20:        char    *name;                  /* Assumes names Null terminated in file */
                     21:        long    line;                   /* line # where it was included */
                     22:        long    offset;                 /* line # of #line directive */
                     23: };
                     24: 
                     25: struct file {                          /* Per input file header to history stack */
                     26:        long            addr;           /* address of first text sym */
                     27:        union {
                     28:                Txtsym          *txt;   /* first text symbol */
                     29:                Sym             *sym;   /* only during initilization */
                     30:        };
                     31:        int             n;              /* size of history stack */
                     32:        Hist            *hist;          /* history stack */
                     33: };
                     34: 
                     35: static int     debug = 0;
                     36: 
                     37: static Sym     **autos;                /* Base of auto variables */
                     38: static File    *files;                 /* Base of file arena */
                     39: static int     fmax;                   /* largest file path index */
                     40: static Sym     **fnames;               /* file names path component table */
                     41: static Sym     **globals;              /* globals by addr table */
                     42: static Hist    *hist;                  /* base of history stack */
                     43: static int     isbuilt;                /* internal table init flag */
                     44: static long    nauto;                  /* number of automatics */
                     45: static long    nfiles;                 /* number of files */
                     46: static long    nglob;                  /* number of globals */
                     47: static long    nhist;                  /* number of history stack entries */
                     48: static long    nsym;                   /* number of symbols */
                     49: static int     ntxt;                   /* number of text symbols */
                     50: static uchar   *pcline;                /* start of pc-line state table */
                     51: static uchar   *pclineend;             /* end of pc-line table */
                     52: static uchar   *spoff;                 /* start of pc-sp state table */
                     53: static uchar   *spoffend;              /* end of pc-sp offset table */
                     54: static Sym     *symbols;               /* symbol table */
                     55: static Txtsym  *txt;                   /* Base of text symbol table */
                     56: static long    txtstart;               /* start of text segment */
                     57: static long    txtend;                 /* end of text segment */
                     58: 
                     59: static void    cleansyms(void);
                     60: static int     decodename(Biobuf*, Sym*);
                     61: static short   *encfname(char *);
                     62: static Hist    *fline(char *, int, long, Hist *);
                     63: static void    fillsym(Sym *, Symbol *);
                     64: static int     findglobal(char *, Symbol *);
                     65: static int     findlocvar(Symbol *, char *, Symbol *);
                     66: static int     findtext(char *, Symbol *);
                     67: static int     hcomp(Hist *, short *);
                     68: static int     hline(File *, short *, ulong *);
                     69: static void    printhist(char *, Hist *, int);
                     70: static int     buildtbls(void);
                     71: static int     symcomp(void *, void *);
                     72: static int     symerrmsg(int, char*);
                     73: static int     txtcomp(void *, void *);
                     74: static int     filecomp(void *, void *);
                     75: 
                     76: /*
                     77:  *     initialize the symbol tables
                     78:  */
                     79: int
                     80: syminit(int fd, Fhdr *fp)
                     81: {
                     82:        Sym *p;
                     83:        int i, size;
                     84:        Biobuf b;
                     85: 
                     86:        if(fp->symsz == 0)
                     87:                return 0;
                     88:        if(fp->type == FNONE)
                     89:                return 0;
                     90: 
                     91:        cleansyms();
                     92:        textseg(fp->txtaddr, fp);
                     93:                /* minimum symbol record size = 4+1+2 bytes */
                     94:        symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym));
                     95:        if(symbols == 0) {
                     96:                werrstr("can't malloc %d bytes", fp->symsz);
                     97:                return -1;
                     98:        }
                     99: 
                    100:        Binit(&b, fd, OREAD);
                    101:        Bseek(&b, fp->symoff, 0);
                    102:        nsym = 0;
                    103:        size = 0;
                    104:        for(p = symbols; size < fp->symsz; p++, nsym++) {
                    105:                if(Bread(&b, &p->value, sizeof(p->value)) != sizeof(p->value))
                    106:                        return symerrmsg(sizeof(p->value), "symbol");
                    107:                p->value = beswal(p->value);
                    108:                if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
                    109:                        return symerrmsg(sizeof(p->value), "symbol");
                    110: 
                    111:                i = decodename(&b, p);
                    112:                if(i < 0)
                    113:                        return -1;
                    114:                size += i+sizeof(p->value)+sizeof(p->type);
                    115: 
                    116:                /* count global & auto vars, text symbols, and file names */
                    117:                switch (p->type) {
                    118:                case 'l':
                    119:                case 'L':
                    120:                case 't':
                    121:                case 'T':
                    122:                        ntxt++;
                    123:                        break;
                    124:                case 'd':
                    125:                case 'D':
                    126:                case 'b':
                    127:                case 'B':
                    128:                        nglob++;
                    129:                        break;
                    130:                case 'f':
                    131:                        if(strcmp(p->name, ".frame") == 0) {
                    132:                                p->type = 'm';
                    133:                                nauto++;
                    134:                        }
                    135:                        else if(p->value > fmax)
                    136:                                fmax = p->value;        /* highest path index */
                    137:                        break;
                    138:                case 'a':
                    139:                case 'p':
                    140:                case 'm':
                    141:                        nauto++;
                    142:                        break;
                    143:                case 'z':
                    144:                        if(p->value == 1) {             /* one extra per file */
                    145:                                nhist++;
                    146:                                nfiles++;
                    147:                        }
                    148:                        nhist++;
                    149:                        break;
                    150:                default:
                    151:                        break;
                    152:                }
                    153:        }
                    154:        if (debug)
                    155:                print("NG: %d NT: %d NF: %d\n", nglob, ntxt, fmax);
                    156:        if (fp->sppcsz) {                       /* pc-sp offset table */
                    157:                spoff = (uchar *)malloc(fp->sppcsz);
                    158:                if(spoff == 0) {
                    159:                        werrstr("can't malloc %d bytes", fp->sppcsz);
                    160:                        return -1;
                    161:                }
                    162:                Bseek(&b, fp->sppcoff, 0);
                    163:                i = Bread(&b, spoff, fp->sppcsz);
                    164:                if(i != fp->sppcsz){
                    165:                        spoff = 0;
                    166:                        return symerrmsg(fp->sppcsz, "sp-pc");
                    167:                }
                    168:                spoffend = spoff+fp->sppcsz;
                    169:        }
                    170:        if (fp->lnpcsz) {                       /* pc-line number table */
                    171:                pcline = (uchar *)malloc(fp->lnpcsz);
                    172:                if(pcline == 0) {
                    173:                        werrstr("can't malloc %d bytes", fp->lnpcsz);
                    174:                        return -1;
                    175:                }
                    176:                Bseek(&b, fp->lnpcoff, 0);
                    177:                i = Bread(&b, pcline, fp->lnpcsz);
                    178:                if(i != fp->lnpcsz){
                    179:                        pcline = 0;
                    180:                        return symerrmsg(fp->lnpcsz, "pc-line");
                    181:                }
                    182:                pclineend = pcline+fp->lnpcsz;
                    183:        }
                    184:        return nsym;
                    185: }
                    186: 
                    187: static int
                    188: symerrmsg(int n, char *table)
                    189: {
                    190:        werrstr("can't read %d bytes of %s table", n, table);
                    191:        return -1;
                    192: }
                    193: 
                    194: static int
                    195: decodename(Biobuf *bp, Sym *p)
                    196: {
                    197:        char *cp;
                    198:        int c1, c2;
                    199:        int n;
                    200: 
                    201:        if((p->type & 0x80) == 0) {             /* old-style, fixed length names */
                    202:                p->name = malloc(NNAME);
                    203:                if(p->name == 0) {
                    204:                        werrstr("can't malloc %d bytes", NNAME);
                    205:                        return -1;
                    206:                }
                    207:                if(Bread(bp, p->name, NNAME) != NNAME)
                    208:                        return symerrmsg(NNAME, "symbol");
                    209:                Bseek(bp, 3, 1);
                    210:                return NNAME+3;
                    211:        }
                    212: 
                    213:        p->type &= ~0x80;
                    214:        if(p->type == 'z' || p->type == 'Z') {
                    215:                n = Bseek(bp, 0, 1);
                    216:                if(Bgetc(bp) < 0) {
                    217:                        werrstr("can't read symbol name");
                    218:                        return -1;
                    219:                }
                    220:                for(;;) {
                    221:                        c1 = Bgetc(bp);
                    222:                        c2 = Bgetc(bp);
                    223:                        if(c1 < 0 || c2 < 0) {
                    224:                                werrstr("can't read symbol name");
                    225:                                return -1;
                    226:                        }
                    227:                        if(c1 == 0 && c2 == 0)
                    228:                                break;
                    229:                }
                    230:                n = Bseek(bp, 0, 1)-n;
                    231:                p->name = malloc(n);
                    232:                if(p->name == 0) {
                    233:                        werrstr("can't malloc %d bytes", n);
                    234:                        return -1;
                    235:                }
                    236:                Bseek(bp, -n, 1);
                    237:                if(Bread(bp, p->name, n) != n) {
                    238:                        werrstr("can't read %d bytes of symbol name", n);
                    239:                        return -1;
                    240:                }
                    241:        } else {
                    242:                cp = Brdline(bp, '\0');
                    243:                if(cp == 0) {
                    244:                        werrstr("can't read symbol name");
                    245:                        return -1;
                    246:                }
                    247:                n = Blinelen(bp);
                    248:                p->name = malloc(n);
                    249:                if(p->name == 0) {
                    250:                        werrstr("can't malloc %d bytes", n);
                    251:                        return -1;
                    252:                }
                    253:                strcpy(p->name, cp);
                    254:        }
                    255:        return n;
                    256: }
                    257: /*
                    258:  *     free any previously loaded symbol tables
                    259:  */
                    260: static void
                    261: cleansyms(void)
                    262: {
                    263:        if(globals)
                    264:                free(globals);
                    265:        globals = 0;
                    266:        nglob = 0;
                    267:        if(txt)
                    268:                free(txt);
                    269:        txt = 0;
                    270:        ntxt = 0;
                    271:        if(fnames)
                    272:                free(fnames);
                    273:        fnames = 0;
                    274:        fmax = 0;
                    275: 
                    276:        if(files)
                    277:                free(files);
                    278:        files = 0;
                    279:        nfiles = 0;
                    280:        if(hist)
                    281:                free(hist);
                    282:        hist = 0;
                    283:        nhist = 0;
                    284:        if(autos)
                    285:                free(autos);
                    286:        autos = 0;
                    287:        nauto = 0;
                    288:        isbuilt = 0;
                    289:        if(symbols)
                    290:                free(symbols);
                    291:        symbols = 0;
                    292:        nsym = 0;
                    293:        if(spoff)
                    294:                free(spoff);
                    295:        spoff = 0;
                    296:        if(pcline)
                    297:                free(pcline);
                    298:        pcline = 0;
                    299: }
                    300: /*
                    301:  *     delimit the text segment
                    302:  */
                    303: void
                    304: textseg(ulong base, Fhdr *fp)
                    305: {
                    306:        txtstart = base;
                    307:        txtend = base+fp->txtsz;
                    308: }
                    309: /*
                    310:  *     symbase: return base and size of raw symbol table
                    311:  *             (special hack for high access rate operations)
                    312:  */
                    313: Sym *
                    314: symbase(long *n)
                    315: {
                    316:        *n = nsym;
                    317:        return symbols;
                    318: }
                    319: /*
                    320:  *     Get the ith symbol table entry
                    321:  */
                    322: Sym *
                    323: getsym(int index)
                    324: {
                    325:        if(index < nsym)
                    326:                return &symbols[index];
                    327:        return 0;
                    328: }
                    329: 
                    330: /*
                    331:  *     initialize internal symbol tables
                    332:  */
                    333: static int
                    334: buildtbls(void)
                    335: {
                    336:        int i, j, nh, ng, nt;
                    337:        File *f;
                    338:        Txtsym *tp;
                    339:        Hist *hp;
                    340:        Sym *p, **ap;
                    341: 
                    342:        if(isbuilt)
                    343:                return 1;
                    344:        isbuilt = 1;
                    345:                        /* allocate the tables */
                    346:        if(nglob) {
                    347:                globals = malloc(nglob*sizeof(*globals));
                    348:                if(!globals) {
                    349:                        werrstr("can't malloc global symbol table");
                    350:                        return 0;
                    351:                }
                    352:        }
                    353:        if(ntxt) {
                    354:                txt = malloc(ntxt*sizeof(*txt));
                    355:                if (!txt) {
                    356:                        werrstr("can't malloc text symbol table");
                    357:                        return 0;
                    358:                }
                    359:        }
                    360:        fmax++;
                    361:        fnames = malloc(fmax*sizeof(*fnames));
                    362:        if (!fnames) {
                    363:                werrstr("can't malloc file name table");
                    364:                return 0;
                    365:        }
                    366:        memset(fnames, 0, fmax*sizeof(*fnames));
                    367:        files = malloc(nfiles*sizeof(*files));
                    368:        if(!files) {
                    369:                werrstr("can't malloc file table");
                    370:                return 0;
                    371:        }
                    372:        hist = malloc(nhist*sizeof(Hist));
                    373:        if(hist == 0) {
                    374:                werrstr("can't malloc history stack");
                    375:                return 0;
                    376:        }
                    377:        autos = malloc(nauto*sizeof(Sym*));
                    378:        if(autos == 0) {
                    379:                werrstr("can't malloc auto symbol table");
                    380:                return 0;
                    381:        }
                    382:                /* load the tables */
                    383:        ng = nt = nh = 0;
                    384:        f = 0;
                    385:        tp = 0;
                    386:        i = nsym;
                    387:        hp = hist;
                    388:        ap = autos;
                    389:        for(p = symbols; i-- > 0; p++) {
                    390:                switch(p->type) {
                    391:                case 'D':
                    392:                case 'd':
                    393:                case 'B':
                    394:                case 'b':
                    395:                        if(debug)
                    396:                                print("Global: %s %lux\n", p->name, p->value);
                    397:                        globals[ng++] = p;
                    398:                        break;
                    399:                case 'z':
                    400:                        if(p->value == 1) {             /* New file */
                    401:                                if(f) {
                    402:                                        f->n = nh;
                    403:                                        f->hist[nh].name = 0;   /* one extra */
                    404:                                        hp += nh+1;
                    405:                                        f++;
                    406:                                }
                    407:                                else f = files;
                    408:                                f->hist = hp;
                    409:                                f->sym = 0;
                    410:                                f->addr = 0;
                    411:                                nh = 0;
                    412:                        }
                    413:                                /* alloc one slot extra as terminator */
                    414:                        f->hist[nh].name = p->name;
                    415:                        f->hist[nh].line = p->value;
                    416:                        f->hist[nh].offset = 0;
                    417:                        if(debug)
                    418:                                printhist("-> ", &f->hist[nh], 1);
                    419:                        nh++;
                    420:                        break;
                    421:                case 'Z':
                    422:                        if(f && nh > 0)
                    423:                                f->hist[nh-1].offset = p->value;
                    424:                        break;
                    425:                case 'T':
                    426:                case 't':       /* Text: terminate history if first in file */
                    427:                case 'L':
                    428:                case 'l':
                    429:                        tp = &txt[nt++];
                    430:                        tp->n = 0;
                    431:                        tp->sym = p;
                    432:                        tp->locals = ap;
                    433:                        if(debug)
                    434:                                print("TEXT: %s at %lux\n", p->name, p->value);
                    435:                        if(f && !f->sym) {                      /* first  */
                    436:                                f->sym = p;
                    437:                                f->addr = p->value;
                    438:                        }
                    439:                        break;
                    440:                case 'a':
                    441:                case 'p':
                    442:                case 'm':               /* Local Vars */
                    443:                        if(!tp)
                    444:                                print("Warning: Free floating local var");
                    445:                        else {
                    446:                                if(debug)
                    447:                                        print("Local: %s %lux\n", p->name, p->value);
                    448:                                tp->locals[tp->n] = p;
                    449:                                tp->n++;
                    450:                                ap++;
                    451:                        }
                    452:                        break;
                    453:                case 'f':               /* File names */
                    454:                        if(debug)
                    455:                                print("Fname: %s\n", p->name);
                    456:                        fnames[p->value] = p;
                    457:                        break;
                    458:                default:
                    459:                        break;
                    460:                }
                    461:        }
                    462:                /* sort global and text tables into ascending address order */
                    463:        qsort(globals, nglob, sizeof(Sym*), symcomp);
                    464:        qsort(txt, ntxt, sizeof(Txtsym), txtcomp);
                    465:        qsort(files, nfiles, sizeof(File), filecomp);
                    466:        tp = txt;
                    467:        for(i = 0, f = files; i < nfiles; i++, f++) {
                    468:                for(j = 0; j < ntxt; j++) {
                    469:                        if(f->sym == tp->sym) {
                    470:                                if(debug) {
                    471:                                        print("LINK: %s to", f->sym->name);
                    472:                                        printhist("... ", f->hist, 1);
                    473:                                }
                    474:                                f->txt = tp++;
                    475:                                break;
                    476:                        }
                    477:                        if(++tp >= txt+ntxt)    /* wrap around */
                    478:                                tp = txt;
                    479:                }
                    480:        }
                    481:        return 1;
                    482: }
                    483: 
                    484: /*
                    485:  * find symbol function.var by name.
                    486:  *     fn != 0 && var != 0     => look for fn in text, var in data
                    487:  *     fn != 0 && var == 0     => look for fn in text
                    488:  *     fn == 0 && var != 0     => look for var first in text then in data space.
                    489:  */
                    490: int
                    491: lookup(char *fn, char *var, Symbol *s)
                    492: {
                    493:        int found;
                    494: 
                    495:        if(buildtbls() == 0)
                    496:                return 0;
                    497:        if(fn) {
                    498:                found = findtext(fn, s);
                    499:                if(var == 0)            /* case 2: fn not in text */
                    500:                        return found;
                    501:                else if(!found)         /* case 1: fn not found */
                    502:                        return 0;
                    503:        } else if(var) {
                    504:                found = findtext(var, s);
                    505:                if(found)
                    506:                        return 1;       /* case 3: var found in text */
                    507:        } else return 0;                /* case 4: fn & var == zero */
                    508: 
                    509:        if(found)
                    510:                return findlocal(s, var, s);    /* case 1: fn found */
                    511:        return findglobal(var, s);              /* case 3: var not found */
                    512: 
                    513: }
                    514: /*
                    515:  * find a function by name
                    516:  */
                    517: static int
                    518: findtext(char *name, Symbol *s)
                    519: {
                    520:        int i;
                    521: 
                    522:        for(i = 0; i < ntxt; i++) {
                    523:                if(strcmp(txt[i].sym->name, name) == 0) {
                    524:                        fillsym(txt[i].sym, s);
                    525:                        s->handle = (void *) &txt[i];
                    526:                        return 1;
                    527:                }
                    528:        }
                    529:        return 0;
                    530: }
                    531: /*
                    532:  * find global variable by name
                    533:  */
                    534: static int
                    535: findglobal(char *name, Symbol *s)
                    536: {
                    537:        int i;
                    538: 
                    539:        for(i = 0; i < nglob; i++) {
                    540:                if(strcmp(globals[i]->name, name) == 0) {
                    541:                        fillsym(globals[i], s);
                    542:                        return 1;
                    543:                }
                    544:        }
                    545:        return 0;
                    546: }
                    547: /*
                    548:  *     find the local variable by name within a given function
                    549:  */
                    550: int
                    551: findlocal(Symbol *s1, char *name, Symbol *s2)
                    552: {
                    553:        if(s1 == 0)
                    554:                return 0;
                    555:        if(buildtbls() == 0)
                    556:                return 0;
                    557:        return findlocvar(s1, name, s2);
                    558: }
                    559: /*
                    560:  *     find the local variable by name within a given function
                    561:  *             (internal function - does no parameter validation)
                    562:  */
                    563: static int
                    564: findlocvar(Symbol *s1, char *name, Symbol *s2)
                    565: {
                    566:        Txtsym *tp;
                    567:        int i;
                    568: 
                    569:        tp = (Txtsym *)s1->handle;
                    570:        if(tp && tp->locals) {
                    571:                for(i = 0; i < tp->n; i++)
                    572:                        if (strcmp(tp->locals[i]->name, name) == 0) {
                    573:                                fillsym(tp->locals[i], s2);
                    574:                                s2->handle = (void *)tp;
                    575:                                return 1;
                    576:                        }
                    577:        }
                    578:        return 0;
                    579: }
                    580: /*
                    581:  *     Get ith text symbol
                    582:  */
                    583: int
                    584: textsym(Symbol *s, int index)
                    585: {
                    586: 
                    587:        if(buildtbls() == 0)
                    588:                return 0;
                    589:        if(index >= ntxt)
                    590:                return 0;
                    591:        fillsym(txt[index].sym, s);
                    592:        s->handle = (void *)&txt[index];
                    593:        return 1;
                    594: }
                    595: /*     
                    596:  *     Get ith file name
                    597:  */
                    598: int
                    599: filesym(int index, char *buf, int n)
                    600: {
                    601:        Hist *hp;
                    602: 
                    603:        if(buildtbls() == 0)
                    604:                return 0;
                    605:        if(index >= nfiles)
                    606:                return 0;
                    607:        hp = files[index].hist;
                    608:        if(!hp || !hp->name)
                    609:                return 0;
                    610:        return fileelem(fnames, (uchar*)hp->name, buf, n);
                    611: }
                    612: /*
                    613:  *     Lookup name of local variable located at an offset into the frame.
                    614:  *     The type selects either a parameter or automatic.
                    615:  */
                    616: int
                    617: getauto(Symbol *s1, int off, int type, Symbol *s2)
                    618: {
                    619:        Txtsym *tp;
                    620:        Sym *p;
                    621:        int i, t;
                    622: 
                    623:        if(s1 == 0)
                    624:                return 0;
                    625:        if(type == CPARAM)
                    626:                t = 'p';
                    627:        else if(type == CAUTO)
                    628:                t = 'a';
                    629:        else
                    630:                return 0;
                    631:        if(buildtbls() == 0)
                    632:                return 0;
                    633:        tp = (Txtsym *)s1->handle;
                    634:        if(tp == 0)
                    635:                return 0;
                    636:        for(i = 0; i < tp->n; i++) {
                    637:                p = tp->locals[i];
                    638:                if(p->type == t && p->value == off) {
                    639:                        fillsym(p, s2);
                    640:                        s2->handle = s1->handle;
                    641:                        return 1;
                    642:                }
                    643:        }
                    644:        return 0;
                    645: }
                    646: 
                    647: /*
                    648:  * Find text symbol containing addr; binary search assumes text array is sorted by addr
                    649:  */
                    650: static int
                    651: srchtext(long addr)
                    652: {
                    653:        ulong val;
                    654:        int top, bot, mid;
                    655:        Sym *sp;
                    656: 
                    657:        val = addr;
                    658:        bot = 0;
                    659:        top = ntxt;
                    660:        for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
                    661:                sp = txt[mid].sym;
                    662:                if(val < (ulong)sp->value)
                    663:                        top = mid;
                    664:                else if(mid != ntxt-1 && val >= (ulong)txt[mid+1].sym->value)
                    665:                        bot = mid;
                    666:                else
                    667:                        return mid;
                    668:        }
                    669:        return -1;
                    670: }
                    671: 
                    672: /*
                    673:  * Find data symbol containing addr; binary search assumes data array is sorted by addr
                    674:  */
                    675: static
                    676: int srchdata(long addr)
                    677: {
                    678:        ulong val;
                    679:        int top, bot, mid;
                    680:        Sym *sp;
                    681: 
                    682:        bot = 0;
                    683:        top = nglob;
                    684:        val = addr;
                    685:        for(mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
                    686:                sp = globals[mid];
                    687:                if(val < (ulong)sp->value)
                    688:                        top = mid;
                    689:                else if(mid < nglob-1 && val >= (ulong)globals[mid+1]->value)
                    690:                        bot = mid;
                    691:                else
                    692:                        return mid;
                    693:        }
                    694:        return -1;
                    695: }
                    696: /*
                    697:  * Find symbol containing val in specified search space
                    698:  * There is a special case when a value falls beyond the end
                    699:  * of the text segment; if the search space is CTEXT, that value
                    700:  * (usually etext) is returned.  If the search space is CANY, symbols in the
                    701:  * data space are searched for a match.
                    702:  */
                    703: int
                    704: findsym(long w, int type, Symbol *s)
                    705: {
                    706:        int i;
                    707: 
                    708:        if(buildtbls() == 0)
                    709:                return 0;
                    710: 
                    711:        if(type == CTEXT || type == CANY) {
                    712:                i = srchtext(w);
                    713:                if(i >= 0) {
                    714:                        if(type == CTEXT || i != ntxt-1) {
                    715:                                fillsym(txt[i].sym, s);
                    716:                                s->handle = (void *) &txt[i];
                    717:                                return 1;
                    718:                        }
                    719:                }
                    720:        }
                    721:        if(type == CDATA || type == CANY) {
                    722:                i = srchdata(w);
                    723:                if(i >= 0) {
                    724:                        fillsym(globals[i], s);
                    725:                        return 1;
                    726:                }
                    727:        }
                    728:        return 0;
                    729: }
                    730: 
                    731: /*
                    732:  *     Find the start and end address of the function containing addr
                    733:  */
                    734: int
                    735: fnbound(long addr, ulong *bounds)
                    736: {
                    737:        int i;
                    738: 
                    739:        if(buildtbls() == 0)
                    740:                return 0;
                    741: 
                    742:        i = srchtext(addr);
                    743:        if(0 <= i && i < ntxt-1) {
                    744:                bounds[0] = txt[i].sym->value;
                    745:                bounds[1] = txt[i+1].sym->value;
                    746:                return 1;
                    747:        }
                    748:        return 0;
                    749: }
                    750: 
                    751: /*
                    752:  * get the ith local symbol for a function
                    753:  * the input symbol table is reverse ordered, so we reverse
                    754:  * accesses here to maintain approx. parameter ordering in a stack trace.
                    755:  */
                    756: int
                    757: localsym(Symbol *s, int index)
                    758: {
                    759:        Txtsym *tp;
                    760: 
                    761:        if(s == 0)
                    762:                return 0;
                    763:        if(buildtbls() == 0)
                    764:                return 0;
                    765: 
                    766:        tp = (Txtsym *)s->handle;
                    767:        if(tp && tp->locals && index < tp->n) {
                    768:                fillsym(tp->locals[tp->n-index-1], s);  /* reverse */
                    769:                s->handle = (void *)tp;
                    770:                return 1;
                    771:        }
                    772:        return 0;
                    773: }
                    774: /*
                    775:  * get the ith global symbol
                    776:  */
                    777: int
                    778: globalsym(Symbol *s, int index)
                    779: {
                    780:        if(s == 0)
                    781:                return 0;
                    782:        if(buildtbls() == 0)
                    783:                return 0;
                    784: 
                    785:        if(index < nglob) {
                    786:                fillsym(globals[index], s);
                    787:                return 1;
                    788:        }
                    789:        return 0;
                    790: }
                    791: /*
                    792:  *     find the pc given a file name and line offset into it.
                    793:  */
                    794: long
                    795: file2pc(char *file, ulong line)
                    796: {
                    797:        File *fp;
                    798:        int i;
                    799:        long pc;
                    800:        ulong start, end;
                    801:        short *name;
                    802: 
                    803:        if(buildtbls() == 0 || files == 0)
                    804:                return -1;
                    805:        name = encfname(file);
                    806:        if(name == 0) {                 /* encode the file name */
                    807:                werrstr("file %s not found", file);
                    808:                return -1;
                    809:        } 
                    810:                /* find this history stack */
                    811:        for(i = 0, fp = files; i < nfiles; i++, fp++)
                    812:                if (hline(fp, name, &line))
                    813:                        break;
                    814:        free(name);
                    815:        if(i >= nfiles) {
                    816:                werrstr("line %d in file %s not found", line, file);
                    817:                return -1;
                    818:        }
                    819:        start = fp->addr;               /* first text addr this file */
                    820:        if(i < nfiles-1)
                    821:                end = (fp+1)->addr;     /* first text addr next file */
                    822:        else
                    823:                end = 0;                /* last file in load module */
                    824:        /*
                    825:         * At this point, line contains the offset into the file.
                    826:         * run the state machine to locate the pc closest to that value.
                    827:         */
                    828:        if(debug)
                    829:                print("find pc for %d - between: %lux and %lux\n", line, start, end);
                    830:        pc = line2addr(line, start, end);
                    831:        if(pc == -1) {
                    832:                werrstr("line %d not in file %s", line, file);
                    833:                return -1;
                    834:        }
                    835:        return pc;
                    836: }
                    837: /*
                    838:  *     search for a path component index
                    839:  */
                    840: static int
                    841: pathcomp(char *s, int n)
                    842: {
                    843:        int i;
                    844: 
                    845:        for(i = 0; i <= fmax; i++)
                    846:                if(fnames[i] && strncmp(s, fnames[i]->name, n) == 0)
                    847:                        return i;
                    848:        return -1;
                    849: }
                    850: /*
                    851:  *     Encode a char file name as a sequence of short indices
                    852:  *     into the file name dictionary.
                    853:  */
                    854: static short*
                    855: encfname(char *file)
                    856: {
                    857:        int i, j;
                    858:        char *cp, *cp2;
                    859:        short *dest;
                    860: 
                    861:        if(*file == '/')        /* always check first '/' */
                    862:                cp2 = file+1;
                    863:        else {
                    864:                cp2 = strchr(file, '/');
                    865:                if(!cp2)
                    866:                        cp2 = strchr(file, 0);
                    867:        }
                    868:        cp = file;
                    869:        dest = 0;
                    870:        for(i = 0; *cp; i++) {
                    871:                j = pathcomp(cp, cp2-cp);
                    872:                if(j < 0)
                    873:                        return 0;       /* not found */
                    874:                dest = realloc(dest, (i+1)*sizeof(short));
                    875:                dest[i] = j;
                    876:                cp = cp2;
                    877:                while(*cp == '/')       /* skip embedded '/'s */
                    878:                        cp++;
                    879:                cp2 = strchr(cp, '/');
                    880:                if(!cp2)
                    881:                        cp2 = strchr(cp, 0);
                    882:        }
                    883:        dest = realloc(dest, (i+1)*sizeof(short));
                    884:        dest[i] = 0;
                    885:        return dest;
                    886: }
                    887: /*
                    888:  *     Search a history stack for a matching file name accumulating
                    889:  *     the size of intervening files in the stack.
                    890:  */
                    891: static int
                    892: hline(File *fp, short *name, ulong *line)
                    893: {
                    894:        Hist *hp;
                    895:        int offset, depth;
                    896:        long ln;
                    897: 
                    898:        for(hp = fp->hist; hp->name; hp++)              /* find name in stack */
                    899:                if(hp->name[1] || hp->name[2]) {
                    900:                        if(hcomp(hp, name))
                    901:                                break;
                    902:                }
                    903:        if(!hp->name)           /* match not found */
                    904:                return 0;
                    905:        if(debug)
                    906:                printhist("hline found ... ", hp, 1);
                    907:        /*
                    908:         * unwind the stack until empty or we hit an entry beyond our line
                    909:         */
                    910:        ln = *line;
                    911:        offset = hp->line-1;
                    912:        depth = 1;
                    913:        for(hp++; depth && hp->name; hp++) {
                    914:                if(debug)
                    915:                        printhist("hline inspect ... ", hp, 1);
                    916:                if(hp->name[1] || hp->name[2]) {
                    917:                        if(hp->offset){                 /* Z record */
                    918:                                offset = 0;
                    919:                                if(hcomp(hp, name)) {
                    920:                                        if(*line <= hp->offset)
                    921:                                                break;
                    922:                                        ln = *line+hp->line-hp->offset;
                    923:                                        depth = 1;      /* implicit pop */
                    924:                                } else
                    925:                                        depth = 2;      /* implicit push */
                    926:                        } else if(depth == 1 && ln < hp->line-offset)
                    927:                                        break;          /* Beyond our line */
                    928:                        else if(depth++ == 1)           /* push */
                    929:                                offset -= hp->line;
                    930:                } else if(--depth == 1)         /* pop */
                    931:                        offset += hp->line;     
                    932:        }
                    933:        *line = ln+offset;
                    934:        return 1;
                    935: }
                    936: /*
                    937:  *     compare two encoded file names
                    938:  */
                    939: static int
                    940: hcomp(Hist *hp, short *sp)
                    941: {
                    942:        uchar *cp;
                    943:        int i, j;
                    944:        short *s;
                    945: 
                    946:        cp = (uchar *)hp->name;
                    947:        s = sp;
                    948:        if (*s == 0)
                    949:                return 0;
                    950:        for (i = 1; j = (cp[i]<<8)|cp[i+1]; i += 2) {
                    951:                if(j == 0)
                    952:                        break;
                    953:                if(*s == j)
                    954:                        s++;
                    955:                else
                    956:                        s = sp;
                    957:        }
                    958:        return *s == 0;
                    959: }
                    960: /*
                    961:  *     Convert a pc to a "file:line {file:line}" string.
                    962:  */
                    963: int
                    964: fileline(char *str, int n, ulong dot)
                    965: {
                    966:        long line;
                    967:        int top, bot, mid;
                    968:        File *f;
                    969: 
                    970:        *str = 0;
                    971:        if(buildtbls() == 0)
                    972:                return 0;
                    973: 
                    974:                /* binary search assumes file list is sorted by addr */
                    975:        bot = 0;
                    976:        top = nfiles;
                    977:        for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
                    978:                f = &files[mid];
                    979:                if(dot < f->addr)
                    980:                        top = mid;
                    981:                else if(mid < nfiles-1 && dot >= (f+1)->addr)
                    982:                        bot = mid;
                    983:                else {
                    984:                        line = pc2line(dot);
                    985:                        if(line > 0 && fline(str, n, line, f->hist))
                    986:                                return 1;
                    987:                        break;
                    988:                }
                    989:        }
                    990:        return 0;
                    991: }
                    992: 
                    993: /*
                    994:  *     Convert a line number within a composite file to relative line
                    995:  *     number in a source file.  A composite file is the source
                    996:  *     file with included files inserted in line.
                    997:  */
                    998: static Hist *
                    999: fline(char *str, int n, long line, Hist *base)
                   1000: {
                   1001:        Hist *start;                    /* start of current level */
                   1002:        Hist *h;                        /* current entry */
                   1003:        int delta;                      /* sum of size of files this level */
                   1004:        int k;
                   1005: 
                   1006:        start = base;
                   1007:        h = base;
                   1008:        delta = h->line;
                   1009:        while(h && h->name && line > h->line) {
                   1010:                if(h->name[1] || h->name[2]) {
                   1011:                        if(h->offset != 0) {    /* #line Directive */
                   1012:                                delta = h->line-h->offset+1;
                   1013:                                start = h;
                   1014:                                base = h++;
                   1015:                        } else {                /* beginning of File */
                   1016:                                if(start == base)
                   1017:                                        start = h++;
                   1018:                                else {
                   1019:                                        h = fline(str, n, line, start);
                   1020:                                        if(!h)
                   1021:                                                break;
                   1022:                                }
                   1023:                        }
                   1024:                } else {
                   1025:                        if(start == base)       /* end of recursion level */
                   1026:                                return h;
                   1027:                        else {                  /* end of included file */
                   1028:                                delta += h->line-start->line;
                   1029:                                h++;
                   1030:                                start = base;
                   1031:                        }
                   1032:                }
                   1033:        }
                   1034:        if(!h)
                   1035:                return 0;
                   1036:        if(start != base)
                   1037:                line = line-start->line+1;
                   1038:        else
                   1039:                line = line-delta+1;
                   1040:        if(!h->name)
                   1041:                strncpy(str, "<eof>", n);
                   1042:        else {
                   1043:                k = fileelem(fnames, (uchar*)start->name, str, n);
                   1044:                if(k+8 < n)
                   1045:                        sprint(str+k, ":%ld", line);
                   1046:        }
                   1047: /**********Remove comments for complete back-trace of include sequence
                   1048:  *     if(start != base) {
                   1049:  *             k = strlen(str);
                   1050:  *             if(k+2 < n) {
                   1051:  *                     str[k++] = ' ';
                   1052:  *                     str[k++] = '{';
                   1053:  *             }
                   1054:  *             k += fileelem(fnames, (uchar*) base->name, str+k, n-k);
                   1055:  *             if(k+10 < n)
                   1056:  *                     sprint(str+k, ":%ld}", start->line-delta);
                   1057:  *     }
                   1058:  ********************/
                   1059:        return h;
                   1060: }
                   1061: /*
                   1062:  *     convert an encoded file name to a string.
                   1063:  */
                   1064: int
                   1065: fileelem(Sym **fp, uchar *cp, char *buf, int n)
                   1066: {
                   1067:        int i, j;
                   1068:        char *c, *bp, *end;
                   1069: 
                   1070:        bp = buf;
                   1071:        end = buf+n-1;
                   1072:        for(i = 1; j = (cp[i]<<8)|cp[i+1]; i+=2){
                   1073:                c = fp[j]->name;
                   1074:                if(bp != buf && bp[-1] != '/' && bp < end)
                   1075:                        *bp++ = '/';
                   1076:                while(bp < end && *c)
                   1077:                        *bp++ = *c++;
                   1078:        }
                   1079:        *bp = 0;
                   1080:        return bp-buf;
                   1081: }
                   1082: /*
                   1083:  *     compare the values of two symbol table entries.
                   1084:  */
                   1085: static int
                   1086: symcomp(void *a, void *b)
                   1087: {
                   1088:        return (*(Sym**)a)->value - (*(Sym**)b)->value;
                   1089: }
                   1090: /*
                   1091:  *     compare the values of the symbols referenced by two text table entries
                   1092:  */
                   1093: static int
                   1094: txtcomp(void *a, void *b)
                   1095: {
                   1096:        return ((Txtsym*)a)->sym->value - ((Txtsym*)b)->sym->value;
                   1097: }
                   1098: /*
                   1099:  *     compare the values of the symbols referenced by two file table entries
                   1100:  */
                   1101: static int
                   1102: filecomp(void *a, void *b)
                   1103: {
                   1104:        return ((File*)a)->addr - ((File*)b)->addr;
                   1105: }
                   1106: /*
                   1107:  *     fill an interface Symbol structure from a symbol table entry
                   1108:  */
                   1109: static void
                   1110: fillsym(Sym *sp, Symbol *s)
                   1111: {
                   1112:        s->type = sp->type;
                   1113:        s->value = sp->value;
                   1114:        s->name = sp->name;
                   1115:        switch(sp->type) {
                   1116:        case 'b':
                   1117:        case 'B':
                   1118:        case 'D':
                   1119:        case 'd':
                   1120:                s->class = CDATA;
                   1121:                break;
                   1122:        case 't':
                   1123:        case 'T':
                   1124:        case 'l':
                   1125:        case 'L':
                   1126:                s->class = CTEXT;
                   1127:                break;
                   1128:        case 'a':
                   1129:                s->class = CAUTO;
                   1130:                break;
                   1131:        case 'p':
                   1132:                s->class = CPARAM;
                   1133:                break;
                   1134:        case 'm':
                   1135:                s->class = CSTAB;
                   1136:                break;
                   1137:        default:
                   1138:                s->class = CNONE;
                   1139:                break;
                   1140:        }
                   1141:        s->handle = 0;
                   1142: }
                   1143: /*
                   1144:  *     find the stack frame, given the pc
                   1145:  */
                   1146: long
                   1147: pc2sp(ulong pc)
                   1148: {
                   1149:        uchar *c;
                   1150:        uchar u;
                   1151:        ulong currpc;
                   1152:        long currsp;
                   1153: 
                   1154:        if(spoff == 0)
                   1155:                return -1;
                   1156:        currsp = 0;
                   1157:        currpc = txtstart - mach->pcquant;
                   1158: 
                   1159:        if(pc<currpc || pc>txtend)
                   1160:                return -1;
                   1161:        for(c = spoff; c < spoffend; c++) {
                   1162:                if (currpc >= pc)
                   1163:                        return currsp;
                   1164:                u = *c;
                   1165:                if (u == 0) {
                   1166:                        currsp += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
                   1167:                        c += 4;
                   1168:                }
                   1169:                else if (u < 65)
                   1170:                        currsp += 4*u;
                   1171:                else if (u < 129)
                   1172:                        currsp -= 4*(u-64);
                   1173:                else 
                   1174:                        currpc += mach->pcquant*(u-129);
                   1175:                currpc += mach->pcquant;
                   1176:        }
                   1177:        return -1;
                   1178: }
                   1179: /*
                   1180:  *     find the source file line number for a given value of the pc
                   1181:  */
                   1182: long
                   1183: pc2line(ulong pc)
                   1184: {
                   1185:        uchar *c;
                   1186:        uchar u;
                   1187:        ulong currpc;
                   1188:        long currline;
                   1189: 
                   1190:        if(pcline == 0)
                   1191:                return -1;
                   1192:        currline = 0;
                   1193:        currpc = txtstart-mach->pcquant;
                   1194:        if(pc<currpc || pc>txtend)
                   1195:                return -1;
                   1196: 
                   1197:        for(c = pcline; c < pclineend; c++) {
                   1198:                if(currpc >= pc)
                   1199:                        return currline;
                   1200:                u = *c;
                   1201:                if(u == 0) {
                   1202:                        currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
                   1203:                        c += 4;
                   1204:                }
                   1205:                else if(u < 65)
                   1206:                        currline += u;
                   1207:                else if(u < 129)
                   1208:                        currline -= (u-64);
                   1209:                else 
                   1210:                        currpc += mach->pcquant*(u-129);
                   1211:                currpc += mach->pcquant;
                   1212:        }
                   1213:        return -1;
                   1214: }
                   1215: /*
                   1216:  *     find the pc associated with a line number
                   1217:  *     basepc and endpc are text addresses bounding the search.
                   1218:  *     if endpc == 0, the end of the table is used (i.e., no upper bound).
                   1219:  *     usually, basepc and endpc contain the first text address in
                   1220:  *     a file and the first text address in the following file, respectively.
                   1221:  */
                   1222: long
                   1223: line2addr(ulong line, ulong basepc, ulong endpc)
                   1224: {
                   1225:        uchar *c;
                   1226:        uchar u;
                   1227:        ulong currpc;
                   1228:        long currline;
                   1229:        long delta, d;
                   1230:        long pc, found;
                   1231: 
                   1232:        if(pcline == 0 || line == 0)
                   1233:                return -1;
                   1234: 
                   1235:        currline = 0;
                   1236:        currpc = txtstart-mach->pcquant;
                   1237:        pc = -1;
                   1238:        found = 0;
                   1239:        delta = HUGEINT;
                   1240: 
                   1241:        for(c = pcline; c < pclineend; c++) {
                   1242:                if(endpc && currpc >= endpc)    /* end of file of interest */
                   1243:                        break;
                   1244:                if(currpc >= basepc) {          /* proper file */
                   1245:                        if(currline >= line) {
                   1246:                                d = currline-line;
                   1247:                                found = 1;
                   1248:                        } else
                   1249:                                d = line-currline;
                   1250:                        if(d < delta) {
                   1251:                                delta = d;
                   1252:                                pc = currpc;
                   1253:                        }
                   1254:                }
                   1255:                u = *c;
                   1256:                if(u == 0) {
                   1257:                        currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
                   1258:                        c += 4;
                   1259:                }
                   1260:                else if(u < 65)
                   1261:                        currline += u;
                   1262:                else if(u < 129)
                   1263:                        currline -= (u-64);
                   1264:                else 
                   1265:                        currpc += mach->pcquant*(u-129);
                   1266:                currpc += mach->pcquant;
                   1267:        }
                   1268:        if(found)
                   1269:                return pc;
                   1270:        return -1;
                   1271: }
                   1272: /*
                   1273:  *     Print a history stack (debug). if count is 0, prints the whole stack
                   1274:  */
                   1275: void
                   1276: printhist(char *msg, Hist *hp, int count)
                   1277: {
                   1278:        int i;
                   1279:        uchar *cp;
                   1280:        char buf[128];
                   1281: 
                   1282:        i = 0;
                   1283:        while(hp->name) {
                   1284:                if(count && ++i > count)
                   1285:                        break;
                   1286:                print("%s Line: %x (%d)  Offset: %x (%d)  Name: ", msg,
                   1287:                        hp->line, hp->line, hp->offset, hp->offset);
                   1288:                for(cp = (uchar *)hp->name+1; (*cp<<8)|cp[1]; cp += 2) {
                   1289:                        if (cp != (uchar *)hp->name+1)
                   1290:                                print("/");
                   1291:                        print("%x", (*cp<<8)|cp[1]);
                   1292:                }
                   1293:                fileelem(fnames, (uchar *) hp->name, buf, sizeof(buf));
                   1294:                print(" (%s)\n", buf);
                   1295:                hp++;
                   1296:        }
                   1297: }
                   1298: 
                   1299: #ifdef DEBUG
                   1300: /*
                   1301:  *     print the history stack for a file. (debug only)
                   1302:  *     if (name == 0) => print all history stacks.
                   1303:  */
                   1304: void
                   1305: dumphist(char *name)
                   1306: {
                   1307:        int i;
                   1308:        File *f;
                   1309:        short *fname;
                   1310: 
                   1311:        if(buildtbls() == 0)
                   1312:                return;
                   1313:        if(name)
                   1314:                fname = encfname(name);
                   1315:        for(i = 0, f = files; i < nfiles; i++, f++)
                   1316:                if(fname == 0 || hcomp(f->hist, fname))
                   1317:                        printhist("> ", f->hist, f->n);
                   1318: 
                   1319:        if(fname)
                   1320:                free(fname);
                   1321: }
                   1322: #endif

unix.superglobalmegacorp.com

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