* Copyright (c) 1991,1990 Carnegie Mellon University
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
* Carnegie Mellon requests users of this software to return to
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
* $Id: db_break.c,v 1.2 1993/10/16 16:47:07 rgrimes Exp $
* Author: David B. Golub, Carnegie Mellon University
#include <ddb/db_break.h>
#include <ddb/db_access.h>
#include <ddb/db_break.h>
extern boolean_t
db_map_equal();
extern boolean_t
db_map_current();
extern vm_map_t
db_map_addr();
struct db_breakpoint db_break_table
[NBREAKPOINTS
];
db_breakpoint_t db_next_free_breakpoint
= &db_break_table
[0];
db_breakpoint_t db_free_breakpoints
= 0;
db_breakpoint_t db_breakpoint_list
= 0;
register db_breakpoint_t bkpt
;
if ((bkpt
= db_free_breakpoints
) != 0) {
db_free_breakpoints
= bkpt
->link
;
if (db_next_free_breakpoint
== &db_break_table
[NBREAKPOINTS
]) {
db_printf("All breakpoints used.\n");
bkpt
= db_next_free_breakpoint
;
db_next_free_breakpoint
++;
register db_breakpoint_t bkpt
;
bkpt
->link
= db_free_breakpoints
;
db_free_breakpoints
= bkpt
;
db_set_breakpoint(map
, addr
, count
)
register db_breakpoint_t bkpt
;
if (db_find_breakpoint(map
, addr
)) {
db_printf("Already set.\n");
bkpt
= db_breakpoint_alloc();
db_printf("Too many breakpoints.\n");
bkpt
->init_count
= count
;
bkpt
->link
= db_breakpoint_list
;
db_breakpoint_list
= bkpt
;
db_delete_breakpoint(map
, addr
)
register db_breakpoint_t bkpt
;
register db_breakpoint_t
*prev
;
for (prev
= &db_breakpoint_list
;
if (db_map_equal(bkpt
->map
, map
) &&
(bkpt
->address
== addr
)) {
db_breakpoint_free(bkpt
);
db_find_breakpoint(map
, addr
)
register db_breakpoint_t bkpt
;
for (bkpt
= db_breakpoint_list
;
if (db_map_equal(bkpt
->map
, map
) &&
db_find_breakpoint_here(addr
)
return db_find_breakpoint(db_map_addr(addr
), addr
);
boolean_t db_breakpoints_inserted
= TRUE
;
register db_breakpoint_t bkpt
;
if (!db_breakpoints_inserted
) {
for (bkpt
= db_breakpoint_list
;
if (db_map_current(bkpt
->map
)) {
bkpt
->bkpt_inst
= db_get_value(bkpt
->address
,
db_put_value(bkpt
->address
,
BKPT_SET(bkpt
->bkpt_inst
));
db_breakpoints_inserted
= TRUE
;
register db_breakpoint_t bkpt
;
if (db_breakpoints_inserted
) {
for (bkpt
= db_breakpoint_list
;
if (db_map_current(bkpt
->map
)) {
db_put_value(bkpt
->address
, BKPT_SIZE
, bkpt
->bkpt_inst
);
db_breakpoints_inserted
= FALSE
;
* Set a temporary breakpoint.
* The instruction is changed immediately,
* so the breakpoint does not have to be on the breakpoint list.
db_set_temp_breakpoint(addr
)
register db_breakpoint_t bkpt
;
bkpt
= db_breakpoint_alloc();
db_printf("Too many breakpoints.\n");
bkpt
->bkpt_inst
= db_get_value(bkpt
->address
, BKPT_SIZE
, FALSE
);
db_put_value(bkpt
->address
, BKPT_SIZE
, BKPT_SET(bkpt
->bkpt_inst
));
db_delete_temp_breakpoint(bkpt
)
db_put_value(bkpt
->address
, BKPT_SIZE
, bkpt
->bkpt_inst
);
db_breakpoint_free(bkpt
);
register db_breakpoint_t bkpt
;
if (db_breakpoint_list
== 0) {
db_printf("No breakpoints set\n");
db_printf(" Map Count Address\n");
for (bkpt
= db_breakpoint_list
;
db_map_current(bkpt
->map
) ? "*" : " ",
bkpt
->map
, bkpt
->init_count
);
db_printsym(bkpt
->address
, DB_STGY_PROC
);
db_delete_cmd(addr
, have_addr
, count
, modif
)
db_delete_breakpoint(db_map_addr(addr
), (db_addr_t
)addr
);
/* Set breakpoint with skip count */
db_breakpoint_cmd(addr
, have_addr
, count
, modif
)
db_set_breakpoint(db_map_addr(addr
), (db_addr_t
)addr
, count
);
db_listbreak_cmd(db_expr_t dummy1
, int dummy2
, db_expr_t dummy3
, char *dummy4
)
* We want ddb to be usable before most of the kernel has been
* initialized. In particular, current_thread() or kernel_map
return ((map1
== map2
) ||
((map1
== NULL
) && (map2
== kernel_map
)) ||
((map1
== kernel_map
) && (map2
== NULL
)));
(((thread
= current_thread()) != NULL
) &&
(map
== thread
->task
->map
)));
* We want to return kernel_map for all
* non-user addresses, even when debugging
* kernel tasks with their own maps.
if ((VM_MIN_ADDRESS
<= addr
) &&
(addr
< VM_MAX_ADDRESS
) &&
((thread
= current_thread()) != NULL
))
return thread
->task
->map
;