Annotation of sys/ddb/db_break.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: db_break.c,v 1.13 2006/03/13 06:23:20 jsg 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/proc.h>
38:
39: #include <uvm/uvm_extern.h>
40:
41: #include <machine/db_machdep.h> /* type definitions */
42:
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>
48:
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;
54:
55: db_breakpoint_t
56: db_breakpoint_alloc(void)
57: {
58: db_breakpoint_t bkpt;
59:
60: if ((bkpt = db_free_breakpoints) != 0) {
61: db_free_breakpoints = bkpt->link;
62: return (bkpt);
63: }
64: if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
65: db_printf("All breakpoints used.\n");
66: return (0);
67: }
68: bkpt = db_next_free_breakpoint;
69: db_next_free_breakpoint++;
70:
71: return (bkpt);
72: }
73:
74: void
75: db_breakpoint_free(db_breakpoint_t bkpt)
76: {
77: bkpt->link = db_free_breakpoints;
78: db_free_breakpoints = bkpt;
79: }
80:
81: void
82: db_set_breakpoint(struct vm_map *map, db_addr_t addr, int count)
83: {
84: db_breakpoint_t bkpt;
85:
86: if (db_find_breakpoint(map, addr)) {
87: db_printf("Already set.\n");
88: return;
89: }
90:
91: #ifdef DB_VALID_BREAKPOINT
92: if (!DB_VALID_BREAKPOINT(addr)) {
93: db_printf("Not a valid address for a breakpoint.\n");
94: return;
95: }
96: #endif
97:
98: bkpt = db_breakpoint_alloc();
99: if (bkpt == 0) {
100: db_printf("Too many breakpoints.\n");
101: return;
102: }
103:
104: bkpt->map = map;
105: bkpt->address = addr;
106: bkpt->flags = 0;
107: bkpt->init_count = count;
108: bkpt->count = count;
109:
110: bkpt->link = db_breakpoint_list;
111: db_breakpoint_list = bkpt;
112: }
113:
114: void
115: db_delete_breakpoint(struct vm_map *map, db_addr_t addr)
116: {
117: db_breakpoint_t bkpt;
118: db_breakpoint_t *prev;
119:
120: for (prev = &db_breakpoint_list;
121: (bkpt = *prev) != 0;
122: prev = &bkpt->link) {
123: if (db_map_equal(bkpt->map, map) &&
124: (bkpt->address == addr)) {
125: *prev = bkpt->link;
126: break;
127: }
128: }
129: if (bkpt == 0) {
130: db_printf("Not set.\n");
131: return;
132: }
133:
134: db_breakpoint_free(bkpt);
135: }
136:
137: db_breakpoint_t
138: db_find_breakpoint(struct vm_map *map, db_addr_t addr)
139: {
140: db_breakpoint_t bkpt;
141:
142: for (bkpt = db_breakpoint_list;
143: bkpt != 0;
144: bkpt = bkpt->link)
145: {
146: if (db_map_equal(bkpt->map, map) &&
147: (bkpt->address == addr))
148: return (bkpt);
149: }
150: return (0);
151: }
152:
153: db_breakpoint_t
154: db_find_breakpoint_here(db_addr_t addr)
155: {
156: return db_find_breakpoint(db_map_addr(addr), addr);
157: }
158:
159: boolean_t db_breakpoints_inserted = TRUE;
160:
161: void
162: db_set_breakpoints(void)
163: {
164: db_breakpoint_t bkpt;
165:
166: if (!db_breakpoints_inserted) {
167:
168: for (bkpt = db_breakpoint_list;
169: bkpt != 0;
170: bkpt = bkpt->link)
171: if (db_map_current(bkpt->map)) {
172: bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE,
173: FALSE);
174: db_put_value(bkpt->address, BKPT_SIZE,
175: BKPT_SET(bkpt->bkpt_inst));
176: }
177: db_breakpoints_inserted = TRUE;
178: }
179: }
180:
181: void
182: db_clear_breakpoints(void)
183: {
184: db_breakpoint_t bkpt;
185:
186: if (db_breakpoints_inserted) {
187:
188: for (bkpt = db_breakpoint_list;
189: bkpt != 0;
190: bkpt = bkpt->link)
191: if (db_map_current(bkpt->map)) {
192: db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
193: }
194: db_breakpoints_inserted = FALSE;
195: }
196: }
197:
198: /*
199: * Set a temporary breakpoint.
200: * The instruction is changed immediately,
201: * so the breakpoint does not have to be on the breakpoint list.
202: */
203: db_breakpoint_t
204: db_set_temp_breakpoint(db_addr_t addr)
205: {
206: db_breakpoint_t bkpt;
207:
208: #ifdef DB_VALID_BREAKPOINT
209: if (!DB_VALID_BREAKPOINT(addr)) {
210: db_printf("Not a valid address for a breakpoint.\n");
211: return (0);
212: }
213: #endif
214:
215: bkpt = db_breakpoint_alloc();
216: if (bkpt == 0) {
217: db_printf("Too many breakpoints.\n");
218: return (0);
219: }
220:
221: bkpt->map = NULL;
222: bkpt->address = addr;
223: bkpt->flags = BKPT_TEMP;
224: bkpt->init_count = 1;
225: bkpt->count = 1;
226:
227: bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
228: db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
229: return bkpt;
230: }
231:
232: void
233: db_delete_temp_breakpoint(db_breakpoint_t bkpt)
234: {
235: db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
236: db_breakpoint_free(bkpt);
237: }
238:
239: /*
240: * List breakpoints.
241: */
242: void
243: db_list_breakpoints(void)
244: {
245: db_breakpoint_t bkpt;
246:
247: if (db_breakpoint_list == 0) {
248: db_printf("No breakpoints set\n");
249: return;
250: }
251:
252: db_printf(" Map Count Address\n");
253: for (bkpt = db_breakpoint_list;
254: bkpt != 0;
255: bkpt = bkpt->link)
256: {
257: db_printf("%s%p %5d ",
258: db_map_current(bkpt->map) ? "*" : " ",
259: bkpt->map, bkpt->init_count);
260: db_printsym(bkpt->address, DB_STGY_PROC, db_printf);
261: db_printf("\n");
262: }
263: }
264:
265: /* Delete breakpoint */
266: /*ARGSUSED*/
267: void
268: db_delete_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
269: {
270: db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
271: }
272:
273: /* Set breakpoint with skip count */
274: /*ARGSUSED*/
275: void
276: db_breakpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
277: {
278: if (count == -1)
279: count = 1;
280:
281: db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
282: }
283:
284: /* list breakpoints */
285: /*ARGSUSED*/
286: void
287: db_listbreak_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
288: {
289: db_list_breakpoints();
290: }
291:
292: /*
293: * We want ddb to be usable before most of the kernel has been
294: * initialized. In particular, current_thread() or kernel_map
295: * (or both) may be null.
296: */
297:
298: boolean_t
299: db_map_equal(struct vm_map *map1, struct vm_map *map2)
300: {
301: return ((map1 == map2) ||
302: ((map1 == NULL) && (map2 == kernel_map)) ||
303: ((map1 == kernel_map) && (map2 == NULL)));
304: }
305:
306: boolean_t
307: db_map_current(struct vm_map *map)
308: {
309: #if 0
310: thread_t thread;
311:
312: return ((map == NULL) ||
313: (map == kernel_map) ||
314: (((thread = current_thread()) != NULL) &&
315: (map == thread->proc->map)));
316: #else
317: return (1);
318: #endif
319: }
320:
321: struct vm_map *
322: db_map_addr(vaddr_t addr)
323: {
324: #if 0
325: thread_t thread;
326:
327: /*
328: * We want to return kernel_map for all
329: * non-user addresses, even when debugging
330: * kernel tasks with their own maps.
331: */
332:
333: if ((VM_MIN_ADDRESS <= addr) &&
334: (addr < VM_MAX_ADDRESS) &&
335: ((thread = current_thread()) != NULL))
336: return thread->proc->map;
337: else
338: #endif
339: return kernel_map;
340: }
CVSweb