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

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:  */
                     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:                 */
1.1.1.2 ! root      165:                if (*s2 == 0 && sp->n_un.n_name <= s1 - 2
1.1       root      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:         */
1.1.1.2 ! root      176:        return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) ||
1.1       root      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++) {
1.1.1.2 ! root      287:                    if (sp->n_type == N_TEXT
1.1       root      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: 
1.1.1.2 ! root      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.