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

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     Author: David B. Golub, Carnegie Mellon University
                     28:  *     Date:   7/90
                     29:  */
                     30: 
                     31: #include "mach_kdb.h"
                     32: #if MACH_KDB
                     33: 
                     34: /*
                     35:  * Command dispatcher.
                     36:  */
                     37: #include <cpus.h>
                     38: #include <norma_ipc.h>
                     39: #include <norma_vm.h>
                     40: 
                     41: #include <mach/boolean.h>
                     42: #include <kern/strings.h>
                     43: #include <machine/db_machdep.h>
                     44: 
                     45: #include <ddb/db_lex.h>
                     46: #include <ddb/db_output.h>
                     47: #include <ddb/db_command.h>
                     48: #include <ddb/db_task_thread.h>
                     49: 
                     50: #include <machine/setjmp.h>
                     51: #include <kern/thread.h>
                     52: #include <ipc/ipc_pset.h> /* 4proto */
                     53: #include <ipc/ipc_port.h> /* 4proto */
                     54: 
                     55: 
                     56: 
                     57: /*
                     58:  * Exported global variables
                     59:  */
                     60: boolean_t      db_cmd_loop_done;
                     61: jmp_buf_t      *db_recover = 0;
                     62: db_addr_t      db_dot;
                     63: db_addr_t      db_last_addr;
                     64: db_addr_t      db_prev;
                     65: db_addr_t      db_next;
                     66: 
                     67: /*
                     68:  * if 'ed' style: 'dot' is set at start of last item printed,
                     69:  * and '+' points to next line.
                     70:  * Otherwise: 'dot' points to next item, '..' points to last.
                     71:  */
                     72: boolean_t      db_ed_style = TRUE;
                     73: 
                     74: /*
                     75:  * Results of command search.
                     76:  */
                     77: #define        CMD_UNIQUE      0
                     78: #define        CMD_FOUND       1
                     79: #define        CMD_NONE        2
                     80: #define        CMD_AMBIGUOUS   3
                     81: #define        CMD_HELP        4
                     82: 
                     83: /*
                     84:  * Search for command prefix.
                     85:  */
                     86: int
                     87: db_cmd_search(name, table, cmdp)
                     88:        char *          name;
                     89:        struct db_command       *table;
                     90:        struct db_command       **cmdp; /* out */
                     91: {
                     92:        struct db_command       *cmd;
                     93:        int             result = CMD_NONE;
                     94: 
                     95:        for (cmd = table; cmd->name != 0; cmd++) {
                     96:            register char *lp;
                     97:            register char *rp;
                     98:            register int  c;
                     99: 
                    100:            lp = name;
                    101:            rp = cmd->name;
                    102:            while ((c = *lp) == *rp) {
                    103:                if (c == 0) {
                    104:                    /* complete match */
                    105:                    *cmdp = cmd;
                    106:                    return (CMD_UNIQUE);
                    107:                }
                    108:                lp++;
                    109:                rp++;
                    110:            }
                    111:            if (c == 0) {
                    112:                /* end of name, not end of command -
                    113:                   partial match */
                    114:                if (result == CMD_FOUND) {
                    115:                    result = CMD_AMBIGUOUS;
                    116:                    /* but keep looking for a full match -
                    117:                       this lets us match single letters */
                    118:                }
                    119:                else {
                    120:                    *cmdp = cmd;
                    121:                    result = CMD_FOUND;
                    122:                }
                    123:            }
                    124:        }
                    125:        if (result == CMD_NONE) {
                    126:            /* check for 'help' */
                    127:            if (!strncmp(name, "help", strlen(name)))
                    128:                result = CMD_HELP;
                    129:        }
                    130:        return (result);
                    131: }
                    132: 
                    133: void
                    134: db_cmd_list(table)
                    135:        struct db_command *table;
                    136: {
                    137:        register struct db_command *cmd;
                    138: 
                    139:        for (cmd = table; cmd->name != 0; cmd++) {
                    140:            db_printf("%-12s", cmd->name);
                    141:            db_end_line();
                    142:        }
                    143: }
                    144: 
                    145: void
                    146: db_command(last_cmdp, cmd_table)
                    147:        struct db_command       **last_cmdp;    /* IN_OUT */
                    148:        struct db_command       *cmd_table;
                    149: {
                    150:        struct db_command       *cmd;
                    151:        int             t;
                    152:        char            modif[TOK_STRING_SIZE];
                    153:        db_expr_t       addr, count;
                    154:        boolean_t       have_addr = FALSE;
                    155:        int             result;
                    156: 
                    157:        t = db_read_token();
                    158:        if (t == tEOL || t == tSEMI_COLON) {
                    159:            /* empty line repeats last command, at 'next' */
                    160:            cmd = *last_cmdp;
                    161:            addr = (db_expr_t)db_next;
                    162:            have_addr = FALSE;
                    163:            count = 1;
                    164:            modif[0]  = '\0';
                    165:            if (t == tSEMI_COLON)
                    166:                db_unread_token(t);
                    167:        }
                    168:        else if (t == tEXCL) {
                    169:            void db_fncall();
                    170:            db_fncall();
                    171:            return;
                    172:        }
                    173:        else if (t != tIDENT) {
                    174:            db_printf("?\n");
                    175:            db_flush_lex();
                    176:            return;
                    177:        }
                    178:        else {
                    179:            /*
                    180:             * Search for command
                    181:             */
                    182:            while (cmd_table) {
                    183:                result = db_cmd_search(db_tok_string,
                    184:                                       cmd_table,
                    185:                                       &cmd);
                    186:                switch (result) {
                    187:                    case CMD_NONE:
                    188:                        if (db_exec_macro(db_tok_string) == 0)
                    189:                            return;
                    190:                        db_printf("No such command \"%s\"\n", db_tok_string);
                    191:                        db_flush_lex();
                    192:                        return;
                    193:                    case CMD_AMBIGUOUS:
                    194:                        db_printf("Ambiguous\n");
                    195:                        db_flush_lex();
                    196:                        return;
                    197:                    case CMD_HELP:
                    198:                        db_cmd_list(cmd_table);
                    199:                        db_flush_lex();
                    200:                        return;
                    201:                    default:
                    202:                        break;
                    203:                }
                    204:                if ((cmd_table = cmd->more) != 0) {
                    205:                    t = db_read_token();
                    206:                    if (t != tIDENT) {
                    207:                        db_cmd_list(cmd_table);
                    208:                        db_flush_lex();
                    209:                        return;
                    210:                    }
                    211:                }
                    212:            }
                    213: 
                    214:            if ((cmd->flag & CS_OWN) == 0) {
                    215:                /*
                    216:                 * Standard syntax:
                    217:                 * command [/modifier] [addr] [,count]
                    218:                 */
                    219:                t = db_read_token();
                    220:                if (t == tSLASH) {
                    221:                    t = db_read_token();
                    222:                    if (t != tIDENT) {
                    223:                        db_printf("Bad modifier \"/%s\"\n", db_tok_string);
                    224:                        db_flush_lex();
                    225:                        return;
                    226:                    }
                    227:                    db_strcpy(modif, db_tok_string);
                    228:                }
                    229:                else {
                    230:                    db_unread_token(t);
                    231:                    modif[0] = '\0';
                    232:                }
                    233: 
                    234:                if (db_expression(&addr)) {
                    235:                    db_dot = (db_addr_t) addr;
                    236:                    db_last_addr = db_dot;
                    237:                    have_addr = TRUE;
                    238:                }
                    239:                else {
                    240:                    addr = (db_expr_t) db_dot;
                    241:                    have_addr = FALSE;
                    242:                }
                    243:                t = db_read_token();
                    244:                if (t == tCOMMA) {
                    245:                    if (!db_expression(&count)) {
                    246:                        db_printf("Count missing after ','\n");
                    247:                        db_flush_lex();
                    248:                        return;
                    249:                    }
                    250:                }
                    251:                else {
                    252:                    db_unread_token(t);
                    253:                    count = -1;
                    254:                }
                    255:            }
                    256:        }
                    257:        *last_cmdp = cmd;
                    258:        if (cmd != 0) {
                    259:            /*
                    260:             * Execute the command.
                    261:             */
                    262:            (*cmd->fcn)(addr, have_addr, count, modif);
                    263: 
                    264:            if (cmd->flag & CS_SET_DOT) {
                    265:                /*
                    266:                 * If command changes dot, set dot to
                    267:                 * previous address displayed (if 'ed' style).
                    268:                 */
                    269:                if (db_ed_style) {
                    270:                    db_dot = db_prev;
                    271:                }
                    272:                else {
                    273:                    db_dot = db_next;
                    274:                }
                    275:            }
                    276:            else {
                    277:                /*
                    278:                 * If command does not change dot,
                    279:                 * set 'next' location to be the same.
                    280:                 */
                    281:                db_next = db_dot;
                    282:            }
                    283:        }
                    284: }
                    285: 
                    286: void
                    287: db_command_list(last_cmdp, cmd_table)
                    288:        struct db_command       **last_cmdp;    /* IN_OUT */
                    289:        struct db_command       *cmd_table;
                    290: {
                    291:        void db_skip_to_eol();
                    292: 
                    293:        do {
                    294:            db_command(last_cmdp, cmd_table);
                    295:            db_skip_to_eol();
                    296:        } while (db_read_token() == tSEMI_COLON && db_cmd_loop_done == 0);
                    297: }
                    298: 
                    299: /*
                    300:  * 'show' commands
                    301:  */
                    302: extern void    db_listbreak_cmd();
                    303: extern void    db_listwatch_cmd();
                    304: extern void    db_show_regs(), db_show_one_thread(), db_show_one_task();
                    305: extern void    db_show_all_threads();
                    306: extern void    db_show_macro();
                    307: extern void    vm_map_print(), vm_object_print(), vm_page_print();
                    308: extern void    vm_map_copy_print();
                    309: extern void    ipc_port_print(), ipc_pset_print(), db_show_all_slocks();
                    310: extern void    ipc_kmsg_print(), ipc_msg_print();
                    311: extern void    db_show_port_id();
                    312: void           db_show_help();
                    313: #if    NORMA_IPC
                    314: extern void    netipc_packet_print(), netipc_pcs_print(), db_show_all_uids();
                    315: extern void    db_show_all_proxies(), db_show_all_principals();
                    316: extern void    db_show_all_uids_verbose();
                    317: #endif NORMA_IPC
                    318: #if    NORMA_VM
                    319: extern void    xmm_obj_print(), xmm_reply_print();
                    320: #endif NORMA_VM
                    321: 
                    322: struct db_command db_show_all_cmds[] = {
                    323:        { "threads",    db_show_all_threads,    0,      0 },
                    324:        { "slocks",     db_show_all_slocks,     0,      0 },
                    325: #if    NORMA_IPC
                    326:        { "uids",       db_show_all_uids,       0,      0 },
                    327:        { "proxies",    db_show_all_proxies,    0,      0 },
                    328:        { "principals", db_show_all_principals, 0,      0 },
                    329:        { "vuids",      db_show_all_uids_verbose, 0,    0 },
                    330: #endif NORMA_IPC
                    331:        { (char *)0 }
                    332: };
                    333: 
                    334: struct db_command db_show_cmds[] = {
                    335:        { "all",        0,                      0,      db_show_all_cmds },
                    336:        { "registers",  db_show_regs,           0,      0 },
                    337:        { "breaks",     db_listbreak_cmd,       0,      0 },
                    338:        { "watches",    db_listwatch_cmd,       0,      0 },
                    339:        { "thread",     db_show_one_thread,     0,      0 },
                    340:        { "task",       db_show_one_task,       0,      0 },
                    341:        { "macro",      db_show_macro,          CS_OWN, 0 },
                    342:        { "map",        vm_map_print,           0,      0 },
                    343:        { "object",     vm_object_print,        0,      0 },
                    344:        { "page",       vm_page_print,          0,      0 },
                    345:        { "copy",       vm_map_copy_print,      0,      0 },
                    346:        { "port",       ipc_port_print,         0,      0 },
                    347:        { "pset",       ipc_pset_print,         0,      0 },
                    348:        { "kmsg",       ipc_kmsg_print,         0,      0 },
                    349:        { "msg",        ipc_msg_print,          0,      0 },
                    350:        { "ipc_port",   db_show_port_id,        0,      0 },
                    351: #if    NORMA_IPC
                    352:        { "packet",     netipc_packet_print,    0,      0 },
                    353:        { "pcs",        netipc_pcs_print,       0,      0 },
                    354: #endif NORMA_IPC
                    355: #if    NORMA_VM
                    356:        { "xmm_obj",    xmm_obj_print,          0,      0 },
                    357:        { "xmm_reply",  xmm_reply_print,        0,      0 },
                    358: #endif NORMA_VM
                    359:        { (char *)0, }
                    360: };
                    361: 
                    362: extern void    db_print_cmd(), db_examine_cmd(), db_set_cmd();
                    363: extern void    db_examine_forward(), db_examine_backward();
                    364: extern void    db_search_cmd();
                    365: extern void    db_write_cmd();
                    366: extern void    db_delete_cmd(), db_breakpoint_cmd();
                    367: extern void    db_deletewatch_cmd(), db_watchpoint_cmd();
                    368: extern void    db_single_step_cmd(), db_trace_until_call_cmd(),
                    369:                db_trace_until_matching_cmd(), db_continue_cmd();
                    370: extern void    db_stack_trace_cmd(), db_cond_cmd();
                    371: void           db_help_cmd();
                    372: void           db_def_macro_cmd(), db_del_macro_cmd();
                    373: void           db_fncall();
                    374: extern void    db_reset_cpu();
                    375: 
                    376: struct db_command db_command_table[] = {
                    377: #ifdef DB_MACHINE_COMMANDS
                    378:   /* this must be the first entry, if it exists */
                    379:        { "machine",    0,                      0,              0},
                    380: #endif
                    381:        { "print",      db_print_cmd,           CS_OWN,         0 },
                    382:        { "examine",    db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
                    383:        { "x",          db_examine_cmd,         CS_MORE|CS_SET_DOT, 0 },
                    384:        { "xf",         db_examine_forward,     CS_SET_DOT,     0 },
                    385:        { "xb",         db_examine_backward,    CS_SET_DOT,     0 },
                    386:        { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
                    387:        { "set",        db_set_cmd,             CS_OWN,         0 },
                    388:        { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
                    389:        { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
                    390:        { "delete",     db_delete_cmd,          CS_OWN,         0 },
                    391:        { "d",          db_delete_cmd,          CS_OWN,         0 },
                    392:        { "break",      db_breakpoint_cmd,      CS_MORE,        0 },
                    393:        { "dwatch",     db_deletewatch_cmd,     CS_MORE,        0 },
                    394:        { "watch",      db_watchpoint_cmd,      CS_MORE,        0 },
                    395:        { "step",       db_single_step_cmd,     0,              0 },
                    396:        { "s",          db_single_step_cmd,     0,              0 },
                    397:        { "continue",   db_continue_cmd,        0,              0 },
                    398:        { "c",          db_continue_cmd,        0,              0 },
                    399:        { "until",      db_trace_until_call_cmd,0,              0 },
                    400:        { "next",       db_trace_until_matching_cmd,0,          0 },
                    401:        { "match",      db_trace_until_matching_cmd,0,          0 },
                    402:        { "trace",      db_stack_trace_cmd,     0,              0 },
                    403:        { "cond",       db_cond_cmd,            CS_OWN,         0 },
                    404:        { "call",       db_fncall,              CS_OWN,         0 },
                    405:        { "macro",      db_def_macro_cmd,       CS_OWN,         0 },
                    406:        { "dmacro",     db_del_macro_cmd,       CS_OWN,         0 },
                    407:        { "show",       0,                      0,      db_show_cmds },
                    408:        { "reset",      db_reset_cpu,           0,              0 },
                    409:        { "reboot",     db_reset_cpu,           0,              0 },
                    410:        { (char *)0, }
                    411: };
                    412: 
                    413: #ifdef DB_MACHINE_COMMANDS
                    414: 
                    415: /* this function should be called to install the machine dependent
                    416:    commands. It should be called before the debugger is enabled  */
                    417: void db_machine_commands_install(ptr)
                    418: struct db_command *ptr;
                    419: {
                    420:   db_command_table[0].more = ptr;
                    421:   return;
                    422: }
                    423: 
                    424: #endif
                    425: 
                    426: 
                    427: struct db_command      *db_last_command = 0;
                    428: 
                    429: void
                    430: db_help_cmd()
                    431: {
                    432:        struct db_command *cmd = db_command_table;
                    433: 
                    434:        while (cmd->name != 0) {
                    435:            db_printf("%-12s", cmd->name);
                    436:            db_end_line();
                    437:            cmd++;
                    438:        }
                    439: }
                    440: 
                    441: int    (*ddb_display)();
                    442: 
                    443: void
                    444: db_command_loop()
                    445: {
                    446:        jmp_buf_t db_jmpbuf;
                    447:        jmp_buf_t *prev = db_recover;
                    448:        extern int db_output_line;
                    449:        extern int db_macro_level;
                    450: #if    NORMA_IPC
                    451:        extern int _node_self;  /* node_self() may not be callable yet */
                    452: #endif NORMA_IPC
                    453: 
                    454:        /*
                    455:         * Initialize 'prev' and 'next' to dot.
                    456:         */
                    457:        db_prev = db_dot;
                    458:        db_next = db_dot;
                    459: 
                    460:        if (ddb_display)
                    461:                (*ddb_display)();
                    462: 
                    463:        db_cmd_loop_done = 0;
                    464:        while (!db_cmd_loop_done) {
                    465:            (void) _setjmp(db_recover = &db_jmpbuf);
                    466:            db_macro_level = 0;
                    467:            if (db_print_position() != 0)
                    468:                db_printf("\n");
                    469:            db_output_line = 0;
                    470:            db_printf("db%s", (db_default_thread)? "t": "");
                    471: #if    NORMA_IPC
                    472:            db_printf("%d", _node_self);
                    473: #endif
                    474: #if    NCPUS > 1
                    475:            db_printf("{%d}", cpu_number());
                    476: #endif
                    477:            db_printf("> ");
                    478: 
                    479:            (void) db_read_line("!!");
                    480:            db_command_list(&db_last_command, db_command_table);
                    481:        }
                    482: 
                    483:        db_recover = prev;
                    484: }
                    485: 
                    486: boolean_t
                    487: db_exec_cmd_nest(cmd, size)
                    488:        char *cmd;
                    489:        int  size;
                    490: {
                    491:        struct db_lex_context lex_context;
                    492: 
                    493:        db_cmd_loop_done = 0;
                    494:        if (cmd) {
                    495:            db_save_lex_context(&lex_context);
                    496:            db_switch_input(cmd, size /**OLD, &lex_context OLD**/);
                    497:        }
                    498:        db_command_list(&db_last_command, db_command_table);
                    499:        if (cmd)
                    500:            db_restore_lex_context(&lex_context);
                    501:        return(db_cmd_loop_done == 0);
                    502: }
                    503: 
                    504: #ifdef __GNUC__
                    505: extern __volatile__ void _longjmp();
                    506: #endif
                    507: 
                    508: void db_error(s)
                    509:        char *s;
                    510: {
                    511:        extern int db_macro_level;
                    512: 
                    513:        db_macro_level = 0;
                    514:        if (db_recover) {
                    515:            if (s)
                    516:                db_printf(s);
                    517:            db_flush_lex();
                    518:            _longjmp(db_recover, 1);
                    519:        }
                    520:        else
                    521:        {
                    522:            if (s)
                    523:                db_printf(s);
                    524:            panic("db_error");
                    525:        }
                    526: }
                    527: 
                    528: /*
                    529:  * Call random function:
                    530:  * !expr(arg,arg,arg)
                    531:  */
                    532: void
                    533: db_fncall()
                    534: {
                    535:        db_expr_t       fn_addr;
                    536: #define        MAXARGS         11
                    537:        db_expr_t       args[MAXARGS];
                    538:        int             nargs = 0;
                    539:        db_expr_t       retval;
                    540:        db_expr_t       (*func)();
                    541:        int             t;
                    542: 
                    543:        if (!db_expression(&fn_addr)) {
                    544:            db_printf("Bad function \"%s\"\n", db_tok_string);
                    545:            db_flush_lex();
                    546:            return;
                    547:        }
                    548:        func = (db_expr_t (*) ()) fn_addr;
                    549: 
                    550:        t = db_read_token();
                    551:        if (t == tLPAREN) {
                    552:            if (db_expression(&args[0])) {
                    553:                nargs++;
                    554:                while ((t = db_read_token()) == tCOMMA) {
                    555:                    if (nargs == MAXARGS) {
                    556:                        db_printf("Too many arguments\n");
                    557:                        db_flush_lex();
                    558:                        return;
                    559:                    }
                    560:                    if (!db_expression(&args[nargs])) {
                    561:                        db_printf("Argument missing\n");
                    562:                        db_flush_lex();
                    563:                        return;
                    564:                    }
                    565:                    nargs++;
                    566:                }
                    567:                db_unread_token(t);
                    568:            }
                    569:            if (db_read_token() != tRPAREN) {
                    570:                db_printf("?\n");
                    571:                db_flush_lex();
                    572:                return;
                    573:            }
                    574:        }
                    575:        while (nargs < MAXARGS) {
                    576:            args[nargs++] = 0;
                    577:        }
                    578: 
                    579:        retval = (*func)(args[0], args[1], args[2], args[3], args[4],
                    580:                         args[5], args[6], args[7], args[8], args[9] );
                    581:        db_printf(" %#N\n", retval);
                    582: }
                    583: 
                    584: boolean_t
                    585: db_option(modif, option)
                    586:        char    *modif;
                    587:        int     option;
                    588: {
                    589:        register char *p;
                    590: 
                    591:        for (p = modif; *p; p++)
                    592:            if (*p == option)
                    593:                return(TRUE);
                    594:        return(FALSE);
                    595: }
                    596: 
                    597: #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.