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

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