root/ddb/db_break.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_breakpoint_alloc
  2. db_breakpoint_free
  3. db_set_breakpoint
  4. db_delete_breakpoint
  5. db_find_breakpoint
  6. db_find_breakpoint_here
  7. db_set_breakpoints
  8. db_clear_breakpoints
  9. db_set_temp_breakpoint
  10. db_delete_temp_breakpoint
  11. db_list_breakpoints
  12. db_delete_cmd
  13. db_breakpoint_cmd
  14. db_listbreak_cmd
  15. db_map_equal
  16. db_map_current
  17. db_map_addr

    1 /*      $OpenBSD: db_break.c,v 1.13 2006/03/13 06:23:20 jsg Exp $       */
    2 /*      $NetBSD: db_break.c,v 1.7 1996/03/30 22:30:03 christos Exp $    */
    3 
    4 /* 
    5  * Mach Operating System
    6  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
    7  * All Rights Reserved.
    8  * 
    9  * Permission to use, copy, modify and distribute this software and its
   10  * documentation is hereby granted, provided that both the copyright
   11  * notice and this permission notice appear in all copies of the
   12  * software, derivative works or modified versions, and any portions
   13  * thereof, and that both notices appear in supporting documentation.
   14  * 
   15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   18  * 
   19  * Carnegie Mellon requests users of this software to return to
   20  * 
   21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   22  *  School of Computer Science
   23  *  Carnegie Mellon University
   24  *  Pittsburgh PA 15213-3890
   25  * 
   26  * any improvements or extensions that they make and grant Carnegie Mellon
   27  * the rights to redistribute these changes.
   28  *
   29  *      Author: David B. Golub, Carnegie Mellon University
   30  *      Date:   7/90
   31  */
   32 
   33 /*
   34  * Breakpoints.
   35  */
   36 #include <sys/param.h>
   37 #include <sys/proc.h>
   38 
   39 #include <uvm/uvm_extern.h>
   40 
   41 #include <machine/db_machdep.h>         /* type definitions */
   42 
   43 #include <ddb/db_lex.h>
   44 #include <ddb/db_access.h>
   45 #include <ddb/db_sym.h>
   46 #include <ddb/db_break.h>
   47 #include <ddb/db_output.h>
   48 
   49 #define NBREAKPOINTS    100
   50 struct db_breakpoint    db_break_table[NBREAKPOINTS];
   51 db_breakpoint_t         db_next_free_breakpoint = &db_break_table[0];
   52 db_breakpoint_t         db_free_breakpoints = 0;
   53 db_breakpoint_t         db_breakpoint_list = 0;
   54 
   55 db_breakpoint_t
   56 db_breakpoint_alloc(void)
   57 {
   58         db_breakpoint_t bkpt;
   59 
   60         if ((bkpt = db_free_breakpoints) != 0) {
   61             db_free_breakpoints = bkpt->link;
   62             return (bkpt);
   63         }
   64         if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
   65             db_printf("All breakpoints used.\n");
   66             return (0);
   67         }
   68         bkpt = db_next_free_breakpoint;
   69         db_next_free_breakpoint++;
   70 
   71         return (bkpt);
   72 }
   73 
   74 void
   75 db_breakpoint_free(db_breakpoint_t bkpt)
   76 {
   77         bkpt->link = db_free_breakpoints;
   78         db_free_breakpoints = bkpt;
   79 }
   80 
   81 void
   82 db_set_breakpoint(struct vm_map *map, db_addr_t addr, int count)
   83 {
   84         db_breakpoint_t bkpt;
   85 
   86         if (db_find_breakpoint(map, addr)) {
   87             db_printf("Already set.\n");
   88             return;
   89         }
   90 
   91 #ifdef DB_VALID_BREAKPOINT
   92         if (!DB_VALID_BREAKPOINT(addr)) {
   93                 db_printf("Not a valid address for a breakpoint.\n");
   94                 return;
   95         }       
   96 #endif
   97 
   98         bkpt = db_breakpoint_alloc();
   99         if (bkpt == 0) {
  100             db_printf("Too many breakpoints.\n");
  101             return;
  102         }
  103 
  104         bkpt->map = map;
  105         bkpt->address = addr;
  106         bkpt->flags = 0;
  107         bkpt->init_count = count;
  108         bkpt->count = count;
  109 
  110         bkpt->link = db_breakpoint_list;
  111         db_breakpoint_list = bkpt;
  112 }
  113 
  114 void
  115 db_delete_breakpoint(struct vm_map *map, db_addr_t addr)
  116 {
  117         db_breakpoint_t bkpt;
  118         db_breakpoint_t *prev;
  119 
  120         for (prev = &db_breakpoint_list;
  121              (bkpt = *prev) != 0;
  122              prev = &bkpt->link) {
  123             if (db_map_equal(bkpt->map, map) &&
  124                 (bkpt->address == addr)) {
  125                 *prev = bkpt->link;
  126                 break;
  127             }
  128         }
  129         if (bkpt == 0) {
  130             db_printf("Not set.\n");
  131             return;
  132         }
  133 
  134         db_breakpoint_free(bkpt);
  135 }
  136 
  137 db_breakpoint_t
  138 db_find_breakpoint(struct vm_map *map, db_addr_t addr)
  139 {
  140         db_breakpoint_t bkpt;
  141 
  142         for (bkpt = db_breakpoint_list;
  143              bkpt != 0;
  144              bkpt = bkpt->link)
  145         {
  146             if (db_map_equal(bkpt->map, map) &&
  147                 (bkpt->address == addr))
  148                 return (bkpt);
  149         }
  150         return (0);
  151 }
  152 
  153 db_breakpoint_t
  154 db_find_breakpoint_here(db_addr_t addr)
  155 {
  156     return db_find_breakpoint(db_map_addr(addr), addr);
  157 }
  158 
  159 boolean_t       db_breakpoints_inserted = TRUE;
  160 
  161 void
  162 db_set_breakpoints(void)
  163 {
  164         db_breakpoint_t bkpt;
  165 
  166         if (!db_breakpoints_inserted) {
  167 
  168             for (bkpt = db_breakpoint_list;
  169                  bkpt != 0;
  170                  bkpt = bkpt->link)
  171                 if (db_map_current(bkpt->map)) {
  172                     bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE,
  173                         FALSE);
  174                     db_put_value(bkpt->address, BKPT_SIZE,
  175                         BKPT_SET(bkpt->bkpt_inst));
  176                 }
  177             db_breakpoints_inserted = TRUE;
  178         }
  179 }
  180 
  181 void
  182 db_clear_breakpoints(void)
  183 {
  184         db_breakpoint_t bkpt;
  185 
  186         if (db_breakpoints_inserted) {
  187 
  188             for (bkpt = db_breakpoint_list;
  189                  bkpt != 0;
  190                  bkpt = bkpt->link)
  191                 if (db_map_current(bkpt->map)) {
  192                     db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
  193                 }
  194             db_breakpoints_inserted = FALSE;
  195         }
  196 }
  197 
  198 /*
  199  * Set a temporary breakpoint.
  200  * The instruction is changed immediately,
  201  * so the breakpoint does not have to be on the breakpoint list.
  202  */
  203 db_breakpoint_t
  204 db_set_temp_breakpoint(db_addr_t addr)
  205 {
  206         db_breakpoint_t bkpt;
  207 
  208 #ifdef DB_VALID_BREAKPOINT
  209         if (!DB_VALID_BREAKPOINT(addr)) {
  210                 db_printf("Not a valid address for a breakpoint.\n");
  211                 return (0);
  212         }       
  213 #endif
  214 
  215         bkpt = db_breakpoint_alloc();
  216         if (bkpt == 0) {
  217             db_printf("Too many breakpoints.\n");
  218             return (0);
  219         }
  220 
  221         bkpt->map = NULL;
  222         bkpt->address = addr;
  223         bkpt->flags = BKPT_TEMP;
  224         bkpt->init_count = 1;
  225         bkpt->count = 1;
  226 
  227         bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
  228         db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
  229         return bkpt;
  230 }
  231 
  232 void
  233 db_delete_temp_breakpoint(db_breakpoint_t bkpt)
  234 {
  235         db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
  236         db_breakpoint_free(bkpt);
  237 }
  238 
  239 /*
  240  * List breakpoints.
  241  */
  242 void
  243 db_list_breakpoints(void)
  244 {
  245         db_breakpoint_t bkpt;
  246 
  247         if (db_breakpoint_list == 0) {
  248             db_printf("No breakpoints set\n");
  249             return;
  250         }
  251 
  252         db_printf(" Map      Count    Address\n");
  253         for (bkpt = db_breakpoint_list;
  254              bkpt != 0;
  255              bkpt = bkpt->link)
  256         {
  257             db_printf("%s%p %5d    ",
  258                       db_map_current(bkpt->map) ? "*" : " ",
  259                       bkpt->map, bkpt->init_count);
  260             db_printsym(bkpt->address, DB_STGY_PROC, db_printf);
  261             db_printf("\n");
  262         }
  263 }
  264 
  265 /* Delete breakpoint */
  266 /*ARGSUSED*/
  267 void
  268 db_delete_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  269 {
  270         db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
  271 }
  272 
  273 /* Set breakpoint with skip count */
  274 /*ARGSUSED*/
  275 void
  276 db_breakpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  277 {
  278         if (count == -1)
  279             count = 1;
  280 
  281         db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
  282 }
  283 
  284 /* list breakpoints */
  285 /*ARGSUSED*/
  286 void
  287 db_listbreak_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  288 {
  289         db_list_breakpoints();
  290 }
  291 
  292 /*
  293  *      We want ddb to be usable before most of the kernel has been
  294  *      initialized.  In particular, current_thread() or kernel_map
  295  *      (or both) may be null.
  296  */
  297 
  298 boolean_t
  299 db_map_equal(struct vm_map *map1, struct vm_map *map2)
  300 {
  301         return ((map1 == map2) ||
  302                 ((map1 == NULL) && (map2 == kernel_map)) ||
  303                 ((map1 == kernel_map) && (map2 == NULL)));
  304 }
  305 
  306 boolean_t
  307 db_map_current(struct vm_map *map)
  308 {
  309 #if 0
  310         thread_t        thread;
  311 
  312         return ((map == NULL) ||
  313                 (map == kernel_map) ||
  314                 (((thread = current_thread()) != NULL) &&
  315                  (map == thread->proc->map)));
  316 #else
  317         return (1);
  318 #endif
  319 }
  320 
  321 struct vm_map *
  322 db_map_addr(vaddr_t addr)
  323 {
  324 #if 0
  325         thread_t        thread;
  326 
  327         /*
  328          *      We want to return kernel_map for all
  329          *      non-user addresses, even when debugging
  330          *      kernel tasks with their own maps.
  331          */
  332 
  333         if ((VM_MIN_ADDRESS <= addr) &&
  334             (addr < VM_MAX_ADDRESS) &&
  335             ((thread = current_thread()) != NULL))
  336             return thread->proc->map;
  337         else
  338 #endif
  339             return kernel_map;
  340 }

/* [<][>][^][v][top][bottom][index][help] */