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  * 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 "AS IS"
   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 Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_watch.c,v $
   29  * Revision 2.10  93/01/14  17:26:16  danner
   30  *      64bit cleanup.
   31  *      [92/11/30            af]
   32  * 
   33  * Revision 2.9  92/08/03  17:32:31  jfriedl
   34  *      removed silly prototypes
   35  *      [92/08/02            jfriedl]
   36  * 
   37  * Revision 2.8  92/05/21  17:08:16  jfriedl
   38  *      tried prototypes.
   39  *      [92/05/20            jfriedl]
   40  * 
   41  * Revision 2.7  91/10/09  16:04:32  af
   42  *      Added user space watch point support including non current task.
   43  *      Changed "map" field of db_watchpoint structure to "task"
   44  *        for a user to easily understand the target space.
   45  *      [91/08/29            tak]
   46  * 
   47  * Revision 2.6  91/05/14  15:37:30  mrt
   48  *      Correcting copyright
   49  * 
   50  * Revision 2.5  91/02/05  17:07:27  mrt
   51  *      Changed to new Mach copyright
   52  *      [91/01/31  16:20:02  mrt]
   53  * 
   54  * Revision 2.4  91/01/08  15:09:24  rpd
   55  *      Use db_map_equal, db_map_current, db_map_addr.
   56  *      [90/11/10            rpd]
   57  * 
   58  * Revision 2.3  90/11/05  14:26:39  rpd
   59  *      Initialize db_watchpoints_inserted to TRUE.
   60  *      [90/11/04            rpd]
   61  * 
   62  * Revision 2.2  90/10/25  14:44:16  rwd
   63  *      Made db_watchpoint_cmd parse a size argument.
   64  *      [90/10/17            rpd]
   65  *      Generalized the watchpoint support.
   66  *      [90/10/16            rwd]
   67  *      Created.
   68  *      [90/10/16            rpd]
   69  * 
   70  */
   71 /*
   72  *      Author: Richard P. Draves, Carnegie Mellon University
   73  *      Date:   10/90
   74  */
   75 
   76 #include <mach/boolean.h>
   77 #include <mach/vm_param.h>
   78 #include <mach/machine/vm_types.h>
   79 #include <mach/machine/vm_param.h>
   80 #include <vm/vm_map.h>
   81 
   82 #include <machine/db_machdep.h>
   83 #include <ddb/db_lex.h>
   84 #include <ddb/db_watch.h>
   85 #include <ddb/db_access.h>
   86 #include <ddb/db_sym.h>
   87 #include <ddb/db_task_thread.h>
   88 
   89 
   90 
   91 /*
   92  * Watchpoints.
   93  */
   94 
   95 boolean_t       db_watchpoints_inserted = TRUE;
   96 
   97 #define NWATCHPOINTS    100
   98 struct db_watchpoint    db_watch_table[NWATCHPOINTS];
   99 db_watchpoint_t         db_next_free_watchpoint = &db_watch_table[0];
  100 db_watchpoint_t         db_free_watchpoints = 0;
  101 db_watchpoint_t         db_watchpoint_list = 0;
  102 
  103 extern vm_map_t         kernel_map;
  104 
  105 db_watchpoint_t
  106 db_watchpoint_alloc()
  107 {
  108         register db_watchpoint_t        watch;
  109 
  110         if ((watch = db_free_watchpoints) != 0) {
  111             db_free_watchpoints = watch->link;
  112             return (watch);
  113         }
  114         if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
  115             db_printf("All watchpoints used.\n");
  116             return (0);
  117         }
  118         watch = db_next_free_watchpoint;
  119         db_next_free_watchpoint++;
  120 
  121         return (watch);
  122 }
  123 
  124 void
  125 db_watchpoint_free(watch)
  126         register db_watchpoint_t        watch;
  127 {
  128         watch->link = db_free_watchpoints;
  129         db_free_watchpoints = watch;
  130 }
  131 
  132 void
  133 db_set_watchpoint(task, addr, size)
  134         task_t          task;
  135         db_addr_t       addr;
  136         vm_size_t       size;
  137 {
  138         register db_watchpoint_t        watch;
  139 
  140         /*
  141          *      Should we do anything fancy with overlapping regions?
  142          */
  143 
  144         for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
  145             if (watch->task == task &&
  146                 (watch->loaddr == addr) &&
  147                 (watch->hiaddr == addr+size)) {
  148                 db_printf("Already set.\n");
  149                 return;
  150             }
  151         }
  152 
  153         watch = db_watchpoint_alloc();
  154         if (watch == 0) {
  155             db_printf("Too many watchpoints.\n");
  156             return;
  157         }
  158 
  159         watch->task = task;
  160         watch->loaddr = addr;
  161         watch->hiaddr = addr+size;
  162 
  163         watch->link = db_watchpoint_list;
  164         db_watchpoint_list = watch;
  165 
  166         db_watchpoints_inserted = FALSE;
  167 }
  168 
  169 void
  170 db_delete_watchpoint(task, addr)
  171         task_t          task;
  172         db_addr_t       addr;
  173 {
  174         register db_watchpoint_t        watch;
  175         register db_watchpoint_t        *prev;
  176 
  177         for (prev = &db_watchpoint_list; (watch = *prev) != 0;
  178              prev = &watch->link) {
  179             if (watch->task == task &&
  180                 (watch->loaddr <= addr) &&
  181                 (addr < watch->hiaddr)) {
  182                 *prev = watch->link;
  183                 db_watchpoint_free(watch);
  184                 return;
  185             }
  186         }
  187 
  188         db_printf("Not set.\n");
  189 }
  190 
  191 void
  192 db_list_watchpoints()
  193 {
  194         register db_watchpoint_t watch;
  195         int      task_id;
  196 
  197         if (db_watchpoint_list == 0) {
  198             db_printf("No watchpoints set\n");
  199             return;
  200         }
  201 
  202         db_printf("Space      Address  Size\n");
  203         for (watch = db_watchpoint_list; watch != 0; watch = watch->link)  {
  204             if (watch->task == TASK_NULL)
  205                 db_printf("kernel  ");
  206             else {
  207                 task_id = db_lookup_task(watch->task);
  208                 if (task_id < 0)
  209                     db_printf("%*X", 2*sizeof(vm_offset_t), watch->task);
  210                 else
  211                     db_printf("task%-3d ", task_id);
  212             }
  213             db_printf("  %*X  %X\n", 2*sizeof(vm_offset_t), watch->loaddr,
  214                       watch->hiaddr - watch->loaddr);
  215         }
  216 }
  217 
  218 static int
  219 db_get_task(modif, taskp, addr)
  220         char            *modif;
  221         task_t          *taskp;
  222         db_addr_t       addr;
  223 {
  224         task_t          task = TASK_NULL;
  225         db_expr_t       value;
  226         boolean_t       user_space;
  227 
  228         user_space = db_option(modif, 'T');
  229         if (user_space) {
  230             if (db_expression(&value)) {
  231                 task = (task_t)value;
  232                 if (db_lookup_task(task) < 0) {
  233                     db_printf("bad task address %X\n", task);
  234                     return(-1);
  235                 }
  236             } else {
  237                 task = db_default_task;
  238                 if (task == TASK_NULL) {
  239                     if ((task = db_current_task()) == TASK_NULL) {
  240                         db_printf("no task\n");
  241                         return(-1);
  242                     }
  243                 }
  244             }
  245         }
  246         if (!DB_VALID_ADDRESS(addr, user_space)) {
  247             db_printf("Address %#X is not in %s space\n", addr, 
  248                         (user_space)? "user": "kernel");
  249             return(-1);
  250         }
  251         *taskp = task;
  252         return(0);
  253 }
  254 
  255 /* Delete watchpoint */
  256 /*ARGSUSED*/
  257 void
  258 db_deletewatch_cmd(addr, have_addr, count, modif)
  259         db_expr_t       addr;
  260         int             have_addr;
  261         db_expr_t       count;
  262         char *          modif;
  263 {
  264         task_t          task;
  265 
  266         if (db_get_task(modif, &task, addr) < 0)
  267             return;
  268         db_delete_watchpoint(task, addr);
  269 }
  270 
  271 /* Set watchpoint */
  272 /*ARGSUSED*/
  273 void
  274 db_watchpoint_cmd(addr, have_addr, count, modif)
  275         db_expr_t       addr;
  276         int             have_addr;
  277         db_expr_t       count;
  278         char *          modif;
  279 {
  280         vm_size_t       size;
  281         db_expr_t       value;
  282         task_t          task;
  283         boolean_t       db_option();
  284 
  285         if (db_get_task(modif, &task, addr) < 0)
  286             return;
  287         if (db_expression(&value))
  288             size = (vm_size_t) value;
  289         else
  290             size = sizeof(int);
  291         db_set_watchpoint(task, addr, size);
  292 }
  293 
  294 /* list watchpoints */
  295 void
  296 db_listwatch_cmd()
  297 {
  298         db_list_watchpoints();
  299 }
  300 
  301 void
  302 db_set_watchpoints()
  303 {
  304         register db_watchpoint_t        watch;
  305         vm_map_t                        map;
  306 
  307         if (!db_watchpoints_inserted) {
  308             for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
  309                 map = (watch->task)? watch->task->map: kernel_map;
  310                 pmap_protect(map->pmap,
  311                              trunc_page(watch->loaddr),
  312                              round_page(watch->hiaddr),
  313                              VM_PROT_READ);
  314             }
  315             db_watchpoints_inserted = TRUE;
  316         }
  317 }
  318 
  319 void
  320 db_clear_watchpoints()
  321 {
  322         db_watchpoints_inserted = FALSE;
  323 }
  324 
  325 boolean_t
  326 db_find_watchpoint(map, addr, regs)
  327         vm_map_t        map;
  328         db_addr_t       addr;
  329         db_regs_t       *regs;
  330 {
  331         register db_watchpoint_t watch;
  332         db_watchpoint_t found = 0;
  333         register task_t task_space;
  334 
  335         task_space = (map == kernel_map)? TASK_NULL: db_current_task();
  336         for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
  337             if (watch->task == task_space) {
  338                 if ((watch->loaddr <= addr) && (addr < watch->hiaddr))
  339                     return (TRUE);
  340                 else if ((trunc_page(watch->loaddr) <= addr) &&
  341                          (addr < round_page(watch->hiaddr)))
  342                     found = watch;
  343             }
  344         }
  345 
  346         /*
  347          *      We didn't hit exactly on a watchpoint, but we are
  348          *      in a protected region.  We want to single-step
  349          *      and then re-protect.
  350          */
  351 
  352         if (found) {
  353             db_watchpoints_inserted = FALSE;
  354             db_single_step(regs, task_space);
  355         }
  356 
  357         return (FALSE);
  358 }

Cache object: 524ebe6985919c445b112651bcb4d574


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