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_watch.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  * SPDX-License-Identifier: MIT-CMU
    3  *
    4  * Mach Operating System
    5  * Copyright (c) 1991,1990 Carnegie Mellon University
    6  * All Rights Reserved.
    7  *
    8  * Permission to use, copy, modify and distribute this software and its
    9  * documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 /*
   29  *      Author: Richard P. Draves, Carnegie Mellon University
   30  *      Date:   10/90
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/lock.h>
   39 #include <sys/proc.h>
   40 
   41 #include <vm/vm.h>
   42 #include <vm/pmap.h>
   43 #include <vm/vm_map.h>
   44 
   45 #include <ddb/ddb.h>
   46 #include <ddb/db_watch.h>
   47 
   48 /*
   49  * Watchpoints.
   50  */
   51 
   52 static bool             db_watchpoints_inserted = true;
   53 
   54 #define NWATCHPOINTS    100
   55 static struct db_watchpoint     db_watch_table[NWATCHPOINTS];
   56 static db_watchpoint_t  db_next_free_watchpoint = &db_watch_table[0];
   57 static db_watchpoint_t  db_free_watchpoints = 0;
   58 static db_watchpoint_t  db_watchpoint_list = 0;
   59 
   60 static db_watchpoint_t  db_watchpoint_alloc(void);
   61 static void             db_watchpoint_free(db_watchpoint_t watch);
   62 static void             db_delete_watchpoint(vm_map_t map, db_addr_t addr);
   63 #ifdef notused
   64 static bool             db_find_watchpoint(vm_map_t map, db_addr_t addr,
   65                                         db_regs_t *regs);
   66 #endif
   67 static void             db_list_watchpoints(void);
   68 static void             db_set_watchpoint(vm_map_t map, db_addr_t addr,
   69                                        vm_size_t size);
   70 
   71 static db_watchpoint_t
   72 db_watchpoint_alloc(void)
   73 {
   74         db_watchpoint_t watch;
   75 
   76         if ((watch = db_free_watchpoints) != 0) {
   77             db_free_watchpoints = watch->link;
   78             return (watch);
   79         }
   80         if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
   81             db_printf("All watchpoints used.\n");
   82             return (0);
   83         }
   84         watch = db_next_free_watchpoint;
   85         db_next_free_watchpoint++;
   86 
   87         return (watch);
   88 }
   89 
   90 static void
   91 db_watchpoint_free(db_watchpoint_t watch)
   92 {
   93         watch->link = db_free_watchpoints;
   94         db_free_watchpoints = watch;
   95 }
   96 
   97 static void
   98 db_set_watchpoint(vm_map_t map, db_addr_t addr, vm_size_t size)
   99 {
  100         db_watchpoint_t watch;
  101 
  102         if (map == NULL) {
  103             db_printf("No map.\n");
  104             return;
  105         }
  106 
  107         /*
  108          *      Should we do anything fancy with overlapping regions?
  109          */
  110 
  111         for (watch = db_watchpoint_list;
  112              watch != 0;
  113              watch = watch->link)
  114             if (db_map_equal(watch->map, map) &&
  115                 (watch->loaddr == addr) &&
  116                 (watch->hiaddr == addr+size)) {
  117                 db_printf("Already set.\n");
  118                 return;
  119             }
  120 
  121         watch = db_watchpoint_alloc();
  122         if (watch == 0) {
  123             db_printf("Too many watchpoints.\n");
  124             return;
  125         }
  126 
  127         watch->map = map;
  128         watch->loaddr = addr;
  129         watch->hiaddr = addr+size;
  130 
  131         watch->link = db_watchpoint_list;
  132         db_watchpoint_list = watch;
  133 
  134         db_watchpoints_inserted = false;
  135 }
  136 
  137 static void
  138 db_delete_watchpoint(vm_map_t map, db_addr_t addr)
  139 {
  140         db_watchpoint_t watch;
  141         db_watchpoint_t *prev;
  142 
  143         for (prev = &db_watchpoint_list;
  144              (watch = *prev) != 0;
  145              prev = &watch->link)
  146             if (db_map_equal(watch->map, map) &&
  147                 (watch->loaddr <= addr) &&
  148                 (addr < watch->hiaddr)) {
  149                 *prev = watch->link;
  150                 db_watchpoint_free(watch);
  151                 return;
  152             }
  153 
  154         db_printf("Not set.\n");
  155 }
  156 
  157 static void
  158 db_list_watchpoints(void)
  159 {
  160         db_watchpoint_t watch;
  161 
  162         if (db_watchpoint_list == 0) {
  163             db_printf("No watchpoints set\n");
  164             return;
  165         }
  166 
  167 #ifdef __LP64__
  168         db_printf(" Map                Address          Size\n");
  169 #else
  170         db_printf(" Map        Address  Size\n");
  171 #endif
  172         for (watch = db_watchpoint_list;
  173              watch != 0;
  174              watch = watch->link)
  175 #ifdef __LP64__
  176             db_printf("%s%16p  %16lx  %lx\n",
  177 #else
  178             db_printf("%s%8p  %8lx  %lx\n",
  179 #endif
  180                       db_map_current(watch->map) ? "*" : " ",
  181                       (void *)watch->map, (long)watch->loaddr,
  182                       (long)watch->hiaddr - (long)watch->loaddr);
  183 }
  184 
  185 /* Delete watchpoint */
  186 /*ARGSUSED*/
  187 void
  188 db_deletewatch_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  189    char *modif)
  190 {
  191         db_delete_watchpoint(db_map_addr(addr), addr);
  192 }
  193 
  194 /* Set watchpoint */
  195 /*ARGSUSED*/
  196 void
  197 db_watchpoint_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  198    char *modif)
  199 {
  200         vm_size_t       size;
  201         db_expr_t       value;
  202 
  203         if (db_expression(&value))
  204             size = (vm_size_t) value;
  205         else
  206             size = 4;
  207         db_skip_to_eol();
  208 
  209         db_set_watchpoint(db_map_addr(addr), addr, size);
  210 }
  211 
  212 /*
  213  * At least one non-optional show-command must be implemented using
  214  * DB_SHOW_COMMAND() so that db_show_cmd_set gets created.  Here is one.
  215  */
  216 DB_SHOW_COMMAND(watches, db_listwatch_cmd)
  217 {
  218         db_list_watchpoints();
  219         db_md_list_watchpoints();
  220 }
  221 
  222 void
  223 db_set_watchpoints(void)
  224 {
  225         db_watchpoint_t watch;
  226 
  227         if (!db_watchpoints_inserted) {
  228             for (watch = db_watchpoint_list;
  229                  watch != 0;
  230                  watch = watch->link)
  231                 pmap_protect(watch->map->pmap,
  232                              trunc_page(watch->loaddr),
  233                              round_page(watch->hiaddr),
  234                              VM_PROT_READ);
  235 
  236             db_watchpoints_inserted = true;
  237         }
  238 }
  239 
  240 void
  241 db_clear_watchpoints(void)
  242 {
  243         db_watchpoints_inserted = false;
  244 }
  245 
  246 #ifdef notused
  247 static bool
  248 db_find_watchpoint(vm_map_t map, db_addr_t addr, db_regs_t regs)
  249 {
  250         db_watchpoint_t watch;
  251         db_watchpoint_t found = 0;
  252 
  253         for (watch = db_watchpoint_list;
  254              watch != 0;
  255              watch = watch->link)
  256             if (db_map_equal(watch->map, map)) {
  257                 if ((watch->loaddr <= addr) &&
  258                     (addr < watch->hiaddr))
  259                     return (true);
  260                 else if ((trunc_page(watch->loaddr) <= addr) &&
  261                          (addr < round_page(watch->hiaddr)))
  262                     found = watch;
  263             }
  264 
  265         /*
  266          *      We didn't hit exactly on a watchpoint, but we are
  267          *      in a protected region.  We want to single-step
  268          *      and then re-protect.
  269          */
  270 
  271         if (found) {
  272             db_watchpoints_inserted = false;
  273             db_single_step(regs);
  274         }
  275 
  276         return (false);
  277 }
  278 #endif
  279 
  280 
  281 
  282 /* Delete hardware watchpoint */
  283 /*ARGSUSED*/
  284 void
  285 db_deletehwatch_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  286    char *modif)
  287 {
  288         int rc;
  289 
  290         if (count < 0)
  291                 count = 4;
  292 
  293         rc = db_md_clr_watchpoint(addr, count);
  294         if (rc < 0)
  295                 db_printf("hardware watchpoint could not be deleted\n");
  296 }
  297 
  298 /* Set hardware watchpoint */
  299 /*ARGSUSED*/
  300 void
  301 db_hwatchpoint_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  302    char *modif)
  303 {
  304         int rc;
  305 
  306         if (count < 0)
  307                 count = 4;
  308 
  309         rc = db_md_set_watchpoint(addr, count);
  310         if (rc < 0)
  311                 db_printf("hardware watchpoint could not be set\n");
  312 }

Cache object: a18f0c3ae0eff45747336027fc0069fc


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