The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_command.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Mach Operating System
    3  * Copyright (c) 1991,1990 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
   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  Software.Distribution@CS.CMU.EDU
   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 the
   24  * rights to redistribute these changes.
   25  *
   26  * $FreeBSD: src/sys/ddb/db_command.c,v 1.34.2.2 2001/07/29 22:48:36 kris Exp $
   27  */
   28 
   29 /*
   30  *      Author: David B. Golub, Carnegie Mellon University
   31  *      Date:   7/90
   32  */
   33 
   34 /*
   35  * Command dispatcher.
   36  */
   37 #include <sys/param.h>
   38 #include <sys/linker_set.h>
   39 #include <sys/reboot.h>
   40 #include <sys/systm.h>
   41 #include <sys/cons.h>
   42 
   43 #include <ddb/ddb.h>
   44 #include <ddb/db_command.h>
   45 #include <ddb/db_lex.h>
   46 #include <ddb/db_output.h>
   47 
   48 #include <machine/md_var.h>     /* needed for db_reset() */
   49 
   50 #include <setjmp.h>
   51 
   52 /*
   53  * Exported global variables
   54  */
   55 boolean_t       db_cmd_loop_done;
   56 db_addr_t       db_dot;
   57 jmp_buf         db_jmpbuf;
   58 db_addr_t       db_last_addr;
   59 db_addr_t       db_prev;
   60 db_addr_t       db_next;
   61 
   62 SET_DECLARE(db_cmd_set, struct command);
   63 SET_DECLARE(db_show_cmd_set, struct command);
   64 
   65 static db_cmdfcn_t      db_fncall;
   66 static db_cmdfcn_t      db_gdb;
   67 static db_cmdfcn_t      db_reset;
   68 
   69 /*
   70  * 'show' commands
   71  */
   72 
   73 static struct command db_show_all_cmds[] = {
   74 #if 0
   75         { "threads",    db_show_all_threads,    0,      0 },
   76 #endif
   77         { "procs",      db_ps,                  0,      0 },
   78         { NULL }
   79 };
   80 
   81 static struct command db_show_cmds[] = {
   82         { "all",        0,                      0,      db_show_all_cmds },
   83         { "registers",  db_show_regs,           0,      0 },
   84         { "breaks",     db_listbreak_cmd,       0,      0 },
   85 #if 0
   86         { "thread",     db_show_one_thread,     0,      0 },
   87 #endif
   88 #if 0
   89         { "port",       ipc_port_print,         0,      0 },
   90 #endif
   91         { NULL, }
   92 };
   93 
   94 static struct command db_command_table[] = {
   95         { "print",      db_print_cmd,           0,      0 },
   96         { "p",          db_print_cmd,           0,      0 },
   97         { "examine",    db_examine_cmd,         CS_SET_DOT, 0 },
   98         { "x",          db_examine_cmd,         CS_SET_DOT, 0 },
   99         { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
  100         { "set",        db_set_cmd,             CS_OWN, 0 },
  101         { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
  102         { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
  103         { "delete",     db_delete_cmd,          0,      0 },
  104         { "d",          db_delete_cmd,          0,      0 },
  105         { "break",      db_breakpoint_cmd,      0,      0 },
  106         { "dwatch",     db_deletewatch_cmd,     0,      0 },
  107         { "watch",      db_watchpoint_cmd,      CS_MORE,0 },
  108         { "dhwatch",    db_deletehwatch_cmd,    0,      0 },
  109         { "hwatch",     db_hwatchpoint_cmd,     0,      0 },
  110         { "step",       db_single_step_cmd,     0,      0 },
  111         { "s",          db_single_step_cmd,     0,      0 },
  112         { "continue",   db_continue_cmd,        0,      0 },
  113         { "c",          db_continue_cmd,        0,      0 },
  114         { "until",      db_trace_until_call_cmd,0,      0 },
  115         { "next",       db_trace_until_matching_cmd,0,  0 },
  116         { "match",      db_trace_until_matching_cmd,0,  0 },
  117         { "trace",      db_stack_trace_cmd,     0,      0 },
  118         { "where",      db_stack_trace_cmd, 0,  0 },
  119         { "call",       db_fncall,              CS_OWN, 0 },
  120         { "show",       0,                      0,      db_show_cmds },
  121         { "ps",         db_ps,                  0,      0 },
  122         { "gdb",        db_gdb,                 0,      0 },
  123         { "reset",      db_reset,               0,      0 },
  124         { NULL, }
  125 };
  126 
  127 static struct command   *db_last_command = NULL;
  128 
  129 /*
  130  * if 'ed' style: 'dot' is set at start of last item printed,
  131  * and '+' points to next line.
  132  * Otherwise: 'dot' points to next item, '..' points to last.
  133  */
  134 static boolean_t        db_ed_style = TRUE;
  135 
  136 /*
  137  * Utility routine - discard tokens through end-of-line.
  138  */
  139 void
  140 db_skip_to_eol(void)
  141 {
  142         int     t;
  143         do {
  144             t = db_read_token();
  145         } while (t != tEOL);
  146 }
  147 
  148 /*
  149  * Results of command search.
  150  */
  151 #define CMD_UNIQUE      0
  152 #define CMD_FOUND       1
  153 #define CMD_NONE        2
  154 #define CMD_AMBIGUOUS   3
  155 #define CMD_HELP        4
  156 
  157 static void     db_cmd_list (struct command *table,
  158                                  struct command **aux_tablep,
  159                                  struct command **aux_tablep_end);
  160 static int      db_cmd_search (char *name, struct command *table,
  161                                    struct command **aux_tablep,
  162                                    struct command **aux_tablep_end,
  163                                    struct command **cmdp);
  164 static void     db_command (struct command **last_cmdp,
  165                                 struct command *cmd_table,
  166                                 struct command **aux_cmd_tablep,
  167                                 struct command **aux_cmd_tablep_end);
  168 
  169 /*
  170  * Search for command prefix.
  171  *
  172  * Parameters:
  173  *     cmdp:    out
  174  */
  175 static int
  176 db_cmd_search(char *name, struct command *table, struct command **aux_tablep,
  177               struct command **aux_tablep_end, struct command **cmdp)
  178 {
  179         struct command  *cmd;
  180         struct command  **aux_cmdp;
  181         int             result = CMD_NONE;
  182 
  183         for (cmd = table; cmd->name != 0; cmd++) {
  184             char *lp;
  185             char *rp;
  186             int  c;
  187 
  188             lp = name;
  189             rp = cmd->name;
  190             while ((c = *lp) == *rp) {
  191                 if (c == 0) {
  192                     /* complete match */
  193                     *cmdp = cmd;
  194                     return (CMD_UNIQUE);
  195                 }
  196                 lp++;
  197                 rp++;
  198             }
  199             if (c == 0) {
  200                 /* end of name, not end of command -
  201                    partial match */
  202                 if (result == CMD_FOUND) {
  203                     result = CMD_AMBIGUOUS;
  204                     /* but keep looking for a full match -
  205                        this lets us match single letters */
  206                 }
  207                 else {
  208                     *cmdp = cmd;
  209                     result = CMD_FOUND;
  210                 }
  211             }
  212         }
  213         if (result == CMD_NONE && aux_tablep != NULL)
  214             /* XXX repeat too much code. */
  215             for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
  216                 char *lp;
  217                 char *rp;
  218                 int  c;
  219 
  220                 lp = name;
  221                 rp = (*aux_cmdp)->name;
  222                 while ((c = *lp) == *rp) {
  223                     if (c == 0) {
  224                         /* complete match */
  225                         *cmdp = *aux_cmdp;
  226                         return (CMD_UNIQUE);
  227                     }
  228                     lp++;
  229                     rp++;
  230                 }
  231                 if (c == 0) {
  232                     /* end of name, not end of command -
  233                        partial match */
  234                     if (result == CMD_FOUND) {
  235                         result = CMD_AMBIGUOUS;
  236                         /* but keep looking for a full match -
  237                            this lets us match single letters */
  238                     }
  239                     else {
  240                         *cmdp = *aux_cmdp;
  241                         result = CMD_FOUND;
  242                     }
  243                 }
  244             }
  245         if (result == CMD_NONE) {
  246             /* check for 'help' */
  247                 if (name[0] == 'h' && name[1] == 'e'
  248                     && name[2] == 'l' && name[3] == 'p')
  249                         result = CMD_HELP;
  250         }
  251         return (result);
  252 }
  253 
  254 static void
  255 db_cmd_list(struct command *table, struct command **aux_tablep,
  256             struct command **aux_tablep_end)
  257 {
  258         struct command *cmd;
  259         struct command **aux_cmdp;
  260 
  261         for (cmd = table; cmd->name != 0; cmd++) {
  262             db_printf("%-12s", cmd->name);
  263             db_end_line(12);
  264         }
  265         if (aux_tablep == NULL)
  266             return;
  267         for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
  268             db_printf("%-12s", (*aux_cmdp)->name);
  269             db_end_line(12);
  270         }
  271 }
  272 
  273 /*
  274  * Parameters:
  275  *     last_cmdp:       IN_OUT
  276  */
  277 static void
  278 db_command(struct command **last_cmdp, struct command *cmd_table,
  279            struct command **aux_cmd_tablep, struct command **aux_cmd_tablep_end)
  280 {
  281         struct command  *cmd;
  282         int             t;
  283         char            modif[TOK_STRING_SIZE];
  284         db_expr_t       addr, count;
  285         boolean_t       have_addr = FALSE;
  286         int             result;
  287 
  288         cmd = NULL;
  289         t = db_read_token();
  290         if (t == tEOL) {
  291             /* empty line repeats last command, at 'next' */
  292             cmd = *last_cmdp;
  293             addr = (db_expr_t)db_next;
  294             have_addr = FALSE;
  295             count = 1;
  296             modif[0] = '\0';
  297         }
  298         else if (t == tEXCL) {
  299             db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, NULL);
  300             return;
  301         }
  302         else if (t != tIDENT) {
  303             db_printf("?\n");
  304             db_flush_lex();
  305             return;
  306         }
  307         else {
  308             /*
  309              * Search for command
  310              */
  311             while (cmd_table) {
  312                 result = db_cmd_search(db_tok_string,
  313                                        cmd_table,
  314                                        aux_cmd_tablep,
  315                                        aux_cmd_tablep_end,
  316                                        &cmd);
  317                 switch (result) {
  318                     case CMD_NONE:
  319                         db_printf("No such command\n");
  320                         db_flush_lex();
  321                         return;
  322                     case CMD_AMBIGUOUS:
  323                         db_printf("Ambiguous\n");
  324                         db_flush_lex();
  325                         return;
  326                     case CMD_HELP:
  327                         db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
  328                         db_flush_lex();
  329                         return;
  330                     default:
  331                         break;
  332                 }
  333                 if ((cmd_table = cmd->more) != NULL) {
  334                     /* XXX usually no more aux's. */
  335                     aux_cmd_tablep = NULL;
  336                     if (cmd_table == db_show_cmds) {
  337                         aux_cmd_tablep = SET_BEGIN(db_show_cmd_set);
  338                         aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set);
  339                     }
  340 
  341                     t = db_read_token();
  342                     if (t != tIDENT) {
  343                         db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
  344                         db_flush_lex();
  345                         return;
  346                     }
  347                 }
  348             }
  349 
  350             if ((cmd->flag & CS_OWN) == 0) {
  351                 /*
  352                  * Standard syntax:
  353                  * command [/modifier] [addr] [,count]
  354                  */
  355                 t = db_read_token();
  356                 if (t == tSLASH) {
  357                     t = db_read_token();
  358                     if (t != tIDENT && t != tNUMBER) {
  359                         db_printf("Bad modifier\n");
  360                         db_flush_lex();
  361                         return;
  362                     }
  363                     db_strcpy(modif, db_tok_string);
  364                 }
  365                 else {
  366                     db_unread_token(t);
  367                     modif[0] = '\0';
  368                 }
  369 
  370                 if (db_expression(&addr)) {
  371                     db_dot = (db_addr_t) addr;
  372                     db_last_addr = db_dot;
  373                     have_addr = TRUE;
  374                 }
  375                 else {
  376                     addr = (db_expr_t) db_dot;
  377                     have_addr = FALSE;
  378                 }
  379                 t = db_read_token();
  380                 if (t == tCOMMA) {
  381                     if (!db_expression(&count)) {
  382                         db_printf("Count missing\n");
  383                         db_flush_lex();
  384                         return;
  385                     }
  386                 }
  387                 else {
  388                     db_unread_token(t);
  389                     count = -1;
  390                 }
  391                 if ((cmd->flag & CS_MORE) == 0) {
  392                     db_skip_to_eol();
  393                 }
  394             }
  395         }
  396         *last_cmdp = cmd;
  397         if (cmd != NULL) {
  398             /*
  399              * Execute the command.
  400              */
  401             (*cmd->fcn)(addr, have_addr, count, modif);
  402 
  403             if (cmd->flag & CS_SET_DOT) {
  404                 /*
  405                  * If command changes dot, set dot to
  406                  * previous address displayed (if 'ed' style).
  407                  */
  408                 if (db_ed_style) {
  409                     db_dot = db_prev;
  410                 }
  411                 else {
  412                     db_dot = db_next;
  413                 }
  414             }
  415             else {
  416                 /*
  417                  * If command does not change dot,
  418                  * set 'next' location to be the same.
  419                  */
  420                 db_next = db_dot;
  421             }
  422         }
  423 }
  424 
  425 #if 0
  426 void
  427 db_help_cmd(void)
  428 {
  429         struct command *cmd = db_command_table;
  430 
  431         while (cmd->name != 0) {
  432             db_printf("%-12s", cmd->name);
  433             db_end_line(12);
  434             cmd++;
  435         }
  436 }
  437 #endif
  438 
  439 /*
  440  * At least one non-optional command must be implemented using
  441  * DB_COMMAND() so that db_cmd_set gets created.  Here is one.
  442  */
  443 DB_COMMAND(panic, db_panic)
  444 {
  445         panic("from debugger");
  446 }
  447 
  448 void
  449 db_command_loop(void)
  450 {
  451         /*
  452          * Initialize 'prev' and 'next' to dot.
  453          */
  454         db_prev = db_dot;
  455         db_next = db_dot;
  456 
  457         db_cmd_loop_done = 0;
  458         while (!db_cmd_loop_done) {
  459 
  460             setjmp(db_jmpbuf);
  461             if (db_print_position() != 0)
  462                 db_printf("\n");
  463 
  464             db_printf("db> ");
  465             db_read_line();
  466 
  467             db_command(&db_last_command, db_command_table,
  468                     SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set));
  469         }
  470 }
  471 
  472 void
  473 db_error(char *s)
  474 {
  475         if (s)
  476             db_printf("%s", s);
  477         db_flush_lex();
  478         longjmp(db_jmpbuf, 1);
  479 }
  480 
  481 
  482 /*
  483  * Call random function:
  484  * !expr(arg,arg,arg)
  485  */
  486 static void
  487 db_fncall(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
  488 {
  489         db_expr_t       fn_addr;
  490 #define MAXARGS         11      /* XXX only 10 are passed */
  491         db_expr_t       args[MAXARGS];
  492         int             nargs = 0;
  493         db_expr_t       retval;
  494         typedef db_expr_t fcn_10args_t (db_expr_t, db_expr_t, db_expr_t,
  495                                             db_expr_t, db_expr_t, db_expr_t,
  496                                             db_expr_t, db_expr_t, db_expr_t,
  497                                             db_expr_t);
  498         fcn_10args_t    *func;
  499         int             t;
  500 
  501         if (!db_expression(&fn_addr)) {
  502             db_printf("Bad function\n");
  503             db_flush_lex();
  504             return;
  505         }
  506         func = (fcn_10args_t *)fn_addr; /* XXX */
  507 
  508         t = db_read_token();
  509         if (t == tLPAREN) {
  510             if (db_expression(&args[0])) {
  511                 nargs++;
  512                 while ((t = db_read_token()) == tCOMMA) {
  513                     if (nargs == MAXARGS) {
  514                         db_printf("Too many arguments\n");
  515                         db_flush_lex();
  516                         return;
  517                     }
  518                     if (!db_expression(&args[nargs])) {
  519                         db_printf("Argument missing\n");
  520                         db_flush_lex();
  521                         return;
  522                     }
  523                     nargs++;
  524                 }
  525                 db_unread_token(t);
  526             }
  527             if (db_read_token() != tRPAREN) {
  528                 db_printf("?\n");
  529                 db_flush_lex();
  530                 return;
  531             }
  532         }
  533         db_skip_to_eol();
  534 
  535         while (nargs < MAXARGS) {
  536             args[nargs++] = 0;
  537         }
  538 
  539         retval = (*func)(args[0], args[1], args[2], args[3], args[4],
  540                          args[5], args[6], args[7], args[8], args[9] );
  541         db_printf("%#lr\n", (long)retval);
  542 }
  543 
  544 /* Enter GDB remote protocol debugger on the next trap. */
  545 
  546 static void
  547 db_gdb(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
  548 {
  549         if (gdb_tab == NULL) {
  550                 db_printf("No gdb port enabled. Set flag 0x80 on desired port\n");
  551                 db_printf("in your configuration file (currently sio only).\n");
  552                 return;
  553         }
  554         boothowto ^= RB_GDB;
  555 
  556         db_printf("Next trap will enter %s\n",
  557                    boothowto & RB_GDB ? "GDB remote protocol mode"
  558                                       : "DDB debugger");
  559 }
  560 
  561 static void
  562 db_reset(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char * dummy4)
  563 {
  564         cpu_reset();
  565 }

Cache object: 21322f33e9aef1108292dd36363d8355


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.