Annotation of Gnu-Mach/ddb/db_examine.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:  */
1.1.1.3   root       30: 
1.1       root       31: #if MACH_KDB
                     32: 
                     33: #include <mach/boolean.h>
                     34: #include <machine/db_machdep.h>
1.1.1.3   root       35: #include <machine/db_interface.h>
1.1       root       36: 
                     37: #include <ddb/db_access.h>
                     38: #include <ddb/db_lex.h>
                     39: #include <ddb/db_output.h>
                     40: #include <ddb/db_command.h>
                     41: #include <ddb/db_sym.h>
                     42: #include <ddb/db_task_thread.h>
1.1.1.3   root       43: #include <ddb/db_examine.h>
                     44: #include <ddb/db_expr.h>
1.1       root       45: #include <kern/thread.h>
                     46: #include <kern/task.h>
                     47: #include <mach/vm_param.h>
                     48: 
                     49: #define db_thread_to_task(thread)      ((thread)? thread->task: TASK_NULL)
                     50: 
                     51: char           db_examine_format[TOK_STRING_SIZE] = "x";
                     52: int            db_examine_count = 1;
                     53: db_addr_t      db_examine_prev_addr = 0;
                     54: thread_t       db_examine_thread = THREAD_NULL;
                     55: 
                     56: /*
                     57:  * Examine (print) data.
                     58:  */
                     59: /*ARGSUSED*/
                     60: void
                     61: db_examine_cmd(addr, have_addr, count, modif)
                     62:        db_expr_t       addr;
                     63:        int             have_addr;
                     64:        db_expr_t       count;
1.1.1.4 ! root       65:        const char *    modif;
1.1       root       66: {
                     67:        thread_t        thread;
                     68: 
                     69:        if (modif[0] != '\0')
                     70:            db_strcpy(db_examine_format, modif);
                     71: 
                     72:        if (count == -1)
                     73:            count = 1;
                     74:        db_examine_count = count;
1.1.1.2   root       75:        if (db_option(modif, 't'))
1.1       root       76:          {
                     77:            if (!db_get_next_thread(&thread, 0))
                     78:              return;
                     79:          }
1.1.1.2   root       80:        else
1.1.1.4 ! root       81:          if (db_option(modif, 'u'))
1.1       root       82:            thread = current_thread();
                     83:          else
                     84:            thread = THREAD_NULL;
1.1.1.2   root       85: 
1.1       root       86:        db_examine_thread = thread;
1.1.1.2   root       87:        db_examine((db_addr_t) addr, db_examine_format, count,
1.1       root       88:                                        db_thread_to_task(thread));
                     89: }
                     90: 
                     91: /* ARGSUSED */
                     92: void
                     93: db_examine_forward(addr, have_addr, count, modif)
                     94:        db_expr_t       addr;
                     95:        int             have_addr;
                     96:        db_expr_t       count;
1.1.1.4 ! root       97:        const char *    modif;
1.1       root       98: {
                     99:        db_examine(db_next, db_examine_format, db_examine_count,
                    100:                                db_thread_to_task(db_examine_thread));
                    101: }
                    102: 
                    103: /* ARGSUSED */
                    104: void
                    105: db_examine_backward(addr, have_addr, count, modif)
                    106:        db_expr_t       addr;
                    107:        int             have_addr;
                    108:        db_expr_t       count;
1.1.1.4 ! root      109:        const char *    modif;
1.1       root      110: {
                    111: 
                    112:        db_examine(db_examine_prev_addr - (db_next - db_examine_prev_addr),
                    113:                         db_examine_format, db_examine_count,
                    114:                                db_thread_to_task(db_examine_thread));
                    115: }
                    116: 
                    117: void
                    118: db_examine(addr, fmt, count, task)
                    119:        db_addr_t       addr;
