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

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.3 ! root       57: #include <kern/debug.h>
1.1       root       58: #include <kern/thread.h>
                     59: #include <ipc/ipc_pset.h> /* 4proto */
                     60: #include <ipc/ipc_port.h> /* 4proto */
                     61: 
1.1.1.3 ! root       62: #include <vm/vm_print.h>
        !            63: #include <ipc/ipc_print.h>
        !            64: #include <kern/lock.h>
1.1       root       65: 
                     66: /*
                     67:  * Exported global variables
                     68:  */
                     69: boolean_t      db_cmd_loop_done;
                     70: jmp_buf_t      *db_recover = 0;
                     71: db_addr_t      db_dot;
                     72: db_addr_t      db_last_addr;
                     73: db_addr_t      db_prev;
                     74: db_addr_t      db_next;
                     75: 
                     76: /*
                     77:  * if 'ed' style: 'dot' is set at start of last item printed,
                     78:  * and '+' points to next line.
                     79:  * Otherwise: 'dot' points to next item, '..' points to last.
                     80:  */
                     81: boolean_t      db_ed_style = TRUE;
                     82: 
                     83: /*
                     84:  * Results of command search.
                     85:  */
                     86: #define        CMD_UNIQUE      0
                     87: #define        CMD_FOUND       1
                     88: #define        CMD_NONE        2
                     89: #define        CMD_AMBIGUOUS   3
                     90: #define        CMD_HELP        4
                     91: 
                     92: /*
                     93:  * Search for command prefix.
                     94:  */
                     95: int
                     96: db_cmd_search(name, table, cmdp)
                     97:        char *          name;
                     98:        struct db_command       *table;
                     99:        struct db_command       **cmdp; /* out */
                    100: {
                    101:        struct db_command       *cmd;
                    102:        int             result = CMD_NONE;
                    103: 
                    104:        for (cmd = table; cmd->name != 0; cmd++) {
                    105:            register char *lp;
                    106:            register char *rp;
                    107:            register int  c;
                    108: 
                    109:            lp = name;
                    110:            rp = cmd->name;
                    111:            while ((c = *lp) == *rp) {
                    112:                if (c == 0) {
                    113:                    /* complete match */
                    114:                    *cmdp = cmd;
                    115:                    return (CMD_UNIQUE);
                    116:                }
                    117:                lp++;
                    118:                rp++;
                    119:            }
                    120:            if (c == 0) {
                    121:                /* end of name, not end of command -
                    122:                   partial match */
                    123:                if (result == CMD_FOUND) {
                    124:                    result = CMD_AMBIGUOUS;
                    125:                    /* but keep looking for a full match -
                    126:                       this lets us match single letters */
                    127:                }
                    128:                else {
                    129:                    *cmdp = cmd;
                    130:                    result = CMD_FOUND;
                    131:                }
                    132:            }
                    133:        }
                    134:        if (result == CMD_NONE) {
                    135:            /* check for 'help' */
                    136:            if (!strncmp(name, "help", strlen(name)))
                    137:                result = CMD_HELP;
                    138:        }
                    139:        return (result);
                    140: }
                    141: 
                    142: void
                    143: db_cmd_list(table)
                    144:        struct db_command *table;
                    145: {
                    146:        register struct db_command *cmd;
                    147: 
                    148:        for (cmd = table; cmd->name != 0; cmd++) {
                    149:            db_printf("%-12s", cmd->name);
                    150:            db_end_line();
                    151:        }
                    152: }
                    153: 
                    154: void
                    155: db_command(last_cmdp, cmd_table)
                    156:        struct db_command       **last_cmdp;    /* IN_OUT */
                    157:        struct db_command       *cmd_table;
                    158: {
                    159:        struct db_command       *cmd;
                    160:        int             t;
                    161:        char            modif[TOK_STRING_SIZE];
                    162:        db_expr_t       addr, count;
                    163:        boolean_t       have_addr = FALSE;
                    164:        int             result;
                    165: 
                    166:        t = db_read_token();
                    167:        if (t == tEOL || t == tSEMI_COLON) {
                    168:            /* empty line repeats last command, at 'next' */
                    169:            cmd = *last_cmdp;
                    170:            addr = (db_expr_t)db_next;
                    171:            have_addr = FALSE;
                    172:            count = 1;
                    173:            modif[0]  = '\0';
                    174:            if (t == tSEMI_COLON)
                    175:                db_unread_token(t);
                    176:        }
                    177:        else if (t == tEXCL) {
                    178:            void db_fncall();
                    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
                    296: db_command_list(last_cmdp, cmd_table)
                    297:        struct db_command       **last_cmdp;    /* IN_OUT */
                    298:        struct db_command       *cmd_table;
                    299: {
                    300:        void db_skip_to_eol();
                    301: 
                    302:        do {
                    303:            db_command(last_cmdp, cmd_table);
                    304:            db_skip_to_eol();
                    305:        } while (db_read_token() == tSEMI_COLON && db_cmd_loop_done == 0);
                    306: }
                    307: 
                    308: struct db_command db_show_all_cmds[] = {
                    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 },
                    331:        { (char *)0, }
                    332: };
                    333: 
                    334: void           db_help_cmd();
1.1.1.3 ! root      335: extern void    db_stack_trace_cmd();
1.1       root      336: extern void    db_reset_cpu();
                    337: 
                    338: struct db_command db_command_table[] = {
                    339: #ifdef DB_MACHINE_COMMANDS
                    340:   /* this must be the first entry, if it exists */
                    341:        { "machine",    0,                      0,              0},
                    342: #endif
                    343:        { "print",      db_print_cmd,           CS_OWN,         0 },
                    344:        { "examine",    db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
                    345:        { "x",          db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
                    346:        { "xf",         db_examine_forward,     CS_SET_DOT,     0 },
                    347:        { "xb",         db_examine_backward,    CS_SET_DOT,     0 },
                    348:        { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
                    349:        { "set",        db_set_cmd,             CS_OWN,         0 },
                    350:        { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
                    351:        { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
                    352:        { "delete",     db_delete_cmd,          CS_OWN,         0 },
                    353:        { "d",          db_delete_cmd,          CS_OWN,         0 },
                    354:        { "break",      db_breakpoint_cmd,      CS_MORE,        0 },
                    355:        { "dwatch",     db_deletewatch_cmd,     CS_MORE,        0 },
                    356:        { "watch",      db_watchpoint_cmd,      CS_MORE,        0 },
                    357:        { "step",       db_single_step_cmd,     0,              0 },
                    358:        { "s",          db_single_step_cmd,     0,              0 },
                    359:        { "continue",   db_continue_cmd,        0,              0 },
                    360:        { "c",          db_continue_cmd,        0,              0 },
                    361:        { "until",      db_trace_until_call_cmd,0,              0 },
                    362:        { "next",       db_trace_until_matching_cmd,0,          0 },
                    363:        { "match",      db_trace_until_matching_cmd,0,          0 },
                    364:        { "trace",      db_stack_trace_cmd,     0,              0 },
                    365:        { "cond",       db_cond_cmd,            CS_OWN,         0 },
                    366:        { "call",       db_fncall,              CS_OWN,         0 },
                    367:        { "macro",      db_def_macro_cmd,       CS_OWN,         0 },
                    368:        { "dmacro",     db_del_macro_cmd,       CS_OWN,         0 },
                    369:        { "show",       0,                      0,      db_show_cmds },
                    370:        { "reset",      db_reset_cpu,           0,              0 },
                    371:        { "reboot",     db_reset_cpu,           0,              0 },
                    372:        { (char *)0, }
                    373: };
                    374: 
                    375: #ifdef DB_MACHINE_COMMANDS
                    376: 
                    377: /* this function should be called to install the machine dependent
                    378:    commands. It should be called before the debugger is enabled  */
                    379: void db_machine_commands_install(ptr)
                    380: struct db_command *ptr;
                    381: {
                    382:   db_command_table[0].more = ptr;
                    383:   return;
                    384: }
                    385: 
                    386: #endif
                    387: 
                    388: 
                    389: struct db_command      *db_last_command = 0;
                    390: 
                    391: void
                    392: db_help_cmd()
                    393: {
                    394:        struct db_command *cmd = db_command_table;
                    395: 
                    396:        while (cmd->name != 0) {
                    397:            db_printf("%-12s", cmd->name);
                    398:            db_end_line();
                    399:            cmd++;
                    400:        }
                    401: }
                    402: 
                    403: int    (*ddb_display)();
                    404: 
                    405: void
1.1.1.3 ! root      406: db_command_loop(void)
1.1       root      407: {
                    408:        jmp_buf_t db_jmpbuf;
                    409:        jmp_buf_t *prev = db_recover;
                    410:        extern int db_output_line;
                    411:        extern int db_macro_level;
                    412: 
                    413:        /*
                    414:         * Initialize 'prev' and 'next' to dot.
                    415:         */
                    416:        db_prev = db_dot;
                    417:        db_next = db_dot;
                    418: 
                    419:        if (ddb_display)
                    420:                (*ddb_display)();
                    421: 
                    422:        db_cmd_loop_done = 0;
                    423:        while (!db_cmd_loop_done) {
                    424:            (void) _setjmp(db_recover = &db_jmpbuf);
                    425:            db_macro_level = 0;
                    426:            if (db_print_position() != 0)
                    427:                db_printf("\n");
                    428:            db_output_line = 0;
                    429:            db_printf("db%s", (db_default_thread)? "t": "");
                    430: #if    NCPUS > 1
                    431:            db_printf("{%d}", cpu_number());
                    432: #endif
                    433:            db_printf("> ");
                    434: 
                    435:            (void) db_read_line("!!");
                    436:            db_command_list(&db_last_command, db_command_table);
                    437:        }
                    438: 
                    439:        db_recover = prev;
                    440: }
                    441: 
                    442: boolean_t
                    443: db_exec_cmd_nest(cmd, size)
                    444:        char *cmd;
                    445:        int  size;
                    446: {
                    447:        struct db_lex_context lex_context;
                    448: 
                    449:        db_cmd_loop_done = 0;
                    450:        if (cmd) {
                    451:            db_save_lex_context(&lex_context);
                    452:            db_switch_input(cmd, size /**OLD, &lex_context OLD**/);
                    453:        }
                    454:        db_command_list(&db_last_command, db_command_table);
                    455:        if (cmd)
                    456:            db_restore_lex_context(&lex_context);
                    457:        return(db_cmd_loop_done == 0);
                    458: }
                    459: 
                    460: void db_error(s)
                    461:        char *s;
                    462: {
                    463:        extern int db_macro_level;
                    464: 
                    465:        db_macro_level = 0;
                    466:        if (db_recover) {
                    467:            if (s)
                    468:                db_printf(s);
                    469:            db_flush_lex();
                    470:            _longjmp(db_recover, 1);
                    471:        }
                    472:        else
                    473:        {
                    474:            if (s)
                    475:                db_printf(s);
                    476:            panic("db_error");
                    477:        }
                    478: }
                    479: 
                    480: /*
                    481:  * Call random function:
                    482:  * !expr(arg,arg,arg)
                    483:  */
                    484: void
                    485: db_fncall()
                    486: {
                    487:        db_expr_t       fn_addr;
                    488: #define        MAXARGS         11
                    489:        db_expr_t       args[MAXARGS];
                    490:        int             nargs = 0;
                    491:        db_expr_t       retval;
                    492:        db_expr_t       (*func)();
                    493:        int             t;
                    494: 
                    495:        if (!db_expression(&fn_addr)) {
                    496:            db_printf("Bad function \"%s\"\n", db_tok_string);
                    497:            db_flush_lex();
                    498:            return;
                    499:        }
                    500:        func = (db_expr_t (*) ()) fn_addr;
                    501: 
                    502:        t = db_read_token();
                    503:        if (t == tLPAREN) {
                    504:            if (db_expression(&args[0])) {
                    505:                nargs++;
                    506:                while ((t = db_read_token()) == tCOMMA) {
                    507:                    if (nargs == MAXARGS) {
                    508:                        db_printf("Too many arguments\n");
                    509:                        db_flush_lex();
                    510:                        return;
                    511:                    }
                    512:                    if (!db_expression(&args[nargs])) {
                    513:                        db_printf("Argument missing\n");
                    514:                        db_flush_lex();
                    515:                        return;
                    516:                    }
                    517:                    nargs++;
                    518:                }
                    519:                db_unread_token(t);
                    520:            }
                    521:            if (db_read_token() != tRPAREN) {
                    522:                db_printf("?\n");
                    523:                db_flush_lex();
                    524:                return;
                    525:            }
                    526:        }
                    527:        while (nargs < MAXARGS) {
                    528:            args[nargs++] = 0;
                    529:        }
                    530: 
                    531:        retval = (*func)(args[0], args[1], args[2], args[3], args[4],
                    532:                         args[5], args[6], args[7], args[8], args[9] );
                    533:        db_printf(" %#N\n", retval);
                    534: }
                    535: 
                    536: boolean_t
                    537: db_option(modif, option)
                    538:        char    *modif;
                    539:        int     option;
                    540: {
                    541:        register char *p;
                    542: 
                    543:        for (p = modif; *p; p++)
                    544:            if (*p == option)
                    545:                return(TRUE);
                    546:        return(FALSE);
                    547: }
                    548: 
1.1.1.2   root      549: #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.