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

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>
1.1.1.4 ! root       40: #include <ddb/db_aout.h>
        !            41: #include <ddb/db_elf.h>
1.1       root       42: 
                     43: #include <vm/vm_map.h> /* vm_map_t */
                     44: 
                     45: /*
                     46:  * Multiple symbol tables
                     47:  */
                     48: #define        MAXNOSYMTABS    5       /* mach, bootstrap, ux, emulator, 1 spare */
                     49: 
                     50: db_symtab_t    db_symtabs[MAXNOSYMTABS] = {{0,},};
                     51: int db_nsymtab = 0;
                     52: 
                     53: db_symtab_t    *db_last_symtab;
                     54: 
                     55: /*
                     56:  * Add symbol table, with given name, to list of symbol tables.
                     57:  */
                     58: boolean_t
1.1.1.4 ! root       59: db_add_symbol_table(
        !            60:        int  type,
        !            61:        char *start,
        !            62:        char *end,
        !            63:        char *name,
        !            64:        char *ref,
        !            65:        char *map_pointer)
1.1       root       66: {
1.1.1.4 ! root       67:        db_symtab_t *st;
1.1       root       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;
1.1.1.4 ! root       79:        strncpy(st->name, name, sizeof st->name - 1);
        !            80:        st->name[sizeof st->name - 1] = '\0';
1.1       root       81: 
                     82:        db_nsymtab++;
                     83: 
                     84:        return (TRUE);
                     85: }
                     86: 
                     87: /*
                     88:  *  db_qualify("vm_map", "ux") returns "ux::vm_map".
                     89:  *
                     90:  *  Note: return value points to static data whose content is
                     91:  *  overwritten by each call... but in practice this seems okay.
                     92:  */
1.1.1.4 ! root       93: static char * __attribute__ ((pure))
1.1       root       94: db_qualify(symname, symtabname)
1.1.1.4 ! root       95:        const char      *symname;
        !            96:        const char      *symtabname;
1.1       root       97: {
                     98:        static char     tmp[256];
1.1.1.4 ! root       99:        char            *s;
1.1       root      100: 
                    101:        s = tmp;
1.1.1.3   root      102:        while ((*s++ = *symtabname++)) {
1.1       root      103:        }
                    104:        s[-1] = ':';
                    105:        *s++ = ':';
1.1.1.3   root      106:        while ((*s++ = *symname++)) {
1.1       root      107:        }
                    108:        return tmp;
                    109: }
                    110: 
                    111: 
                    112: boolean_t
1.1.1.4 ! root      113: db_eqname( const char* src, const char* dst, char c )
1.1       root      114: {
                    115:        if (!strcmp(src, dst))
                    116:            return (TRUE);
                    117:        if (src[0] == c)
                    118:            return (!strcmp(src+1,dst));
                    119:        return (FALSE);
                    120: }
                    121: 
                    122: boolean_t
1.1.1.4 ! root      123: db_value_of_name(
        !           124:        char            *name,
        !           125:        db_expr_t       *valuep)
1.1       root      126: {
                    127:        db_sym_t        sym;
                    128: 
                    129:        sym = db_lookup(name);
                    130:        if (sym == DB_SYM_NULL)
                    131:            return (FALSE);
                    132:        db_symbol_values(0, sym, &name, valuep);
1.1.1.3   root      133:        
                    134:        db_free_symbol(sym);
1.1       root      135:        return (TRUE);
                    136: }
                    137: 
                    138: /*
                    139:  * Lookup a symbol.
                    140:  * If the symbol has a qualifier (e.g., ux::vm_map),
                    141:  * then only the specified symbol table will be searched;
                    142:  * otherwise, all symbol tables will be searched.
                    143:  */
                    144: db_sym_t
