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 /*
   27  *      Author: David B. Golub, Carnegie Mellon University
   28  *      Date:   7/90
   29  */
   30 /*
   31  * Command dispatcher.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/6.3/sys/ddb/db_command.c 172908 2007-10-23 16:07:30Z obrien $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/linker_set.h>
   39 #include <sys/lock.h>
   40 #include <sys/kdb.h>
   41 #include <sys/mutex.h>
   42 #include <sys/proc.h>
   43 #include <sys/reboot.h>
   44 #include <sys/signalvar.h>
   45 #include <sys/systm.h>
   46 #include <sys/cons.h>
   47 #include <sys/watchdog.h>
   48 
   49 #include <ddb/ddb.h>
   50 #include <ddb/db_command.h>
   51 #include <ddb/db_lex.h>
   52 #include <ddb/db_output.h>
   53 
   54 #include <machine/cpu.h>
   55 #include <machine/setjmp.h>
   56 
   57 /*
   58  * Exported global variables
   59  */
   60 boolean_t       db_cmd_loop_done;
   61 db_addr_t       db_dot;
   62 db_addr_t       db_last_addr;
   63 db_addr_t       db_prev;
   64 db_addr_t       db_next;
   65 
   66 SET_DECLARE(db_cmd_set, struct command);
   67 SET_DECLARE(db_show_cmd_set, struct command);
   68 
   69 static db_cmdfcn_t      db_fncall;
   70 static db_cmdfcn_t      db_gdb;
   71 static db_cmdfcn_t      db_halt;
   72 static db_cmdfcn_t      db_kill;
   73 static db_cmdfcn_t      db_reset;
   74 static db_cmdfcn_t      db_stack_trace;
   75 static db_cmdfcn_t      db_stack_trace_all;
   76 static db_cmdfcn_t      db_watchdog;
   77 
   78 /*
   79  * 'show' commands
   80  */
   81 
   82 static struct command db_show_all_cmds[] = {
   83         { "procs",      db_ps,                  0,      0 },
   84         { (char *)0 }
   85 };
   86 
   87 static struct command db_show_cmds[] = {
   88         { "all",        0,                      0,      db_show_all_cmds },
   89         { "registers",  db_show_regs,           0,      0 },
   90         { "breaks",     db_listbreak_cmd,       0,      0 },
   91         { "threads",    db_show_threads,        0,      0 },
   92         { (char *)0, }
   93 };
   94 
   95 static struct command db_command_table[] = {
   96         { "print",      db_print_cmd,           0,      0 },
   97         { "p",          db_print_cmd,           0,      0 },
   98         { "examine",    db_examine_cmd,         CS_SET_DOT, 0 },
   99         { "x",          db_examine_cmd,         CS_SET_DOT, 0 },
  100         { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, 0 },
  101         { "set",        db_set_cmd,             CS_OWN, 0 },
  102         { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
  103         { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, 0 },
  104         { "delete",     db_delete_cmd,          0,      0 },
  105         { "d",          db_delete_cmd,          0,      0 },
  106         { "break",      db_breakpoint_cmd,      0,      0 },
  107         { "dwatch",     db_deletewatch_cmd,     0,      0 },
  108         { "watch",      db_watchpoint_cmd,      CS_MORE,0 },
  109         { "dhwatch",    db_deletehwatch_cmd,    0,      0 },
  110         { "hwatch",     db_hwatchpoint_cmd,     0,      0 },
  111         { "step",       db_single_step_cmd,     0,      0 },
  112         { "s",          db_single_step_cmd,     0,      0 },
  113         { "continue",   db_continue_cmd,        0,      0 },
  114         { "c",          db_continue_cmd,        0,      0 },
  115         { "until",      db_trace_until_call_cmd,0,      0 },
  116         { "next",       db_trace_until_matching_cmd,0,  0 },
  117         { "match",      db_trace_until_matching_cmd,0,  0 },
  118         { "trace",      db_stack_trace,         CS_OWN, 0 },
  119         { "alltrace",   db_stack_trace_all,     0,      0 },
  120         { "where",      db_stack_trace,         CS_OWN, 0 },
  121         { "bt",         db_stack_trace,         CS_OWN, 0 },
  122         { "call",       db_fncall,              CS_OWN, 0 },
  123         { "show",       0,                      0,      db_show_cmds },
  124         { "ps",         db_ps,                  0,      0 },
  125         { "gdb",        db_gdb,                 0,      0 },
  126         { "halt",       db_halt,                0,      0 },
  127         { "reboot",     db_reset,               0,      0 },
  128         { "reset",      db_reset,               0,      0 },
  129         { "kill",       db_kill,                CS_OWN, 0 },
  130         { "watchdog",   db_watchdog,            0,      0 },
  131         { "thread",     db_set_thread,          CS_OWN, 0 },
  132         { (char *)0, }
  133 };
  134 
  135 static struct command   *db_last_command = 0;
  136 
  137 
  138 /*
  139  * if 'ed' style: 'dot' is set at start of last item printed,
  140  * and '+' points to next line.
  141  * Otherwise: 'dot' points to next item, '..' points to last.
  142  */
  143 static boolean_t        db_ed_style = TRUE;
  144 
  145 /*
  146  * Utility routine - discard tokens through end-of-line.
  147  */
  148 void
  149 db_skip_to_eol()
  150 {
  151         int     t;
  152         do {
  153             t = db_read_token();
  154         } while (t != tEOL);
  155 }
  156 
  157 /*
  158  * Results of command search.
  159  */
  160 #define CMD_UNIQUE      0
  161 #define CMD_FOUND       1
  162 #define CMD_NONE        2
  163 #define CMD_AMBIGUOUS   3
  164 #define CMD_HELP        4
  165 
  166 static void     db_cmd_list(struct command *table, struct command **aux_tablep,
  167                     struct command **aux_tablep_end);
  168 static int      db_cmd_search(char *name, struct command *table,
  169                     struct command **aux_tablep,
  170                     struct command **aux_tablep_end, struct command **cmdp);
  171 static void     db_command(struct command **last_cmdp,
  172                     struct command *cmd_table, struct command **aux_cmd_tablep,
  173                     struct command **aux_cmd_tablep_end);
  174 
  175 /*
  176  * Search for command prefix.
  177  */
  178 static int
  179 db_cmd_search(name, table, aux_tablep, aux_tablep_end, cmdp)
  180         char *          name;
  181         struct command  *table;
  182         struct command  **aux_tablep;
  183         struct command  **aux_tablep_end;
  184         struct command  **cmdp; /* out */
  185 {
  186         struct command  *cmd;
  187         struct command  **aux_cmdp;
  188         int             result = CMD_NONE;
  189 
  190         for (cmd = table; cmd->name != 0; cmd++) {
  191             register char *lp;
  192             register char *rp;
  193             register int  c;
  194 
  195             lp = name;
  196             rp = cmd->name;
  197             while ((c = *lp) == *rp) {
  198                 if (c == 0) {
  199                     /* complete match */
  200                     *cmdp = cmd;
  201                     return (CMD_UNIQUE);
  202                 }
  203                 lp++;
  204                 rp++;
  205             }
  206             if (c == 0) {
  207                 /* end of name, not end of command -
  208                    partial match */
  209                 if (result == CMD_FOUND) {
  210                     result = CMD_AMBIGUOUS;
  211                     /* but keep looking for a full match -
  212                        this lets us match single letters */
  213                 }
  214                 else {
  215                     *cmdp = cmd;
  216                     result = CMD_FOUND;
  217                 }
  218             }
  219         }
  220         if (result == CMD_NONE && aux_tablep != 0)
  221             /* XXX repeat too much code. */
  222             for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
  223                 register char *lp;
  224                 register char *rp;
  225                 register int  c;
  226 
  227                 lp = name;
  228                 rp = (*aux_cmdp)->name;
  229                 while ((c = *lp) == *rp) {
  230                     if (c == 0) {
  231                         /* complete match */
  232                         *cmdp = *aux_cmdp;
  233                         return (CMD_UNIQUE);
  234                     }
  235                     lp++;
  236                     rp++;
  237                 }
  238                 if (c == 0) {
  239                     /* end of name, not end of command -
  240                        partial match */
  241                     if (result == CMD_FOUND) {
  242                         result = CMD_AMBIGUOUS;
  243                         /* but keep looking for a full match -
  244                            this lets us match single letters */
  245                     }
  246                     else {
  247                         *cmdp = *aux_cmdp;
  248                         result = CMD_FOUND;
  249                     }
  250                 }
  251             }
  252         if (result == CMD_NONE) {
  253             /* check for 'help' */
  254                 if (name[0] == 'h' && name[1] == 'e'
  255                     && name[2] == 'l' && name[3] == 'p')
  256                         result = CMD_HELP;
  257         }
  258         return (result);
  259 }
  260 
  261 static void
  262 db_cmd_list(table, aux_tablep, aux_tablep_end)
  263         struct command *table;
  264         struct command **aux_tablep;
  265         struct command **aux_tablep_end;
  266 {
  267         register struct command *cmd;
  268         register struct command **aux_cmdp;
  269 
  270         for (cmd = table; cmd->name != 0; cmd++) {
  271             db_printf("%-12s", cmd->name);
  272             db_end_line();
  273         }
  274         if (aux_tablep == 0)
  275             return;
  276         for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
  277             db_printf("%-12s", (*aux_cmdp)->name);
  278             db_end_line();
  279         }
  280 }
  281 
  282 static void
  283 db_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end)
  284         struct command  **last_cmdp;    /* IN_OUT */
  285         struct command  *cmd_table;
  286         struct command  **aux_cmd_tablep;
  287         struct command  **aux_cmd_tablep_end;
  288 {
  289         struct command  *cmd;
  290         int             t;
  291         char            modif[TOK_STRING_SIZE];
  292         db_expr_t       addr, count;
  293         boolean_t       have_addr = FALSE;
  294         int             result;
  295 
  296         t = db_read_token();
  297         if (t == tEOL) {
  298             /* empty line repeats last command, at 'next' */
  299             cmd = *last_cmdp;
  300             addr = (db_expr_t)db_next;
  301             have_addr = FALSE;
  302             count = 1;
  303             modif[0] = '\0';
  304         }
  305         else if (t == tEXCL) {
  306             db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, (char *)0);
  307             return;
  308         }
  309         else if (t != tIDENT) {
  310             db_printf("?\n");
  311             db_flush_lex();
  312             return;
  313         }
  314         else {
  315             /*
  316              * Search for command
  317              */
  318             while (cmd_table) {
  319                 result = db_cmd_search(db_tok_string,
  320                                        cmd_table,
  321                                        aux_cmd_tablep,
  322                                        aux_cmd_tablep_end,
  323                                        &cmd);
  324                 switch (result) {
  325                     case CMD_NONE:
  326                         db_printf("No such command\n");
  327                         db_flush_lex();
  328                         return;
  329                     case CMD_AMBIGUOUS:
  330                         db_printf("Ambiguous\n");
  331                         db_flush_lex();
  332                         return;
  333                     case CMD_HELP:
  334                         db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
  335                         db_flush_lex();
  336                         return;
  337                     default:
  338                         break;
  339                 }
  340                 if ((cmd_table = cmd->more) != 0) {
  341                     /* XXX usually no more aux's. */
  342                     aux_cmd_tablep = 0;
  343                     if (cmd_table == db_show_cmds) {
  344                         aux_cmd_tablep = SET_BEGIN(db_show_cmd_set);
  345                         aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set);
  346                     }
  347 
  348                     t = db_read_token();
  349                     if (t != tIDENT) {
  350                         db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
  351                         db_flush_lex();
  352                         return;
  353                     }
  354                 }
  355             }
  356 
  357             if ((cmd->flag & CS_OWN) == 0) {
  358                 /*
  359                  * Standard syntax:
  360                  * command [/modifier] [addr] [,count]
  361                  */
  362                 t = db_read_token();
  363                 if (t == tSLASH) {
  364                     t = db_read_token();
  365                     if (t != tIDENT) {
  366                         db_printf("Bad modifier\n");
  367                         db_flush_lex();
  368                         return;
  369                     }
  370                     db_strcpy(modif, db_tok_string);
  371                 }
  372                 else {
  373                     db_unread_token(t);
  374                     modif[0] = '\0';
  375                 }
  376 
  377                 if (db_expression(&addr)) {
  378                     db_dot = (db_addr_t) addr;
  379                     db_last_addr = db_dot;
  380                     have_addr = TRUE;
  381                 }
  382                 else {
  383                     addr = (db_expr_t) db_dot;
  384                     have_addr = FALSE;
  385                 }
  386                 t = db_read_token();
  387                 if (t == tCOMMA) {
  388                     if (!db_expression(&count)) {
  389                         db_printf("Count missing\n");
  390                         db_flush_lex();
  391                         return;
  392                     }
  393                 }
  394                 else {
  395                     db_unread_token(t);
  396                     count = -1;
  397                 }
  398                 if ((cmd->flag & CS_MORE) == 0) {
  399                     db_skip_to_eol();
  400                 }
  401             }
  402         }
  403         *last_cmdp = cmd;
  404         if (cmd != 0) {
  405             /*
  406              * Execute the command.
  407              */
  408             (*cmd->fcn)(addr, have_addr, count, modif);
  409             db_setup_paging(NULL, NULL, -1);
  410 
  411             if (cmd->flag & CS_SET_DOT) {
  412                 /*
  413                  * If command changes dot, set dot to
  414                  * previous address displayed (if 'ed' style).
  415                  */
  416                 if (db_ed_style) {
  417                     db_dot = db_prev;
  418                 }
  419                 else {
  420                     db_dot = db_next;
  421                 }
  422             }
  423             else {
  424                 /*
  425                  * If command does not change dot,
  426                  * set 'next' location to be the same.
  427                  */
  428                 db_next = db_dot;
  429             }
  430         }
  431 }
  432 
  433 /*
  434  * At least one non-optional command must be implemented using
  435  * DB_COMMAND() so that db_cmd_set gets created.  Here is one.
  436  */
  437 DB_COMMAND(panic, db_panic)
  438 {
  439         panic("from debugger");
  440 }
  441 
  442 void
  443 db_command_loop()
  444 {
  445         /*
  446          * Initialize 'prev' and 'next' to dot.
  447          */
  448         db_prev = db_dot;
  449         db_next = db_dot;
  450 
  451         db_cmd_loop_done = 0;
  452         while (!db_cmd_loop_done) {
  453             if (db_print_position() != 0)
  454                 db_printf("\n");
  455 
  456             db_printf("db> ");
  457             (void) db_read_line();
  458 
  459             db_command(&db_last_command, db_command_table,
  460                        SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set));
  461         }
  462 }
  463 
  464 void
  465 db_error(s)
  466         const char *s;
  467 {
  468         if (s)
  469             db_printf("%s", s);
  470         db_flush_lex();
  471         kdb_reenter();
  472 }
  473 
  474 
  475 /*
  476  * Call random function:
  477  * !expr(arg,arg,arg)
  478  */
  479 
  480 /* The generic implementation supports a maximum of 10 arguments. */
  481 typedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t,
  482     db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t);
  483 
  484 static __inline int
  485 db_fncall_generic(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
  486 {
  487         __db_f *f = (__db_f *)addr;
  488 
  489         if (nargs > 10) {
  490                 db_printf("Too many arguments (max 10)\n");
  491                 return (0);
  492         }
  493         *rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
  494             args[6], args[7], args[8], args[9]);
  495         return (1);
  496 }
  497 
  498 static void
  499 db_fncall(dummy1, dummy2, dummy3, dummy4)
  500         db_expr_t       dummy1;
  501         boolean_t       dummy2;
  502         db_expr_t       dummy3;
  503         char *          dummy4;
  504 {
  505         db_expr_t       fn_addr;
  506         db_expr_t       args[DB_MAXARGS];
  507         int             nargs = 0;
  508         db_expr_t       retval;
  509         int             t;
  510 
  511         if (!db_expression(&fn_addr)) {
  512             db_printf("Bad function\n");
  513             db_flush_lex();
  514             return;
  515         }
  516 
  517         t = db_read_token();
  518         if (t == tLPAREN) {
  519             if (db_expression(&args[0])) {
  520                 nargs++;
  521                 while ((t = db_read_token()) == tCOMMA) {
  522                     if (nargs == DB_MAXARGS) {
  523                         db_printf("Too many arguments (max %d)\n", DB_MAXARGS);
  524                         db_flush_lex();
  525                         return;
  526                     }
  527                     if (!db_expression(&args[nargs])) {
  528                         db_printf("Argument missing\n");
  529                         db_flush_lex();
  530                         return;
  531                     }
  532                     nargs++;
  533                 }
  534                 db_unread_token(t);
  535             }
  536             if (db_read_token() != tRPAREN) {
  537                 db_printf("?\n");
  538                 db_flush_lex();
  539                 return;
  540             }
  541         }
  542         db_skip_to_eol();
  543 
  544         if (DB_CALL(fn_addr, &retval, nargs, args))
  545                 db_printf("= %#lr\n", (long)retval);
  546 }
  547 
  548 static void
  549 db_halt(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
  550 {
  551 
  552         cpu_halt();
  553 }
  554 
  555 static void
  556 db_kill(dummy1, dummy2, dummy3, dummy4)
  557         db_expr_t       dummy1;
  558         boolean_t       dummy2;
  559         db_expr_t       dummy3;
  560         char *          dummy4;
  561 {
  562         db_expr_t old_radix, pid, sig;
  563         struct proc *p;
  564 
  565 #define DB_ERROR(f)     do { db_printf f; db_flush_lex(); goto out; } while (0)
  566 
  567         /*
  568          * PIDs and signal numbers are typically represented in base
  569          * 10, so make that the default here.  It can, of course, be
  570          * overridden by specifying a prefix.
  571          */
  572         old_radix = db_radix;
  573         db_radix = 10;
  574         /* Retrieve arguments. */
  575         if (!db_expression(&sig))
  576                 DB_ERROR(("Missing signal number\n"));
  577         if (!db_expression(&pid))
  578                 DB_ERROR(("Missing process ID\n"));
  579         db_skip_to_eol();
  580         if (sig < 0 || sig > _SIG_MAXSIG)
  581                 DB_ERROR(("Signal number out of range\n"));
  582 
  583         /*
  584          * Find the process in question.  allproc_lock is not needed
  585          * since we're in DDB.
  586          */
  587         /* sx_slock(&allproc_lock); */
  588         LIST_FOREACH(p, &allproc, p_list)
  589             if (p->p_pid == pid)
  590                     break;
  591         /* sx_sunlock(&allproc_lock); */
  592         if (p == NULL)
  593                 DB_ERROR(("Can't find process with pid %ld\n", (long) pid));
  594 
  595         /* If it's already locked, bail; otherwise, do the deed. */
  596         if (PROC_TRYLOCK(p) == 0)
  597                 DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
  598         else {
  599                 psignal(p, sig);
  600                 PROC_UNLOCK(p);
  601         }
  602 
  603 out:
  604         db_radix = old_radix;
  605 #undef DB_ERROR
  606 }
  607 
  608 static void
  609 db_reset(dummy1, dummy2, dummy3, dummy4)
  610         db_expr_t       dummy1;
  611         boolean_t       dummy2;
  612         db_expr_t       dummy3;
  613         char *          dummy4;
  614 {
  615 
  616         cpu_reset();
  617 }
  618 
  619 static void
  620 db_watchdog(dummy1, dummy2, dummy3, dummy4)
  621         db_expr_t       dummy1;
  622         boolean_t       dummy2;
  623         db_expr_t       dummy3;
  624         char *          dummy4;
  625 {
  626         int i;
  627 
  628         /*
  629          * XXX: It might make sense to be able to set the watchdog to a
  630          * XXX: timeout here so that failure or hang as a result of subsequent
  631          * XXX: ddb commands could be recovered by a reset.
  632          */
  633 
  634         EVENTHANDLER_INVOKE(watchdog_list, 0, &i);
  635 }
  636 
  637 static void
  638 db_gdb(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
  639 {
  640 
  641         if (kdb_dbbe_select("gdb") != 0)
  642                 db_printf("The remote GDB backend could not be selected.\n");
  643         else
  644                 db_printf("Step to enter the remote GDB backend.\n");
  645 }
  646 
  647 static void
  648 db_stack_trace(db_expr_t tid, boolean_t hastid, db_expr_t count, char *modif)
  649 {
  650         struct thread *td;
  651         db_expr_t radix;
  652         pid_t pid;
  653         int t;
  654 
  655         /*
  656          * We parse our own arguments. We don't like the default radix.
  657          */
  658         radix = db_radix;
  659         db_radix = 10;
  660         hastid = db_expression(&tid);
  661         t = db_read_token();
  662         if (t == tCOMMA) {
  663                 if (!db_expression(&count)) {
  664                         db_printf("Count missing\n");
  665                         db_flush_lex();
  666                         return;
  667                 }
  668         } else {
  669                 db_unread_token(t);
  670                 count = -1;
  671         }
  672         db_skip_to_eol();
  673         db_radix = radix;
  674 
  675         if (hastid) {
  676                 td = kdb_thr_lookup((lwpid_t)tid);
  677                 if (td == NULL)
  678                         td = kdb_thr_from_pid((pid_t)tid);
  679                 if (td == NULL) {
  680                         db_printf("Thread %d not found\n", (int)tid);
  681                         return;
  682                 }
  683         } else
  684                 td = kdb_thread;
  685         if (td->td_proc != NULL)
  686                 pid = td->td_proc->p_pid;
  687         else
  688                 pid = -1;
  689         db_printf("Tracing pid %d tid %ld td %p\n", pid, (long)td->td_tid, td);
  690         db_trace_thread(td, count);
  691 }
  692 
  693 static void
  694 db_stack_trace_all(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3,
  695     char *dummy4)
  696 {
  697         struct proc *p;
  698         struct thread *td;
  699 
  700         for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
  701                 FOREACH_THREAD_IN_PROC(p, td) {
  702                         db_printf("\nTracing command %s pid %d tid %ld td %p\n",
  703                             p->p_comm, p->p_pid, (long)td->td_tid, td);
  704                         db_trace_thread(td, -1);
  705                 }
  706         }
  707 }

Cache object: bcfffbb88f57a1cad28f7306eda87164


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