Line data Source code
1 : /* $OpenBSD: db_break.c,v 1.20 2016/04/19 12:23:25 mpi Exp $ */
2 : /* $NetBSD: db_break.c,v 1.7 1996/03/30 22:30:03 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: David B. Golub, Carnegie Mellon University
30 : * Date: 7/90
31 : */
32 :
33 : /*
34 : * Breakpoints.
35 : */
36 : #include <sys/param.h>
37 : #include <sys/systm.h>
38 :
39 : #include <machine/db_machdep.h> /* type definitions */
40 :
41 : #include <ddb/db_access.h>
42 : #include <ddb/db_sym.h>
43 : #include <ddb/db_break.h>
44 : #include <ddb/db_output.h>
45 :
46 : #define NBREAKPOINTS 100
47 : struct db_breakpoint db_break_table[NBREAKPOINTS];
48 : db_breakpoint_t db_next_free_breakpoint = &db_break_table[0];
49 : db_breakpoint_t db_free_breakpoints = 0;
50 : db_breakpoint_t db_breakpoint_list = 0;
51 :
52 : db_breakpoint_t db_breakpoint_alloc(void);
53 : void db_breakpoint_free(db_breakpoint_t);
54 : void db_set_breakpoint(db_addr_t, int);
55 : void db_delete_breakpoint(db_addr_t);
56 : void db_list_breakpoints(void);
57 :
58 : db_breakpoint_t
59 0 : db_breakpoint_alloc(void)
60 : {
61 : db_breakpoint_t bkpt;
62 :
63 0 : if ((bkpt = db_free_breakpoints) != 0) {
64 0 : db_free_breakpoints = bkpt->link;
65 0 : return (bkpt);
66 : }
67 0 : if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
68 0 : db_printf("All breakpoints used.\n");
69 0 : return (0);
70 : }
71 : bkpt = db_next_free_breakpoint;
72 0 : db_next_free_breakpoint++;
73 :
74 0 : return (bkpt);
75 0 : }
76 :
77 : void
78 0 : db_breakpoint_free(db_breakpoint_t bkpt)
79 : {
80 0 : bkpt->link = db_free_breakpoints;
81 0 : db_free_breakpoints = bkpt;
82 0 : }
83 :
84 : void
85 0 : db_set_breakpoint(db_addr_t addr, int count)
86 : {
87 : db_breakpoint_t bkpt;
88 :
89 0 : if (db_find_breakpoint(addr)) {
90 0 : db_printf("Already set.\n");
91 0 : return;
92 : }
93 :
94 : #ifdef DB_VALID_BREAKPOINT
95 : if (!DB_VALID_BREAKPOINT(addr)) {
96 : db_printf("Not a valid address for a breakpoint.\n");
97 : return;
98 : }
99 : #endif
100 :
101 0 : bkpt = db_breakpoint_alloc();
102 0 : if (bkpt == 0) {
103 0 : db_printf("Too many breakpoints.\n");
104 0 : return;
105 : }
106 :
107 0 : bkpt->address = addr;
108 0 : bkpt->flags = 0;
109 0 : bkpt->init_count = count;
110 0 : bkpt->count = count;
111 :
112 0 : bkpt->link = db_breakpoint_list;
113 0 : db_breakpoint_list = bkpt;
114 0 : }
115 :
116 : void
117 0 : db_delete_breakpoint(db_addr_t addr)
118 : {
119 : db_breakpoint_t bkpt;
120 : db_breakpoint_t *prev;
121 :
122 0 : for (prev = &db_breakpoint_list; (bkpt = *prev) != 0;
123 : prev = &bkpt->link) {
124 0 : if (bkpt->address == addr) {
125 0 : *prev = bkpt->link;
126 0 : break;
127 : }
128 : }
129 0 : if (bkpt == 0) {
130 0 : db_printf("Not set.\n");
131 0 : return;
132 : }
133 :
134 0 : db_breakpoint_free(bkpt);
135 0 : }
136 :
137 : db_breakpoint_t
138 0 : db_find_breakpoint(db_addr_t addr)
139 : {
140 : db_breakpoint_t bkpt;
141 :
142 0 : for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link)
143 0 : if (bkpt->address == addr)
144 0 : return (bkpt);
145 :
146 0 : return (0);
147 0 : }
148 :
149 : int db_breakpoints_inserted = 1;
150 :
151 : void
152 0 : db_set_breakpoints(void)
153 : {
154 : db_breakpoint_t bkpt;
155 :
156 0 : if (!db_breakpoints_inserted) {
157 0 : for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
158 0 : bkpt->bkpt_inst =
159 0 : db_get_value(bkpt->address, BKPT_SIZE, 0);
160 0 : db_put_value(bkpt->address, BKPT_SIZE,
161 : BKPT_SET(bkpt->bkpt_inst));
162 : }
163 0 : db_breakpoints_inserted = 1;
164 0 : }
165 0 : }
166 :
167 : void
168 0 : db_clear_breakpoints(void)
169 : {
170 : db_breakpoint_t bkpt;
171 :
172 0 : if (db_breakpoints_inserted) {
173 0 : for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link)
174 0 : db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
175 0 : db_breakpoints_inserted = 0;
176 0 : }
177 0 : }
178 :
179 : /*
180 : * Set a temporary breakpoint.
181 : * The instruction is changed immediately,
182 : * so the breakpoint does not have to be on the breakpoint list.
183 : */
184 : db_breakpoint_t
185 0 : db_set_temp_breakpoint(db_addr_t addr)
186 : {
187 : db_breakpoint_t bkpt;
188 :
189 : #ifdef DB_VALID_BREAKPOINT
190 : if (!DB_VALID_BREAKPOINT(addr)) {
191 : db_printf("Not a valid address for a breakpoint.\n");
192 : return (0);
193 : }
194 : #endif
195 :
196 0 : bkpt = db_breakpoint_alloc();
197 0 : if (bkpt == 0) {
198 0 : db_printf("Too many breakpoints.\n");
199 0 : return (0);
200 : }
201 :
202 0 : bkpt->address = addr;
203 0 : bkpt->flags = BKPT_TEMP;
204 0 : bkpt->init_count = 1;
205 0 : bkpt->count = 1;
206 :
207 0 : bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, 0);
208 0 : db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
209 0 : return bkpt;
210 0 : }
211 :
212 : void
213 0 : db_delete_temp_breakpoint(db_breakpoint_t bkpt)
214 : {
215 0 : db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
216 0 : db_breakpoint_free(bkpt);
217 0 : }
218 :
219 : /*
220 : * List breakpoints.
221 : */
222 : void
223 0 : db_list_breakpoints(void)
224 : {
225 : db_breakpoint_t bkpt;
226 :
227 0 : if (db_breakpoint_list == NULL) {
228 0 : db_printf("No breakpoints set\n");
229 0 : return;
230 : }
231 :
232 0 : db_printf(" Count Address\n");
233 0 : for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
234 0 : db_printf(" %5d ", bkpt->init_count);
235 0 : db_printsym(bkpt->address, DB_STGY_PROC, db_printf);
236 0 : db_printf("\n");
237 : }
238 0 : }
239 :
240 : /* Delete breakpoint */
241 : /*ARGSUSED*/
242 : void
243 0 : db_delete_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
244 : {
245 0 : db_delete_breakpoint((db_addr_t)addr);
246 0 : }
247 :
248 : /* Set breakpoint with skip count */
249 : /*ARGSUSED*/
250 : void
251 0 : db_breakpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
252 : {
253 0 : if (count == -1)
254 0 : count = 1;
255 :
256 0 : db_set_breakpoint((db_addr_t)addr, count);
257 0 : }
258 :
259 : /* list breakpoints */
260 : /*ARGSUSED*/
261 : void
262 0 : db_listbreak_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
263 : {
264 0 : db_list_breakpoints();
265 0 : }
|