sync
[bitrig.git] / sys / ddb / db_break.c
blob04706be4540ba3d339d34c33100af24bfafa03e6
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 $ */
4 /*
5 * Mach Operating System
6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
7 * All Rights Reserved.
8 *
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
30 * Date: 7/90
34 * Breakpoints.
36 #include <sys/param.h>
37 #include <sys/proc.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;
55 db_breakpoint_t
56 db_breakpoint_alloc(void)
58 db_breakpoint_t bkpt;
60 if ((bkpt = db_free_breakpoints) != 0) {
61 db_free_breakpoints = bkpt->link;
62 return (bkpt);
64 if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
65 db_printf("All breakpoints used.\n");
66 return (0);
68 bkpt = db_next_free_breakpoint;
69 db_next_free_breakpoint++;
71 return (bkpt);
74 void
75 db_breakpoint_free(db_breakpoint_t bkpt)
77 bkpt->link = db_free_breakpoints;
78 db_free_breakpoints = bkpt;
81 void
82 db_set_breakpoint(db_addr_t addr, int count)
84 db_breakpoint_t bkpt;
86 if (db_find_breakpoint(addr)) {
87 db_printf("Already set.\n");
88 return;
91 #ifdef DB_VALID_BREAKPOINT
92 if (!DB_VALID_BREAKPOINT(addr)) {
93 db_printf("Not a valid address for a breakpoint.\n");
94 return;
96 #endif
98 bkpt = db_breakpoint_alloc();
99 if (bkpt == 0) {
100 db_printf("Too many breakpoints.\n");
101 return;
104 bkpt->address = addr;
105 bkpt->flags = 0;
106 bkpt->init_count = count;
107 bkpt->count = count;
109 bkpt->link = db_breakpoint_list;
110 db_breakpoint_list = bkpt;
113 void
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) {
122 *prev = bkpt->link;
123 break;
126 if (bkpt == 0) {
127 db_printf("Not set.\n");
128 return;
131 db_breakpoint_free(bkpt);
134 db_breakpoint_t
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)
141 return (bkpt);
143 return (0);
146 boolean_t db_breakpoints_inserted = TRUE;
148 void
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) {
155 bkpt->bkpt_inst =
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;
164 void
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.
181 db_breakpoint_t
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");
189 return (0);
191 #endif
193 bkpt = db_breakpoint_alloc();
194 if (bkpt == 0) {
195 db_printf("Too many breakpoints.\n");
196 return (0);
199 bkpt->address = addr;
200 bkpt->flags = BKPT_TEMP;
201 bkpt->init_count = 1;
202 bkpt->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));
206 return bkpt;
209 void
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);
217 * List breakpoints.
219 void
220 db_list_breakpoints(void)
222 db_breakpoint_t bkpt;
224 if (db_breakpoint_list == NULL) {
225 db_printf("No breakpoints set\n");
226 return;
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);
233 db_printf("\n");
237 /* Delete breakpoint */
238 /*ARGSUSED*/
239 void
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 */
246 /*ARGSUSED*/
247 void
248 db_breakpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
250 if (count == -1)
251 count = 1;
253 db_set_breakpoint((db_addr_t)addr, count);
256 /* list breakpoints */
257 /*ARGSUSED*/
258 void
259 db_listbreak_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
261 db_list_breakpoints();