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

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991 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: 
                     33: /*
                     34:  * Command dispatcher.
                     35:  */
                     36: 
1.1.1.3   root       37: #include <string.h>
1.1       root       38: #include <mach/boolean.h>
                     39: #include <machine/db_machdep.h>
                     40: 
                     41: #include <ddb/db_lex.h>
                     42: #include <ddb/db_output.h>
                     43: #include <ddb/db_command.h>
                     44: #include <ddb/db_task_thread.h>
1.1.1.3   root       45: #include <ddb/db_macro.h>
                     46: #include <ddb/db_expr.h>
                     47: #include <ddb/db_examine.h>
                     48: #include <ddb/db_print.h>
                     49: #include <ddb/db_break.h>
                     50: #include <ddb/db_watch.h>
                     51: #include <ddb/db_variables.h>
                     52: #include <ddb/db_write_cmd.h>
                     53: #include <ddb/db_run.h>
                     54: #include <ddb/db_cond.h>
1.1       root       55: 
                     56: #include <machine/setjmp.h>
1.1.1.4 ! root       57: #include <machine/db_interface.h>
1.1.1.3   root       58: #include <kern/debug.h>
1.1       root       59: #include <kern/thread.h>
                     60: #include <ipc/ipc_pset.h> /* 4proto */
                     61: #include <ipc/ipc_port.h> /* 4proto */
                     62: 
1.1.1.3   root       63: #include <vm/vm_print.h>
                     64: #include <ipc/ipc_print.h>
                     65: #include <kern/lock.h>
1.1       root       66: 
                     67: /*
                     68:  * Exported global variables
                     69:  */
                     70: boolean_t      db_cmd_loop_done;
                     71: jmp_buf_t      *db_recover = 0;
                     72: db_addr_t      db_dot;
                     73: db_addr_t      db_last_addr;
                     74: db_addr_t      db_prev;
                     75: db_addr_t      db_next;
                     76: 
                     77: /*
                     78:  * if 'ed' style: 'dot' is set at start of last item printed,
                     79:  * and '+' points to next line.
                     80:  * Otherwise: 'dot' points to next item, '..' points to last.
                     81:  */
                     82: boolean_t      db_ed_style = TRUE;
                     83: 
                     84: /*
                     85:  * Results of command search.
                     86:  */
                     87: #define        CMD_UNIQUE      0
                     88: #define        CMD_FOUND       1
                     89: #define        CMD_NONE        2
                     90: #define        CMD_AMBIGUOUS   3
                     91: #define        CMD_HELP        4
                     92: 
                     93: /*
                     94:  * Search for command prefix.
                     95:  */
                     96: int
                     97: db_cmd_search(name, table, cmdp)
1.1.1.4 ! root       98:        const char *            name;
        !            99:        const struct db_command *table;
        !           100:        const struct db_command **cmdp; /* out */
1.1       root      101: {
1.1.1.4 ! root      102:        const struct db_command *cmd;
1.1       root      103:        int             result = CMD_NONE;
                    104: 
                    105:        for (cmd = table; cmd->name != 0; cmd++) {
1.1.1.4 ! root      106:            const char *lp;
        !           107:            char *rp;
        !           108:            int  c;
1.1       root      109: 
                    110:            lp = name;
                    111:            rp = cmd->name;
                    112:            while ((c = *lp) == *rp) {
                    113:                if (c == 0) {
                    114:                    /* complete match */
                    115:                    *cmdp = cmd;
                    116:                    return (CMD_UNIQUE);
                    117:                }
                    118:                lp++;
                    119:                rp++;
                    120:            }
                    121:            if (c == 0) {
                    122:                /* end of name, not end of command -
                    123:                   partial match */
                    124:                if (result == CMD_FOUND) {
                    125:                    result = CMD_AMBIGUOUS;
                    126:                    /* but keep looking for a full match -
                    127:                       this lets us match single letters */
                    128:                }
                    129:                else {
                    130:                    *cmdp = cmd;
                    131:                    result = CMD_FOUND;
                    132:                }
                    133:            }
                    134:        }
                    135:        if (result == CMD_NONE) {
                    136:            /* check for 'help' */
                    137:            if (!strncmp(name, "help", strlen(name)))
                    138:                result = CMD_HELP;
                    139:        }
                    140:        return (result);
                    141: }
                    142: 
                    143: void
                    144: db_cmd_list(table)
