root/ddb/db_watch.c

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

DEFINITIONS

This source file includes following definitions.
  1. db_watchpoint_alloc
  2. db_watchpoint_free
  3. db_set_watchpoint
  4. db_delete_watchpoint
  5. db_list_watchpoints
  6. db_deletewatch_cmd
  7. db_watchpoint_cmd
  8. db_listwatch_cmd
  9. db_set_watchpoints
  10. db_clear_watchpoints
  11. db_find_watchpoint

    1 /*      $OpenBSD: db_watch.c,v 1.9 2006/03/13 06:23:20 jsg Exp $ */
    2 /*      $NetBSD: db_watch.c,v 1.9 1996/03/30 22:30:12 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: Richard P. Draves, Carnegie Mellon University
   30  *      Date:   10/90
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/proc.h>
   35 
   36 #include <machine/db_machdep.h>
   37 
   38 #include <ddb/db_break.h>
   39 #include <ddb/db_watch.h>
   40 #include <ddb/db_lex.h>
   41 #include <ddb/db_access.h>
   42 #include <ddb/db_run.h>
   43 #include <ddb/db_sym.h>
   44 #include <ddb/db_output.h>
   45 #include <ddb/db_command.h>
   46 #include <ddb/db_extern.h>
   47 
   48 /*
   49  * Watchpoints.
   50  */
   51 
   52 boolean_t       db_watchpoints_inserted = TRUE;
   53 
   54 #define NWATCHPOINTS    100
   55 struct db_watchpoint    db_watch_table[NWATCHPOINTS];
   56 db_watchpoint_t         db_next_free_watchpoint = &db_watch_table[0];
   57 db_watchpoint_t         db_free_watchpoints = 0;
   58 db_watchpoint_t         db_watchpoint_list = 0;
   59 
   60 db_watchpoint_t
   61 db_watchpoint_alloc(void)
   62 {
   63         db_watchpoint_t watch;
   64 
   65         if ((watch = db_free_watchpoints) != 0) {
   66             db_free_watchpoints = watch->link;
   67             return (watch);
   68         }
   69         if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
   70             db_printf("All watchpoints used.\n");
   71             return (0);
   72         }
   73         watch = db_next_free_watchpoint;
   74         db_next_free_watchpoint++;
   75 
   76         return (watch);
   77 }
   78 
   79 void
   80 db_watchpoint_free(db_watchpoint_t watch)
   81 {
   82         watch->link = db_free_watchpoints;
   83         db_free_watchpoints = watch;
   84 }
   85 
   86 void
   87 db_set_watchpoint(struct vm_map *map, db_addr_t addr, vsize_t size)
   88 {
   89         db_watchpoint_t watch;
   90 
   91         if (map == NULL) {
   92             db_printf("No map.\n");
   93             return;
   94         }
   95 
   96         /*
   97          *      Should we do anything fancy with overlapping regions?
   98          */
   99 
  100         for (watch = db_watchpoint_list;
  101              watch != 0;
  102              watch = watch->link)
  103             if (db_map_equal(watch->map, map) &&
  104                 (watch->loaddr == addr) &&
  105                 (watch->hiaddr == addr+size)) {
  106                 db_printf("Already set.\n");
  107                 return;
  108             }
  109 
  110         watch = db_watchpoint_alloc();
  111         if (watch == 0) {
  112             db_printf("Too many watchpoints.\n");
  113             return;
  114         }
  115 
  116         watch->map = map;
  117         watch->loaddr = addr;
  118         watch->hiaddr = addr+size;
  119 
  120         watch->link = db_watchpoint_list;
  121         db_watchpoint_list = watch;
  122 
  123         db_watchpoints_inserted = FALSE;
  124 }
  125 
  126 void
  127 db_delete_watchpoint(struct vm_map *map, db_addr_t addr)
  128 {
  129         db_watchpoint_t watch;
  130         db_watchpoint_t *prev;
  131 
  132         for (prev = &db_watchpoint_list;
  133              (watch = *prev) != 0;
  134              prev = &watch->link)
  135             if (db_map_equal(watch->map, map) &&
  136                 (watch->loaddr <= addr) &&
  137                 (addr < watch->hiaddr)) {
  138                 *prev = watch->link;
  139                 db_watchpoint_free(watch);
  140                 return;
  141             }
  142 
  143         db_printf("Not set.\n");
  144 }
  145 
  146 void
  147 db_list_watchpoints(void)
  148 {
  149         db_watchpoint_t watch;
  150 
  151         if (db_watchpoint_list == 0) {
  152             db_printf("No watchpoints set\n");
  153             return;
  154         }
  155 
  156         db_printf(" Map        Address  Size\n");
  157         for (watch = db_watchpoint_list;
  158              watch != 0;
  159              watch = watch->link)
  160             db_printf("%s%p  %8lx  %lx\n",
  161                       db_map_current(watch->map) ? "*" : " ",
  162                       watch->map, watch->loaddr,
  163                       watch->hiaddr - watch->loaddr);
  164 }
  165 
  166 /* Delete watchpoint */
  167 /*ARGSUSED*/
  168 void
  169 db_deletewatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  170 {
  171         db_delete_watchpoint(db_map_addr(addr), addr);
  172 }
  173 
  174 /* Set watchpoint */
  175 /*ARGSUSED*/
  176 void
  177 db_watchpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  178 {
  179         vsize_t         size;
  180         db_expr_t       value;
  181 
  182         if (db_expression(&value))
  183             size = (vsize_t) value;
  184         else
  185             size = 4;
  186         db_skip_to_eol();
  187 
  188         db_set_watchpoint(db_map_addr(addr), addr, size);
  189 }
  190 
  191 /* list watchpoints */
  192 /*ARGSUSED*/
  193 void
  194 db_listwatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  195 {
  196         db_list_watchpoints();
  197 }
  198 
  199 void
  200 db_set_watchpoints(void)
  201 {
  202         db_watchpoint_t watch;
  203 
  204         if (!db_watchpoints_inserted && db_watchpoint_list != NULL) {
  205             for (watch = db_watchpoint_list;
  206                  watch != 0;
  207                  watch = watch->link)
  208                 pmap_protect(watch->map->pmap,
  209                              trunc_page(watch->loaddr),
  210                              round_page(watch->hiaddr),
  211                              VM_PROT_READ);
  212             pmap_update(watch->map->pmap);
  213             db_watchpoints_inserted = TRUE;
  214         }
  215 }
  216 
  217 void
  218 db_clear_watchpoints(void)
  219 {
  220         db_watchpoints_inserted = FALSE;
  221 }
  222 
  223 boolean_t
  224 db_find_watchpoint(struct vm_map *map, db_addr_t addr, db_regs_t *regs)
  225 {
  226         db_watchpoint_t watch;
  227         db_watchpoint_t found = 0;
  228 
  229         for (watch = db_watchpoint_list;
  230              watch != 0;
  231              watch = watch->link)
  232             if (db_map_equal(watch->map, map)) {
  233                 if ((watch->loaddr <= addr) &&
  234                     (addr < watch->hiaddr))
  235                     return (TRUE);
  236                 else if ((trunc_page(watch->loaddr) <= addr) &&
  237                          (addr < round_page(watch->hiaddr)))
  238                     found = watch;
  239             }
  240 
  241         /*
  242          *      We didn't hit exactly on a watchpoint, but we are
  243          *      in a protected region.  We want to single-step
  244          *      and then re-protect.
  245          */
  246 
  247         if (found) {
  248             db_watchpoints_inserted = FALSE;
  249             db_single_step(regs);
  250         }
  251 
  252         return (FALSE);
  253 }

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