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

Cache object: 98dbcfbda78717473c10eec9a69d7360


[ 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.