1.1.1.4 ! root      120:        const char *    fmt;    /* format string */
1.1       root      121:        int             count;  /* repeat count */
                    122:        task_t          task;
                    123: {
                    124:        int             c;
                    125:        db_expr_t       value;
                    126:        int             size;   /* in bytes */
                    127:        int             width;
1.1.1.4 ! root      128:        const char *    fp;
1.1       root      129: 
                    130:        db_examine_prev_addr = addr;
                    131:        while (--count >= 0) {
                    132:            fp = fmt;
                    133:            size = sizeof(int);
                    134:            width = 4*size;
                    135:            while ((c = *fp++) != 0) {
                    136:                switch (c) {
                    137:                    case 'b':
                    138:                        size = sizeof(char);
                    139:                        width = 4*size;
                    140:                        break;
                    141:                    case 'h':
                    142:                        size = sizeof(short);
                    143:                        width = 4*size;
                    144:                        break;
                    145:                    case 'l':
                    146:                        size = sizeof(long);
                    147:                        width = 4*size;
                    148:                        break;
                    149:                    case 'a':   /* address */
                    150:                    case 'A':   /* function address */
                    151:                        /* always forces a new line */
                    152:                        if (db_print_position() != 0)
                    153:                            db_printf("\n");
                    154:                        db_prev = addr;
1.1.1.2   root      155:                        db_task_printsym(addr,
1.1       root      156:                                        (c == 'a')?DB_STGY_ANY:DB_STGY_PROC,
                    157:                                        task);
                    158:                        db_printf(":\t");
                    159:                        break;
                    160:                    case 'm':
1.1.1.4 ! root      161:                        db_next = db_xcdump(addr, size, count + 1, task);
1.1       root      162:                        return;
                    163:                    default:
                    164:                        if (db_print_position() == 0) {
                    165:                            /* If we hit a new symbol, print it */
                    166:                            char *      name;
                    167:                            db_addr_t   off;
                    168: 
1.1.1.4 ! root      169:                            db_find_task_sym_and_offset(addr, &name, &off, task);
1.1       root      170:                            if (off == 0)
                    171:                                db_printf("%s:\t", name);
                    172:                            else
                    173:                                db_printf("\t\t");
                    174: 
                    175:                            db_prev = addr;
                    176:                        }
                    177: 
                    178:                        switch (c) {
                    179:                            case ',':   /* skip one unit w/o printing */
                    180:                                addr += size;
                    181:                                break;
                    182: 
                    183:                            case 'r':   /* signed, current radix */
                    184:                                value = db_get_task_value(addr,size,TRUE,task);
                    185:                                addr += size;
                    186:                                db_printf("%-*R", width, value);
                    187:                                break;
                    188:                            case 'x':   /* unsigned hex */
                    189:                                value = db_get_task_value(addr,size,FALSE,task);
                    190:                                addr += size;
                    191:                                db_printf("%-*X", width, value);
                    192:                                break;
                    193:                            case 'z':   /* signed hex */
                    194:                                value = db_get_task_value(addr,size,TRUE,task);
                    195:                                addr += size;
                    196:                                db_printf("%-*Z", width, value);
                    197:                                break;
                    198:                            case 'd':   /* signed decimal */
                    199:                                value = db_get_task_value(addr,size,TRUE,task);
                    200:                                addr += size;
                    201:                                db_printf("%-*D", width, value);
                    202:                                break;
                    203:                            case 'U':   /* unsigned decimal */
                    204:                                value = db_get_task_value(addr,size,FALSE,task);
                    205:                                addr += size;
                    206:                                db_printf("%-*U", width, value);
                    207:                                break;
                    208:                            case 'o':   /* unsigned octal */
                    209:                                value = db_get_task_value(addr,size,FALSE,task);
                    210:                                addr += size;
                    211:                                db_printf("%-*O", width, value);
                    212:                                break;
                    213:                            case 'c':   /* character */
                    214:                                value = db_get_task_value(addr,1,FALSE,task);
                    215:                                addr += 1;
                    216:                                if (value >= ' ' && value <= '~')
                    217:                                    db_printf("%c", value);
                    218:                                else
                    219:                                    db_printf("\\%03o", value);
                    220:                                break;
                    221:                            case 's':   /* null-terminated string */
                    222:                                for (;;) {
                    223:                                    value = db_get_task_value(addr,1,FALSE,task);
                    224:                                    addr += 1;
                    225:                                    if (value == 0)
                    226:                                        break;
                    227:                                    if (value >= ' ' && value <= '~')
                    228:                                        db_printf("%c", value);
                    229:                                    else
                    230:                                        db_printf("\\%03o", value);
                    231:                                }
                    232:                                break;
                    233:                            case 'i':   /* instruction */
                    234:                                addr = db_disasm(addr, FALSE, task);
                    235:                                break;
                    236:                            case 'I':   /* instruction, alternate form */
                    237:                                addr = db_disasm(addr, TRUE, task);
                    238:                                break;
                    239:                            default:
                    240:                                break;
                    241:                        }
                    242:                        if (db_print_position() != 0)
                    243:                            db_end_line();
                    244:                        break;
                    245:                }
                    246:            }
                    247:        }
                    248:        db_next = addr;
                    249: }
                    250: 
                    251: /*
                    252:  * Print value.
                    253:  */
                    254: char   db_print_format = 'x';
                    255: 
                    256: /*ARGSUSED*/
                    257: void
