Home | History | Annotate | Line # | Download | only in ddb
db_watch.c revision 1.6
      1  1.6  mycroft /*	$NetBSD: db_watch.c,v 1.6 1994/10/09 08:19:43 mycroft Exp $	*/
      2  1.5      cgd 
      3  1.1      cgd /*
      4  1.1      cgd  * Mach Operating System
      5  1.1      cgd  * Copyright (c) 1991,1990 Carnegie Mellon University
      6  1.1      cgd  * All Rights Reserved.
      7  1.1      cgd  *
      8  1.1      cgd  * Permission to use, copy, modify and distribute this software and its
      9  1.1      cgd  * documentation is hereby granted, provided that both the copyright
     10  1.1      cgd  * notice and this permission notice appear in all copies of the
     11  1.1      cgd  * software, derivative works or modified versions, and any portions
     12  1.1      cgd  * thereof, and that both notices appear in supporting documentation.
     13  1.1      cgd  *
     14  1.1      cgd  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
     15  1.1      cgd  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     16  1.1      cgd  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17  1.1      cgd  *
     18  1.1      cgd  * Carnegie Mellon requests users of this software to return to
     19  1.1      cgd  *
     20  1.1      cgd  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21  1.1      cgd  *  School of Computer Science
     22  1.1      cgd  *  Carnegie Mellon University
     23  1.1      cgd  *  Pittsburgh PA 15213-3890
     24  1.1      cgd  *
     25  1.1      cgd  * any improvements or extensions that they make and grant Carnegie the
     26  1.1      cgd  * rights to redistribute these changes.
     27  1.1      cgd  *
     28  1.1      cgd  * 	Author: Richard P. Draves, Carnegie Mellon University
     29  1.1      cgd  *	Date:	10/90
     30  1.1      cgd  */
     31  1.1      cgd 
     32  1.3  mycroft #include <sys/param.h>
     33  1.3  mycroft #include <sys/proc.h>
     34  1.3  mycroft 
     35  1.6  mycroft #include <ddb/db_watch.h>
     36  1.1      cgd #include <ddb/db_lex.h>
     37  1.1      cgd #include <ddb/db_access.h>
     38  1.1      cgd #include <ddb/db_sym.h>
     39  1.1      cgd 
     40  1.1      cgd /*
     41  1.1      cgd  * Watchpoints.
     42  1.1      cgd  */
     43  1.1      cgd 
     44  1.1      cgd boolean_t	db_watchpoints_inserted = TRUE;
     45  1.1      cgd 
     46  1.1      cgd #define	NWATCHPOINTS	100
     47  1.1      cgd struct db_watchpoint	db_watch_table[NWATCHPOINTS];
     48  1.1      cgd db_watchpoint_t		db_next_free_watchpoint = &db_watch_table[0];
     49  1.1      cgd db_watchpoint_t		db_free_watchpoints = 0;
     50  1.1      cgd db_watchpoint_t		db_watchpoint_list = 0;
     51  1.1      cgd 
     52  1.1      cgd db_watchpoint_t
     53  1.1      cgd db_watchpoint_alloc()
     54  1.1      cgd {
     55  1.1      cgd 	register db_watchpoint_t	watch;
     56  1.1      cgd 
     57  1.1      cgd 	if ((watch = db_free_watchpoints) != 0) {
     58  1.1      cgd 	    db_free_watchpoints = watch->link;
     59  1.1      cgd 	    return (watch);
     60  1.1      cgd 	}
     61  1.1      cgd 	if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
     62  1.1      cgd 	    db_printf("All watchpoints used.\n");
     63  1.1      cgd 	    return (0);
     64  1.1      cgd 	}
     65  1.1      cgd 	watch = db_next_free_watchpoint;
     66  1.1      cgd 	db_next_free_watchpoint++;
     67  1.1      cgd 
     68  1.1      cgd 	return (watch);
     69  1.1      cgd }
     70  1.1      cgd 
     71  1.1      cgd void
     72  1.1      cgd db_watchpoint_free(watch)
     73  1.1      cgd 	register db_watchpoint_t	watch;
     74  1.1      cgd {
     75  1.1      cgd 	watch->link = db_free_watchpoints;
     76  1.1      cgd 	db_free_watchpoints = watch;
     77  1.1      cgd }
     78  1.1      cgd 
     79  1.1      cgd void
     80  1.1      cgd db_set_watchpoint(map, addr, size)
     81  1.1      cgd 	vm_map_t	map;
     82  1.1      cgd 	db_addr_t	addr;
     83  1.1      cgd 	vm_size_t	size;
     84  1.1      cgd {
     85  1.1      cgd 	register db_watchpoint_t	watch;
     86  1.1      cgd 
     87  1.1      cgd 	if (map == NULL) {
     88  1.1      cgd 	    db_printf("No map.\n");
     89  1.1      cgd 	    return;
     90  1.1      cgd 	}
     91  1.1      cgd 
     92  1.1      cgd 	/*
     93  1.1      cgd 	 *	Should we do anything fancy with overlapping regions?
     94  1.1      cgd 	 */
     95  1.1      cgd 
     96  1.1      cgd 	for (watch = db_watchpoint_list;
     97  1.1      cgd 	     watch != 0;
     98  1.1      cgd 	     watch = watch->link)
     99  1.1      cgd 	    if (db_map_equal(watch->map, map) &&
    100  1.1      cgd 		(watch->loaddr == addr) &&
    101  1.1      cgd 		(watch->hiaddr == addr+size)) {
    102  1.1      cgd 		db_printf("Already set.\n");
    103  1.1      cgd 		return;
    104  1.1      cgd 	    }
    105  1.1      cgd 
    106  1.1      cgd 	watch = db_watchpoint_alloc();
    107  1.1      cgd 	if (watch == 0) {
    108  1.1      cgd 	    db_printf("Too many watchpoints.\n");
    109  1.1      cgd 	    return;
    110  1.1      cgd 	}
    111  1.1      cgd 
    112  1.1      cgd 	watch->map = map;
    113  1.1      cgd 	watch->loaddr = addr;
    114  1.1      cgd 	watch->hiaddr = addr+size;
    115  1.1      cgd 
    116  1.1      cgd 	watch->link = db_watchpoint_list;
    117  1.1      cgd 	db_watchpoint_list = watch;
    118  1.1      cgd 
    119  1.1      cgd 	db_watchpoints_inserted = FALSE;
    120  1.1      cgd }
    121  1.1      cgd 
    122  1.1      cgd void
    123  1.1      cgd db_delete_watchpoint(map, addr)
    124  1.1      cgd 	vm_map_t	map;
    125  1.1      cgd 	db_addr_t	addr;
    126  1.1      cgd {
    127  1.1      cgd 	register db_watchpoint_t	watch;
    128  1.1      cgd 	register db_watchpoint_t	*prev;
    129  1.1      cgd 
    130  1.1      cgd 	for (prev = &db_watchpoint_list;
    131  1.1      cgd 	     (watch = *prev) != 0;
    132  1.1      cgd 	     prev = &watch->link)
    133  1.1      cgd 	    if (db_map_equal(watch->map, map) &&
    134  1.1      cgd 		(watch->loaddr <= addr) &&
    135  1.1      cgd 		(addr < watch->hiaddr)) {
    136  1.1      cgd 		*prev = watch->link;
    137  1.1      cgd 		db_watchpoint_free(watch);
    138  1.1      cgd 		return;
    139  1.1      cgd 	    }
    140  1.1      cgd 
    141  1.1      cgd 	db_printf("Not set.\n");
    142  1.1      cgd }
    143  1.1      cgd 
    144  1.1      cgd void
    145  1.1      cgd db_list_watchpoints()
    146  1.1      cgd {
    147  1.1      cgd 	register db_watchpoint_t	watch;
    148  1.1      cgd 
    149  1.1      cgd 	if (db_watchpoint_list == 0) {
    150  1.1      cgd 	    db_printf("No watchpoints set\n");
    151  1.1      cgd 	    return;
    152  1.1      cgd 	}
    153  1.1      cgd 
    154  1.1      cgd 	db_printf(" Map        Address  Size\n");
    155  1.1      cgd 	for (watch = db_watchpoint_list;
    156  1.1      cgd 	     watch != 0;
    157  1.1      cgd 	     watch = watch->link)
    158  1.1      cgd 	    db_printf("%s%8x  %8x  %x\n",
    159  1.1      cgd 		      db_map_current(watch->map) ? "*" : " ",
    160  1.1      cgd 		      watch->map, watch->loaddr,
    161  1.1      cgd 		      watch->hiaddr - watch->loaddr);
    162  1.1      cgd }
    163  1.1      cgd 
    164  1.1      cgd /* Delete watchpoint */
    165  1.1      cgd /*ARGSUSED*/
    166  1.1      cgd void
    167  1.1      cgd db_deletewatch_cmd(addr, have_addr, count, modif)
    168  1.1      cgd 	db_expr_t	addr;
    169  1.1      cgd 	int		have_addr;
    170  1.1      cgd 	db_expr_t	count;
    171  1.1      cgd 	char *		modif;
    172  1.1      cgd {
    173  1.1      cgd 	db_delete_watchpoint(db_map_addr(addr), addr);
    174  1.1      cgd }
    175  1.1      cgd 
    176  1.1      cgd /* Set watchpoint */
    177  1.1      cgd /*ARGSUSED*/
    178  1.1      cgd void
    179  1.1      cgd db_watchpoint_cmd(addr, have_addr, count, modif)
    180  1.1      cgd 	db_expr_t	addr;
    181  1.1      cgd 	int		have_addr;
    182  1.1      cgd 	db_expr_t	count;
    183  1.1      cgd 	char *		modif;
    184  1.1      cgd {
    185  1.1      cgd 	vm_size_t	size;
    186  1.1      cgd 	db_expr_t	value;
    187  1.1      cgd 
    188  1.1      cgd 	if (db_expression(&value))
    189  1.1      cgd 	    size = (vm_size_t) value;
    190  1.1      cgd 	else
    191  1.1      cgd 	    size = 4;
    192  1.1      cgd 	db_skip_to_eol();
    193  1.1      cgd 
    194  1.1      cgd 	db_set_watchpoint(db_map_addr(addr), addr, size);
    195  1.1      cgd }
    196  1.1      cgd 
    197  1.1      cgd /* list watchpoints */
    198  1.1      cgd void
    199  1.1      cgd db_listwatch_cmd()
    200  1.1      cgd {
    201  1.1      cgd 	db_list_watchpoints();
    202  1.1      cgd }
    203  1.1      cgd 
    204  1.1      cgd void
    205  1.1      cgd db_set_watchpoints()
    206  1.1      cgd {
    207  1.1      cgd 	register db_watchpoint_t	watch;
    208  1.1      cgd 
    209  1.1      cgd 	if (!db_watchpoints_inserted) {
    210  1.1      cgd 	    for (watch = db_watchpoint_list;
    211  1.1      cgd 	         watch != 0;
    212  1.1      cgd 	         watch = watch->link)
    213  1.1      cgd 		pmap_protect(watch->map->pmap,
    214  1.1      cgd 			     trunc_page(watch->loaddr),
    215  1.1      cgd 			     round_page(watch->hiaddr),
    216  1.1      cgd 			     VM_PROT_READ);
    217  1.1      cgd 
    218  1.1      cgd 	    db_watchpoints_inserted = TRUE;
    219  1.1      cgd 	}
    220  1.1      cgd }
    221  1.1      cgd 
    222  1.1      cgd void
    223  1.1      cgd db_clear_watchpoints()
    224  1.1      cgd {
    225  1.1      cgd 	db_watchpoints_inserted = FALSE;
    226  1.1      cgd }
    227  1.1      cgd 
    228  1.1      cgd boolean_t
    229  1.1      cgd db_find_watchpoint(map, addr, regs)
    230  1.1      cgd 	vm_map_t	map;
    231  1.1      cgd 	db_addr_t	addr;
    232  1.1      cgd 	db_regs_t	*regs;
    233  1.1      cgd {
    234  1.1      cgd 	register db_watchpoint_t watch;
    235  1.1      cgd 	db_watchpoint_t found = 0;
    236  1.1      cgd 
    237  1.1      cgd 	for (watch = db_watchpoint_list;
    238  1.1      cgd 	     watch != 0;
    239  1.1      cgd 	     watch = watch->link)
    240  1.1      cgd 	    if (db_map_equal(watch->map, map)) {
    241  1.1      cgd 		if ((watch->loaddr <= addr) &&
    242  1.1      cgd 		    (addr < watch->hiaddr))
    243  1.1      cgd 		    return (TRUE);
    244  1.1      cgd 		else if ((trunc_page(watch->loaddr) <= addr) &&
    245  1.1      cgd 			 (addr < round_page(watch->hiaddr)))
    246  1.1      cgd 		    found = watch;
    247  1.1      cgd 	    }
    248  1.1      cgd 
    249  1.1      cgd 	/*
    250  1.1      cgd 	 *	We didn't hit exactly on a watchpoint, but we are
    251  1.1      cgd 	 *	in a protected region.  We want to single-step
    252  1.1      cgd 	 *	and then re-protect.
    253  1.1      cgd 	 */
    254  1.1      cgd 
    255  1.1      cgd 	if (found) {
    256  1.1      cgd 	    db_watchpoints_inserted = FALSE;
    257  1.1      cgd 	    db_single_step(regs);
    258  1.1      cgd 	}
    259  1.1      cgd 
    260  1.1      cgd 	return (FALSE);
    261  1.1      cgd }
    262