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

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