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

Cache object: 00cae78d63fddfe803753428ee5eba0c


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