2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
28 * Revision 1.1.1.1 1998/09/22 21:05:47 wsanchez
29 * Import of Mac OS X kernel (~semeria)
31 * Revision 1.2 1998/04/29 17:35:26 mburg
34 * Revision 1.2.47.1 1998/02/03 09:23:57 gdt
36 * [1998/02/03 09:10:14 gdt]
38 * Revision 1.2.45.1 1997/03/27 18:46:16 barbou
39 * ri-osc CR1557: re-enable thread-specific breakpoints.
40 * [1995/09/20 15:23:46 bolinger]
43 * Revision 1.2.21.6 1996/01/09 19:15:21 devrcs
44 * Changed declarations of 'register foo' to 'register int foo'
45 * Fixed printfs which print addresses.
46 * [1995/12/01 21:41:51 jfraser]
48 * Merged '64-bit safe' changes from DEC alpha port.
49 * [1995/11/21 18:02:40 jfraser]
51 * Revision 1.2.21.5 1995/04/07 18:52:54 barbou
52 * Allow breakpoints on non-resident pages. The breakpoint will
53 * actually be set when the page is paged in.
57 * Revision 1.2.21.4 1995/02/23 21:43:19 alanl
58 * Merged with DIPC2_SHARED.
59 * [1995/01/04 20:15:04 alanl]
61 * Revision 1.2.28.1 1994/11/04 09:52:15 dwm
62 * mk6 CR668 - 1.3b26 merge
63 * * Revision 1.2.4.5 1994/05/06 18:38:52 tmt
64 * Merged osc1.3dec/shared with osc1.3b19
65 * Moved struct db_breakpoint from here to db_break.h.
66 * Merge Alpha changes into osc1.312b source code.
69 * [1994/11/04 08:49:10 dwm]
71 * Revision 1.2.21.2 1994/09/23 01:17:57 ezf
72 * change marker to not FREE
73 * [1994/09/22 21:09:19 ezf]
75 * Revision 1.2.21.1 1994/06/11 21:11:24 bolinger
76 * Merge up to NMK17.2.
77 * [1994/06/11 20:01:06 bolinger]
79 * Revision 1.2.25.2 1994/10/28 18:56:21 rwd
83 * Revision 1.2.25.1 1994/08/04 01:42:15 mmp
84 * 23-Jun-94 Stan Smith (stans@ssd.intel.com)
85 * Let d * delete all breakpoints.
86 * [1994/06/28 13:54:00 sjs]
88 * Revision 1.2.19.2 1994/04/11 09:34:22 bernadat
89 * Moved db_breakpoint struct declaration to db_break.h
92 * Revision 1.2.19.1 1994/02/08 10:57:22 bernadat
93 * When setting a breakpoint, force user_space if breakpoint is
94 * outside kernel_space (like in the case of an emulator).
97 * Changed silly decimal display to hex (to match input conventions).
98 * Change from NORMA_MK14.6 [93/01/09 sjs]
100 * [94/02/07 bernadat]
102 * Revision 1.2.4.3 1993/07/27 18:26:48 elliston
103 * Add ANSI prototypes. CR #9523.
104 * [1993/07/27 18:10:54 elliston]
106 * Revision 1.2.4.2 1993/06/09 02:19:39 gm
107 * Added to OSF/1 R1.3 from NMK15.0.
108 * [1993/06/02 20:55:42 jeffc]
110 * Revision 1.2 1993/04/19 16:01:31 devrcs
112 * Removed unused variable from db_delete_cmd().
113 * Added declaration for arg 'count' of db_add_thread_breakpoint().
115 * Fixed b/tu to b/Tu work if the specified address is valid in the
116 * target address space but not the current user space. Explicit
117 * user space breakpoints (b/u, b/Tu, etc) will no longer get
118 * inserted into the kernel if the specified address is invalid.
122 * Revision 1.1 1992/09/30 02:00:52 robert
129 * Revision 2.11.3.1 92/03/03 16:13:20 jeffreyh
130 * Pick up changes from TRUNK
131 * [92/02/26 10:58:37 jeffreyh]
133 * Revision 2.12 92/02/19 16:46:24 elf
134 * Removed one of the many user-unfriendlinesses.
135 * [92/02/10 17:48:25 af]
137 * Revision 2.11 91/11/12 11:50:24 rvb
138 * Fixed db_delete_cmd so that just "d" works in user space.
140 * Fixed db_delete_thread_breakpoint for zero task_thd.
143 * Revision 2.10 91/10/09 15:57:41 af
144 * Supported thread-oriented break points.
147 * Revision 2.9 91/07/09 23:15:39 danner
148 * Conditionalized db_map_addr to work right on the luna. Used a
149 * ifdef luna88k. This is evil, and needs to be fixed.
152 * Revision 2.2 91/04/10 22:54:50 mbj
153 * Grabbed 3.0 copyright/disclaimer since ddb comes from 3.0.
156 * Revision 2.7 91/02/05 17:06:00 mrt
157 * Changed to new Mach copyright
158 * [91/01/31 16:17:01 mrt]
160 * Revision 2.6 91/01/08 15:09:03 rpd
161 * Added db_map_equal, db_map_current, db_map_addr.
164 * Revision 2.5 90/11/05 14:26:32 rpd
165 * Initialize db_breakpoints_inserted to TRUE.
168 * Revision 2.4 90/10/25 14:43:33 rwd
169 * Added map field to breakpoints.
170 * Added map argument to db_set_breakpoint, db_delete_breakpoint,
171 * db_find_breakpoint. Added db_find_breakpoint_here.
174 * Revision 2.3 90/09/28 16:57:07 jsb
175 * Fixed db_breakpoint_free.
178 * Revision 2.2 90/08/27 21:49:53 dbg
179 * Reflected changes in db_printsym()'s calling seq.
181 * Clear breakpoints only if inserted.
190 * Mach Operating System
191 * Copyright (c) 1991,1990 Carnegie Mellon University
192 * All Rights Reserved.
194 * Permission to use, copy, modify and distribute this software and its
195 * documentation is hereby granted, provided that both the copyright
196 * notice and this permission notice appear in all copies of the
197 * software, derivative works or modified versions, and any portions
198 * thereof, and that both notices appear in supporting documentation.
200 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
201 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
202 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
204 * Carnegie Mellon requests users of this software to return to
206 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
207 * School of Computer Science
208 * Carnegie Mellon University
209 * Pittsburgh PA 15213-3890
211 * any improvements or extensions that they make and grant Carnegie Mellon
212 * the rights to redistribute these changes.
217 * Author: David B. Golub, Carnegie Mellon University
224 #include <mach/boolean.h>
225 #include <machine/db_machdep.h>
226 #include <ddb/db_lex.h>
227 #include <ddb/db_break.h>
228 #include <ddb/db_access.h>
229 #include <ddb/db_sym.h>
230 #include <ddb/db_variables.h>
231 #include <ddb/db_command.h>
232 #include <ddb/db_cond.h>
233 #include <ddb/db_expr.h>
234 #include <ddb/db_output.h> /* For db_printf() */
235 #include <ddb/db_task_thread.h>
238 #define NBREAKPOINTS 100
239 #define NTHREAD_LIST (NBREAKPOINTS*3)
241 struct db_breakpoint db_break_table
[NBREAKPOINTS
];
242 db_breakpoint_t db_next_free_breakpoint
= &db_break_table
[0];
243 db_breakpoint_t db_free_breakpoints
= 0;
244 db_breakpoint_t db_breakpoint_list
= 0;
246 static struct db_thread_breakpoint db_thread_break_list
[NTHREAD_LIST
];
247 static db_thread_breakpoint_t db_free_thread_break_list
= 0;
248 static boolean_t db_thread_break_init
= FALSE
;
249 static int db_breakpoint_number
= 0;
251 /* Prototypes for functions local to this file. XXX -- should be static!
253 static int db_add_thread_breakpoint(
254 register db_breakpoint_t bkpt
,
255 vm_offset_t task_thd
,
259 static int db_delete_thread_breakpoint(
260 register db_breakpoint_t bkpt
,
261 vm_offset_t task_thd
);
263 static db_thread_breakpoint_t
db_find_thread_breakpoint(
264 db_breakpoint_t bkpt
,
265 thread_act_t thr_act
);
267 static void db_force_delete_breakpoint(
268 db_breakpoint_t bkpt
,
269 vm_offset_t task_thd
,
272 db_breakpoint_t
db_breakpoint_alloc(void);
274 void db_breakpoint_free(register db_breakpoint_t bkpt
);
276 void db_delete_breakpoint(
279 vm_offset_t task_thd
);
282 db_delete_all_breakpoints(
285 void db_list_breakpoints(void);
290 db_breakpoint_alloc(void)
292 register db_breakpoint_t bkpt
;
294 if ((bkpt
= db_free_breakpoints
) != 0) {
295 db_free_breakpoints
= bkpt
->link
;
298 if (db_next_free_breakpoint
== &db_break_table
[NBREAKPOINTS
]) {
299 db_printf("All breakpoints used.\n");
302 bkpt
= db_next_free_breakpoint
;
303 db_next_free_breakpoint
++;
309 db_breakpoint_free(register db_breakpoint_t bkpt
)
311 bkpt
->link
= db_free_breakpoints
;
312 db_free_breakpoints
= bkpt
;
316 db_add_thread_breakpoint(
317 register db_breakpoint_t bkpt
,
318 vm_offset_t task_thd
,
322 register db_thread_breakpoint_t tp
;
324 if (db_thread_break_init
== FALSE
) {
325 for (tp
= db_thread_break_list
;
326 tp
< &db_thread_break_list
[NTHREAD_LIST
-1]; tp
++)
329 db_free_thread_break_list
= db_thread_break_list
;
330 db_thread_break_init
= TRUE
;
332 if (db_free_thread_break_list
== 0)
334 tp
= db_free_thread_break_list
;
335 db_free_thread_break_list
= tp
->tb_next
;
336 tp
->tb_is_task
= task_bpt
;
337 tp
->tb_task_thd
= task_thd
;
338 tp
->tb_count
= count
;
339 tp
->tb_init_count
= count
;
341 tp
->tb_number
= ++db_breakpoint_number
;
342 tp
->tb_next
= bkpt
->threads
;
348 db_delete_thread_breakpoint(
349 register db_breakpoint_t bkpt
,
350 vm_offset_t task_thd
)
352 register db_thread_breakpoint_t tp
;
353 register db_thread_breakpoint_t
*tpp
;
356 /* delete all the thread-breakpoints */
358 for (tpp
= &bkpt
->threads
; (tp
= *tpp
) != 0; tpp
= &tp
->tb_next
)
361 *tpp
= db_free_thread_break_list
;
362 db_free_thread_break_list
= bkpt
->threads
;
366 /* delete the specified thread-breakpoint */
368 for (tpp
= &bkpt
->threads
; (tp
= *tpp
) != 0; tpp
= &tp
->tb_next
)
369 if (tp
->tb_task_thd
== task_thd
) {
372 tp
->tb_next
= db_free_thread_break_list
;
373 db_free_thread_break_list
= tp
;
377 return -1; /* not found */
381 static db_thread_breakpoint_t
382 db_find_thread_breakpoint(
383 db_breakpoint_t bkpt
,
384 thread_act_t thr_act
)
386 register db_thread_breakpoint_t tp
;
387 register task_t task
=
388 (thr_act
== THR_ACT_NULL
|| thr_act
->kernel_loaded
)
389 ? TASK_NULL
: thr_act
->task
;
391 for (tp
= bkpt
->threads
; tp
; tp
= tp
->tb_next
) {
392 if (tp
->tb_is_task
) {
393 if (tp
->tb_task_thd
== (vm_offset_t
)task
)
397 if (tp
->tb_task_thd
== (vm_offset_t
)thr_act
|| tp
->tb_task_thd
== 0)
403 db_thread_breakpoint_t
404 db_find_thread_breakpoint_here(
408 db_breakpoint_t bkpt
;
410 bkpt
= db_find_breakpoint(task
, (db_addr_t
)addr
);
413 return(db_find_thread_breakpoint(bkpt
, current_act()));
416 db_thread_breakpoint_t
417 db_find_breakpoint_number(
419 db_breakpoint_t
*bkptp
)
421 register db_thread_breakpoint_t tp
;
422 register db_breakpoint_t bkpt
;
424 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
425 for (tp
= bkpt
->threads
; tp
; tp
= tp
->tb_next
) {
426 if (tp
->tb_number
== num
) {
437 db_force_delete_breakpoint(
438 db_breakpoint_t bkpt
,
439 vm_offset_t task_thd
,
442 db_printf("deleted a stale breakpoint at ");
443 if (bkpt
->task
== TASK_NULL
|| db_lookup_task(bkpt
->task
) >= 0)
444 db_task_printsym(bkpt
->address
, DB_STGY_PROC
, bkpt
->task
);
446 db_printf("%#X", bkpt
->address
);
448 db_printf(" in task %X", bkpt
->task
);
450 db_printf(" for %s %X", (is_task
)? "task": "thr_act", task_thd
);
452 db_delete_thread_breakpoint(bkpt
, task_thd
);
456 db_check_breakpoint_valid(void)
458 register db_thread_breakpoint_t tbp
, tbp_next
;
459 register db_breakpoint_t bkpt
, *bkptp
;
461 bkptp
= &db_breakpoint_list
;
462 for (bkpt
= *bkptp
; bkpt
; bkpt
= *bkptp
) {
463 if (bkpt
->task
!= TASK_NULL
) {
464 if (db_lookup_task(bkpt
->task
) < 0) {
465 db_force_delete_breakpoint(bkpt
, 0, FALSE
);
467 db_breakpoint_free(bkpt
);
471 for (tbp
= bkpt
->threads
; tbp
; tbp
= tbp_next
) {
472 tbp_next
= tbp
->tb_next
;
473 if (tbp
->tb_task_thd
== 0)
475 if ((tbp
->tb_is_task
&&
476 db_lookup_task((task_t
)(tbp
->tb_task_thd
)) < 0) ||
478 db_lookup_act((thread_act_t
)(tbp
->tb_task_thd
)) < 0)) {
479 db_force_delete_breakpoint(bkpt
,
480 tbp
->tb_task_thd
, tbp
->tb_is_task
);
483 if (bkpt
->threads
== 0) {
484 db_put_task_value(bkpt
->address
, BKPT_SIZE
,
485 bkpt
->bkpt_inst
, bkpt
->task
);
487 db_breakpoint_free(bkpt
);
500 thread_act_t thr_act
,
503 register db_breakpoint_t bkpt
;
504 db_breakpoint_t alloc_bkpt
= 0;
505 vm_offset_t task_thd
;
507 bkpt
= db_find_breakpoint(task
, addr
);
509 if (thr_act
== THR_ACT_NULL
510 || db_find_thread_breakpoint(bkpt
, thr_act
)) {
511 db_printf("Already set.\n");
515 if (!DB_CHECK_ACCESS(addr
, BKPT_SIZE
, task
)) {
517 db_printf("Warning: non-resident page for breakpoint at %lX",
519 db_printf(" in task %lX.\n", task
);
521 db_printf("Cannot set breakpoint at %lX in kernel space.\n",
526 alloc_bkpt
= bkpt
= db_breakpoint_alloc();
528 db_printf("Too many breakpoints.\n");
532 bkpt
->flags
= (task
&& thr_act
== THR_ACT_NULL
)?
533 (BKPT_USR_GLOBAL
|BKPT_1ST_SET
): 0;
534 bkpt
->address
= addr
;
537 if (db_breakpoint_list
== 0)
538 db_breakpoint_number
= 0;
539 task_thd
= (task_bpt
) ? (vm_offset_t
)(thr_act
->task
)
540 : (vm_offset_t
)thr_act
;
541 if (db_add_thread_breakpoint(bkpt
, task_thd
, count
, task_bpt
) < 0) {
543 db_breakpoint_free(alloc_bkpt
);
544 db_printf("Too many thread_breakpoints.\n");
546 db_printf("set breakpoint #%x\n", db_breakpoint_number
);
548 bkpt
->link
= db_breakpoint_list
;
549 db_breakpoint_list
= bkpt
;
555 db_delete_breakpoint(
558 vm_offset_t task_thd
)
560 register db_breakpoint_t bkpt
;
561 register db_breakpoint_t
*prev
;
563 for (prev
= &db_breakpoint_list
; (bkpt
= *prev
) != 0;
564 prev
= &bkpt
->link
) {
565 if ((bkpt
->task
== task
566 || (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
)))
567 && bkpt
->address
== addr
)
570 if (bkpt
&& (bkpt
->flags
& BKPT_SET_IN_MEM
)) {
571 db_printf("cannot delete it now.\n");
575 || db_delete_thread_breakpoint(bkpt
, task_thd
) < 0) {
576 db_printf("Not set.\n");
579 if (bkpt
->threads
== 0) {
581 db_breakpoint_free(bkpt
);
590 register db_breakpoint_t bkpt
;
592 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
593 if ((bkpt
->task
== task
594 || (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
)))
595 && bkpt
->address
== addr
)
602 db_find_breakpoint_here(
606 register db_breakpoint_t bkpt
;
608 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
609 if ((bkpt
->task
== task
610 || (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
)))
611 && bkpt
->address
== addr
)
613 if ((bkpt
->flags
& BKPT_USR_GLOBAL
) == 0 &&
614 DB_PHYS_EQ(task
, addr
, bkpt
->task
, bkpt
->address
))
620 boolean_t db_breakpoints_inserted
= TRUE
;
623 db_set_breakpoints(void)
625 register db_breakpoint_t bkpt
;
626 register task_t task
;
628 thread_act_t cur_act
= current_act();
630 (cur_act
&& !cur_act
->kernel_loaded
) ?
631 cur_act
->task
: TASK_NULL
;
632 boolean_t inserted
= TRUE
;
634 if (!db_breakpoints_inserted
) {
635 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
636 if (bkpt
->flags
& BKPT_SET_IN_MEM
)
639 if (bkpt
->flags
& BKPT_USR_GLOBAL
) {
640 if ((bkpt
->flags
& BKPT_1ST_SET
) == 0) {
641 if (cur_task
== TASK_NULL
)
645 bkpt
->flags
&= ~BKPT_1ST_SET
;
647 if (DB_CHECK_ACCESS(bkpt
->address
, BKPT_SIZE
, task
)) {
648 inst
= db_get_task_value(bkpt
->address
, BKPT_SIZE
, FALSE
,
650 if (inst
== BKPT_SET(inst
))
652 bkpt
->bkpt_inst
= inst
;
653 db_put_task_value(bkpt
->address
,
655 BKPT_SET(bkpt
->bkpt_inst
), task
);
656 bkpt
->flags
|= BKPT_SET_IN_MEM
;
661 db_breakpoints_inserted
= inserted
;
666 db_clear_breakpoints(void)
668 register db_breakpoint_t bkpt
, *bkptp
;
669 register task_t task
;
671 thread_act_t cur_act
= current_act();
672 task_t cur_task
= (cur_act
&& !cur_act
->kernel_loaded
) ?
673 cur_act
->task
: TASK_NULL
;
675 if (db_breakpoints_inserted
) {
676 bkptp
= &db_breakpoint_list
;
677 for (bkpt
= *bkptp
; bkpt
; bkpt
= *bkptp
) {
679 if (bkpt
->flags
& BKPT_USR_GLOBAL
) {
680 if (cur_task
== TASK_NULL
) {
686 if ((bkpt
->flags
& BKPT_SET_IN_MEM
)
687 && DB_CHECK_ACCESS(bkpt
->address
, BKPT_SIZE
, task
)) {
688 inst
= db_get_task_value(bkpt
->address
, BKPT_SIZE
, FALSE
,
690 if (inst
!= BKPT_SET(inst
)) {
691 if (bkpt
->flags
& BKPT_USR_GLOBAL
) {
695 db_force_delete_breakpoint(bkpt
, 0, FALSE
);
697 db_breakpoint_free(bkpt
);
700 db_put_task_value(bkpt
->address
, BKPT_SIZE
,
701 bkpt
->bkpt_inst
, task
);
702 bkpt
->flags
&= ~BKPT_SET_IN_MEM
;
706 db_breakpoints_inserted
= FALSE
;
711 * Set a temporary breakpoint.
712 * The instruction is changed immediately,
713 * so the breakpoint does not have to be on the breakpoint list.
716 db_set_temp_breakpoint(
720 register db_breakpoint_t bkpt
;
722 bkpt
= db_breakpoint_alloc();
724 db_printf("Too many breakpoints.\n");
728 bkpt
->address
= addr
;
729 bkpt
->flags
= BKPT_TEMP
;
731 if (db_add_thread_breakpoint(bkpt
, 0, 1, FALSE
) < 0) {
733 db_breakpoint_free(bkpt
);
734 db_printf("Too many thread_breakpoints.\n");
737 bkpt
->bkpt_inst
= db_get_task_value(bkpt
->address
, BKPT_SIZE
,
739 db_put_task_value(bkpt
->address
, BKPT_SIZE
,
740 BKPT_SET(bkpt
->bkpt_inst
), task
);
745 db_delete_temp_breakpoint(
747 db_breakpoint_t bkpt
)
749 db_put_task_value(bkpt
->address
, BKPT_SIZE
, bkpt
->bkpt_inst
, task
);
750 db_delete_thread_breakpoint(bkpt
, 0);
751 db_breakpoint_free(bkpt
);
758 db_list_breakpoints(void)
760 register db_breakpoint_t bkpt
;
762 if (db_breakpoint_list
== 0) {
763 db_printf("No breakpoints set\n");
767 db_printf(" No Space Task.Act Cnt Address(Cond)\n");
768 for (bkpt
= db_breakpoint_list
;
772 register db_thread_breakpoint_t tp
;
777 for (tp
= bkpt
->threads
; tp
; tp
= tp
->tb_next
) {
778 db_printf("%3d ", tp
->tb_number
);
779 if (bkpt
->flags
& BKPT_USR_GLOBAL
)
781 else if (bkpt
->task
== TASK_NULL
)
782 db_printf("kernel ");
783 else if ((task_id
= db_lookup_task(bkpt
->task
)) < 0)
784 db_printf("%0*X ", 2*sizeof(vm_offset_t
), bkpt
->task
);
786 db_printf("task%-3d ", task_id
);
787 if (tp
->tb_task_thd
== 0) {
790 if (tp
->tb_is_task
) {
791 task_id
= db_lookup_task((task_t
)(tp
->tb_task_thd
));
793 db_printf("%0*X ", 2*sizeof(vm_offset_t
),
796 db_printf("task%03d ", task_id
);
798 thread_act_t thd
= (thread_act_t
)(tp
->tb_task_thd
);
799 task_id
= db_lookup_task(thd
->task
);
800 act_id
= db_lookup_task_act(thd
->task
, thd
);
801 if (task_id
< 0 || act_id
< 0)
802 db_printf("%0*X ", 2*sizeof(vm_offset_t
),
805 db_printf("task%03d.%-3d ", task_id
, act_id
);
808 db_printf("%3d ", tp
->tb_init_count
);
809 db_task_printsym(bkpt
->address
, DB_STGY_PROC
, bkpt
->task
);
810 if (tp
->tb_cond
> 0) {
818 if (bkpt
->task
== TASK_NULL
)
819 db_printf(" ? kernel ");
821 db_printf("%*X ", 2*sizeof(vm_offset_t
), bkpt
->task
);
823 db_task_printsym(bkpt
->address
, DB_STGY_PROC
, bkpt
->task
);
830 db_delete_all_breakpoints(
833 register db_breakpoint_t bkpt
;
835 bkpt
= db_breakpoint_list
;
836 while ( bkpt
!= 0 ) {
837 if (bkpt
->task
== task
||
838 (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
))) {
839 db_delete_breakpoint(task
, bkpt
->address
, 0);
840 bkpt
= db_breakpoint_list
;
848 /* Delete breakpoint */
853 thread_act_t thr_act
;
854 vm_offset_t task_thd
;
855 boolean_t user_global
= FALSE
;
856 boolean_t task_bpt
= FALSE
;
857 boolean_t user_space
= FALSE
;
858 boolean_t thd_bpt
= FALSE
;
866 db_printf("Bad modifier \"%s\"\n", db_tok_string
);
869 user_global
= db_option(db_tok_string
, 'U');
870 user_space
= (user_global
)? TRUE
: db_option(db_tok_string
, 'u');
871 task_bpt
= db_option(db_tok_string
, 'T');
872 thd_bpt
= db_option(db_tok_string
, 't');
873 if (task_bpt
&& user_global
)
874 db_error("Cannot specify both 'T' and 'U' option\n");
879 db_printf("Delete ALL breakpoints\n");
880 db_delete_all_breakpoints( (task_t
)task_bpt
);
885 db_thread_breakpoint_t tbp
;
886 db_breakpoint_t bkpt
;
888 if (db_read_token() != tNUMBER
) {
889 db_printf("Bad break point number #%s\n", db_tok_string
);
892 if ((tbp
= db_find_breakpoint_number(db_tok_number
, &bkpt
)) == 0) {
893 db_printf("No such break point #%d\n", db_tok_number
);
896 db_delete_breakpoint(bkpt
->task
, bkpt
->address
, tbp
->tb_task_thd
);
900 if (!db_expression(&addr
)) {
902 * We attempt to pick up the user_space indication from db_dot,
903 * so that a plain "d" always works.
905 addr
= (db_expr_t
)db_dot
;
906 if (!user_space
&& !DB_VALID_ADDRESS(addr
, FALSE
))
909 if (!DB_VALID_ADDRESS(addr
, user_space
)) {
910 db_printf("Address %#X is not in %s space\n", addr
,
911 (user_space
)? "user": "kernel");
914 if (thd_bpt
|| task_bpt
) {
915 for (n
= 0; db_get_next_act(&thr_act
, n
); n
++) {
916 if (thr_act
== THR_ACT_NULL
)
917 db_error("No active thr_act\n");
919 if (thr_act
->task
== TASK_NULL
)
920 db_error("No task\n");
921 task_thd
= (vm_offset_t
) (thr_act
->task
);
923 task_thd
= (user_global
)? 0: (vm_offset_t
) thr_act
;
924 db_delete_breakpoint(db_target_space(thr_act
, user_space
),
925 (db_addr_t
)addr
, task_thd
);
928 db_delete_breakpoint(db_target_space(THR_ACT_NULL
, user_space
),
933 /* Set breakpoint with skip count */
934 #include <mach/machine/vm_param.h>
944 thread_act_t thr_act
;
945 boolean_t user_global
= db_option(modif
, 'U');
946 boolean_t task_bpt
= db_option(modif
, 'T');
947 boolean_t user_space
;
952 if (!task_bpt
&& db_option(modif
,'t'))
956 if (task_bpt
&& user_global
)
957 db_error("Cannot specify both 'T' and 'U'\n");
958 user_space
= (user_global
)? TRUE
: db_option(modif
, 'u');
959 if (user_space
&& db_access_level
< DB_ACCESS_CURRENT
)
960 db_error("User space break point is not supported\n");
961 if ((!task_bpt
|| !user_space
) &&
962 !DB_VALID_ADDRESS(addr
, user_space
)) {
963 /* if the user has explicitly specified user space,
964 do not insert a breakpoint into the kernel */
966 db_error("Invalid user space address\n");
968 db_printf("%#X is in user space\n", addr
);
969 db_printf("kernel is from %#X to %#x\n", VM_MIN_KERNEL_ADDRESS
, VM_MAX_KERNEL_ADDRESS
);
971 if (db_option(modif
, 't') || task_bpt
) {
972 for (n
= 0; db_get_next_act(&thr_act
, n
); n
++) {
973 if (thr_act
== THR_ACT_NULL
)
974 db_error("No active thr_act\n");
975 if (task_bpt
&& thr_act
->task
== TASK_NULL
)
976 db_error("No task\n");
977 if (db_access_level
<= DB_ACCESS_CURRENT
&& user_space
978 && thr_act
->task
!= db_current_space())
979 db_error("Cannot set break point in inactive user space\n");
980 db_set_breakpoint(db_target_space(thr_act
, user_space
),
981 (db_addr_t
)addr
, count
,
982 (user_global
)? THR_ACT_NULL
: thr_act
,
986 db_set_breakpoint(db_target_space(THR_ACT_NULL
, user_space
),
988 count
, THR_ACT_NULL
, FALSE
);
992 /* list breakpoints */
994 db_listbreak_cmd(void)
996 db_list_breakpoints();