[BACK]Return to db_aout.c CVS log [TXT][DIR] Up to [local] / sys / ddb

Annotation of sys/ddb/db_aout.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: db_aout.c,v 1.30 2006/07/06 18:12:50 miod Exp $       */
        !             2: /*     $NetBSD: db_aout.c,v 1.29 2000/07/07 21:55:18 jhawk Exp $       */
        !             3:
        !             4: /*
        !             5:  * Mach Operating System
        !             6:  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
        !             7:  * All Rights Reserved.
        !             8:  *
        !             9:  * Permission to use, copy, modify and distribute this software and its
        !            10:  * documentation is hereby granted, provided that both the copyright
        !            11:  * notice and this permission notice appear in all copies of the
        !            12:  * software, derivative works or modified versions, and any portions
        !            13:  * thereof, and that both notices appear in supporting documentation.
        !            14:  *
        !            15:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            16:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            17:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            18:  *
        !            19:  * Carnegie Mellon requests users of this software to return to
        !            20:  *
        !            21:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            22:  *  School of Computer Science
        !            23:  *  Carnegie Mellon University
        !            24:  *  Pittsburgh PA 15213-3890
        !            25:  *
        !            26:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            27:  * the rights to redistribute these changes.
        !            28:  */
        !            29:
        !            30: #include <sys/types.h>
        !            31: #include <sys/param.h>
        !            32: #include <sys/systm.h>
        !            33: #include <sys/proc.h>
        !            34:
        !            35: #include <machine/db_machdep.h>                /* data types */
        !            36:
        !            37: #include <ddb/db_sym.h>
        !            38: #include <ddb/db_output.h>
        !            39: #include <ddb/db_extern.h>
        !            40:
        !            41: #ifdef DB_AOUT_SYMBOLS
        !            42:
        !            43: #include <ddb/db_aout.h>
        !            44:
        !            45: boolean_t      db_aout_sym_init(int, void *, void *, const char *);
        !            46: db_sym_t       db_aout_lookup(db_symtab_t *, char *);
        !            47: db_sym_t       db_aout_search_symbol(db_symtab_t *, db_addr_t,
        !            48:                    db_strategy_t, db_expr_t *);
        !            49: void           db_aout_symbol_values(db_symtab_t *, db_sym_t,
        !            50:                    char **, db_expr_t *);
        !            51: boolean_t      db_aout_line_at_pc(db_symtab_t *, db_sym_t,
        !            52:                    char **, int *, db_expr_t);
        !            53: boolean_t      db_aout_sym_numargs(db_symtab_t *, db_sym_t, int *,
        !            54:                    char **);
        !            55: void           db_aout_forall(db_symtab_t *,
        !            56:                    db_forall_func_t db_forall_func, void *);
        !            57:
        !            58: db_symformat_t db_symformat_aout = {
        !            59:        "a.out",
        !            60:        db_aout_sym_init,
        !            61:        db_aout_lookup,
        !            62:        db_aout_search_symbol,
        !            63:        db_aout_symbol_values,
        !            64:        db_aout_line_at_pc,
        !            65:        db_aout_sym_numargs,
        !            66:        db_aout_forall
        !            67: };
        !            68:
        !            69: /*
        !            70:  * An a.out symbol table as loaded into the kernel debugger:
        !            71:  *
        !            72:  * symtab      -> size of symbol entries, in bytes
        !            73:  * sp          -> first symbol entry
        !            74:  *                ...
        !            75:  * ep          -> last symbol entry + 1
        !            76:  * strtab      == start of string table
        !            77:  *                size of string table in bytes,
        !            78:  *                including this word
        !            79:  *             -> strings
        !            80:  */
        !            81: static char *strtab;
        !            82: static int slen;
        !            83:
        !            84: #define X_db_getname(t, s)     (s->n_un.n_strx ? t->end + s->n_un.n_strx : NULL)
        !            85:
        !            86: /*
        !            87:  * Find the symbol table and strings; tell ddb about them.
        !            88:  *
        !            89:  * symsize:    size of symbol table
        !            90:  * vsymtab:    pointer to end of string table
        !            91:  * vesymtab:   pointer to end of string table, for checking - rounded up to
        !            92:  *                 integer boundry
        !            93:  */
        !            94: boolean_t
        !            95: db_aout_sym_init(int symsize, void *vsymtab, void *vesymtab, const char *name)
        !            96: {
        !            97:        struct nlist    *sym_start, *sym_end;
        !            98:        struct nlist    *sp;
        !            99:        int bad = 0;
        !           100:        char *estrtab;
        !           101:
        !           102:        /*
        !           103:         * XXX - ddb_init should take arguments.
        !           104:         *       Fixup the arguments.
        !           105:         */
        !           106:        symsize = *(long *)vsymtab;
        !           107:        vsymtab = (void *)((long *)vsymtab + 1);
        !           108:
        !           109:
        !           110:        if (ALIGNED_POINTER(vsymtab, long) == 0) {
        !           111:                printf("[ %s symbol table has bad start address %p ]\n",
        !           112:                    name, vsymtab);
        !           113:                return (FALSE);
        !           114:        }
        !           115:
        !           116:        /*
        !           117:         * Find pointers to the start and end of the symbol entries,
        !           118:         * given a pointer to the start of the symbol table.
        !           119:         */
        !           120:        sym_start = (struct nlist *)vsymtab;
        !           121:        sym_end   = (struct nlist *)((char *)sym_start + symsize);
        !           122:
        !           123:        strtab = (char *)sym_end;
        !           124:        if (ALIGNED_POINTER(strtab, int) == 0) {
        !           125:                printf("[ %s symbol table has bad string table address %p ]\n",
        !           126:                    name, strtab);
        !           127:                return (FALSE);
        !           128:        }
        !           129:        slen = *(int *)strtab;
        !           130:
        !           131:        estrtab = strtab + slen;
        !           132:
        !           133: #define        round_to_size(x) \
        !           134:     (((vaddr_t)(x) + sizeof(vsize_t) - 1) & ~(sizeof(vsize_t) - 1))
        !           135:
        !           136:        if (round_to_size(estrtab) != round_to_size(vesymtab)) {
        !           137:                printf("[ %s a.out symbol table not valid ]\n", name);
        !           138:                return (FALSE);
        !           139:         }
        !           140: #undef round_to_size
        !           141:
        !           142:        for (sp = sym_start; sp < sym_end; sp++) {
        !           143:                int strx;
        !           144:                strx = sp->n_un.n_strx;
        !           145:                if (strx != 0) {
        !           146:                        if (strx > slen) {
        !           147:                                printf("[ %s has bad a.out string table index "
        !           148:                                    "(0x%x) ]\n",
        !           149:                                    name, strx);
        !           150:                                bad = 1;
        !           151:                                continue;
        !           152:                        }
        !           153:                }
        !           154:        }
        !           155:
        !           156:        if (bad)
        !           157:                return (FALSE);
        !           158:
        !           159:        if (db_add_symbol_table((char *)sym_start, (char *)sym_end, name,
        !           160:            NULL) !=  -1) {
        !           161:                 printf("[ using %ld bytes of %s a.out symbol table ]\n",
        !           162:                     (long)vesymtab - (long)vsymtab, name);
        !           163:                return (TRUE);
        !           164:         }
        !           165:
        !           166:        return (FALSE);
        !           167: }
        !           168:
        !           169: db_sym_t
        !           170: db_aout_lookup(db_symtab_t *stab, char *symstr)
        !           171: {
        !           172:        struct nlist *sp, *ep;
        !           173:        char *n_name;
        !           174:
        !           175:        sp = (struct nlist *)stab->start;
        !           176:        ep = (struct nlist *)stab->end;
        !           177:
        !           178:        for (; sp < ep; sp++) {
        !           179:                if ((n_name = X_db_getname(stab, sp)) == 0)
        !           180:                        continue;
        !           181:                if ((sp->n_type & N_STAB) == 0 &&
        !           182:                    db_eqname(n_name, symstr, '_'))
        !           183:                        return ((db_sym_t)sp);
        !           184:        }
        !           185:        return ((db_sym_t)0);
        !           186: }
        !           187:
        !           188: db_sym_t
        !           189: db_aout_search_symbol(db_symtab_t *symtab, db_addr_t off,
        !           190:     db_strategy_t strategy, db_expr_t *diffp)
        !           191: {
        !           192:        unsigned int    diff = *diffp;
        !           193:        struct nlist    *symp = 0;
        !           194:        struct nlist    *sp, *ep;
        !           195:
        !           196:        sp = (struct nlist *)symtab->start;
        !           197:        ep = (struct nlist *)symtab->end;
        !           198:
        !           199:        for (; sp < ep; sp++) {
        !           200:                if ((sp->n_type & N_STAB) != 0 ||
        !           201:                    (sp->n_type & N_TYPE) == N_FN)
        !           202:                        continue;
        !           203:                if (X_db_getname(symtab, sp) == 0)
        !           204:                        continue;
        !           205:                if (off >= sp->n_value) {
        !           206:                        if (off - sp->n_value < diff) {
        !           207:                                diff = off - sp->n_value;
        !           208:                                symp = sp;
        !           209:                                if (diff == 0 && ((strategy == DB_STGY_PROC &&
        !           210:                                    sp->n_type == (N_TEXT|N_EXT)) ||
        !           211:                                    (strategy == DB_STGY_ANY &&
        !           212:                                    (sp->n_type & N_EXT))))
        !           213:                                        break;
        !           214:                        } else if (off - sp->n_value == diff) {
        !           215:                                if (symp == 0)
        !           216:                                        symp = sp;
        !           217:                                else if ((symp->n_type & N_EXT) == 0 &&
        !           218:                                    (sp->n_type & N_EXT) != 0)
        !           219:                                        symp = sp;      /* pick the ext. sym */
        !           220:                        }
        !           221:                }
        !           222:        }
        !           223:        if (symp == 0) {
        !           224:                *diffp = off;
        !           225:        } else {
        !           226:                *diffp = diff;
        !           227:        }
        !           228:        return ((db_sym_t)symp);
        !           229: }
        !           230:
        !           231: /*
        !           232:  * Return the name and value for a symbol.
        !           233:  */
        !           234: void
        !           235: db_aout_symbol_values(db_symtab_t *symtab, db_sym_t sym, char **namep,
        !           236:     db_expr_t *valuep)
        !           237: {
        !           238:        struct nlist *sp;
        !           239:
        !           240:        sp = (struct nlist *)sym;
        !           241:        if (namep)
        !           242:                *namep = X_db_getname(symtab, sp);
        !           243:        if (valuep)
        !           244:                *valuep = sp->n_value;
        !           245: }
        !           246:
        !           247:
        !           248: boolean_t
        !           249: db_aout_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename,
        !           250:     int *linenum, db_expr_t off)
        !           251: {
        !           252:        struct nlist    *sp, *ep;
        !           253:        unsigned long   sodiff = -1UL, lndiff = -1UL, ln = 0;
        !           254:        char            *fname = NULL;
        !           255:
        !           256:        sp = (struct nlist *)symtab->start;
        !           257:        ep = (struct nlist *)symtab->end;
        !           258:
        !           259: /* XXX - gcc specific */
        !           260: #define NEWSRC(str)    ((str) != NULL && \
        !           261:     (str)[0] == 'g' && strcmp((str), "gcc_compiled.") == 0)
        !           262:
        !           263:        for (; sp < ep; sp++) {
        !           264:
        !           265:                /*
        !           266:                 * Prevent bogus linenumbers in case module not compiled
        !           267:                 * with debugging options
        !           268:                 */
        !           269: #if 0
        !           270:                if (sp->n_value <= off && (off - sp->n_value) <= sodiff &&
        !           271:                    NEWSRC(X_db_getname(symtab, sp))) {
        !           272: #endif
        !           273:                if ((sp->n_type & N_TYPE) == N_FN ||
        !           274:                    NEWSRC(X_db_getname(symtab, sp))) {
        !           275:                        sodiff = lndiff = -1UL;
        !           276:                        ln = 0;
        !           277:                        fname = NULL;
        !           278:                }
        !           279:
        !           280:                if (sp->n_type == N_SO) {
        !           281:                        if (sp->n_value <= off &&
        !           282:                            (off - sp->n_value) < sodiff) {
        !           283:                                sodiff = off - sp->n_value;
        !           284:                                fname = X_db_getname(symtab, sp);
        !           285:                        }
        !           286:                        continue;
        !           287:                }
        !           288:
        !           289:                if (sp->n_type != N_SLINE)
        !           290:                        continue;
        !           291:
        !           292:                if (sp->n_value > off)
        !           293:                        break;
        !           294:
        !           295:                if (off - sp->n_value < lndiff) {
        !           296:                        lndiff = off - sp->n_value;
        !           297:                        ln = sp->n_desc;
        !           298:                }
        !           299:        }
        !           300:
        !           301:        if (fname != NULL && ln != 0) {
        !           302:                *filename = fname;
        !           303:                *linenum = ln;
        !           304:                return (TRUE);
        !           305:        }
        !           306:
        !           307:        return (FALSE);
        !           308: }
        !           309:
        !           310: boolean_t
        !           311: db_aout_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
        !           312:     char **argnamep)
        !           313: {
        !           314:        struct nlist    *sp, *ep;
        !           315:        u_long          addr;
        !           316:        int             maxnarg = *nargp, nargs = 0;
        !           317:        char            *n_name;
        !           318:
        !           319:        if (cursym == NULL)
        !           320:                return (FALSE);
        !           321:
        !           322:        addr = ((struct nlist *)cursym)->n_value;
        !           323:        sp = (struct nlist *)symtab->start;
        !           324:        ep = (struct nlist *)symtab->end;
        !           325:
        !           326:        for (; sp < ep; sp++) {
        !           327:                if (sp->n_type == N_FUN && sp->n_value == addr) {
        !           328:                        while (++sp < ep && sp->n_type == N_PSYM) {
        !           329:                                if (nargs >= maxnarg)
        !           330:                                        break;
        !           331:                                nargs++;
        !           332:                                n_name = X_db_getname(symtab, sp);
        !           333:                                *argnamep++ = n_name ? n_name : "???";
        !           334:                                {
        !           335:                                        /* XXX - remove trailers */
        !           336:                                        char *cp = *(argnamep - 1);
        !           337:
        !           338:                                        while (*cp != '\0' && *cp != ':')
        !           339:                                                cp++;
        !           340:                                        if (*cp == ':') *cp = '\0';
        !           341:                                }
        !           342:                        }
        !           343:                        *nargp = nargs;
        !           344:                        return (TRUE);
        !           345:                }
        !           346:        }
        !           347:        return (FALSE);
        !           348: }
        !           349:
        !           350: void
        !           351: db_aout_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
        !           352: {
        !           353:        static char suffix[2];
        !           354:        struct nlist *sp, *ep;
        !           355:
        !           356:        sp = (struct nlist *)stab->start;
        !           357:        ep = (struct nlist *)stab->end;
        !           358:
        !           359:        for (; sp < ep; sp++) {
        !           360:                if (X_db_getname(stab, sp) == 0)
        !           361:                        continue;
        !           362:                if ((sp->n_type & N_STAB) == 0) {
        !           363:                        suffix[1] = '\0';
        !           364:                        switch(sp->n_type & N_TYPE) {
        !           365:                        case N_ABS:
        !           366:                                suffix[0] = '@';
        !           367:                                break;
        !           368:                        case N_TEXT:
        !           369:                                suffix[0] = '*';
        !           370:                                break;
        !           371:                        case N_DATA:
        !           372:                                suffix[0] = '+';
        !           373:                                break;
        !           374:                        case N_BSS:
        !           375:                                suffix[0] = '-';
        !           376:                                break;
        !           377:                        case N_FN:
        !           378:                                suffix[0] = '/';
        !           379:                                break;
        !           380:                        default:
        !           381:                                suffix[0] = '\0';
        !           382:                        }
        !           383:                        (*db_forall_func)(stab, (db_sym_t)sp,
        !           384:                            X_db_getname(stab, sp), suffix, '_', arg);
        !           385:                }
        !           386:        }
        !           387:        return;
        !           388: }
        !           389:
        !           390:
        !           391: #endif /* DB_AOUT_SYMBOLS */

CVSweb