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_break.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  */
   27 /*
   28  *      Author: David B. Golub, Carnegie Mellon University
   29  *      Date:   7/90
   30  */
   31 /*
   32  * Breakpoints.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/6.1/sys/ddb/db_break.c 139747 2005-01-06 01:34:41Z imp $");
   37 
   38 #include "opt_comconsole.h"
   39 
   40 #include <sys/param.h>
   41 
   42 #include <vm/vm.h>
   43 #include <vm/vm_kern.h>
   44 
   45 #include <ddb/ddb.h>
   46 #include <ddb/db_break.h>
   47 #include <ddb/db_access.h>
   48 #include <ddb/db_sym.h>
   49 
   50 #define NBREAKPOINTS    100
   51 static struct db_breakpoint     db_break_table[NBREAKPOINTS];
   52 static db_breakpoint_t          db_next_free_breakpoint = &db_break_table[0];
   53 static db_breakpoint_t          db_free_breakpoints = 0;
   54 static db_breakpoint_t          db_breakpoint_list = 0;
   55 
   56 static db_breakpoint_t  db_breakpoint_alloc(void);
   57 static void     db_breakpoint_free(db_breakpoint_t bkpt);
   58 static void     db_delete_breakpoint(vm_map_t map, db_addr_t addr);
   59 static db_breakpoint_t  db_find_breakpoint(vm_map_t map, db_addr_t addr);
   60 static void     db_list_breakpoints(void);
   61 static void     db_set_breakpoint(vm_map_t map, db_addr_t addr, int count);
   62 
   63 static db_breakpoint_t
   64 db_breakpoint_alloc()
   65 {
   66         register db_breakpoint_t        bkpt;
   67 
   68         if ((bkpt = db_free_breakpoints) != 0) {
   69             db_free_breakpoints = bkpt->link;
   70             return (bkpt);
   71         }
   72         if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
   73             db_printf("All breakpoints used.\n");
   74             return (0);
   75         }
   76         bkpt = db_next_free_breakpoint;
   77         db_next_free_breakpoint++;
   78 
   79         return (bkpt);
   80 }
   81 
   82 static void
   83 db_breakpoint_free(bkpt)
   84         register db_breakpoint_t        bkpt;
   85 {
   86         bkpt->link = db_free_breakpoints;
   87         db_free_breakpoints = bkpt;
   88 }
   89 
   90 static void
   91 db_set_breakpoint(map, addr, count)
   92         vm_map_t        map;
   93         db_addr_t       addr;
   94         int             count;
   95 {
   96         register db_breakpoint_t        bkpt;
   97 
   98         if (db_find_breakpoint(map, addr)) {
   99             db_printf("Already set.\n");
  100             return;
  101         }
  102 
  103         bkpt = db_breakpoint_alloc();
  104         if (bkpt == 0) {
  105             db_printf("Too many breakpoints.\n");
  106             return;
  107         }
  108 
  109         bkpt->map = map;
  110         bkpt->address = addr;
  111         bkpt->flags = 0;
  112         bkpt->init_count = count;
  113         bkpt->count = count;
  114 
  115         bkpt->link = db_breakpoint_list;
  116         db_breakpoint_list = bkpt;
  117 }
  118 
  119 static void
  120 db_delete_breakpoint(map, addr)
  121         vm_map_t        map;
  122         db_addr_t       addr;
  123 {
  124         register db_breakpoint_t        bkpt;
  125         register db_breakpoint_t        *prev;
  126 
  127         for (prev = &db_breakpoint_list;
  128              (bkpt = *prev) != 0;
  129              prev = &bkpt->link) {
  130             if (db_map_equal(bkpt->map, map) &&
  131                 (bkpt->address == addr)) {
  132                 *prev = bkpt->link;
  133                 break;
  134             }
  135         }
  136         if (bkpt == 0) {
  137             db_printf("Not set.\n");
  138             return;
  139         }
  140 
  141         db_breakpoint_free(bkpt);
  142 }
  143 
  144 static db_breakpoint_t
  145 db_find_breakpoint(map, addr)
  146         vm_map_t        map;
  147         db_addr_t       addr;
  148 {
  149         register db_breakpoint_t        bkpt;
  150 
  151         for (bkpt = db_breakpoint_list;
  152              bkpt != 0;
  153              bkpt = bkpt->link)
  154         {
  155             if (db_map_equal(bkpt->map, map) &&
  156                 (bkpt->address == addr))
  157                 return (bkpt);
  158         }
  159         return (0);
  160 }
  161 
  162 db_breakpoint_t
  163 db_find_breakpoint_here(addr)
  164         db_addr_t       addr;
  165 {
  166     return db_find_breakpoint(db_map_addr(addr), addr);
  167 }
  168 
  169 static boolean_t        db_breakpoints_inserted = TRUE;
  170 
  171 #ifndef BKPT_WRITE
  172 #define BKPT_WRITE(addr, storage)                               \
  173 do {                                                            \
  174         *storage = db_get_value(addr, BKPT_SIZE, FALSE);        \
  175         db_put_value(addr, BKPT_SIZE, BKPT_SET(*storage));      \
  176 } while (0)
  177 #endif
  178 
  179 #ifndef BKPT_CLEAR
  180 #define BKPT_CLEAR(addr, storage) \
  181         db_put_value(addr, BKPT_SIZE, *storage)
  182 #endif
  183 
  184 void
  185 db_set_breakpoints()
  186 {
  187         register db_breakpoint_t        bkpt;
  188 
  189         if (!db_breakpoints_inserted) {
  190 
  191                 for (bkpt = db_breakpoint_list;
  192                      bkpt != 0;
  193                      bkpt = bkpt->link)
  194                         if (db_map_current(bkpt->map)) {
  195                                 BKPT_WRITE(bkpt->address, &bkpt->bkpt_inst);
  196                         }
  197                 db_breakpoints_inserted = TRUE;
  198         }
  199 }
  200 
  201 void
  202 db_clear_breakpoints()
  203 {
  204         register db_breakpoint_t        bkpt;
  205 
  206         if (db_breakpoints_inserted) {
  207 
  208                 for (bkpt = db_breakpoint_list;
  209                      bkpt != 0;
  210                      bkpt = bkpt->link)
  211                         if (db_map_current(bkpt->map)) {
  212                                 BKPT_CLEAR(bkpt->address, &bkpt->bkpt_inst);
  213                         }
  214                 db_breakpoints_inserted = FALSE;
  215         }
  216 }
  217 
  218 #ifdef SOFTWARE_SSTEP
  219 /*
  220  * Set a temporary breakpoint.
  221  * The instruction is changed immediately,
  222  * so the breakpoint does not have to be on the breakpoint list.
  223  */
  224 db_breakpoint_t
  225 db_set_temp_breakpoint(addr)
  226         db_addr_t       addr;
  227 {
  228         register db_breakpoint_t        bkpt;
  229 
  230         bkpt = db_breakpoint_alloc();
  231         if (bkpt == 0) {
  232             db_printf("Too many breakpoints.\n");
  233             return 0;
  234         }
  235 
  236         bkpt->map = NULL;
  237         bkpt->address = addr;
  238         bkpt->flags = BKPT_TEMP;
  239         bkpt->init_count = 1;
  240         bkpt->count = 1;
  241 
  242         BKPT_WRITE(bkpt->address, &bkpt->bkpt_inst);
  243         return bkpt;
  244 }
  245 
  246 void
  247 db_delete_temp_breakpoint(bkpt)
  248         db_breakpoint_t bkpt;
  249 {
  250         BKPT_CLEAR(bkpt->address, &bkpt->bkpt_inst);
  251         db_breakpoint_free(bkpt);
  252 }
  253 #endif /* SOFTWARE_SSTEP */
  254 
  255 /*
  256  * List breakpoints.
  257  */
  258 static void
  259 db_list_breakpoints()
  260 {
  261         register db_breakpoint_t        bkpt;
  262 
  263         if (db_breakpoint_list == 0) {
  264             db_printf("No breakpoints set\n");
  265             return;
  266         }
  267 
  268         db_printf(" Map      Count    Address\n");
  269         for (bkpt = db_breakpoint_list;
  270              bkpt != 0;
  271              bkpt = bkpt->link) {
  272             db_printf("%s%8p %5d    ",
  273                       db_map_current(bkpt->map) ? "*" : " ",
  274                       (void *)bkpt->map, bkpt->init_count);
  275             db_printsym(bkpt->address, DB_STGY_PROC);
  276             db_printf("\n");
  277         }
  278 }
  279 
  280 /* Delete breakpoint */
  281 /*ARGSUSED*/
  282 void
  283 db_delete_cmd(addr, have_addr, count, modif)
  284         db_expr_t       addr;
  285         boolean_t       have_addr;
  286         db_expr_t       count;
  287         char *          modif;
  288 {
  289         db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
  290 }
  291 
  292 /* Set breakpoint with skip count */
  293 /*ARGSUSED*/
  294 void
  295 db_breakpoint_cmd(addr, have_addr, count, modif)
  296         db_expr_t       addr;
  297         boolean_t       have_addr;
  298         db_expr_t       count;
  299         char *          modif;
  300 {
  301         if (count == -1)
  302             count = 1;
  303 
  304         db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
  305 }
  306 
  307 /* list breakpoints */
  308 void
  309 db_listbreak_cmd(dummy1, dummy2, dummy3, dummy4)
  310         db_expr_t       dummy1;
  311         boolean_t       dummy2;
  312         db_expr_t       dummy3;
  313         char *          dummy4;
  314 {
  315         db_list_breakpoints();
  316 }
  317 
  318 /*
  319  *      We want ddb to be usable before most of the kernel has been
  320  *      initialized.  In particular, current_thread() or kernel_map
  321  *      (or both) may be null.
  322  */
  323 
  324 boolean_t
  325 db_map_equal(map1, map2)
  326         vm_map_t        map1, map2;
  327 {
  328         return ((map1 == map2) ||
  329                 ((map1 == NULL) && (map2 == kernel_map)) ||
  330                 ((map1 == kernel_map) && (map2 == NULL)));
  331 }
  332 
  333 boolean_t
  334 db_map_current(map)
  335         vm_map_t        map;
  336 {
  337 #if 0
  338         thread_t        thread;
  339 
  340         return ((map == NULL) ||
  341                 (map == kernel_map) ||
  342                 (((thread = current_thread()) != NULL) &&
  343                  (map == thread->task->map)));
  344 #else
  345         return (1);
  346 #endif
  347 }
  348 
  349 vm_map_t
  350 db_map_addr(addr)
  351         vm_offset_t addr;
  352 {
  353 #if 0
  354         thread_t        thread;
  355 
  356         /*
  357          *      We want to return kernel_map for all
  358          *      non-user addresses, even when debugging
  359          *      kernel tasks with their own maps.
  360          */
  361 
  362         if ((VM_MIN_ADDRESS <= addr) &&
  363             (addr < VM_MAX_ADDRESS) &&
  364             ((thread = current_thread()) != NULL))
  365             return thread->task->map;
  366         else
  367 #endif
  368             return kernel_map;
  369 }

Cache object: 4f777945a0cfa015dda04b8ef3c6d02a


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