1.1.1.4 ! root      258: db_print_cmd(void)
1.1       root      259: {
                    260:        db_expr_t       value;
                    261:        int             t;
                    262:        task_t          task = TASK_NULL;
                    263: 
                    264:        if ((t = db_read_token()) == tSLASH) {
                    265:            if (db_read_token() != tIDENT) {
                    266:                db_printf("Bad modifier \"/%s\"\n", db_tok_string);
                    267:                db_error(0);
                    268:                /* NOTREACHED */
                    269:            }
                    270:            if (db_tok_string[0])
                    271:                db_print_format = db_tok_string[0];
                    272:            if (db_option(db_tok_string, 't') && db_default_thread)
                    273:                task = db_default_thread->task;
                    274:        } else
                    275:            db_unread_token(t);
1.1.1.2   root      276: 
1.1       root      277:        for ( ; ; ) {
                    278:            t = db_read_token();
                    279:            if (t == tSTRING) {
                    280:                db_printf("%s", db_tok_string);
                    281:                continue;
                    282:            }
                    283:            db_unread_token(t);
                    284:            if (!db_expression(&value))
                    285:                break;
                    286:            switch (db_print_format) {
                    287:            case 'a':
                    288:                db_task_printsym((db_addr_t)value, DB_STGY_ANY, task);
                    289:                break;
                    290:            case 'r':
                    291:                db_printf("%*r", 3+2*sizeof(db_expr_t), value);
                    292:                break;
                    293:            case 'x':
                    294:                db_printf("%*x", 2*sizeof(db_expr_t), value);
                    295:                break;
                    296:            case 'z':
                    297:                db_printf("%*z", 2*sizeof(db_expr_t), value);
                    298:                break;
                    299:            case 'd':
                    300:                db_printf("%*d", 3+2*sizeof(db_expr_t), value);
                    301:                break;
                    302:            case 'u':
                    303:                db_printf("%*u", 3+2*sizeof(db_expr_t), value);
                    304:                break;
                    305:            case 'o':
                    306:                db_printf("%o", 4*sizeof(db_expr_t), value);
                    307:                break;
                    308:            case 'c':
                    309:                value = value & 0xFF;
                    310:                if (value >= ' ' && value <= '~')
                    311:                    db_printf("%c", value);
                    312:                else
                    313:                    db_printf("\\%03o", value);
                    314:                break;
                    315:            default:
                    316:                db_printf("Unknown format %c\n", db_print_format);
                    317:                db_print_format = 'x';
                    318:                db_error(0);
                    319:            }
                    320:        }
                    321: }
                    322: 
                    323: void
1.1.1.4 ! root      324: db_print_loc_and_inst(
        !           325:        db_addr_t       loc,
        !           326:        task_t          task)
1.1       root      327: {
                    328:        db_task_printsym(loc, DB_STGY_PROC, task);
                    329:        db_printf(":\t");
                    330:        (void) db_disasm(loc, TRUE, task);
                    331: }
                    332: 
                    333: void
                    334: db_strcpy(dst, src)
1.1.1.4 ! root      335:        char *dst;
        !           336:        const char *src;
1.1       root      337: {
1.1.1.3   root      338:        while ((*dst++ = *src++))
1.1       root      339:            ;
                    340: }
                    341: 
                    342: /*
                    343:  * Search for a value in memory.
                    344:  * Syntax: search [/bhl] addr value [mask] [,count] [thread]
                    345:  */
                    346: void
