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

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