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