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  * 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 /*
   32  * Commands to run process.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/10.4/sys/ddb/db_run.c 273265 2014-10-18 19:22:59Z pfg $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/kdb.h>
   40 #include <sys/proc.h>
   41 
   42 #include <machine/kdb.h>
   43 #include <machine/pcb.h>
   44 
   45 #include <vm/vm.h>
   46 
   47 #include <ddb/ddb.h>
   48 #include <ddb/db_break.h>
   49 #include <ddb/db_access.h>
   50 
   51 static int      db_run_mode;
   52 #define STEP_NONE       0
   53 #define STEP_ONCE       1
   54 #define STEP_RETURN     2
   55 #define STEP_CALLT      3
   56 #define STEP_CONTINUE   4
   57 #define STEP_INVISIBLE  5
   58 #define STEP_COUNT      6
   59 
   60 static boolean_t        db_sstep_print;
   61 static int              db_loop_count;
   62 static int              db_call_depth;
   63 
   64 int             db_inst_count;
   65 int             db_load_count;
   66 int             db_store_count;
   67 
   68 #ifndef db_set_single_step
   69 void db_set_single_step(void);
   70 #endif
   71 #ifndef db_clear_single_step
   72 void db_clear_single_step(void);
   73 #endif
   74 
   75 #ifdef SOFTWARE_SSTEP
   76 db_breakpoint_t db_not_taken_bkpt = 0;
   77 db_breakpoint_t db_taken_bkpt = 0;
   78 #endif
   79 
   80 boolean_t
   81 db_stop_at_pc(boolean_t *is_breakpoint)
   82 {
   83         register db_addr_t      pc;
   84         register db_breakpoint_t bkpt;
   85 
   86         pc = PC_REGS();
   87 #ifdef SOFTWARE_SSTEP
   88         if ((db_not_taken_bkpt != 0 && pc == db_not_taken_bkpt->address)
   89             || (db_taken_bkpt != 0 && pc == db_taken_bkpt->address))
   90                 *is_breakpoint = FALSE;
   91 #endif
   92 
   93         db_clear_single_step();
   94         db_clear_breakpoints();
   95         db_clear_watchpoints();
   96 
   97 #ifdef  FIXUP_PC_AFTER_BREAK
   98         if (*is_breakpoint) {
   99             /*
  100              * Breakpoint trap.  Fix up the PC if the
  101              * machine requires it.
  102              */
  103             FIXUP_PC_AFTER_BREAK
  104             pc = PC_REGS();
  105         }
  106 #endif
  107 
  108         /*
  109          * Now check for a breakpoint at this address.
  110          */
  111         bkpt = db_find_breakpoint_here(pc);
  112         if (bkpt) {
  113             if (--bkpt->count == 0) {
  114                 bkpt->count = bkpt->init_count;
  115                 *is_breakpoint = TRUE;
  116                 return (TRUE);  /* stop here */
  117             }
  118         } else if (*is_breakpoint) {
  119 #ifdef BKPT_SKIP
  120                 BKPT_SKIP;
  121 #endif
  122         }
  123 
  124         *is_breakpoint = FALSE;
  125 
  126         if (db_run_mode == STEP_INVISIBLE) {
  127             db_run_mode = STEP_CONTINUE;
  128             return (FALSE);     /* continue */
  129         }
  130         if (db_run_mode == STEP_COUNT) {
  131             return (FALSE); /* continue */
  132         }
  133         if (db_run_mode == STEP_ONCE) {
  134             if (--db_loop_count > 0) {
  135                 if (db_sstep_print) {
  136                     db_printf("\t\t");
  137                     db_print_loc_and_inst(pc);
  138                     db_printf("\n");
  139                 }
  140                 return (FALSE); /* continue */
  141             }
  142         }
  143         if (db_run_mode == STEP_RETURN) {
  144             /* continue until matching return */
  145             db_expr_t ins;
  146 
  147             ins = db_get_value(pc, sizeof(int), FALSE);
  148             if (!inst_trap_return(ins) &&
  149                 (!inst_return(ins) || --db_call_depth != 0)) {
  150                 if (db_sstep_print) {
  151                     if (inst_call(ins) || inst_return(ins)) {
  152                         register int i;
  153 
  154                         db_printf("[after %6d]     ", db_inst_count);
  155                         for (i = db_call_depth; --i > 0; )
  156                             db_printf("  ");
  157                         db_print_loc_and_inst(pc);
  158                         db_printf("\n");
  159                     }
  160                 }
  161                 if (inst_call(ins))
  162                     db_call_depth++;
  163                 return (FALSE); /* continue */
  164             }
  165         }
  166         if (db_run_mode == STEP_CALLT) {
  167             /* continue until call or return */
  168             db_expr_t ins;
  169 
  170             ins = db_get_value(pc, sizeof(int), FALSE);
  171             if (!inst_call(ins) &&
  172                 !inst_return(ins) &&
  173                 !inst_trap_return(ins)) {
  174                 return (FALSE); /* continue */
  175             }
  176         }
  177         db_run_mode = STEP_NONE;
  178         return (TRUE);
  179 }
  180 
  181 void
  182 db_restart_at_pc(boolean_t watchpt)
  183 {
  184         register db_addr_t      pc = PC_REGS();
  185 
  186         if ((db_run_mode == STEP_COUNT) ||
  187             (db_run_mode == STEP_RETURN) ||
  188             (db_run_mode == STEP_CALLT)) {
  189             db_expr_t           ins;
  190 
  191             /*
  192              * We are about to execute this instruction,
  193              * so count it now.
  194              */
  195 
  196             ins = db_get_value(pc, sizeof(int), FALSE);
  197             db_inst_count++;
  198             db_load_count += inst_load(ins);
  199             db_store_count += inst_store(ins);
  200 #ifdef  SOFTWARE_SSTEP
  201             /* XXX works on mips, but... */
  202             if (inst_branch(ins) || inst_call(ins)) {
  203                 ins = db_get_value(next_instr_address(pc,1),
  204                                    sizeof(int), FALSE);
  205                 db_inst_count++;
  206                 db_load_count += inst_load(ins);
  207                 db_store_count += inst_store(ins);
  208             }
  209 #endif  /* SOFTWARE_SSTEP */
  210         }
  211 
  212         if (db_run_mode == STEP_CONTINUE) {
  213             if (watchpt || db_find_breakpoint_here(pc)) {
  214                 /*
  215                  * Step over breakpoint/watchpoint.
  216                  */
  217                 db_run_mode = STEP_INVISIBLE;
  218                 db_set_single_step();
  219             } else {
  220                 db_set_breakpoints();
  221                 db_set_watchpoints();
  222             }
  223         } else {
  224             db_set_single_step();
  225         }
  226 }
  227 
  228 #ifdef  SOFTWARE_SSTEP
  229 /*
  230  *      Software implementation of single-stepping.
  231  *      If your machine does not have a trace mode
  232  *      similar to the vax or sun ones you can use
  233  *      this implementation, done for the mips.
  234  *      Just define the above conditional and provide
  235  *      the functions/macros defined below.
  236  *
  237  * extern boolean_t
  238  *      inst_branch(),          returns true if the instruction might branch
  239  * extern unsigned
  240  *      branch_taken(),         return the address the instruction might
  241  *                              branch to
  242  *      db_getreg_val();        return the value of a user register,
  243  *                              as indicated in the hardware instruction
  244  *                              encoding, e.g. 8 for r8
  245  *
  246  * next_instr_address(pc,bd)    returns the address of the first
  247  *                              instruction following the one at "pc",
  248  *                              which is either in the taken path of
  249  *                              the branch (bd==1) or not.  This is
  250  *                              for machines (mips) with branch delays.
  251  *
  252  *      A single-step may involve at most 2 breakpoints -
  253  *      one for branch-not-taken and one for branch taken.
  254  *      If one of these addresses does not already have a breakpoint,
  255  *      we allocate a breakpoint and save it here.
  256  *      These breakpoints are deleted on return.
  257  */
  258 
  259 void
  260 db_set_single_step(void)
  261 {
  262         db_addr_t pc = PC_REGS(), brpc;
  263         unsigned inst;
  264 
  265         /*
  266          *      User was stopped at pc, e.g. the instruction
  267          *      at pc was not executed.
  268          */
  269         inst = db_get_value(pc, sizeof(int), FALSE);
  270         if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) {
  271                 brpc = branch_taken(inst, pc);
  272                 if (brpc != pc) {       /* self-branches are hopeless */
  273                         db_taken_bkpt = db_set_temp_breakpoint(brpc);
  274                 }
  275                 pc = next_instr_address(pc, 1);
  276         }
  277         pc = next_instr_address(pc, 0);
  278         db_not_taken_bkpt = db_set_temp_breakpoint(pc);
  279 }
  280 
  281 void
  282 db_clear_single_step(void)
  283 {
  284 
  285         if (db_not_taken_bkpt != 0) {
  286                 db_delete_temp_breakpoint(db_not_taken_bkpt);
  287                 db_not_taken_bkpt = 0;
  288         }
  289         if (db_taken_bkpt != 0) {
  290                 db_delete_temp_breakpoint(db_taken_bkpt);
  291                 db_taken_bkpt = 0;
  292         }
  293 }
  294 
  295 #endif  /* SOFTWARE_SSTEP */
  296 
  297 extern int      db_cmd_loop_done;
  298 
  299 /* single-step */
  300 /*ARGSUSED*/
  301 void
  302 db_single_step_cmd(addr, have_addr, count, modif)
  303         db_expr_t       addr;
  304         boolean_t       have_addr;
  305         db_expr_t       count;
  306         char *          modif;
  307 {
  308         boolean_t       print = FALSE;
  309 
  310         if (count == -1)
  311             count = 1;
  312 
  313         if (modif[0] == 'p')
  314             print = TRUE;
  315 
  316         db_run_mode = STEP_ONCE;
  317         db_loop_count = count;
  318         db_sstep_print = print;
  319         db_inst_count = 0;
  320         db_load_count = 0;
  321         db_store_count = 0;
  322 
  323         db_cmd_loop_done = 1;
  324 }
  325 
  326 /* trace and print until call/return */
  327 /*ARGSUSED*/
  328 void
  329 db_trace_until_call_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
  330     char *modif)
  331 {
  332         boolean_t       print = FALSE;
  333 
  334         if (modif[0] == 'p')
  335             print = TRUE;
  336 
  337         db_run_mode = STEP_CALLT;
  338         db_sstep_print = print;
  339         db_inst_count = 0;
  340         db_load_count = 0;
  341         db_store_count = 0;
  342 
  343         db_cmd_loop_done = 1;
  344 }
  345 
  346 /*ARGSUSED*/
  347 void
  348 db_trace_until_matching_cmd(db_expr_t addr, boolean_t have_addr,
  349     db_expr_t count, char *modif)
  350 {
  351         boolean_t       print = FALSE;
  352 
  353         if (modif[0] == 'p')
  354             print = TRUE;
  355 
  356         db_run_mode = STEP_RETURN;
  357         db_call_depth = 1;
  358         db_sstep_print = print;
  359         db_inst_count = 0;
  360         db_load_count = 0;
  361         db_store_count = 0;
  362 
  363         db_cmd_loop_done = 1;
  364 }
  365 
  366 /* continue */
  367 /*ARGSUSED*/
  368 void
  369 db_continue_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
  370     char *modif)
  371 {
  372         if (modif[0] == 'c')
  373             db_run_mode = STEP_COUNT;
  374         else
  375             db_run_mode = STEP_CONTINUE;
  376         db_inst_count = 0;
  377         db_load_count = 0;
  378         db_store_count = 0;
  379 
  380         db_cmd_loop_done = 1;
  381 }

Cache object: 8b801ccb00522b40e00ce36224a3978e


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