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

1.1.1.2 ! root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1992,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: 
                     31: #include "mach_kdb.h"
                     32: #if MACH_KDB
                     33: 
                     34: #include <mach/std_types.h>
                     35: #include <kern/strings.h>
                     36: #include <machine/db_machdep.h>
                     37: #include <ddb/db_sym.h>
                     38: #include <ddb/db_task_thread.h>
                     39: 
                     40: #include <vm/vm_map.h> /* vm_map_t */
                     41: 
                     42: /*
                     43:  * Multiple symbol tables
                     44:  */
                     45: #define        MAXNOSYMTABS    5       /* mach, bootstrap, ux, emulator, 1 spare */
                     46: 
                     47: db_symtab_t    db_symtabs[MAXNOSYMTABS] = {{0,},};
                     48: int db_nsymtab = 0;
                     49: 
                     50: db_symtab_t    *db_last_symtab;
                     51: 
                     52: db_sym_t       db_lookup();    /* forward */
                     53: 
                     54: /*
                     55:  * Add symbol table, with given name, to list of symbol tables.
                     56:  */
                     57: boolean_t
                     58: db_add_symbol_table(type, start, end, name, ref, map_pointer)
                     59:        int type;
                     60:        char *start;
                     61:        char *end;
                     62:        char *name;
                     63:        char *ref;
                     64:        char *map_pointer;
                     65: {
                     66:        register db_symtab_t *st;
                     67:        extern vm_map_t kernel_map;
                     68: 
                     69:        if (db_nsymtab >= MAXNOSYMTABS)
                     70:            return (FALSE);
                     71: 
                     72:        st = &db_symtabs[db_nsymtab];
                     73:        st->type = type;
                     74:        st->start = start;
                     75:        st->end = end;
                     76:        st->private = ref;
                     77:        st->map_pointer = (map_pointer == (char *)kernel_map)? 0: map_pointer;
                     78:        strcpy(st->name, name);
                     79: 
                     80:        db_nsymtab++;
                     81: 
                     82:        return (TRUE);
                     83: }
                     84: 
                     85: /*
                     86:  *  db_qualify("vm_map", "ux") returns "ux::vm_map".
                     87:  *
                     88:  *  Note: return value points to static data whose content is
                     89:  *  overwritten by each call... but in practice this seems okay.
                     90:  */
                     91: static char *
                     92: db_qualify(symname, symtabname)
                     93:        char            *symname;
                     94:        register char   *symtabname;
                     95: {
                     96:        static char     tmp[256];
                     97:        register char   *s;
                     98: 
                     99:        s = tmp;
                    100:        while (*s++ = *symtabname++) {
                    101:        }
                    102:        s[-1] = ':';
                    103:        *s++ = ':';
                    104:        while (*s++ = *symname++) {
                    105:        }
                    106:        return tmp;
                    107: }
                    108: 
                    109: 
                    110: boolean_t
                    111: db_eqname( char* src, char* dst, char c )
                    112: {
                    113:        if (!strcmp(src, dst))
                    114:            return (TRUE);
                    115:        if (src[0] == c)
                    116:            return (!strcmp(src+1,dst));
                    117:        return (FALSE);
                    118: }
                    119: 
                    120: boolean_t
                    121: db_value_of_name(name, valuep)
                    122:        char            *name;
                    123:        db_expr_t       *valuep;
                    124: {
                    125:        db_sym_t        sym;
                    126: 
                    127:        sym = db_lookup(name);
                    128:        if (sym == DB_SYM_NULL)
                    129:            return (FALSE);
                    130:        db_symbol_values(0, sym, &name, valuep);
                    131:        return (TRUE);
                    132: }
                    133: 
                    134: /*
                    135:  * Lookup a symbol.
                    136:  * If the symbol has a qualifier (e.g., ux::vm_map),
                    137:  * then only the specified symbol table will be searched;
                    138:  * otherwise, all symbol tables will be searched.
                    139:  */
                    140: db_sym_t
                    141: db_lookup(symstr)
                    142:        char *symstr;
                    143: {
                    144:        db_sym_t sp;
                    145:        register int i;
                    146:        int symtab_start = 0;
                    147:        int symtab_end = db_nsymtab;
                    148:        register char *cp;
                    149: 
                    150:        /*
                    151:         * Look for, remove, and remember any symbol table specifier.
                    152:         */
                    153:        for (cp = symstr; *cp; cp++) {
                    154:                if (*cp == ':' && cp[1] == ':') {
                    155:                        *cp = '\0';
                    156:                        for (i = 0; i < db_nsymtab; i++) {
                    157:                                if (! strcmp(symstr, db_symtabs[i].name)) {
                    158:                                        symtab_start = i;
                    159:                                        symtab_end = i + 1;
                    160:                                        break;
                    161:                                }
                    162:                        }
                    163:                        *cp = ':';
                    164:                        if (i == db_nsymtab)
                    165:                                db_error("Invalid symbol table name\n");
                    166:                        symstr = cp+2;
                    167:                }
                    168:        }
                    169: 
                    170:        /*
                    171:         * Look in the specified set of symbol tables.
                    172:         * Return on first match.
                    173:         */
                    174:        for (i = symtab_start; i < symtab_end; i++) {
                    175:                if (sp = X_db_lookup(&db_symtabs[i], symstr)) {
                    176:                        db_last_symtab = &db_symtabs[i];
                    177:                        return sp;
                    178:                }
                    179:        }
                    180:        return 0;
                    181: }
                    182: 
                    183: /*
                    184:  * Common utility routine to parse a symbol string into a file
                    185:  * name, a symbol name and line number.
                    186:  * This routine is called from X_db_lookup if the object dependent
                    187:  * handler supports qualified search with a file name or a line number.
                    188:  * It parses the symbol string, and call an object dependent routine
                    189:  * with parsed file name, symbol name and line number.
1.1.1.2 ! root      190:  */
1.1       root      191: db_sym_t
                    192: db_sym_parse_and_lookup(func, symtab, symstr)
                    193:        db_sym_t        (*func)();
                    194:        db_symtab_t     *symtab;
                    195:        char            *symstr;
                    196: {
                    197:        register        char *p;
                    198:        register        n;
                    199:        int             n_name;
                    200:        int             line_number;
                    201:        char            *file_name = 0;
                    202:        char            *sym_name = 0;
                    203:        char            *component[3];
                    204:        db_sym_t        found = DB_SYM_NULL;
                    205: 
                    206:        /*
                    207:         * disassemble the symbol into components:
                    208:         *      [file_name:]symbol[:line_nubmer]
                    209:         */
                    210:        component[0] = symstr;
                    211:        component[1] = component[2] = 0;
                    212:        for (p = symstr, n = 1; *p; p++) {
                    213:                if (*p == ':') {
                    214:                        if (n >= 3)
                    215:                                break;
                    216:                        *p = 0;
                    217:                        component[n++] = p+1;
                    218:                }
                    219:        }
                    220:        if (*p != 0)
                    221:                goto out;
                    222:        line_number = 0;
                    223:        n_name = n;
                    224:        p = component[n-1];
                    225:        if (*p >= '0' && *p <= '9') {
                    226:                if (n == 1)
                    227:                        goto out;
                    228:                for (line_number = 0; *p; p++) {
                    229:                        if (*p < '0' || *p > '9')
                    230:                                goto out;
                    231:                        line_number = line_number*10 + *p - '0';
                    232:                }
                    233:                n_name--;
                    234:        } else if (n >= 3)
                    235:                goto out;
                    236:        if (n_name == 1) {
                    237:                for (p = component[0]; *p && *p != '.'; p++);
                    238:                if (*p == '.') {
                    239:                        file_name = component[0];
                    240:                        sym_name = 0;
                    241:                } else {
                    242:                        file_name = 0;
                    243:                        sym_name = component[0];
                    244:                }
                    245:        } else {
                    246:                file_name = component[0];
                    247:                sym_name = component[1];
                    248:        }
                    249:        found = func(symtab, file_name, sym_name, line_number);
1.1.1.2 ! root      250: 
1.1       root      251: out:
                    252:        while (--n >= 1)
                    253:                component[n][-1] = ':';
                    254:        return(found);
                    255: }
                    256: 
                    257: /*
                    258:  * Does this symbol name appear in more than one symbol table?
                    259:  * Used by db_symbol_values to decide whether to qualify a symbol.
                    260:  */
                    261: boolean_t db_qualify_ambiguous_names = FALSE;
                    262: 
                    263: boolean_t
                    264: db_name_is_ambiguous(sym_name)
                    265:        char            *sym_name;
                    266: {
                    267:        register int    i;
                    268:        register
                    269:        boolean_t       found_once = FALSE;
                    270: 
                    271:        if (!db_qualify_ambiguous_names)
                    272:                return FALSE;
                    273: 
                    274:        for (i = 0; i < db_nsymtab; i++) {
                    275:                if (X_db_lookup(&db_symtabs[i], sym_name)) {
                    276:                        if (found_once)
                    277:                                return TRUE;
                    278:                        found_once = TRUE;
                    279:                }
                    280:        }
                    281:        return FALSE;
                    282: }
                    283: 
                    284: 
                    285: db_sym_t db_search_in_task_symbol();
                    286: 
                    287: /*
                    288:  * Find the closest symbol to val, and return its name
                    289:  * and the difference between val and the symbol found.
                    290:  *
                    291:  * Logic change. If the task argument is non NULL and a
                    292:  * matching symbol is found in a symbol table which explictly
1.1.1.2 ! root      293:  * specifies its map to be task->map, that symbol will have
        !           294:  * precedence over any symbol from a symbol table will a null
1.1       root      295:  * map. This allows overlapping kernel/user maps to work correctly.
                    296:  *
                    297:  */
                    298: db_sym_t
                    299: db_search_task_symbol(val, strategy, offp, task)
                    300:        register db_addr_t      val;
                    301:        db_strategy_t           strategy;
                    302:        db_addr_t               *offp; /* better be unsigned */
                    303:        task_t                  task;
                    304: {
                    305:   db_sym_t ret;
                    306: 
                    307:   if (task != TASK_NULL)
                    308:     ret = db_search_in_task_symbol(val, strategy, offp, task);
                    309:   else
                    310:     {
                    311:       ret = db_search_in_task_symbol(val, strategy, offp, task);
1.1.1.2 ! root      312:       /*
        !           313:        db_search_in_task_symbol will return success with
        !           314:        a very large offset when it should have failed.
1.1       root      315:        */
                    316:       if (ret == DB_SYM_NULL || (*offp) > 0x1000000)
                    317:        {
                    318:          task = db_current_task();
                    319:          ret = db_search_in_task_symbol(val, strategy, offp, task);
                    320:        }
                    321:     }
                    322: 
                    323:   return ret;
                    324: }
                    325: 
                    326: db_sym_t
                    327: db_search_in_task_symbol(val, strategy, offp, task)
                    328:        register db_addr_t      val;
                    329:        db_strategy_t           strategy;
                    330:        db_addr_t               *offp;
                    331:        task_t                  task;
                    332: {
                    333:   register vm_size_t diff;
                    334:   vm_size_t    newdiff;
                    335:   register int i;
                    336:   db_symtab_t  *sp;
                    337:   db_sym_t     ret = DB_SYM_NULL, sym;
                    338:   vm_map_t     map_for_val;
                    339: 
                    340:   map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map;
                    341:   newdiff = diff = ~0;
                    342:   db_last_symtab = (db_symtab_t *) 0;
1.1.1.2 ! root      343:   for (sp = &db_symtabs[0], i = 0; i < db_nsymtab;  sp++, i++)
1.1       root      344:     {
                    345:       newdiff = ~0;
                    346:       if ((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
1.1.1.2 ! root      347:          (vm_map_t)sp->map_pointer == map_for_val)
1.1       root      348:        {
                    349:          sym = X_db_search_symbol(sp, val, strategy, (db_expr_t*)&newdiff);
                    350:          if (sym == DB_SYM_NULL)
                    351:            continue;
                    352:          if (db_last_symtab == (db_symtab_t *) 0)
                    353:            { /* first hit */
                    354:              db_last_symtab = sp;
                    355:              diff = newdiff;
                    356:              ret = sym;
                    357:              continue;
                    358:            }
1.1.1.2 ! root      359:          if ((vm_map_t) sp->map_pointer == VM_MAP_NULL &&
1.1       root      360:              (vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL &&
                    361:              newdiff < diff )
                    362:            { /* closer null map match */
                    363:              db_last_symtab = sp;
                    364:              diff = newdiff;
                    365:              ret = sym;
                    366:              continue;
1.1.1.2 ! root      367:            }
        !           368:          if ((vm_map_t) sp->map_pointer != VM_MAP_NULL &&
1.1       root      369:              (newdiff < 0x100000) &&
                    370:              ((vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL ||
                    371:               newdiff < diff ))
1.1.1.2 ! root      372:            { /* update if new is in matching map and symbol is "close",
        !           373:                 and
        !           374:                 old is VM_MAP_NULL or old in is matching map but is further away
1.1       root      375:                 */
                    376:              db_last_symtab = sp;
                    377:              diff = newdiff;
                    378:              ret = sym;
                    379:              continue;
1.1.1.2 ! root      380:            }
1.1       root      381:        }
                    382:     }
1.1.1.2 ! root      383: 
1.1       root      384:   *offp = diff;
                    385:   return ret;
                    386: }
                    387: 
                    388: /*
                    389:  * Return name and value of a symbol
                    390:  */
                    391: void
                    392: db_symbol_values(stab, sym, namep, valuep)
                    393:        db_symtab_t     *stab;
                    394:        db_sym_t        sym;
                    395:        char            **namep;
                    396:        db_expr_t       *valuep;
                    397: {
                    398:        db_expr_t       value;
                    399:        char            *name;
                    400: 
                    401:        if (sym == DB_SYM_NULL) {
                    402:                *namep = 0;
                    403:                return;
                    404:        }
                    405:        if (stab == 0)
                    406:                stab = db_last_symtab;
                    407: 
                    408:        X_db_symbol_values(stab, sym, &name, &value);
                    409: 
                    410:        if (db_name_is_ambiguous(name))
                    411:                *namep = db_qualify(name, db_last_symtab->name);
                    412:        else
                    413:                *namep = name;
                    414:        if (valuep)
                    415:                *valuep = value;
                    416: }
                    417: 
                    418: 
                    419: /*
                    420:  * Print the closest symbol to value
                    421:  *
                    422:  * After matching the symbol according to the given strategy
                    423:  * we print it in the name+offset format, provided the symbol's
                    424:  * value is close enough (eg smaller than db_maxoff).
                    425:  * We also attempt to print [filename:linenum] when applicable
                    426:  * (eg for procedure names).
                    427:  *
                    428:  * If we could not find a reasonable name+offset representation,
                    429:  * then we just print the value in hex.  Small values might get
                    430:  * bogus symbol associations, e.g. 3 might get some absolute
                    431:  * value like _INCLUDE_VERSION or something, therefore we do
                    432:  * not accept symbols whose value is zero (and use plain hex).
                    433:  */
                    434: 
                    435: unsigned int   db_maxoff = 0x4000;
                    436: 
                    437: void
                    438: db_task_printsym(off, strategy, task)
                    439:        db_expr_t       off;
                    440:        db_strategy_t   strategy;
                    441:        task_t          task;
                    442: {
                    443:        db_addr_t       d;
                    444:        char            *filename;
                    445:        char            *name;
                    446:        db_expr_t       value;
                    447:        int             linenum;
                    448:        db_sym_t        cursym;
                    449: 
                    450:        cursym = db_search_task_symbol(off, strategy, &d, task);
                    451:        db_symbol_values(0, cursym, &name, &value);
                    452:        if (name == 0 || d >= db_maxoff || value == 0) {
                    453:                db_printf("%#n", off);
                    454:                return;
                    455:        }
                    456:        db_printf("%s", name);
                    457:        if (d)
                    458:                db_printf("+0x%x", d);
                    459:        if (strategy == DB_STGY_PROC) {
                    460:                if (db_line_at_pc(cursym, &filename, &linenum, off)) {
                    461:                        db_printf(" [%s", filename);
                    462:                        if (linenum > 0)
                    463:                                db_printf(":%d", linenum);
                    464:                        db_printf("]");
                    465:                }
                    466:        }
                    467: }
                    468: 
                    469: void
                    470: db_printsym(off, strategy)
                    471:        db_expr_t       off;
                    472:        db_strategy_t   strategy;
                    473: {
                    474:        db_task_printsym(off, strategy, TASK_NULL);
                    475: }
                    476: 
                    477: boolean_t
                    478: db_line_at_pc( sym, filename, linenum, pc)
                    479:        db_sym_t        sym;
                    480:        char            **filename;
                    481:        int             *linenum;
                    482:        db_expr_t       pc;
                    483: {
                    484:        return (db_last_symtab) ?
                    485:                X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc) :
                    486:                FALSE;
                    487: }
                    488: 
                    489: /*
                    490:  * Switch into symbol-table specific routines
                    491:  */
                    492: 
                    493: extern boolean_t aout_db_sym_init(), aout_db_line_at_pc();
                    494: extern db_sym_t aout_db_lookup(), aout_db_search_symbol();
                    495: extern void aout_db_symbol_values();
                    496: 
                    497: extern boolean_t coff_db_sym_init(), coff_db_line_at_pc();
                    498: extern db_sym_t coff_db_lookup(), coff_db_search_symbol();
                    499: extern void coff_db_symbol_values();
                    500: 
                    501: struct db_sym_switch x_db[] = {
                    502: 
                    503:        /* BSD a.out format (really, sdb/dbx(1) symtabs) */
                    504: #ifdef DB_NO_AOUT
                    505:        { 0,},
                    506: #else  /* DB_NO_AOUT */
                    507:        { aout_db_sym_init, aout_db_lookup, aout_db_search_symbol,
                    508:          aout_db_line_at_pc, aout_db_symbol_values },
                    509: #endif /* DB_NO_AOUT */
                    510: 
                    511: #ifdef DB_NO_COFF
                    512:        { 0,},
                    513: #else  /* DB_NO_COFF */
                    514:        { coff_db_sym_init, coff_db_lookup, coff_db_search_symbol,
                    515:          coff_db_line_at_pc, coff_db_symbol_values },
                    516: #endif /* DB_NO_COFF */
                    517: 
                    518:        /* Machdep, not inited here */
                    519:        { 0,}
                    520: 
                    521: };
                    522: 
1.1.1.2 ! root      523: #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.