1.1.1.4 ! root      347: db_search_cmd(void)
1.1       root      348: {
                    349:        int             t;
                    350:        db_addr_t       addr;
                    351:        int             size = 0;
                    352:        db_expr_t       value;
                    353:        db_expr_t       mask;
                    354:        db_addr_t       count;
                    355:        thread_t        thread;
                    356:        boolean_t       thread_flag = FALSE;
1.1.1.4 ! root      357:        char            *p;
1.1       root      358: 
                    359:        t = db_read_token();
                    360:        if (t == tSLASH) {
                    361:            t = db_read_token();
                    362:            if (t != tIDENT) {
                    363:              bad_modifier:
                    364:                db_printf("Bad modifier \"/%s\"\n", db_tok_string);
                    365:                db_flush_lex();
                    366:                return;
                    367:            }
                    368: 
                    369:            for (p = db_tok_string; *p; p++) {
                    370:                switch(*p) {
                    371:                case 'b':
                    372:                    size = sizeof(char);
                    373:                    break;
                    374:                case 'h':
                    375:                    size = sizeof(short);
                    376:                    break;
                    377:                case 'l':
                    378:                    size = sizeof(long);
                    379:                    break;
                    380:                case 't':
                    381:                    thread_flag = TRUE;
                    382:                    break;
                    383:                default:
                    384:                    goto bad_modifier;
                    385:                }
                    386:            }
                    387:        } else {
                    388:            db_unread_token(t);
                    389:            size = sizeof(int);
                    390:        }
                    391: 
1.1.1.4 ! root      392:        if (!db_expression((db_expr_t *)&addr)) {
1.1       root      393:            db_printf("Address missing\n");
                    394:            db_flush_lex();
                    395:            return;
                    396:        }
                    397: 
                    398:        if (!db_expression(&value)) {
                    399:            db_printf("Value missing\n");
                    400:            db_flush_lex();
                    401:            return;
                    402:        }
                    403: 
                    404:        if (!db_expression(&mask))
                    405:            mask = ~0;
                    406: 
                    407:        t = db_read_token();
                    408:        if (t == tCOMMA) {
1.1.1.4 ! root      409:            if (!db_expression((db_expr_t *)&count)) {
1.1       root      410:                db_printf("Count missing\n");
                    411:                db_flush_lex();
                    412:                return;
                    413:            }
                    414:        } else {
                    415:            db_unread_token(t);
                    416:            count = -1;         /* effectively forever */
                    417:        }
                    418:        if (thread_flag) {
                    419:            if (!db_get_next_thread(&thread, 0))
                    420:                return;
                    421:        } else
                    422:            thread = THREAD_NULL;
                    423: 
                    424:        db_search(addr, size, value, mask, count, db_thread_to_task(thread));
                    425: }
                    426: 
                    427: void
1.1.1.4 ! root      428: db_search(
        !           429:        db_addr_t       addr,
        !           430:        int             size,
        !           431:        db_expr_t       value,
        !           432:        db_expr_t       mask,
        !           433:        unsigned int    count,
        !           434:        task_t          task)
1.1       root      435: {
                    436:        while (count-- != 0) {
                    437:                db_prev = addr;
1.1.1.4 ! root      438:                if ((db_get_task_value(addr, size, FALSE, task) & mask) == value)
1.1       root      439:                        break;
                    440:                addr += size;
                    441:        }
                    442:        db_next = addr;
                    443: }
                    444: 
                    445: #define DB_XCDUMP_NC   16
                    446: 
                    447: int
1.1.1.4 ! root      448: db_xcdump(
        !           449:        db_addr_t       addr,
        !           450:        int             size,
        !           451:        int             count,
        !           452:        task_t          task)
1.1       root      453: {
1.1.1.4 ! root      454:        int             i, n;
1.1       root      455:        db_expr_t       value;
                    456:        int             bcount;
                    457:        db_addr_t       off;
                    458:        char            *name;
                    459:        char            data[DB_XCDUMP_NC];
                    460: 
                    461:        db_find_task_sym_and_offset(addr, &name, &off, task);
                    462:        for (n = count*size; n > 0; n -= bcount) {
                    463:            db_prev = addr;
                    464:            if (off == 0) {
                    465:                db_printf("%s:\n", name);
                    466:                off = -1;
                    467:            }
                    468:            db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr,
                    469:                        (size != 1)? " ": "");
                    470:            bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n);
                    471:            if (trunc_page(addr) != trunc_page(addr+bcount-1)) {
                    472:                db_addr_t next_page_addr = trunc_page(addr+bcount-1);
                    473:                if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task))
                    474:                    bcount = next_page_addr - addr;
                    475:            }
1.1.1.3   root      476:            db_read_bytes(addr, bcount, data, task);
1.1       root      477:            for (i = 0; i < bcount && off != 0; i += size) {
                    478:                if (i % 4 == 0)
                    479:                        db_printf(" ");
                    480:                value = db_get_task_value(addr, size, FALSE, task);
                    481:                db_printf("%0*x ", size*2, value);
                    482:                addr += size;
                    483:                db_find_task_sym_and_offset(addr, &name, &off, task);
                    484:            }
                    485:            db_printf("%*s",
                    486:                        ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4,
                    487:                         "");
                    488:            bcount = i;
                    489:            db_printf("%s*", (size != 1)? " ": "");
                    490:            for (i = 0; i < bcount; i++) {
                    491:                value = data[i];
                    492:                db_printf("%c", (value >= ' ' && value <= '~')? value: '.');
                    493:            }
                    494:            db_printf("*\n");
                    495:        }
                    496:        return(addr);
                    497: }
                    498: 
1.1.1.2   root      499: #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.