Home | History | Annotate | Line # | Download | only in ddb
db_break.c revision 1.2.4.1
      1      1.1      cgd /*
      2      1.1      cgd  * Mach Operating System
      3      1.1      cgd  * Copyright (c) 1991,1990 Carnegie Mellon University
      4      1.1      cgd  * All Rights Reserved.
      5      1.1      cgd  *
      6      1.1      cgd  * Permission to use, copy, modify and distribute this software and its
      7      1.1      cgd  * documentation is hereby granted, provided that both the copyright
      8      1.1      cgd  * notice and this permission notice appear in all copies of the
      9      1.1      cgd  * software, derivative works or modified versions, and any portions
     10      1.1      cgd  * thereof, and that both notices appear in supporting documentation.
     11      1.1      cgd  *
     12      1.1      cgd  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
     13      1.1      cgd  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     14      1.1      cgd  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     15      1.1      cgd  *
     16      1.1      cgd  * Carnegie Mellon requests users of this software to return to
     17      1.1      cgd  *
     18      1.1      cgd  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     19      1.1      cgd  *  School of Computer Science
     20      1.1      cgd  *  Carnegie Mellon University
     21      1.1      cgd  *  Pittsburgh PA 15213-3890
     22      1.1      cgd  *
     23      1.1      cgd  * any improvements or extensions that they make and grant Carnegie the
     24      1.1      cgd  * rights to redistribute these changes.
     25      1.1      cgd  */
     26      1.1      cgd /*
     27  1.2.4.1  mycroft  * $Id: db_break.c,v 1.2.4.1 1993/11/14 22:48:28 mycroft Exp $
     28      1.2      cgd  *
     29      1.1      cgd  * HISTORY
     30      1.1      cgd  * $Log: db_break.c,v $
     31  1.2.4.1  mycroft  * Revision 1.2.4.1  1993/11/14 22:48:28  mycroft
     32  1.2.4.1  mycroft  * Canonicalize all #includes.
     33  1.2.4.1  mycroft  *
     34      1.2      cgd  * Revision 1.2  1993/05/20  03:39:08  cgd
     35      1.2      cgd  * add explicit rcs id
     36      1.2      cgd  *
     37      1.1      cgd  * Revision 1.1.1.1  1993/03/21  09:46:26  cgd
     38      1.1      cgd  * initial import of 386bsd-0.1 sources
     39      1.1      cgd  *
     40      1.1      cgd  * Revision 1.1  1992/03/25  21:44:57  pace
     41      1.1      cgd  * Initial revision
     42      1.1      cgd  *
     43      1.1      cgd  * Revision 2.7  91/02/05  17:06:00  mrt
     44      1.1      cgd  * 	Changed to new Mach copyright
     45      1.1      cgd  * 	[91/01/31  16:17:01  mrt]
     46      1.1      cgd  *
     47      1.1      cgd  * Revision 2.6  91/01/08  15:09:03  rpd
     48      1.1      cgd  * 	Added db_map_equal, db_map_current, db_map_addr.
     49      1.1      cgd  * 	[90/11/10            rpd]
     50      1.1      cgd  *
     51      1.1      cgd  * Revision 2.5  90/11/05  14:26:32  rpd
     52      1.1      cgd  * 	Initialize db_breakpoints_inserted to TRUE.
     53      1.1      cgd  * 	[90/11/04            rpd]
     54      1.1      cgd  *
     55      1.1      cgd  * Revision 2.4  90/10/25  14:43:33  rwd
     56      1.1      cgd  * 	Added map field to breakpoints.
     57      1.1      cgd  * 	Added map argument to db_set_breakpoint, db_delete_breakpoint,
     58      1.1      cgd  * 	db_find_breakpoint.  Added db_find_breakpoint_here.
     59      1.1      cgd  * 	[90/10/18            rpd]
     60      1.1      cgd  *
     61      1.1      cgd  * Revision 2.3  90/09/28  16:57:07  jsb
     62      1.1      cgd  * 	Fixed db_breakpoint_free.
     63      1.1      cgd  * 	[90/09/18            rpd]
     64      1.1      cgd  *
     65      1.1      cgd  * Revision 2.2  90/08/27  21:49:53  dbg
     66      1.1      cgd  * 	Reflected changes in db_printsym()'s calling seq.
     67      1.1      cgd  * 	[90/08/20            af]
     68      1.1      cgd  * 	Clear breakpoints only if inserted.
     69      1.1      cgd  * 	Reduce lint.
     70      1.1      cgd  * 	[90/08/07            dbg]
     71      1.1      cgd  * 	Created.
     72      1.1      cgd  * 	[90/07/25            dbg]
     73      1.1      cgd  *
     74      1.1      cgd  */
     75      1.1      cgd /*
     76      1.1      cgd  *	Author: David B. Golub, Carnegie Mellon University
     77      1.1      cgd  *	Date:	7/90
     78      1.1      cgd  */
     79  1.2.4.1  mycroft /*
     80  1.2.4.1  mycroft  * Breakpoints.
     81      1.1      cgd  */
     82      1.1      cgd #include <sys/param.h>
     83      1.1      cgd #include <sys/proc.h>
     84      1.1      cgd #include <machine/db_machdep.h>		/* type definitions */
     85      1.1      cgd 
     86      1.1      cgd #include <ddb/db_lex.h>
     87      1.1      cgd #include <ddb/db_break.h>
     88      1.1      cgd #include <ddb/db_access.h>
     89      1.1      cgd #include <ddb/db_sym.h>
     90      1.1      cgd #include <ddb/db_break.h>
     91      1.1      cgd 
     92      1.1      cgd extern boolean_t db_map_equal();
     93      1.1      cgd extern boolean_t db_map_current();
     94      1.1      cgd extern vm_map_t db_map_addr();
     95      1.1      cgd 
     96      1.1      cgd #define	NBREAKPOINTS	100
     97      1.1      cgd struct db_breakpoint	db_break_table[NBREAKPOINTS];
     98      1.1      cgd db_breakpoint_t		db_next_free_breakpoint = &db_break_table[0];
     99      1.1      cgd db_breakpoint_t		db_free_breakpoints = 0;
    100      1.1      cgd db_breakpoint_t		db_breakpoint_list = 0;
    101      1.1      cgd 
    102      1.1      cgd db_breakpoint_t
    103      1.1      cgd db_breakpoint_alloc()
    104      1.1      cgd {
    105      1.1      cgd 	register db_breakpoint_t	bkpt;
    106      1.1      cgd 
    107      1.1      cgd 	if ((bkpt = db_free_breakpoints) != 0) {
    108      1.1      cgd 	    db_free_breakpoints = bkpt->link;
    109      1.1      cgd 	    return (bkpt);
    110      1.1      cgd 	}
    111      1.1      cgd 	if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
    112      1.1      cgd 	    db_printf("All breakpoints used.\n");
    113      1.1      cgd 	    return (0);
    114      1.1      cgd 	}
    115      1.1      cgd 	bkpt = db_next_free_breakpoint;
    116      1.1      cgd 	db_next_free_breakpoint++;
    117      1.1      cgd 
    118      1.1      cgd 	return (bkpt);
    119      1.1      cgd }
    120      1.1      cgd 
    121      1.1      cgd void
    122      1.1      cgd db_breakpoint_free(bkpt)
    123      1.1      cgd 	register db_breakpoint_t	bkpt;
    124      1.1      cgd {
    125      1.1      cgd 	bkpt->link = db_free_breakpoints;
    126      1.1      cgd 	db_free_breakpoints = bkpt;
    127      1.1      cgd }
    128      1.1      cgd 
    129      1.1      cgd void
    130      1.1      cgd db_set_breakpoint(map, addr, count)
    131      1.1      cgd 	vm_map_t	map;
    132      1.1      cgd 	db_addr_t	addr;
    133      1.1      cgd 	int		count;
    134      1.1      cgd {
    135      1.1      cgd 	register db_breakpoint_t	bkpt;
    136      1.1      cgd 
    137      1.1      cgd 	if (db_find_breakpoint(map, addr)) {
    138      1.1      cgd 	    db_printf("Already set.\n");
    139      1.1      cgd 	    return;
    140      1.1      cgd 	}
    141      1.1      cgd 
    142      1.1      cgd 	bkpt = db_breakpoint_alloc();
    143      1.1      cgd 	if (bkpt == 0) {
    144      1.1      cgd 	    db_printf("Too many breakpoints.\n");
    145      1.1      cgd 	    return;
    146      1.1      cgd 	}
    147      1.1      cgd 
    148      1.1      cgd 	bkpt->map = map;
    149      1.1      cgd 	bkpt->address = addr;
    150      1.1      cgd 	bkpt->flags = 0;
    151      1.1      cgd 	bkpt->init_count = count;
    152      1.1      cgd 	bkpt->count = count;
    153      1.1      cgd 
    154      1.1      cgd 	bkpt->link = db_breakpoint_list;
    155      1.1      cgd 	db_breakpoint_list = bkpt;
    156      1.1      cgd }
    157      1.1      cgd 
    158      1.1      cgd void
    159      1.1      cgd db_delete_breakpoint(map, addr)
    160      1.1      cgd 	vm_map_t	map;
    161      1.1      cgd 	db_addr_t	addr;
    162      1.1      cgd {
    163      1.1      cgd 	register db_breakpoint_t	bkpt;
    164      1.1      cgd 	register db_breakpoint_t	*prev;
    165      1.1      cgd 
    166      1.1      cgd 	for (prev = &db_breakpoint_list;
    167      1.1      cgd 	     (bkpt = *prev) != 0;
    168      1.1      cgd 	     prev = &bkpt->link) {
    169      1.1      cgd 	    if (db_map_equal(bkpt->map, map) &&
    170      1.1      cgd 		(bkpt->address == addr)) {
    171      1.1      cgd 		*prev = bkpt->link;
    172      1.1      cgd 		break;
    173      1.1      cgd 	    }
    174      1.1      cgd 	}
    175      1.1      cgd 	if (bkpt == 0) {
    176      1.1      cgd 	    db_printf("Not set.\n");
    177      1.1      cgd 	    return;
    178      1.1      cgd 	}
    179      1.1      cgd 
    180      1.1      cgd 	db_breakpoint_free(bkpt);
    181      1.1      cgd }
    182      1.1      cgd 
    183      1.1      cgd db_breakpoint_t
    184      1.1      cgd db_find_breakpoint(map, addr)
    185      1.1      cgd 	vm_map_t	map;
    186      1.1      cgd 	db_addr_t	addr;
    187      1.1      cgd {
    188      1.1      cgd 	register db_breakpoint_t	bkpt;
    189      1.1      cgd 
    190      1.1      cgd 	for (bkpt = db_breakpoint_list;
    191      1.1      cgd 	     bkpt != 0;
    192      1.1      cgd 	     bkpt = bkpt->link)
    193      1.1      cgd 	{
    194      1.1      cgd 	    if (db_map_equal(bkpt->map, map) &&
    195      1.1      cgd 		(bkpt->address == addr))
    196      1.1      cgd 		return (bkpt);
    197      1.1      cgd 	}
    198      1.1      cgd 	return (0);
    199      1.1      cgd }
    200      1.1      cgd 
    201      1.1      cgd db_breakpoint_t
    202      1.1      cgd db_find_breakpoint_here(addr)
    203      1.1      cgd 	db_addr_t	addr;
    204      1.1      cgd {
    205      1.1      cgd     return db_find_breakpoint(db_map_addr(addr), addr);
    206      1.1      cgd }
    207      1.1      cgd 
    208      1.1      cgd boolean_t	db_breakpoints_inserted = TRUE;
    209      1.1      cgd 
    210      1.1      cgd void
    211      1.1      cgd db_set_breakpoints()
    212      1.1      cgd {
    213      1.1      cgd 	register db_breakpoint_t	bkpt;
    214      1.1      cgd 
    215      1.1      cgd 	if (!db_breakpoints_inserted) {
    216      1.1      cgd 
    217      1.1      cgd 	    for (bkpt = db_breakpoint_list;
    218      1.1      cgd 	         bkpt != 0;
    219      1.1      cgd 	         bkpt = bkpt->link)
    220      1.1      cgd 		if (db_map_current(bkpt->map)) {
    221      1.1      cgd 		    bkpt->bkpt_inst = db_get_value(bkpt->address,
    222      1.1      cgd 						   BKPT_SIZE,
    223      1.1      cgd 						   FALSE);
    224      1.1      cgd 		    db_put_value(bkpt->address,
    225      1.1      cgd 				 BKPT_SIZE,
    226      1.1      cgd 				 BKPT_SET(bkpt->bkpt_inst));
    227      1.1      cgd 		}
    228      1.1      cgd 	    db_breakpoints_inserted = TRUE;
    229      1.1      cgd 	}
    230      1.1      cgd }
    231      1.1      cgd 
    232      1.1      cgd void
    233      1.1      cgd db_clear_breakpoints()
    234      1.1      cgd {
    235      1.1      cgd 	register db_breakpoint_t	bkpt;
    236      1.1      cgd 
    237      1.1      cgd 	if (db_breakpoints_inserted) {
    238      1.1      cgd 
    239      1.1      cgd 	    for (bkpt = db_breakpoint_list;
    240      1.1      cgd 	         bkpt != 0;
    241      1.1      cgd 		 bkpt = bkpt->link)
    242      1.1      cgd 		if (db_map_current(bkpt->map)) {
    243      1.1      cgd 		    db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
    244      1.1      cgd 		}
    245      1.1      cgd 	    db_breakpoints_inserted = FALSE;
    246      1.1      cgd 	}
    247      1.1      cgd }
    248      1.1      cgd 
    249      1.1      cgd /*
    250      1.1      cgd  * Set a temporary breakpoint.
    251      1.1      cgd  * The instruction is changed immediately,
    252      1.1      cgd  * so the breakpoint does not have to be on the breakpoint list.
    253      1.1      cgd  */
    254      1.1      cgd db_breakpoint_t
    255      1.1      cgd db_set_temp_breakpoint(addr)
    256      1.1      cgd 	db_addr_t	addr;
    257      1.1      cgd {
    258      1.1      cgd 	register db_breakpoint_t	bkpt;
    259      1.1      cgd 
    260      1.1      cgd 	bkpt = db_breakpoint_alloc();
    261      1.1      cgd 	if (bkpt == 0) {
    262      1.1      cgd 	    db_printf("Too many breakpoints.\n");
    263      1.1      cgd 	    return 0;
    264      1.1      cgd 	}
    265      1.1      cgd 
    266      1.1      cgd 	bkpt->map = NULL;
    267      1.1      cgd 	bkpt->address = addr;
    268      1.1      cgd 	bkpt->flags = BKPT_TEMP;
    269      1.1      cgd 	bkpt->init_count = 1;
    270      1.1      cgd 	bkpt->count = 1;
    271      1.1      cgd 
    272      1.1      cgd 	bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
    273      1.1      cgd 	db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
    274      1.1      cgd 	return bkpt;
    275      1.1      cgd }
    276      1.1      cgd 
    277      1.1      cgd void
    278      1.1      cgd db_delete_temp_breakpoint(bkpt)
    279      1.1      cgd 	db_breakpoint_t	bkpt;
    280      1.1      cgd {
    281      1.1      cgd 	db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
    282      1.1      cgd 	db_breakpoint_free(bkpt);
    283      1.1      cgd }
    284      1.1      cgd 
    285      1.1      cgd /*
    286      1.1      cgd  * List breakpoints.
    287      1.1      cgd  */
    288      1.1      cgd void
    289      1.1      cgd db_list_breakpoints()
    290      1.1      cgd {
    291      1.1      cgd 	register db_breakpoint_t	bkpt;
    292      1.1      cgd 
    293      1.1      cgd 	if (db_breakpoint_list == 0) {
    294      1.1      cgd 	    db_printf("No breakpoints set\n");
    295      1.1      cgd 	    return;
    296      1.1      cgd 	}
    297      1.1      cgd 
    298      1.1      cgd 	db_printf(" Map      Count    Address\n");
    299      1.1      cgd 	for (bkpt = db_breakpoint_list;
    300      1.1      cgd 	     bkpt != 0;
    301      1.1      cgd 	     bkpt = bkpt->link)
    302      1.1      cgd 	{
    303      1.1      cgd 	    db_printf("%s%8x %5d    ",
    304      1.1      cgd 		      db_map_current(bkpt->map) ? "*" : " ",
    305      1.1      cgd 		      bkpt->map, bkpt->init_count);
    306      1.1      cgd 	    db_printsym(bkpt->address, DB_STGY_PROC);
    307      1.1      cgd 	    db_printf("\n");
    308      1.1      cgd 	}
    309      1.1      cgd }
    310      1.1      cgd 
    311      1.1      cgd /* Delete breakpoint */
    312      1.1      cgd /*ARGSUSED*/
    313      1.1      cgd void
    314      1.1      cgd db_delete_cmd(addr, have_addr, count, modif)
    315      1.1      cgd 	db_expr_t	addr;
    316      1.1      cgd 	int		have_addr;
    317      1.1      cgd 	db_expr_t	count;
    318      1.1      cgd 	char *		modif;
    319      1.1      cgd {
    320      1.1      cgd 	db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
    321      1.1      cgd }
    322      1.1      cgd 
    323      1.1      cgd /* Set breakpoint with skip count */
    324      1.1      cgd /*ARGSUSED*/
    325      1.1      cgd void
    326      1.1      cgd db_breakpoint_cmd(addr, have_addr, count, modif)
    327      1.1      cgd 	db_expr_t	addr;
    328      1.1      cgd 	int		have_addr;
    329      1.1      cgd 	db_expr_t	count;
    330      1.1      cgd 	char *		modif;
    331      1.1      cgd {
    332      1.1      cgd 	if (count == -1)
    333      1.1      cgd 	    count = 1;
    334      1.1      cgd 
    335      1.1      cgd 	db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
    336      1.1      cgd }
    337      1.1      cgd 
    338      1.1      cgd /* list breakpoints */
    339      1.1      cgd void
    340      1.1      cgd db_listbreak_cmd()
    341      1.1      cgd {
    342      1.1      cgd 	db_list_breakpoints();
    343      1.1      cgd }
    344      1.1      cgd 
    345      1.1      cgd #include <vm/vm_kern.h>
    346      1.1      cgd 
    347      1.1      cgd /*
    348      1.1      cgd  *	We want ddb to be usable before most of the kernel has been
    349      1.1      cgd  *	initialized.  In particular, current_thread() or kernel_map
    350      1.1      cgd  *	(or both) may be null.
    351      1.1      cgd  */
    352      1.1      cgd 
    353      1.1      cgd boolean_t
    354      1.1      cgd db_map_equal(map1, map2)
    355      1.1      cgd 	vm_map_t	map1, map2;
    356      1.1      cgd {
    357      1.1      cgd 	return ((map1 == map2) ||
    358      1.1      cgd 		((map1 == NULL) && (map2 == kernel_map)) ||
    359      1.1      cgd 		((map1 == kernel_map) && (map2 == NULL)));
    360      1.1      cgd }
    361      1.1      cgd 
    362      1.1      cgd boolean_t
    363      1.1      cgd db_map_current(map)
    364      1.1      cgd 	vm_map_t	map;
    365      1.1      cgd {
    366      1.1      cgd #if 0
    367      1.1      cgd 	thread_t	thread;
    368      1.1      cgd 
    369      1.1      cgd 	return ((map == NULL) ||
    370      1.1      cgd 		(map == kernel_map) ||
    371      1.1      cgd 		(((thread = current_thread()) != NULL) &&
    372      1.1      cgd 		 (map == thread->task->map)));
    373      1.1      cgd #else
    374      1.1      cgd 	return (1);
    375      1.1      cgd #endif
    376      1.1      cgd }
    377      1.1      cgd 
    378      1.1      cgd vm_map_t
    379      1.1      cgd db_map_addr(addr)
    380      1.1      cgd 	vm_offset_t addr;
    381      1.1      cgd {
    382      1.1      cgd #if 0
    383      1.1      cgd 	thread_t	thread;
    384      1.1      cgd 
    385      1.1      cgd 	/*
    386      1.1      cgd 	 *	We want to return kernel_map for all
    387      1.1      cgd 	 *	non-user addresses, even when debugging
    388      1.1      cgd 	 *	kernel tasks with their own maps.
    389      1.1      cgd 	 */
    390      1.1      cgd 
    391      1.1      cgd 	if ((VM_MIN_ADDRESS <= addr) &&
    392      1.1      cgd 	    (addr < VM_MAX_ADDRESS) &&
    393      1.1      cgd 	    ((thread = current_thread()) != NULL))
    394      1.1      cgd 	    return thread->task->map;
    395      1.1      cgd 	else
    396                   #endif
    397                   	    return kernel_map;
    398                   }
    399