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_run.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  * SPDX-License-Identifier: MIT-CMU
    3  *
    4  * Mach Operating System
    5  * Copyright (c) 1991,1990 Carnegie Mellon University
    6  * All Rights Reserved.
    7  *
    8  * Permission to use, copy, modify and distribute this software and its
    9  * documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 /*
   29  *      Author: David B. Golub, Carnegie Mellon University
   30  *      Date:   7/90
   31  */
   32 
   33 /*
   34  * Commands to run process.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 #include <sys/param.h>
   41 #include <sys/kdb.h>
   42 #include <sys/proc.h>
   43 #include <sys/reg.h>
   44 #include <sys/systm.h>
   45 
   46 #include <machine/kdb.h>
   47 #include <machine/pcb.h>
   48 
   49 #include <vm/vm.h>
   50 
   51 #include <ddb/ddb.h>
   52 #include <ddb/db_access.h>
   53 #include <ddb/db_break.h>
   54 #include <ddb/db_command.h>
   55 
   56 #define STEP_ONCE       1
   57 #define STEP_RETURN     2
   58 #define STEP_CALLT      3
   59 #define STEP_CONTINUE   4
   60 #define STEP_INVISIBLE  5
   61 #define STEP_COUNT      6
   62 static int      db_run_mode = STEP_CONTINUE;
   63 
   64 static bool             db_sstep_multiple;
   65 static bool             db_sstep_print;
   66 static int              db_loop_count;
   67 static int              db_call_depth;
   68 
   69 int             db_inst_count;
   70 int             db_load_count;
   71 int             db_store_count;
   72 
   73 bool
   74 db_stop_at_pc(int type, int code, bool *is_breakpoint, bool *is_watchpoint)
   75 {
   76         db_addr_t       pc;
   77         db_breakpoint_t bkpt;
   78 
   79         *is_breakpoint = IS_BREAKPOINT_TRAP(type, code);
   80         *is_watchpoint = IS_WATCHPOINT_TRAP(type, code);
   81         pc = PC_REGS();
   82 
   83         db_clear_single_step();
   84         db_clear_breakpoints();
   85         db_clear_watchpoints();
   86 
   87 #ifdef  FIXUP_PC_AFTER_BREAK
   88         if (*is_breakpoint) {
   89             /*
   90              * Breakpoint trap.  Fix up the PC if the
   91              * machine requires it.
   92              */
   93             FIXUP_PC_AFTER_BREAK
   94             pc = PC_REGS();
   95         }
   96 #endif
   97 
   98         /*
   99          * Now check for a breakpoint at this address.
  100          */
  101         bkpt = db_find_breakpoint_here(pc);
  102         if (bkpt) {
  103             if (--bkpt->count == 0) {
  104                 bkpt->count = bkpt->init_count;
  105                 *is_breakpoint = true;
  106                 return (true);  /* stop here */
  107             }
  108             return (false);     /* continue the countdown */
  109         } else if (*is_breakpoint) {
  110 #ifdef BKPT_SKIP
  111                 BKPT_SKIP;
  112 #endif
  113         }
  114 
  115         *is_breakpoint = false; /* might be a breakpoint, but not ours */
  116 
  117         /*
  118          * If not stepping, then silently ignore single-step traps
  119          * (except for clearing the single-step-flag above).
  120          *
  121          * If stepping, then abort if the trap type is unexpected.
  122          * Breakpoints owned by us are expected and were handled above.
  123          * Single-steps are expected and are handled below.  All others
  124          * are unexpected.
  125          *
  126          * Only do either of these if the MD layer claims to classify
  127          * single-step traps unambiguously (by defining IS_SSTEP_TRAP).
  128          * Otherwise, fall through to the bad historical behaviour
  129          * given by turning unexpected traps into expected traps: if not
  130          * stepping, then expect only breakpoints and stop, and if
  131          * stepping, then expect only single-steps and step.
  132          */
  133 #ifdef IS_SSTEP_TRAP
  134         if (db_run_mode == STEP_CONTINUE && IS_SSTEP_TRAP(type, code))
  135             return (false);
  136         if (db_run_mode != STEP_CONTINUE && !IS_SSTEP_TRAP(type, code)) {
  137             printf("Stepping aborted\n");
  138             return (true);
  139         }
  140 #endif
  141 
  142         if (db_run_mode == STEP_INVISIBLE) {
  143             db_run_mode = STEP_CONTINUE;
  144             return (false);     /* continue */
  145         }
  146         if (db_run_mode == STEP_COUNT) {
  147             return (false); /* continue */
  148         }
  149         if (db_run_mode == STEP_ONCE) {
  150             if (--db_loop_count > 0) {
  151                 if (db_sstep_print) {
  152                     db_printf("\t\t");
  153                     db_print_loc_and_inst(pc);
  154                 }
  155                 return (false); /* continue */
  156             }
  157         }
  158         if (db_run_mode == STEP_RETURN) {
  159             /* continue until matching return */
  160             db_expr_t ins;
  161 
  162             ins = db_get_value(pc, sizeof(int), false);
  163             if (!inst_trap_return(ins) &&
  164                 (!inst_return(ins) || --db_call_depth != 0)) {
  165                 if (db_sstep_print) {
  166                     if (inst_call(ins) || inst_return(ins)) {
  167                         int i;
  168 
  169                         db_printf("[after %6d]     ", db_inst_count);
  170                         for (i = db_call_depth; --i > 0; )
  171                             db_printf("  ");
  172                         db_print_loc_and_inst(pc);
  173                     }
  174                 }
  175                 if (inst_call(ins))
  176                     db_call_depth++;
  177                 return (false); /* continue */
  178             }
  179         }
  180         if (db_run_mode == STEP_CALLT) {
  181             /* continue until call or return */
  182             db_expr_t ins;
  183 
  184             ins = db_get_value(pc, sizeof(int), false);
  185             if (!inst_call(ins) &&
  186                 !inst_return(ins) &&
  187                 !inst_trap_return(ins)) {
  188                 return (false); /* continue */
  189             }
  190         }
  191         return (true);
  192 }
  193 
  194 void
  195 db_restart_at_pc(bool watchpt)
  196 {
  197         db_addr_t       pc = PC_REGS();
  198 
  199         if ((db_run_mode == STEP_COUNT) ||
  200             ((db_run_mode == STEP_ONCE) && db_sstep_multiple) ||
  201             (db_run_mode == STEP_RETURN) ||
  202             (db_run_mode == STEP_CALLT)) {
  203             /*
  204              * We are about to execute this instruction,
  205              * so count it now.
  206              */
  207             db_get_value(pc, sizeof(int), false);
  208             db_inst_count++;
  209             db_load_count += inst_load(ins);
  210             db_store_count += inst_store(ins);
  211         }
  212 
  213         if (db_run_mode == STEP_CONTINUE) {
  214             if (watchpt || db_find_breakpoint_here(pc)) {
  215                 /*
  216                  * Step over breakpoint/watchpoint.
  217                  */
  218                 db_run_mode = STEP_INVISIBLE;
  219                 db_set_single_step();
  220             } else {
  221                 db_set_breakpoints();
  222                 db_set_watchpoints();
  223             }
  224         } else {
  225             db_set_single_step();
  226         }
  227 }
  228 
  229 /* single-step */
  230 /*ARGSUSED*/
  231 void
  232 db_single_step_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
  233 {
  234         bool            print = false;
  235 
  236         if (count == -1)
  237             count = 1;
  238 
  239         if (modif[0] == 'p')
  240             print = true;
  241 
  242         db_run_mode = STEP_ONCE;
  243         db_loop_count = count;
  244         db_sstep_multiple = (count != 1);
  245         db_sstep_print = print;
  246         db_inst_count = 0;
  247         db_load_count = 0;
  248         db_store_count = 0;
  249 
  250         db_cmd_loop_done = 1;
  251 }
  252 
  253 /* trace and print until call/return */
  254 /*ARGSUSED*/
  255 void
  256 db_trace_until_call_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  257     char *modif)
  258 {
  259         bool    print = false;
  260 
  261         if (modif[0] == 'p')
  262             print = true;
  263 
  264         db_run_mode = STEP_CALLT;
  265         db_sstep_print = print;
  266         db_inst_count = 0;
  267         db_load_count = 0;
  268         db_store_count = 0;
  269 
  270         db_cmd_loop_done = 1;
  271 }
  272 
  273 /*ARGSUSED*/
  274 void
  275 db_trace_until_matching_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  276     char *modif)
  277 {
  278         bool    print = false;
  279 
  280         if (modif[0] == 'p')
  281             print = true;
  282 
  283         db_run_mode = STEP_RETURN;
  284         db_call_depth = 1;
  285         db_sstep_print = print;
  286         db_inst_count = 0;
  287         db_load_count = 0;
  288         db_store_count = 0;
  289 
  290         db_cmd_loop_done = 1;
  291 }
  292 
  293 /* continue */
  294 /*ARGSUSED*/
  295 void
  296 db_continue_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
  297 {
  298         if (modif[0] == 'c')
  299             db_run_mode = STEP_COUNT;
  300         else
  301             db_run_mode = STEP_CONTINUE;
  302         db_inst_count = 0;
  303         db_load_count = 0;
  304         db_store_count = 0;
  305 
  306         db_cmd_loop_done = 1;
  307 }

Cache object: 662a9f8f93cd48490de6a500a7b5ee6a


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