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

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