1.1.1.4 ! root      145:        const struct db_command *table;
1.1       root      146: {
1.1.1.4 ! root      147:        const struct db_command *cmd;
1.1       root      148: 
                    149:        for (cmd = table; cmd->name != 0; cmd++) {
                    150:            db_printf("%-12s", cmd->name);
                    151:            db_end_line();
                    152:        }
                    153: }
                    154: 
                    155: void
1.1.1.4 ! root      156: db_command(
        !           157:        struct db_command       **last_cmdp,    /* IN_OUT */
        !           158:        struct db_command       *cmd_table)
1.1       root      159: {
                    160:        struct db_command       *cmd;
                    161:        int             t;
                    162:        char            modif[TOK_STRING_SIZE];
                    163:        db_expr_t       addr, count;
                    164:        boolean_t       have_addr = FALSE;
                    165:        int             result;
                    166: 
                    167:        t = db_read_token();
                    168:        if (t == tEOL || t == tSEMI_COLON) {
                    169:            /* empty line repeats last command, at 'next' */
                    170:            cmd = *last_cmdp;
                    171:            addr = (db_expr_t)db_next;
                    172:            have_addr = FALSE;
                    173:            count = 1;
                    174:            modif[0]  = '\0';
                    175:            if (t == tSEMI_COLON)
                    176:                db_unread_token(t);
                    177:        }
                    178:        else if (t == tEXCL) {
                    179:            db_fncall();
                    180:            return;
                    181:        }
                    182:        else if (t != tIDENT) {
                    183:            db_printf("?\n");
                    184:            db_flush_lex();
                    185:            return;
                    186:        }
                    187:        else {
                    188:            /*
                    189:             * Search for command
                    190:             */
                    191:            while (cmd_table) {
                    192:                result = db_cmd_search(db_tok_string,
                    193:                                       cmd_table,
                    194:                                       &cmd);
                    195:                switch (result) {
                    196:                    case CMD_NONE:
                    197:                        if (db_exec_macro(db_tok_string) == 0)
                    198:                            return;
                    199:                        db_printf("No such command \"%s\"\n", db_tok_string);
                    200:                        db_flush_lex();
                    201:                        return;
                    202:                    case CMD_AMBIGUOUS:
                    203:                        db_printf("Ambiguous\n");
                    204:                        db_flush_lex();
                    205:                        return;
                    206:                    case CMD_HELP:
                    207:                        db_cmd_list(cmd_table);
                    208:                        db_flush_lex();
                    209:                        return;
                    210:                    default:
                    211:                        break;
                    212:                }
                    213:                if ((cmd_table = cmd->more) != 0) {
                    214:                    t = db_read_token();
                    215:                    if (t != tIDENT) {
                    216:                        db_cmd_list(cmd_table);
                    217:                        db_flush_lex();
                    218:                        return;
                    219:                    }
                    220:                }
                    221:            }
                    222: 
                    223:            if ((cmd->flag & CS_OWN) == 0) {
                    224:                /*
                    225:                 * Standard syntax:
                    226:                 * command [/modifier] [addr] [,count]
                    227:                 */
                    228:                t = db_read_token();
                    229:                if (t == tSLASH) {
                    230:                    t = db_read_token();
                    231:                    if (t != tIDENT) {
                    232:                        db_printf("Bad modifier \"/%s\"\n", db_tok_string);
                    233:                        db_flush_lex();
                    234:                        return;
                    235:                    }
                    236:                    db_strcpy(modif, db_tok_string);
                    237:                }
                    238:                else {
                    239:                    db_unread_token(t);
                    240:                    modif[0] = '\0';
                    241:                }
                    242: 
                    243:                if (db_expression(&addr)) {
                    244:                    db_dot = (db_addr_t) addr;
                    245:                    db_last_addr = db_dot;
                    246:                    have_addr = TRUE;
                    247:                }
                    248:                else {
                    249:                    addr = (db_expr_t) db_dot;
                    250:                    have_addr = FALSE;
                    251:                }
                    252:                t = db_read_token();
                    253:                if (t == tCOMMA) {
                    254:                    if (!db_expression(&count)) {
                    255:                        db_printf("Count missing after ','\n");
                    256:                        db_flush_lex();
                    257:                        return;
                    258:                    }
                    259:                }
                    260:                else {
                    261:                    db_unread_token(t);
                    262:                    count = -1;
                    263:                }
                    264:            }
                    265:        }
                    266:        *last_cmdp = cmd;
                    267:        if (cmd != 0) {
                    268:            /*
                    269:             * Execute the command.
                    270:             */
                    271:            (*cmd->fcn)(addr, have_addr, count, modif);
                    272: 
                    273:            if (cmd->flag & CS_SET_DOT) {
                    274:                /*
                    275:                 * If command changes dot, set dot to
                    276:                 * previous address displayed (if 'ed' style).
                    277:                 */
                    278:                if (db_ed_style) {
                    279:                    db_dot = db_prev;
                    280:                }
                    281:                else {
                    282:                    db_dot = db_next;
                    283:                }
                    284:            }
                    285:            else {
                    286:                /*
                    287:                 * If command does not change dot,
                    288:                 * set 'next' location to be the same.
                    289:                 */
                    290:                db_next = db_dot;
                    291:            }
                    292:        }
                    293: }
                    294: 
                    295: void
