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

Cache object: 812260606c94cbf1025f1f15d12761c2


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