Annotation of Gnu-Mach/ddb/db_aout.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /*
        !            27:  *     Author: David B. Golub, Carnegie Mellon University
        !            28:  *     Date:   7/90
        !            29:  */
        !            30: #include "mach_kdb.h"
        !            31: #if MACH_KDB
        !            32: 
        !            33: /*
        !            34:  * Symbol table routines for a.out format files.
        !            35:  */
        !            36: 
        !            37: #include <mach/std_types.h>
        !            38: #include <machine/db_machdep.h>                /* data types */
        !            39: #include <ddb/db_sym.h>
        !            40: 
        !            41: #ifndef        DB_NO_AOUT
        !            42: 
        !            43: #include <ddb/nlist.h>                 /* a.out symbol table */
        !            44: #include <ddb/stab.h>
        !            45: 
        !            46: #define private static
        !            47: 
        !            48: /*
        !            49:  * An a.out symbol table as loaded into the kernel debugger:
        !            50:  *
        !            51:  * symtab      -> size of symbol entries, in bytes
        !            52:  * sp          -> first symbol entry
        !            53:  *                ...
        !            54:  * ep          -> last symbol entry + 1
        !            55:  * strtab      == start of string table
        !            56:  *                size of string table in bytes,
        !            57:  *                including this word
        !            58:  *             -> strings
        !            59:  */
        !            60: 
        !            61: /*
        !            62:  * Find pointers to the start and end of the symbol entries,
        !            63:  * given a pointer to the start of the symbol table.
        !            64:  */
        !            65: #define        db_get_aout_symtab(symtab, sp, ep) \
        !            66:        (sp = (struct nlist *)((vm_offset_t *)(symtab) + 1), \
        !            67:         ep = (struct nlist *)((char *)sp + *((int*)symtab)))
        !            68: 
        !            69: boolean_t
        !            70: aout_db_sym_init(symtab, esymtab, name, task_addr)
        !            71:        char *  symtab;         /* pointer to start of symbol table */
        !            72:        char *  esymtab;        /* pointer to end of string table,
        !            73:                                   for checking - may be rounded up to
        !            74:                                   integer boundary */
        !            75:        char *  name;
        !            76:        char *  task_addr;      /* use for this task only */
        !            77: {
        !            78:        register struct nlist   *sym_start, *sym_end;
        !            79:        register struct nlist   *sp;
        !            80:        register char * strtab;
        !            81:        register int    strlen;
        !            82:        char *          estrtab;
        !            83: 
        !            84:        db_get_aout_symtab(symtab, sym_start, sym_end);
        !            85: 
        !            86:        strtab = (char *)sym_end;
        !            87:        strlen = *(int *)strtab;
        !            88:        estrtab = strtab + strlen;
        !            89: 
        !            90: #define        round_to_size(x) \
        !            91:        (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1))
        !            92: 
        !            93:        if (round_to_size(estrtab) != round_to_size(esymtab)) {
        !            94:            db_printf("[ %s symbol table not valid ]\n", name);
        !            95:            return (FALSE);
        !            96:        }
        !            97: 
        !            98: #undef round_to_size
        !            99: 
        !           100:        for (sp = sym_start; sp < sym_end; sp++) {
        !           101:            register long strx;
        !           102:            strx = sp->n_un.n_strx;
        !           103:            if (strx != 0) {
        !           104:                if (strx > strlen) {
        !           105:                    db_printf("Bad string table index (%#x)\n", strx);
        !           106:                    sp->n_un.n_name = 0;
        !           107:                    continue;
        !           108:                }
        !           109:                sp->n_un.n_name = strtab + strx;
        !           110:            }
        !           111:        }
        !           112: 
        !           113:        if (db_add_symbol_table(SYMTAB_AOUT,
        !           114:                                (char *)sym_start,
        !           115:                                (char *)sym_end,
        !           116:                                name,
        !           117:                                symtab,
        !           118:                                task_addr))
        !           119:        {
        !           120:            /* Successfully added symbol table */
        !           121:            db_printf("[ preserving %d bytes of %s symbol table ]\n",
        !           122:                esymtab - (char *)symtab, name);
        !           123:            return TRUE;
        !           124:        }
        !           125:        else
        !           126:            return FALSE;
        !           127: }
        !           128: 
        !           129: /*
        !           130:  * check file name or not (check xxxx.x pattern)
        !           131:  */
        !           132: private boolean_t
        !           133: aout_db_is_filename(name)
        !           134:        register char *name;
        !           135: {
        !           136:        while (*name) {
        !           137:            if (*name == '.') {
        !           138:                if (name[1])
        !           139:                    return(TRUE);
        !           140:            }
        !           141:            name++;
        !           142:        }
        !           143:        return(FALSE);
        !           144: }
        !           145: 
        !           146: /*
        !           147:  * special name comparison routine with a name in the symbol table entry
        !           148:  */
        !           149: private boolean_t
        !           150: aout_db_eq_name(sp, name)
        !           151:        struct nlist *sp;
        !           152:        char *name;
        !           153: {
        !           154:        register char *s1, *s2;
        !           155: 
        !           156:        s1 = sp->n_un.n_name;
        !           157:        s2 = name;
        !           158:        if (*s1 == '_' && *s2 && *s2 != '_')
        !           159:            s1++;
        !           160:        while (*s2) {
        !           161:            if (*s1++ != *s2++) {
        !           162:                /*
        !           163:                 * check .c .o file name comparison case
        !           164:                 */
        !           165:                if (*s2 == 0 && sp->n_un.n_name <= s1 - 2 
        !           166:                        && s1[-2] == '.' && s1[-1] == 'o')
        !           167:                    return(TRUE);
        !           168:                return(FALSE);
        !           169:            }
        !           170:        }
        !           171:        /*
        !           172:         * do special check for
        !           173:         *     xxx:yyy for N_FUN
        !           174:         *     xxx.ttt for N_DATA and N_BSS
        !           175:         */
        !           176:        return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) || 
        !           177:                (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
        !           178: }
        !           179: 
        !           180: /*
        !           181:  * search a symbol table with name and type
        !           182:  *     fp(in,out): last found text file name symbol entry
        !           183:  */
        !           184: private struct nlist *
        !           185: aout_db_search_name(sp, ep, name, type, fp)
        !           186:        register struct nlist *sp;
        !           187:        struct nlist    *ep;
        !           188:        char            *name;
        !           189:        int             type;
        !           190:        struct nlist    **fp;
        !           191: {
        !           192:        struct nlist    *file_sp = *fp;
        !           193:        struct nlist    *found_sp = 0;
        !           194: 
        !           195:        for ( ; sp < ep; sp++) {
        !           196:            if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name))
        !           197:                *fp = sp;
        !           198:            if (type) {
        !           199:                if (sp->n_type == type) {
        !           200:                    if (aout_db_eq_name(sp, name))
        !           201:                        return(sp);
        !           202:                }
        !           203:                if (sp->n_type == N_SO)
        !           204:                    *fp = sp;
        !           205:                continue;
        !           206:            }
        !           207:            if (sp->n_type & N_STAB)
        !           208:                continue;
        !           209:            if (sp->n_un.n_name && aout_db_eq_name(sp, name)) {
        !           210:                /*
        !           211:                 * In case of qaulified search by a file,
        !           212:                 * return it immediately with some check.
        !           213:                 * Otherwise, search external one
        !           214:                 */
        !           215:                if (file_sp) {
        !           216:                    if ((file_sp == *fp) || (sp->n_type & N_EXT))
        !           217:                        return(sp);
        !           218:                } else if (sp->n_type & N_EXT)
        !           219:                    return(sp);
        !           220:                else
        !           221:                    found_sp = sp;
        !           222:            }
        !           223:        }
        !           224:        return(found_sp);
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * search a symbol with file, func and line qualification
        !           229:  */
        !           230: private db_sym_t
        !           231: aout_db_qualified_search(stab, file, sym, line)
        !           232:        db_symtab_t     *stab;
        !           233:        char            *file;
        !           234:        char            *sym;
        !           235:        int             line;
        !           236: {
        !           237:        register struct nlist *sp = (struct nlist *)stab->start;
        !           238:        struct nlist    *ep = (struct nlist *)stab->end;
        !           239:        struct nlist    *fp = 0;
        !           240:        struct nlist    *found_sp;
        !           241:        unsigned long   func_top;
        !           242:        boolean_t       in_file;
        !           243: 
        !           244:        if (file == 0 && sym == 0)
        !           245:            return(0);
        !           246:        if (file) {
        !           247:            if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp)) == 0)
        !           248:                return(0);
        !           249:        }
        !           250:        if (sym) {
        !           251:            sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp);
        !           252:            if (sp == 0)
        !           253:                return(0);
        !           254:        }
        !           255:        if (line > 0) {
        !           256:            if (file && !aout_db_eq_name(fp, file))
        !           257:                return(0);
        !           258:            found_sp = 0;
        !           259:            if (sp->n_type == N_FUN) {
        !           260:                /*
        !           261:                 * qualified by function name
        !           262:                 *     search backward because line number entries
        !           263:                 *     for the function are above it in this case.
        !           264:                 */
        !           265:                func_top = sp->n_value;
        !           266:                for (sp--; sp >= (struct nlist *)stab->start; sp--) {
        !           267:                    if (sp->n_type != N_SLINE)
        !           268:                        continue;
        !           269:                    if (sp->n_value < func_top)
        !           270:                        break;
        !           271:                    if (sp->n_desc <= line) {
        !           272:                        if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
        !           273:                            found_sp = sp;
        !           274:                        if (sp->n_desc == line)
        !           275:                            break;
        !           276:                    }
        !           277:                }
        !           278:                if (sp->n_type != N_SLINE || sp->n_value < func_top)
        !           279:                    return(0);
        !           280:            } else {
        !           281:                /*
        !           282:                 * qualified by only file name
        !           283:                 *    search forward in this case
        !           284:                 */
        !           285:                in_file = TRUE;
        !           286:                for (sp++; sp < ep; sp++) {
        !           287:                    if (sp->n_type == N_TEXT 
        !           288:                        && aout_db_is_filename(sp->n_un.n_name))
        !           289:                        break;          /* enter into another file */
        !           290:                    if (sp->n_type == N_SOL) {
        !           291:                        in_file = aout_db_eq_name(sp, file);
        !           292:                        continue;
        !           293:                    }
        !           294:                    if (!in_file || sp->n_type != N_SLINE)
        !           295:                        continue;
        !           296:                    if (sp->n_desc <= line) {
        !           297:                        if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
        !           298:                            found_sp = sp;
        !           299:                        if (sp->n_desc == line)
        !           300:                            break;
        !           301:                    }
        !           302:                }
        !           303:            }
        !           304:            sp = found_sp;
        !           305:        }
        !           306:        return((db_sym_t) sp);
        !           307: }
        !           308: 
        !           309: /*
        !           310:  * lookup symbol by name
        !           311:  */
        !           312: db_sym_t
        !           313: aout_db_lookup(stab, symstr)
        !           314:        db_symtab_t     *stab;
        !           315:        char *          symstr;
        !           316: {
        !           317:        db_sym_t db_sym_parse_and_lookup();
        !           318: 
        !           319:        return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr));
        !           320: }
        !           321: 
        !           322: db_sym_t
        !           323: aout_db_search_symbol(symtab, off, strategy, diffp)
        !           324:        db_symtab_t *   symtab;
        !           325:        register
        !           326:        db_addr_t       off;
        !           327:        db_strategy_t   strategy;
        !           328:        db_expr_t       *diffp;         /* in/out */
        !           329: {
        !           330:        register unsigned long  diff = *diffp;
        !           331:        register struct nlist   *symp = 0;
        !           332:        register struct nlist   *sp, *ep;
        !           333: 
        !           334:        sp = (struct nlist *)symtab->start;
        !           335:        ep = (struct nlist *)symtab->end;
        !           336: 
        !           337:        for (; sp < ep; sp++) {
        !           338:            if (sp->n_un.n_name == 0)
        !           339:                continue;
        !           340:            if ((sp->n_type & N_STAB) != 0)
        !           341:                continue;
        !           342:            if (strategy == DB_STGY_XTRN && (sp->n_type & N_EXT) == 0)
        !           343:                continue;
        !           344:            if (off >= sp->n_value) {
        !           345: 
        !           346:                unsigned int type = sp->n_type;
        !           347: 
        !           348:                if (type == N_FN) continue;
        !           349:                if (off - sp->n_value < diff) {
        !           350:                    diff = off - sp->n_value;
        !           351:                    symp = sp;
        !           352:                    if (diff == 0 && (type & N_EXT))
        !           353:                        break;
        !           354:                }
        !           355:                else if (off - sp->n_value == diff) {
        !           356:                    if (symp == 0)
        !           357:                        symp = sp;
        !           358:                    else if ((symp->n_type & N_EXT) == 0 &&
        !           359:                                (type & N_EXT) != 0)
        !           360:                        symp = sp;      /* pick the external symbol */
        !           361:                }
        !           362:            }
        !           363:        }
        !           364:        if (symp == 0) {
        !           365:            *diffp = off;
        !           366:        }
        !           367:        else {
        !           368:            *diffp = diff;
        !           369:        }
        !           370:        return ((db_sym_t)symp);
        !           371: }
        !           372: 
        !           373: /*
        !           374:  * Return the name and value for a symbol.
        !           375:  */
        !           376: void
        !           377: aout_db_symbol_values(sym, namep, valuep)
        !           378:        db_sym_t        sym;
        !           379:        char            **namep;
        !           380:        db_expr_t       *valuep;
        !           381: {
        !           382:        register struct nlist *sp;
        !           383: 
        !           384:        sp = (struct nlist *)sym;
        !           385:        if (namep)
        !           386:            *namep = sp->n_un.n_name;
        !           387:        if (valuep)
        !           388:            *valuep = sp->n_value;
        !           389: }
        !           390: 
        !           391: #define X_DB_MAX_DIFF  8       /* maximum allowable diff at the end of line */
        !           392: 
        !           393: /*
        !           394:  * search symbol by value
        !           395:  */
        !           396: private boolean_t
        !           397: aout_db_search_by_addr(stab, addr, file, func, line, diff)
        !           398:        db_symtab_t     *stab;
        !           399:        register        vm_offset_t addr;
        !           400:        char            **file;
        !           401:        char            **func;
        !           402:        int             *line;
        !           403:        unsigned long   *diff;
        !           404: {
        !           405:        register        struct nlist *sp;
        !           406:        register        struct nlist *line_sp, *func_sp, *file_sp, *line_func;
        !           407:        register vm_size_t func_diff, line_diff;
        !           408:        boolean_t       found_line = FALSE;
        !           409:        struct          nlist *ep = (struct nlist *)stab->end;
        !           410: 
        !           411:        line_sp = func_sp = file_sp = line_func = 0;
        !           412:        *file = *func = 0;
        !           413:        *line = 0;
        !           414:        func_diff = line_diff = ~0;
        !           415:        for (sp = (struct nlist *)stab->start; sp < ep; sp++) {
        !           416:            switch(sp->n_type) {
        !           417:            case N_SLINE:
        !           418:                if (sp->n_value <= addr) {
        !           419:                    if (line_sp == 0 || line_diff >= addr - sp->n_value) {
        !           420:                        if (line_func)
        !           421:                            line_func = 0;
        !           422:                        line_sp = sp;
        !           423:                        line_diff = addr - sp->n_value;
        !           424:                    }
        !           425:                }
        !           426:                if (sp->n_value >= addr && line_sp)
        !           427:                    found_line = TRUE;
        !           428:                continue;
        !           429:            case N_FUN:
        !           430:                if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
        !           431:                    && line_func == 0)
        !           432:                    line_func = sp;
        !           433:                continue;
        !           434:            case N_SO:
        !           435:                if (sp->n_value > addr)
        !           436:                    continue;
        !           437:                if (file_sp == 0 || file_sp->n_value <= sp->n_value)
        !           438:                    file_sp = sp;
        !           439:                continue;
        !           440:            case N_TEXT:
        !           441:                if (aout_db_is_filename(sp->n_un.n_name)) {
        !           442:                    if (sp->n_value > addr)
        !           443:                        continue;
        !           444:                    if (file_sp == 0 || file_sp->n_value <= sp->n_value)
        !           445:                        file_sp = sp;
        !           446:                } else if (sp->n_value <= addr &&
        !           447:                         (func_sp == 0 || func_diff > addr - sp->n_value)) {
        !           448:                    func_sp = sp;
        !           449:                    func_diff = addr - sp->n_value;
        !           450:                }
        !           451:                continue;
        !           452:            case N_TEXT|N_EXT:
        !           453:                if (sp->n_value <= addr &&
        !           454:                         (func_sp == 0 || func_diff >= addr - sp->n_value)) {
        !           455:                    func_sp = sp;
        !           456:                    func_diff = addr - sp->n_value;
        !           457:                    if (func_diff == 0 && file_sp && func_sp)
        !           458:                        break;
        !           459:                }
        !           460:            default:
        !           461:                continue;
        !           462:            }
        !           463:            break;
        !           464:        }
        !           465:        if (line_sp) {
        !           466:            if (line_func == 0 || func_sp == 0
        !           467:                || line_func->n_value != func_sp->n_value)
        !           468:                line_sp = 0;
        !           469:        }
        !           470:        if (file_sp) {
        !           471:            *diff = addr - file_sp->n_value;
        !           472:            *file = file_sp->n_un.n_name;
        !           473:        }
        !           474:        if (func_sp) {
        !           475:            *diff = addr - func_sp->n_value;
        !           476:            *func = (func_sp->n_un.n_name[0] == '_')?
        !           477:                        func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
        !           478:        }
        !           479:        if (line_sp) {
        !           480:            *diff = addr - line_sp->n_value;
        !           481:            *line = line_sp->n_desc;
        !           482:        }
        !           483:        return(file_sp || func_sp || line_sp);
        !           484: }
        !           485: 
        !           486: /*
        !           487:  * Find filename and lineno within, given the current pc.
        !           488:  */
        !           489: boolean_t
        !           490: aout_db_line_at_pc(stab, sym, file, line, pc)
        !           491:        db_symtab_t     *stab;
        !           492:        db_sym_t        sym;
        !           493:        char            **file;
        !           494:        int             *line;
        !           495:        db_expr_t       pc;
        !           496: {
        !           497:        char            *func;
        !           498:        unsigned long   diff;
        !           499:        boolean_t       found;
        !           500: 
        !           501:        found = aout_db_search_by_addr(stab,(vm_offset_t)pc,file,&func,line,&diff);
        !           502:        return(found && func && *file);
        !           503: }
        !           504: 
        !           505: #endif /* DB_NO_AOUT */
        !           506: 
        !           507: #endif MACH_KDB

unix.superglobalmegacorp.com

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