1.1.1.4 ! root      296: db_command_list(
        !           297:        struct db_command       **last_cmdp,    /* IN_OUT */
        !           298:        struct db_command       *cmd_table)
1.1       root      299: {
                    300:        do {
                    301:            db_command(last_cmdp, cmd_table);
                    302:            db_skip_to_eol();
1.1.1.4 ! root      303:        } while (db_read_token() == tSEMI_COLON && db_cmd_loop_done == FALSE);
1.1       root      304: }
                    305: 
                    306: struct db_command db_show_all_cmds[] = {
1.1.1.4 ! root      307:        { "tasks",      db_show_all_tasks,      0,      0 },
1.1       root      308:        { "threads",    db_show_all_threads,    0,      0 },
                    309:        { "slocks",     db_show_all_slocks,     0,      0 },
                    310:        { (char *)0 }
                    311: };
                    312: 
                    313: struct db_command db_show_cmds[] = {
                    314:        { "all",        0,                      0,      db_show_all_cmds },
                    315:        { "registers",  db_show_regs,           0,      0 },
                    316:        { "breaks",     db_listbreak_cmd,       0,      0 },
                    317:        { "watches",    db_listwatch_cmd,       0,      0 },
                    318:        { "thread",     db_show_one_thread,     0,      0 },
                    319:        { "task",       db_show_one_task,       0,      0 },
                    320:        { "macro",      db_show_macro,          CS_OWN, 0 },
                    321:        { "map",        vm_map_print,           0,      0 },
                    322:        { "object",     vm_object_print,        0,      0 },
                    323:        { "page",       vm_page_print,          0,      0 },
                    324:        { "copy",       vm_map_copy_print,      0,      0 },
                    325:        { "port",       ipc_port_print,         0,      0 },
                    326:        { "pset",       ipc_pset_print,         0,      0 },
                    327:        { "kmsg",       ipc_kmsg_print,         0,      0 },
                    328:        { "msg",        ipc_msg_print,          0,      0 },
                    329:        { "ipc_port",   db_show_port_id,        0,      0 },
                    330:        { (char *)0, }
                    331: };
                    332: 
                    333: struct db_command db_command_table[] = {
                    334: #ifdef DB_MACHINE_COMMANDS
                    335:   /* this must be the first entry, if it exists */
                    336:        { "machine",    0,                      0,              0},
                    337: #endif
                    338:        { "print",      db_print_cmd,           CS_OWN,         0 },
                    339:        { "examine",    db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
                    340:        { "x",          db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
                    341:        { "xf",         db_examine_forward,     CS_SET_DOT,     0 },
                    342:        { "xb",         db_examine_backward,    CS_SET_DOT,     0 },
                    343:        { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
                    344:        { "set",        db_set_cmd,             CS_OWN,         0 },
                    345:        { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
                    346:        { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
                    347:        { "delete",     db_delete_cmd,          CS_OWN,         0 },
                    348:        { "d",          db_delete_cmd,          CS_OWN,         0 },
                    349:        { "break",      db_breakpoint_cmd,      CS_MORE,        0 },
                    350:        { "dwatch",     db_deletewatch_cmd,     CS_MORE,        0 },
                    351:        { "watch",      db_watchpoint_cmd,      CS_MORE,        0 },
                    352:        { "step",       db_single_step_cmd,     0,              0 },
                    353:        { "s",          db_single_step_cmd,     0,              0 },
                    354:        { "continue",   db_continue_cmd,        0,              0 },
                    355:        { "c",          db_continue_cmd,        0,              0 },
                    356:        { "until",      db_trace_until_call_cmd,0,              0 },
                    357:        { "next",       db_trace_until_matching_cmd,0,          0 },
                    358:        { "match",      db_trace_until_matching_cmd,0,          0 },
                    359:        { "trace",      db_stack_trace_cmd,     0,              0 },
                    360:        { "cond",       db_cond_cmd,            CS_OWN,         0 },
                    361:        { "call",       db_fncall,              CS_OWN,         0 },
                    362:        { "macro",      db_def_macro_cmd,       CS_OWN,         0 },
                    363:        { "dmacro",     db_del_macro_cmd,       CS_OWN,         0 },
                    364:        { "show",       0,                      0,      db_show_cmds },
                    365:        { "reset",      db_reset_cpu,           0,              0 },
                    366:        { "reboot",     db_reset_cpu,           0,              0 },
1.1.1.4 ! root      367:        { "halt",       db_halt_cpu,            0,              0 },
1.1       root      368:        { (char *)0, }
                    369: };
                    370: 
                    371: #ifdef DB_MACHINE_COMMANDS
                    372: 
                    373: /* this function should be called to install the machine dependent
                    374:    commands. It should be called before the debugger is enabled  */
1.1.1.4 ! root      375: void db_machine_commands_install(struct db_command *ptr)
1.1       root      376: {
                    377:   db_command_table[0].more = ptr;
                    378:   return;
                    379: }
                    380: 
1.1.1.4 ! root      381: #endif /* DB_MACHINE_COMMANDS */
1.1       root      382: 
                    383: 
                    384: struct db_command      *db_last_command = 0;
                    385: 
                    386: void
1.1.1.4 ! root      387: db_help_cmd(void)
1.1       root      388: {
                    389:        struct db_command *cmd = db_command_table;
                    390: 
                    391:        while (cmd->name != 0) {
                    392:            db_printf("%-12s", cmd->name);
                    393:            db_end_line();
                    394:            cmd++;
                    395:        }
                    396: }
                    397: 
                    398: void
1.1.1.3   root      399: db_command_loop(void)
1.1       root      400: {
                    401:        jmp_buf_t db_jmpbuf;
                    402:        jmp_buf_t *prev = db_recover;
                    403:        extern int db_output_line;
                    404:        extern int db_macro_level;
                    405: 
                    406:        /*
                    407:         * Initialize 'prev' and 'next' to dot.
                    408:         */
                    409:        db_prev = db_dot;
                    410:        db_next = db_dot;
                    411: 
1.1.1.4 ! root      412:        db_cmd_loop_done = FALSE;
1.1       root      413:        while (!db_cmd_loop_done) {
                    414:            (void) _setjmp(db_recover = &db_jmpbuf);
                    415:            db_macro_level = 0;
                    416:            if (db_print_position() != 0)
                    417:                db_printf("\n");
                    418:            db_output_line = 0;
                    419:            db_printf("db%s", (db_default_thread)? "t": "");
                    420: #if    NCPUS > 1
                    421:            db_printf("{%d}", cpu_number());
                    422: #endif
                    423:            db_printf("> ");
                    424: 
                    425:            (void) db_read_line("!!");
                    426:            db_command_list(&db_last_command, db_command_table);
                    427:        }
                    428: 
                    429:        db_recover = prev;
                    430: }
                    431: 
                    432: boolean_t
1.1.1.4 ! root      433: db_exec_cmd_nest(
        !           434:        char *cmd,
        !           435:        int  size)
1.1       root      436: {
                    437:        struct db_lex_context lex_context;
                    438: 
1.1.1.4 ! root      439:        db_cmd_loop_done = FALSE;
1.1       root      440:        if (cmd) {
                    441:            db_save_lex_context(&lex_context);
                    442:            db_switch_input(cmd, size /**OLD, &lex_context OLD**/);
                    443:        }
                    444:        db_command_list(&db_last_command, db_command_table);
                    445:        if (cmd)
                    446:            db_restore_lex_context(&lex_context);
1.1.1.4 ! root      447:        return(db_cmd_loop_done == FALSE);
1.1       root      448: }
                    449: 
                    450: void db_error(s)
1.1.1.4 ! root      451:        const char *s;
1.1       root      452: {
                    453:        extern int db_macro_level;
                    454: 
                    455:        db_macro_level = 0;
                    456:        if (db_recover) {
                    457:            if (s)
                    458:                db_printf(s);
                    459:            db_flush_lex();
                    460:            _longjmp(db_recover, 1);
                    461:        }
                    462:        else
                    463:        {
                    464:            if (s)
                    465:                db_printf(s);
                    466:            panic("db_error");
                    467:        }
                    468: }
                    469: 
                    470: /*
                    471:  * Call random function:
                    472:  * !expr(arg,arg,arg)
                    473:  */
                    474: void
1.1.1.4 ! root      475: db_fncall(void)
1.1       root      476: {
                    477:        db_expr_t       fn_addr;
                    478: #define        MAXARGS         11
                    479:        db_expr_t       args[MAXARGS];
                    480:        int             nargs = 0;
                    481:        db_expr_t       retval;
                    482:        db_expr_t       (*func)();
                    483:        int             t;
                    484: 
                    485:        if (!db_expression(&fn_addr)) {
                    486:            db_printf("Bad function \"%s\"\n", db_tok_string);
                    487:            db_flush_lex();
                    488:            return;
                    489:        }
                    490:        func = (db_expr_t (*) ()) fn_addr;
                    491: 
                    492:        t = db_read_token();
                    493:        if (t == tLPAREN) {
                    494:            if (db_expression(&args[0])) {
                    495:                nargs++;
                    496:                while ((t = db_read_token()) == tCOMMA) {
                    497:                    if (nargs == MAXARGS) {
                    498:                        db_printf("Too many arguments\n");
                    499:                        db_flush_lex();
                    500:                        return;
                    501:                    }
                    502:                    if (!db_expression(&args[nargs])) {
                    503:                        db_printf("Argument missing\n");
                    504:                        db_flush_lex();
                    505:                        return;
                    506:                    }
                    507:                    nargs++;
                    508:                }
                    509:                db_unread_token(t);
                    510:            }
                    511:            if (db_read_token() != tRPAREN) {
                    512:                db_printf("?\n");
                    513:                db_flush_lex();
                    514:                return;
                    515:            }
                    516:        }
                    517:        while (nargs < MAXARGS) {
                    518:            args[nargs++] = 0;
                    519:        }
                    520: 
                    521:        retval = (*func)(args[0], args[1], args[2], args[3], args[4],
                    522:                         args[5], args[6], args[7], args[8], args[9] );
                    523:        db_printf(" %#N\n", retval);
                    524: }
                    525: 
1.1.1.4 ! root      526: boolean_t __attribute__ ((pure))
1.1       root      527: db_option(modif, option)
1.1.1.4 ! root      528:        const char      *modif;
        !           529:        int             option;
1.1       root      530: {
1.1.1.4 ! root      531:        const char *p;
1.1       root      532: 
                    533:        for (p = modif; *p; p++)
                    534:            if (*p == option)
                    535:                return(TRUE);
                    536:        return(FALSE);
                    537: }
                    538: 
1.1.1.2   root      539: #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.