1.1.1.4 ! root      145: db_lookup(char *symstr)
1.1       root      146: {
                    147:        db_sym_t sp;
1.1.1.4 ! root      148:        int i;
1.1       root      149:        int symtab_start = 0;
                    150:        int symtab_end = db_nsymtab;
1.1.1.4 ! root      151:        char *cp;
1.1       root      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
1.1.1.4 ! root      196: db_sym_parse_and_lookup(
        !           197:        db_sym_t        (*func)(),
        !           198:        db_symtab_t     *symtab,
        !           199:        char            *symstr)
1.1       root      200: {
1.1.1.4 ! root      201:        char            *p;
        !           202:        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
1.1.1.4 ! root      268: db_name_is_ambiguous(char *sym_name)
1.1       root      269: {
1.1.1.4 ! root      270:        int             i;
1.1       root      271:        boolean_t       found_once = FALSE;
                    272: 
                    273:        if (!db_qualify_ambiguous_names)
                    274:                return FALSE;
                    275: 
                    276:        for (i = 0; i < db_nsymtab; i++) {
1.1.1.4 ! root      277:                db_sym_t sp = X_db_lookup(&db_symtabs[i], sym_name);
        !           278:                if (sp) {
1.1       root      279:                        if (found_once)
1.1.1.3   root      280:                        {
                    281:                                db_free_symbol(sp);
1.1       root      282:                                return TRUE;
1.1.1.3   root      283:                        }
1.1       root      284:                        found_once = TRUE;
                    285:                }
1.1.1.3   root      286:                db_free_symbol(sp);
1.1       root      287:        }
                    288:        return FALSE;
                    289: }
                    290: 
                    291: /*
                    292:  * Find the closest symbol to val, and return its name
                    293:  * and the difference between val and the symbol found.
                    294:  *
                    295:  * Logic change. If the task argument is non NULL and a
1.1.1.4 ! root      296:  * matching symbol is found in a symbol table which explicitly
1.1.1.2   root      297:  * specifies its map to be task->map, that symbol will have
                    298:  * precedence over any symbol from a symbol table will a null
1.1       root      299:  * map. This allows overlapping kernel/user maps to work correctly.
                    300:  *
                    301:  */
                    302: db_sym_t
1.1.1.4 ! root      303: db_search_task_symbol(
        !           304:        db_addr_t               val,
        !           305:        db_strategy_t           strategy,
        !           306:        db_addr_t               *offp, /* better be unsigned */
        !           307:        task_t                  task)
1.1       root      308: {
                    309:   db_sym_t ret;
                    310: 
                    311:   if (task != TASK_NULL)
                    312:     ret = db_search_in_task_symbol(val, strategy, offp, task);
                    313:   else
                    314:     {
                    315:       ret = db_search_in_task_symbol(val, strategy, offp, task);
1.1.1.2   root      316:       /*
                    317:        db_search_in_task_symbol will return success with
                    318:        a very large offset when it should have failed.
1.1       root      319:        */
                    320:       if (ret == DB_SYM_NULL || (*offp) > 0x1000000)
                    321:        {
1.1.1.3   root      322:          db_free_symbol(ret);
1.1       root      323:          task = db_current_task();
                    324:          ret = db_search_in_task_symbol(val, strategy, offp, task);
                    325:        }
                    326:     }
                    327: 
                    328:   return ret;
                    329: }
                    330: 
                    331: db_sym_t
1.1.1.4 ! root      332: db_search_in_task_symbol(
        !           333:        db_addr_t               val,
        !           334:        db_strategy_t           strategy,
        !           335:        db_addr_t               *offp,
        !           336:        task_t                  task)
1.1       root      337: {
1.1.1.4 ! root      338:   vm_size_t    diff;
1.1       root      339:   vm_size_t    newdiff;
1.1.1.4 ! root      340:   int          i;
1.1       root      341:   db_symtab_t  *sp;
                    342:   db_sym_t     ret = DB_SYM_NULL, sym;
                    343:   vm_map_t     map_for_val;
                    344: 
                    345:   map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map;
                    346:   newdiff = diff = ~0;
                    347:   db_last_symtab = (db_symtab_t *) 0;
1.1.1.2   root      348:   for (sp = &db_symtabs[0], i = 0; i < db_nsymtab;  sp++, i++)
1.1       root      349:     {
                    350:       newdiff = ~0;
                    351:       if ((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
1.1.1.2   root      352:          (vm_map_t)sp->map_pointer == map_for_val)
1.1       root      353:        {
                    354:          sym = X_db_search_symbol(sp, val, strategy, (db_expr_t*)&newdiff);
                    355:          if (sym == DB_SYM_NULL)
                    356:            continue;
                    357:          if (db_last_symtab == (db_symtab_t *) 0)
                    358:            { /* first hit */
                    359:              db_last_symtab = sp;
                    360:              diff = newdiff;
1.1.1.3   root      361:              db_free_symbol(ret);
1.1       root      362:              ret = sym;
                    363:              continue;
                    364:            }
1.1.1.2   root      365:          if ((vm_map_t) sp->map_pointer == VM_MAP_NULL &&
1.1       root      366:              (vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL &&
                    367:              newdiff < diff )
                    368:            { /* closer null map match */
                    369:              db_last_symtab = sp;
                    370:              diff = newdiff;
1.1.1.3   root      371:              db_free_symbol(ret);
1.1       root      372:              ret = sym;
                    373:              continue;
1.1.1.2   root      374:            }
                    375:          if ((vm_map_t) sp->map_pointer != VM_MAP_NULL &&
1.1       root      376:              (newdiff < 0x100000) &&
                    377:              ((vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL ||
                    378:               newdiff < diff ))
1.1.1.2   root      379:            { /* update if new is in matching map and symbol is "close",
                    380:                 and
                    381:                 old is VM_MAP_NULL or old in is matching map but is further away
1.1       root      382:                 */
                    383:              db_last_symtab = sp;
                    384:              diff = newdiff;
1.1.1.3   root      385:              db_free_symbol(ret);
1.1       root      386:              ret = sym;
                    387:              continue;
1.1.1.2   root      388:            }
1.1       root      389:        }
                    390:     }
1.1.1.2   root      391: 
1.1       root      392:   *offp = diff;
                    393:   return ret;
                    394: }
                    395: 
                    396: /*
                    397:  * Return name and value of a symbol
                    398:  */
                    399: void
1.1.1.4 ! root      400: db_symbol_values(
        !           401:        db_symtab_t     *stab,
        !           402:        db_sym_t        sym,
        !           403:        char            **namep,
        !           404:        db_expr_t       *valuep)
1.1       root      405: {
                    406:        db_expr_t       value;
                    407:        char            *name;
                    408: 
                    409:        if (sym == DB_SYM_NULL) {
                    410:                *namep = 0;
                    411:                return;
                    412:        }
                    413:        if (stab == 0)
                    414:                stab = db_last_symtab;
                    415: 
                    416:        X_db_symbol_values(stab, sym, &name, &value);
                    417: 
                    418:        if (db_name_is_ambiguous(name))
                    419:                *namep = db_qualify(name, db_last_symtab->name);
                    420:        else
                    421:                *namep = name;
                    422:        if (valuep)
                    423:                *valuep = value;
                    424: }
                    425: 
                    426: 
                    427: /*
                    428:  * Print the closest symbol to value
                    429:  *
                    430:  * After matching the symbol according to the given strategy
                    431:  * we print it in the name+offset format, provided the symbol's
                    432:  * value is close enough (eg smaller than db_maxoff).
                    433:  * We also attempt to print [filename:linenum] when applicable
                    434:  * (eg for procedure names).
                    435:  *
                    436:  * If we could not find a reasonable name+offset representation,
                    437:  * then we just print the value in hex.  Small values might get
                    438:  * bogus symbol associations, e.g. 3 might get some absolute
                    439:  * value like _INCLUDE_VERSION or something, therefore we do
                    440:  * not accept symbols whose value is zero (and use plain hex).
                    441:  */
                    442: 
1.1.1.3   root      443: unsigned long  db_maxoff = 0x4000;
1.1       root      444: 
                    445: void
                    446: db_task_printsym(off, strategy, task)
1.1.1.4 ! root      447:        db_addr_t       off;
1.1       root      448:        db_strategy_t   strategy;
                    449:        task_t          task;
                    450: {
                    451:        db_addr_t       d;
                    452:        char            *filename;
                    453:        char            *name;
                    454:        db_expr_t       value;
                    455:        int             linenum;
                    456:        db_sym_t        cursym;
                    457: 
                    458:        cursym = db_search_task_symbol(off, strategy, &d, task);
                    459:        db_symbol_values(0, cursym, &name, &value);
1.1.1.3   root      460:        if (name == 0 || d >= db_maxoff || value == 0 || *name == 0) {
1.1       root      461:                db_printf("%#n", off);
1.1.1.3   root      462:                db_free_symbol(cursym);
1.1       root      463:                return;
                    464:        }
                    465:        db_printf("%s", name);
                    466:        if (d)
                    467:                db_printf("+0x%x", d);
                    468:        if (strategy == DB_STGY_PROC) {
                    469:                if (db_line_at_pc(cursym, &filename, &linenum, off)) {
                    470:                        db_printf(" [%s", filename);
                    471:                        if (linenum > 0)
                    472:                                db_printf(":%d", linenum);
                    473:                        db_printf("]");
                    474:                }
                    475:        }
1.1.1.3   root      476:        db_free_symbol(cursym);
1.1       root      477: }
                    478: 
                    479: void
                    480: db_printsym(off, strategy)
                    481:        db_expr_t       off;
                    482:        db_strategy_t   strategy;
                    483: {
                    484:        db_task_printsym(off, strategy, TASK_NULL);
                    485: }
                    486: 
                    487: boolean_t
                    488: db_line_at_pc( sym, filename, linenum, pc)
                    489:        db_sym_t        sym;
                    490:        char            **filename;
                    491:        int             *linenum;
1.1.1.4 ! root      492:        db_addr_t       pc;
1.1       root      493: {
                    494:        return (db_last_symtab) ?
                    495:                X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc) :
                    496:                FALSE;
                    497: }
                    498: 
1.1.1.3   root      499: void db_free_symbol(db_sym_t s)
                    500: {
                    501:        return (db_last_symtab) ?
                    502:                X_db_free_symbol( db_last_symtab, s) :
                    503:                FALSE;
                    504: }
                    505: 
1.1       root      506: /*
                    507:  * Switch into symbol-table specific routines
                    508:  */
                    509: 
1.1.1.4 ! root      510: void dummy_db_free_symbol(db_sym_t symbol) { }
        !           511: boolean_t dummy_db_sym_init(char *a, char *b, char *c, char *d) {
        !           512:   return FALSE;
        !           513: }
1.1       root      514: 
1.1.1.3   root      515: 
1.1       root      516: struct db_sym_switch x_db[] = {
                    517: 
                    518:        /* BSD a.out format (really, sdb/dbx(1) symtabs) */
                    519: #ifdef DB_NO_AOUT
                    520:        { 0,},
                    521: #else  /* DB_NO_AOUT */
                    522:        { aout_db_sym_init, aout_db_lookup, aout_db_search_symbol,
1.1.1.3   root      523:          aout_db_line_at_pc, aout_db_symbol_values, dummy_db_free_symbol },
1.1       root      524: #endif /* DB_NO_AOUT */
                    525: 
                    526:        { 0,},
                    527: 
                    528:        /* Machdep, not inited here */
1.1.1.4 ! root      529:        { 0,},
        !           530: 
        !           531: #ifdef DB_NO_ELF
        !           532:        { 0,},
        !           533: #else  /* DB_NO_ELF */
        !           534:        { dummy_db_sym_init, elf_db_lookup, elf_db_search_symbol,
        !           535:          elf_db_line_at_pc, elf_db_symbol_values, dummy_db_free_symbol },
        !           536: #endif /* DB_NO_ELF */
1.1       root      537: 
                    538: };
                    539: 
1.1.1.2   root      540: #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.