|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie the
24: * rights to redistribute these changes.
25: */
26: /*
27: * HISTORY
28: * $Log: db_break.c,v $
29: * Revision 1.1 1992/03/25 21:44:57 pace
30: * Initial revision
31: *
32: * Revision 2.7 91/02/05 17:06:00 mrt
33: * Changed to new Mach copyright
34: * [91/01/31 16:17:01 mrt]
35: *
36: * Revision 2.6 91/01/08 15:09:03 rpd
37: * Added db_map_equal, db_map_current, db_map_addr.
38: * [90/11/10 rpd]
39: *
40: * Revision 2.5 90/11/05 14:26:32 rpd
41: * Initialize db_breakpoints_inserted to TRUE.
42: * [90/11/04 rpd]
43: *
44: * Revision 2.4 90/10/25 14:43:33 rwd
45: * Added map field to breakpoints.
46: * Added map argument to db_set_breakpoint, db_delete_breakpoint,
47: * db_find_breakpoint. Added db_find_breakpoint_here.
48: * [90/10/18 rpd]
49: *
50: * Revision 2.3 90/09/28 16:57:07 jsb
51: * Fixed db_breakpoint_free.
52: * [90/09/18 rpd]
53: *
54: * Revision 2.2 90/08/27 21:49:53 dbg
55: * Reflected changes in db_printsym()'s calling seq.
56: * [90/08/20 af]
57: * Clear breakpoints only if inserted.
58: * Reduce lint.
59: * [90/08/07 dbg]
60: * Created.
61: * [90/07/25 dbg]
62: *
63: */
64: /*
65: * Author: David B. Golub, Carnegie Mellon University
66: * Date: 7/90
67: */
68: /*
69: * Breakpoints.
70: */
71: #include "param.h"
72: #include "proc.h"
73: #include <machine/db_machdep.h> /* type definitions */
74:
75: #include <ddb/db_lex.h>
76: #include <ddb/db_break.h>
77: #include <ddb/db_access.h>
78: #include <ddb/db_sym.h>
79: #include <ddb/db_break.h>
80:
81: extern boolean_t db_map_equal();
82: extern boolean_t db_map_current();
83: extern vm_map_t db_map_addr();
84:
85: #define NBREAKPOINTS 100
86: struct db_breakpoint db_break_table[NBREAKPOINTS];
87: db_breakpoint_t db_next_free_breakpoint = &db_break_table[0];
88: db_breakpoint_t db_free_breakpoints = 0;
89: db_breakpoint_t db_breakpoint_list = 0;
90:
91: db_breakpoint_t
92: db_breakpoint_alloc()
93: {
94: register db_breakpoint_t bkpt;
95:
96: if ((bkpt = db_free_breakpoints) != 0) {
97: db_free_breakpoints = bkpt->link;
98: return (bkpt);
99: }
100: if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
101: db_printf("All breakpoints used.\n");
102: return (0);
103: }
104: bkpt = db_next_free_breakpoint;
105: db_next_free_breakpoint++;
106:
107: return (bkpt);
108: }
109:
110: void
111: db_breakpoint_free(bkpt)
112: register db_breakpoint_t bkpt;
113: {
114: bkpt->link = db_free_breakpoints;
115: db_free_breakpoints = bkpt;
116: }
117:
118: void
119: db_set_breakpoint(map, addr, count)
120: vm_map_t map;
121: db_addr_t addr;
122: int count;
123: {
124: register db_breakpoint_t bkpt;
125:
126: if (db_find_breakpoint(map, addr)) {
127: db_printf("Already set.\n");
128: return;
129: }
130:
131: bkpt = db_breakpoint_alloc();
132: if (bkpt == 0) {
133: db_printf("Too many breakpoints.\n");
134: return;
135: }
136:
137: bkpt->map = map;
138: bkpt->address = addr;
139: bkpt->flags = 0;
140: bkpt->init_count = count;
141: bkpt->count = count;
142:
143: bkpt->link = db_breakpoint_list;
144: db_breakpoint_list = bkpt;
145: }
146:
147: void
148: db_delete_breakpoint(map, addr)
149: vm_map_t map;
150: db_addr_t addr;
151: {
152: register db_breakpoint_t bkpt;
153: register db_breakpoint_t *prev;
154:
155: for (prev = &db_breakpoint_list;
156: (bkpt = *prev) != 0;
157: prev = &bkpt->link) {
158: if (db_map_equal(bkpt->map, map) &&
159: (bkpt->address == addr)) {
160: *prev = bkpt->link;
161: break;
162: }
163: }
164: if (bkpt == 0) {
165: db_printf("Not set.\n");
166: return;
167: }
168:
169: db_breakpoint_free(bkpt);
170: }
171:
172: db_breakpoint_t
173: db_find_breakpoint(map, addr)
174: vm_map_t map;
175: db_addr_t addr;
176: {
177: register db_breakpoint_t bkpt;
178:
179: for (bkpt = db_breakpoint_list;
180: bkpt != 0;
181: bkpt = bkpt->link)
182: {
183: if (db_map_equal(bkpt->map, map) &&
184: (bkpt->address == addr))
185: return (bkpt);
186: }
187: return (0);
188: }
189:
190: db_breakpoint_t
191: db_find_breakpoint_here(addr)
192: db_addr_t addr;
193: {
194: return db_find_breakpoint(db_map_addr(addr), addr);
195: }
196:
197: boolean_t db_breakpoints_inserted = TRUE;
198:
199: void
200: db_set_breakpoints()
201: {
202: register db_breakpoint_t bkpt;
203:
204: if (!db_breakpoints_inserted) {
205:
206: for (bkpt = db_breakpoint_list;
207: bkpt != 0;
208: bkpt = bkpt->link)
209: if (db_map_current(bkpt->map)) {
210: bkpt->bkpt_inst = db_get_value(bkpt->address,
211: BKPT_SIZE,
212: FALSE);
213: db_put_value(bkpt->address,
214: BKPT_SIZE,
215: BKPT_SET(bkpt->bkpt_inst));
216: }
217: db_breakpoints_inserted = TRUE;
218: }
219: }
220:
221: void
222: db_clear_breakpoints()
223: {
224: register db_breakpoint_t bkpt;
225:
226: if (db_breakpoints_inserted) {
227:
228: for (bkpt = db_breakpoint_list;
229: bkpt != 0;
230: bkpt = bkpt->link)
231: if (db_map_current(bkpt->map)) {
232: db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
233: }
234: db_breakpoints_inserted = FALSE;
235: }
236: }
237:
238: /*
239: * Set a temporary breakpoint.
240: * The instruction is changed immediately,
241: * so the breakpoint does not have to be on the breakpoint list.
242: */
243: db_breakpoint_t
244: db_set_temp_breakpoint(addr)
245: db_addr_t addr;
246: {
247: register db_breakpoint_t bkpt;
248:
249: bkpt = db_breakpoint_alloc();
250: if (bkpt == 0) {
251: db_printf("Too many breakpoints.\n");
252: return 0;
253: }
254:
255: bkpt->map = NULL;
256: bkpt->address = addr;
257: bkpt->flags = BKPT_TEMP;
258: bkpt->init_count = 1;
259: bkpt->count = 1;
260:
261: bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
262: db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
263: return bkpt;
264: }
265:
266: void
267: db_delete_temp_breakpoint(bkpt)
268: db_breakpoint_t bkpt;
269: {
270: db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
271: db_breakpoint_free(bkpt);
272: }
273:
274: /*
275: * List breakpoints.
276: */
277: void
278: db_list_breakpoints()
279: {
280: register db_breakpoint_t bkpt;
281:
282: if (db_breakpoint_list == 0) {
283: db_printf("No breakpoints set\n");
284: return;
285: }
286:
287: db_printf(" Map Count Address\n");
288: for (bkpt = db_breakpoint_list;
289: bkpt != 0;
290: bkpt = bkpt->link)
291: {
292: db_printf("%s%8x %5d ",
293: db_map_current(bkpt->map) ? "*" : " ",
294: bkpt->map, bkpt->init_count);
295: db_printsym(bkpt->address, DB_STGY_PROC);
296: db_printf("\n");
297: }
298: }
299:
300: /* Delete breakpoint */
301: /*ARGSUSED*/
302: void
303: db_delete_cmd(addr, have_addr, count, modif)
304: db_expr_t addr;
305: int have_addr;
306: db_expr_t count;
307: char * modif;
308: {
309: db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
310: }
311:
312: /* Set breakpoint with skip count */
313: /*ARGSUSED*/
314: void
315: db_breakpoint_cmd(addr, have_addr, count, modif)
316: db_expr_t addr;
317: int have_addr;
318: db_expr_t count;
319: char * modif;
320: {
321: if (count == -1)
322: count = 1;
323:
324: db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
325: }
326:
327: /* list breakpoints */
328: void
329: db_listbreak_cmd()
330: {
331: db_list_breakpoints();
332: }
333:
334: #include <vm/vm_kern.h>
335:
336: /*
337: * We want ddb to be usable before most of the kernel has been
338: * initialized. In particular, current_thread() or kernel_map
339: * (or both) may be null.
340: */
341:
342: boolean_t
343: db_map_equal(map1, map2)
344: vm_map_t map1, map2;
345: {
346: return ((map1 == map2) ||
347: ((map1 == NULL) && (map2 == kernel_map)) ||
348: ((map1 == kernel_map) && (map2 == NULL)));
349: }
350:
351: boolean_t
352: db_map_current(map)
353: vm_map_t map;
354: {
355: #if 0
356: thread_t thread;
357:
358: return ((map == NULL) ||
359: (map == kernel_map) ||
360: (((thread = current_thread()) != NULL) &&
361: (map == thread->task->map)));
362: #else
363: return (1);
364: #endif
365: }
366:
367: vm_map_t
368: db_map_addr(addr)
369: vm_offset_t addr;
370: {
371: #if 0
372: thread_t thread;
373:
374: /*
375: * We want to return kernel_map for all
376: * non-user addresses, even when debugging
377: * kernel tasks with their own maps.
378: */
379:
380: if ((VM_MIN_ADDRESS <= addr) &&
381: (addr < VM_MAX_ADDRESS) &&
382: ((thread = current_thread()) != NULL))
383: return thread->task->map;
384: else
385: #endif
386: return kernel_map;
387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.