1 /* $OpenBSD: db_break.c,v 1.14 2010/11/27 19:59:11 miod Exp $ */
2 /* $NetBSD: db_break.c,v 1.7 1996/03/30 22:30:03 christos Exp $ */
5 * Mach Operating System
6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
9 * Permission to use, copy, modify and distribute this software and its
10 * documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 * Carnegie Mellon requests users of this software to return to
21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
26 * any improvements or extensions that they make and grant Carnegie Mellon
27 * the rights to redistribute these changes.
29 * Author: David B. Golub, Carnegie Mellon University
36 #include <sys/param.h>
39 #include <uvm/uvm_extern.h>
41 #include <machine/db_machdep.h> /* type definitions */
43 #include <ddb/db_lex.h>
44 #include <ddb/db_access.h>
45 #include <ddb/db_sym.h>
46 #include <ddb/db_break.h>
47 #include <ddb/db_output.h>
49 #define NBREAKPOINTS 100
50 struct db_breakpoint db_break_table
[NBREAKPOINTS
];
51 db_breakpoint_t db_next_free_breakpoint
= &db_break_table
[0];
52 db_breakpoint_t db_free_breakpoints
= 0;
53 db_breakpoint_t db_breakpoint_list
= 0;
56 db_breakpoint_alloc(void)
60 if ((bkpt
= db_free_breakpoints
) != 0) {
61 db_free_breakpoints
= bkpt
->link
;
64 if (db_next_free_breakpoint
== &db_break_table
[NBREAKPOINTS
]) {
65 db_printf("All breakpoints used.\n");
68 bkpt
= db_next_free_breakpoint
;
69 db_next_free_breakpoint
++;
75 db_breakpoint_free(db_breakpoint_t bkpt
)
77 bkpt
->link
= db_free_breakpoints
;
78 db_free_breakpoints
= bkpt
;
82 db_set_breakpoint(db_addr_t addr
, int count
)
86 if (db_find_breakpoint(addr
)) {
87 db_printf("Already set.\n");
91 #ifdef DB_VALID_BREAKPOINT
92 if (!DB_VALID_BREAKPOINT(addr
)) {
93 db_printf("Not a valid address for a breakpoint.\n");
98 bkpt
= db_breakpoint_alloc();
100 db_printf("Too many breakpoints.\n");
104 bkpt
->address
= addr
;
106 bkpt
->init_count
= count
;
109 bkpt
->link
= db_breakpoint_list
;
110 db_breakpoint_list
= bkpt
;
114 db_delete_breakpoint(db_addr_t addr
)
116 db_breakpoint_t bkpt
;
117 db_breakpoint_t
*prev
;
119 for (prev
= &db_breakpoint_list
; (bkpt
= *prev
) != 0;
120 prev
= &bkpt
->link
) {
121 if (bkpt
->address
== addr
) {
127 db_printf("Not set.\n");
131 db_breakpoint_free(bkpt
);
135 db_find_breakpoint(db_addr_t addr
)
137 db_breakpoint_t bkpt
;
139 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
)
140 if (bkpt
->address
== addr
)
146 boolean_t db_breakpoints_inserted
= TRUE
;
149 db_set_breakpoints(void)
151 db_breakpoint_t bkpt
;
153 if (!db_breakpoints_inserted
) {
154 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
156 db_get_value(bkpt
->address
, BKPT_SIZE
, FALSE
);
157 db_put_value(bkpt
->address
, BKPT_SIZE
,
158 BKPT_SET(bkpt
->bkpt_inst
));
160 db_breakpoints_inserted
= TRUE
;
165 db_clear_breakpoints(void)
167 db_breakpoint_t bkpt
;
169 if (db_breakpoints_inserted
) {
170 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
)
171 db_put_value(bkpt
->address
, BKPT_SIZE
, bkpt
->bkpt_inst
);
172 db_breakpoints_inserted
= FALSE
;
177 * Set a temporary breakpoint.
178 * The instruction is changed immediately,
179 * so the breakpoint does not have to be on the breakpoint list.
182 db_set_temp_breakpoint(db_addr_t addr
)
184 db_breakpoint_t bkpt
;
186 #ifdef DB_VALID_BREAKPOINT
187 if (!DB_VALID_BREAKPOINT(addr
)) {
188 db_printf("Not a valid address for a breakpoint.\n");
193 bkpt
= db_breakpoint_alloc();
195 db_printf("Too many breakpoints.\n");
199 bkpt
->address
= addr
;
200 bkpt
->flags
= BKPT_TEMP
;
201 bkpt
->init_count
= 1;
204 bkpt
->bkpt_inst
= db_get_value(bkpt
->address
, BKPT_SIZE
, FALSE
);
205 db_put_value(bkpt
->address
, BKPT_SIZE
, BKPT_SET(bkpt
->bkpt_inst
));
210 db_delete_temp_breakpoint(db_breakpoint_t bkpt
)
212 db_put_value(bkpt
->address
, BKPT_SIZE
, bkpt
->bkpt_inst
);
213 db_breakpoint_free(bkpt
);
220 db_list_breakpoints(void)
222 db_breakpoint_t bkpt
;
224 if (db_breakpoint_list
== NULL
) {
225 db_printf("No breakpoints set\n");
229 db_printf(" Count Address\n");
230 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
231 db_printf(" %5d ", bkpt
->init_count
);
232 db_printsym(bkpt
->address
, DB_STGY_PROC
, db_printf
);
237 /* Delete breakpoint */
240 db_delete_cmd(db_expr_t addr
, int have_addr
, db_expr_t count
, char *modif
)
242 db_delete_breakpoint((db_addr_t
)addr
);
245 /* Set breakpoint with skip count */
248 db_breakpoint_cmd(db_expr_t addr
, int have_addr
, db_expr_t count
, char *modif
)
253 db_set_breakpoint((db_addr_t
)addr
, count
);
256 /* list breakpoints */
259 db_listbreak_cmd(db_expr_t addr
, int have_addr
, db_expr_t count
, char *modif
)
261 db_list_breakpoints();