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

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1992,1991,1990 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             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.
        !            11:  * 
        !            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.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            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.
        !           190:  */ 
        !           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);
        !           250:        
        !           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
        !           293:  * specifies its map to be task->map, that symbol will have 
        !           294:  * precedence over any symbol from a symbol table will a null 
        !           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);
        !           312:       /* 
        !           313:        db_search_in_task_symbol will return success with 
        !           314:        a very large offset when it should have failed. 
        !           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;
        !           343:   for (sp = &db_symtabs[0], i = 0; i < db_nsymtab;  sp++, i++) 
        !           344:     {
        !           345:       newdiff = ~0;
        !           346:       if ((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
        !           347:          (vm_map_t)sp->map_pointer == map_for_val) 
        !           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:            }
        !           359:          if ((vm_map_t) sp->map_pointer == VM_MAP_NULL && 
        !           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;
        !           367:            }               
        !           368:          if ((vm_map_t) sp->map_pointer != VM_MAP_NULL && 
        !           369:              (newdiff < 0x100000) &&
        !           370:              ((vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL ||
        !           371:               newdiff < diff ))
        !           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 
        !           375:                 */
        !           376:              db_last_symtab = sp;
        !           377:              diff = newdiff;
        !           378:              ret = sym;
        !           379:              continue;
        !           380:            }               
        !           381:        }
        !           382:     }
        !           383:   
        !           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: 
        !           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.