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

Cache object: c0361cb3c3e4138cd988f1ec5cfb850f


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