Line data Source code
1 : /* $OpenBSD: db_watch.c,v 1.16 2016/04/19 10:24:42 mpi Exp $ */
2 : /* $NetBSD: db_watch.c,v 1.9 1996/03/30 22:30:12 christos Exp $ */
3 :
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.
14 : *
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.
18 : *
19 : * Carnegie Mellon requests users of this software to return to
20 : *
21 : * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 : * School of Computer Science
23 : * Carnegie Mellon University
24 : * Pittsburgh PA 15213-3890
25 : *
26 : * any improvements or extensions that they make and grant Carnegie Mellon
27 : * the rights to redistribute these changes.
28 : *
29 : * Author: Richard P. Draves, Carnegie Mellon University
30 : * Date: 10/90
31 : */
32 :
33 : #include <sys/param.h>
34 : #include <sys/systm.h>
35 :
36 : #include <machine/db_machdep.h>
37 :
38 : #include <ddb/db_break.h>
39 : #include <ddb/db_watch.h>
40 : #include <ddb/db_lex.h>
41 : #include <ddb/db_run.h>
42 : #include <ddb/db_sym.h>
43 : #include <ddb/db_output.h>
44 : #include <ddb/db_command.h>
45 : #include <ddb/db_extern.h>
46 :
47 : /*
48 : * Watchpoints.
49 : */
50 :
51 : int db_watchpoints_inserted = 1;
52 :
53 : #define NWATCHPOINTS 100
54 : struct db_watchpoint db_watch_table[NWATCHPOINTS];
55 : db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
56 : db_watchpoint_t db_free_watchpoints = 0;
57 : db_watchpoint_t db_watchpoint_list = 0;
58 :
59 : db_watchpoint_t
60 0 : db_watchpoint_alloc(void)
61 : {
62 : db_watchpoint_t watch;
63 :
64 0 : if ((watch = db_free_watchpoints) != 0) {
65 0 : db_free_watchpoints = watch->link;
66 0 : return (watch);
67 : }
68 0 : if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
69 0 : db_printf("All watchpoints used.\n");
70 0 : return (0);
71 : }
72 : watch = db_next_free_watchpoint;
73 0 : db_next_free_watchpoint++;
74 :
75 0 : return (watch);
76 0 : }
77 :
78 : void
79 0 : db_watchpoint_free(db_watchpoint_t watch)
80 : {
81 0 : watch->link = db_free_watchpoints;
82 0 : db_free_watchpoints = watch;
83 0 : }
84 :
85 : void
86 0 : db_set_watchpoint(db_addr_t addr, vsize_t size)
87 : {
88 : db_watchpoint_t watch;
89 :
90 : /*
91 : * Should we do anything fancy with overlapping regions?
92 : */
93 :
94 0 : for (watch = db_watchpoint_list; watch != 0; watch = watch->link)
95 0 : if (watch->loaddr == addr && watch->hiaddr == addr + size) {
96 0 : db_printf("Already set.\n");
97 0 : return;
98 : }
99 :
100 0 : watch = db_watchpoint_alloc();
101 0 : if (watch == 0) {
102 0 : db_printf("Too many watchpoints.\n");
103 0 : return;
104 : }
105 :
106 0 : watch->loaddr = addr;
107 0 : watch->hiaddr = addr+size;
108 :
109 0 : watch->link = db_watchpoint_list;
110 0 : db_watchpoint_list = watch;
111 :
112 0 : db_watchpoints_inserted = 0;
113 0 : }
114 :
115 : void
116 0 : db_delete_watchpoint(db_addr_t addr)
117 : {
118 : db_watchpoint_t watch;
119 : db_watchpoint_t *prev;
120 :
121 0 : for (prev = &db_watchpoint_list; (watch = *prev) != 0;
122 0 : prev = &watch->link)
123 0 : if (watch->loaddr <= addr && addr < watch->hiaddr) {
124 0 : *prev = watch->link;
125 0 : db_watchpoint_free(watch);
126 0 : return;
127 : }
128 :
129 0 : db_printf("Not set.\n");
130 0 : }
131 :
132 : void
133 0 : db_list_watchpoints(void)
134 : {
135 : db_watchpoint_t watch;
136 :
137 0 : if (db_watchpoint_list == 0) {
138 0 : db_printf("No watchpoints set\n");
139 0 : return;
140 : }
141 :
142 0 : db_printf(" Address Size\n");
143 0 : for (watch = db_watchpoint_list; watch != 0; watch = watch->link)
144 0 : db_printf("%8lx %lx\n",
145 0 : watch->loaddr, watch->hiaddr - watch->loaddr);
146 0 : }
147 :
148 : /* Delete watchpoint */
149 : /*ARGSUSED*/
150 : void
151 0 : db_deletewatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
152 : {
153 0 : db_delete_watchpoint(addr);
154 0 : }
155 :
156 : /* Set watchpoint */
157 : /*ARGSUSED*/
158 : void
159 0 : db_watchpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
160 : {
161 : vsize_t size;
162 0 : db_expr_t value;
163 :
164 0 : if (db_expression(&value))
165 0 : size = (vsize_t) value;
166 : else
167 : size = 4;
168 0 : db_skip_to_eol();
169 :
170 0 : db_set_watchpoint(addr, size);
171 0 : }
172 :
173 : /* list watchpoints */
174 : /*ARGSUSED*/
175 : void
176 0 : db_listwatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
177 : {
178 0 : db_list_watchpoints();
179 0 : }
180 :
181 : void
182 0 : db_set_watchpoints(void)
183 : {
184 : db_watchpoint_t watch;
185 :
186 0 : if (!db_watchpoints_inserted && db_watchpoint_list != NULL) {
187 0 : for (watch = db_watchpoint_list; watch != 0;
188 0 : watch = watch->link)
189 0 : pmap_protect(pmap_kernel(), trunc_page(watch->loaddr),
190 0 : round_page(watch->hiaddr), PROT_READ);
191 : pmap_update(pmap_kernel());
192 0 : db_watchpoints_inserted = 1;
193 0 : }
194 0 : }
195 :
196 : void
197 0 : db_clear_watchpoints(void)
198 : {
199 0 : db_watchpoints_inserted = 0;
200 0 : }
|