1 /* $NetBSD: db_watch.c,v 1.26 2007/02/22 04:38:06 matt Exp $ */
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
28 * Author: Richard P. Draves, Carnegie Mellon University
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: db_watch.c,v 1.26 2007/02/22 04:38:06 matt Exp $");
35 #include <sys/param.h>
38 #include <machine/db_machdep.h>
40 #include <ddb/db_break.h>
41 #include <ddb/db_watch.h>
42 #include <ddb/db_lex.h>
43 #include <ddb/db_access.h>
44 #include <ddb/db_run.h>
45 #include <ddb/db_sym.h>
46 #include <ddb/db_output.h>
47 #include <ddb/db_command.h>
48 #include <ddb/db_extern.h>
54 static bool db_watchpoints_inserted
= true;
56 #define NWATCHPOINTS 100
57 static struct db_watchpoint db_watch_table
[NWATCHPOINTS
];
58 static db_watchpoint_t db_next_free_watchpoint
= &db_watch_table
[0];
59 static db_watchpoint_t db_free_watchpoints
= 0;
60 static db_watchpoint_t db_watchpoint_list
= 0;
62 static void db_delete_watchpoint(struct vm_map
*, db_addr_t
);
63 static void db_list_watchpoints(void);
64 static void db_set_watchpoint(struct vm_map
*, db_addr_t
, vsize_t
);
65 static db_watchpoint_t
db_watchpoint_alloc(void);
66 static void db_watchpoint_free(db_watchpoint_t
);
69 db_watchpoint_alloc(void)
71 db_watchpoint_t watch
;
73 if ((watch
= db_free_watchpoints
) != 0) {
74 db_free_watchpoints
= watch
->link
;
77 if (db_next_free_watchpoint
== &db_watch_table
[NWATCHPOINTS
]) {
78 db_printf("All watchpoints used.\n");
81 watch
= db_next_free_watchpoint
;
82 db_next_free_watchpoint
++;
88 db_watchpoint_free(db_watchpoint_t watch
)
90 watch
->link
= db_free_watchpoints
;
91 db_free_watchpoints
= watch
;
95 db_set_watchpoint(struct vm_map
*map
, db_addr_t addr
, vsize_t size
)
97 db_watchpoint_t watch
;
100 db_printf("No map.\n");
105 * Should we do anything fancy with overlapping regions?
108 for (watch
= db_watchpoint_list
; watch
!= 0; watch
= watch
->link
)
109 if (db_map_equal(watch
->map
, map
) &&
110 (watch
->loaddr
== addr
) &&
111 (watch
->hiaddr
== addr
+size
)) {
112 db_printf("Already set.\n");
116 watch
= db_watchpoint_alloc();
118 db_printf("Too many watchpoints.\n");
123 watch
->loaddr
= addr
;
124 watch
->hiaddr
= addr
+size
;
126 watch
->link
= db_watchpoint_list
;
127 db_watchpoint_list
= watch
;
129 db_watchpoints_inserted
= false;
133 db_delete_watchpoint(struct vm_map
*map
, db_addr_t addr
)
135 db_watchpoint_t watch
;
136 db_watchpoint_t
*prev
;
138 for (prev
= &db_watchpoint_list
;
139 (watch
= *prev
) != 0;
141 if (db_map_equal(watch
->map
, map
) &&
142 (watch
->loaddr
<= addr
) &&
143 (addr
< watch
->hiaddr
)) {
145 db_watchpoint_free(watch
);
149 db_printf("Not set.\n");
153 db_list_watchpoints(void)
155 db_watchpoint_t watch
;
157 if (db_watchpoint_list
== 0) {
158 db_printf("No watchpoints set\n");
162 db_printf(" Map Address Size\n");
163 for (watch
= db_watchpoint_list
; watch
!= 0; watch
= watch
->link
)
164 db_printf("%s%p %8lx %lx\n",
165 db_map_current(watch
->map
) ? "*" : " ",
166 watch
->map
, (long)watch
->loaddr
,
167 (long)(watch
->hiaddr
- watch
->loaddr
));
170 /* Delete watchpoint */
173 db_deletewatch_cmd(db_expr_t addr
, bool have_addr
,
174 db_expr_t count
, const char *modif
)
177 db_delete_watchpoint(db_map_addr(addr
), addr
);
183 db_watchpoint_cmd(db_expr_t addr
, bool have_addr
,
184 db_expr_t count
, const char *modif
)
189 if (db_expression(&value
))
190 size
= (vsize_t
) value
;
195 db_set_watchpoint(db_map_addr(addr
), addr
, size
);
198 /* list watchpoints */
201 db_listwatch_cmd(db_expr_t addr
, bool have_addr
,
202 db_expr_t count
, const char *modif
)
205 db_list_watchpoints();
209 db_set_watchpoints(void)
211 db_watchpoint_t watch
;
213 if (!db_watchpoints_inserted
) {
214 for (watch
= db_watchpoint_list
;
216 watch
= watch
->link
) {
217 pmap_protect(watch
->map
->pmap
,
218 trunc_page(watch
->loaddr
),
219 round_page(watch
->hiaddr
),
221 pmap_update(watch
->map
->pmap
);
224 db_watchpoints_inserted
= true;
229 db_clear_watchpoints(void)
232 db_watchpoints_inserted
= false;