2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
31 * Revision 1.1.1.1 1998/09/22 21:05:47 wsanchez
32 * Import of Mac OS X kernel (~semeria)
34 * Revision 1.2 1998/04/29 17:35:26 mburg
37 * Revision 1.2.47.1 1998/02/03 09:23:57 gdt
39 * [1998/02/03 09:10:14 gdt]
41 * Revision 1.2.45.1 1997/03/27 18:46:16 barbou
42 * ri-osc CR1557: re-enable thread-specific breakpoints.
43 * [1995/09/20 15:23:46 bolinger]
46 * Revision 1.2.21.6 1996/01/09 19:15:21 devrcs
47 * Changed declarations of 'register foo' to 'register int foo'
48 * Fixed printfs which print addresses.
49 * [1995/12/01 21:41:51 jfraser]
51 * Merged '64-bit safe' changes from DEC alpha port.
52 * [1995/11/21 18:02:40 jfraser]
54 * Revision 1.2.21.5 1995/04/07 18:52:54 barbou
55 * Allow breakpoints on non-resident pages. The breakpoint will
56 * actually be set when the page is paged in.
60 * Revision 1.2.21.4 1995/02/23 21:43:19 alanl
61 * Merged with DIPC2_SHARED.
62 * [1995/01/04 20:15:04 alanl]
64 * Revision 1.2.28.1 1994/11/04 09:52:15 dwm
65 * mk6 CR668 - 1.3b26 merge
66 * * Revision 1.2.4.5 1994/05/06 18:38:52 tmt
67 * Merged osc1.3dec/shared with osc1.3b19
68 * Moved struct db_breakpoint from here to db_break.h.
69 * Merge Alpha changes into osc1.312b source code.
72 * [1994/11/04 08:49:10 dwm]
74 * Revision 1.2.21.2 1994/09/23 01:17:57 ezf
75 * change marker to not FREE
76 * [1994/09/22 21:09:19 ezf]
78 * Revision 1.2.21.1 1994/06/11 21:11:24 bolinger
79 * Merge up to NMK17.2.
80 * [1994/06/11 20:01:06 bolinger]
82 * Revision 1.2.25.2 1994/10/28 18:56:21 rwd
86 * Revision 1.2.25.1 1994/08/04 01:42:15 mmp
87 * 23-Jun-94 Stan Smith (stans@ssd.intel.com)
88 * Let d * delete all breakpoints.
89 * [1994/06/28 13:54:00 sjs]
91 * Revision 1.2.19.2 1994/04/11 09:34:22 bernadat
92 * Moved db_breakpoint struct declaration to db_break.h
95 * Revision 1.2.19.1 1994/02/08 10:57:22 bernadat
96 * When setting a breakpoint, force user_space if breakpoint is
97 * outside kernel_space (like in the case of an emulator).
100 * Changed silly decimal display to hex (to match input conventions).
101 * Change from NORMA_MK14.6 [93/01/09 sjs]
102 * [93/07/16 bernadat]
103 * [94/02/07 bernadat]
105 * Revision 1.2.4.3 1993/07/27 18:26:48 elliston
106 * Add ANSI prototypes. CR #9523.
107 * [1993/07/27 18:10:54 elliston]
109 * Revision 1.2.4.2 1993/06/09 02:19:39 gm
110 * Added to OSF/1 R1.3 from NMK15.0.
111 * [1993/06/02 20:55:42 jeffc]
113 * Revision 1.2 1993/04/19 16:01:31 devrcs
115 * Removed unused variable from db_delete_cmd().
116 * Added declaration for arg 'count' of db_add_thread_breakpoint().
118 * Fixed b/tu to b/Tu work if the specified address is valid in the
119 * target address space but not the current user space. Explicit
120 * user space breakpoints (b/u, b/Tu, etc) will no longer get
121 * inserted into the kernel if the specified address is invalid.
125 * Revision 1.1 1992/09/30 02:00:52 robert
132 * Revision 2.11.3.1 92/03/03 16:13:20 jeffreyh
133 * Pick up changes from TRUNK
134 * [92/02/26 10:58:37 jeffreyh]
136 * Revision 2.12 92/02/19 16:46:24 elf
137 * Removed one of the many user-unfriendlinesses.
138 * [92/02/10 17:48:25 af]
140 * Revision 2.11 91/11/12 11:50:24 rvb
141 * Fixed db_delete_cmd so that just "d" works in user space.
143 * Fixed db_delete_thread_breakpoint for zero task_thd.
146 * Revision 2.10 91/10/09 15:57:41 af
147 * Supported thread-oriented break points.
150 * Revision 2.9 91/07/09 23:15:39 danner
151 * Conditionalized db_map_addr to work right on the luna. Used a
152 * ifdef luna88k. This is evil, and needs to be fixed.
155 * Revision 2.2 91/04/10 22:54:50 mbj
156 * Grabbed 3.0 copyright/disclaimer since ddb comes from 3.0.
159 * Revision 2.7 91/02/05 17:06:00 mrt
160 * Changed to new Mach copyright
161 * [91/01/31 16:17:01 mrt]
163 * Revision 2.6 91/01/08 15:09:03 rpd
164 * Added db_map_equal, db_map_current, db_map_addr.
167 * Revision 2.5 90/11/05 14:26:32 rpd
168 * Initialize db_breakpoints_inserted to TRUE.
171 * Revision 2.4 90/10/25 14:43:33 rwd
172 * Added map field to breakpoints.
173 * Added map argument to db_set_breakpoint, db_delete_breakpoint,
174 * db_find_breakpoint. Added db_find_breakpoint_here.
177 * Revision 2.3 90/09/28 16:57:07 jsb
178 * Fixed db_breakpoint_free.
181 * Revision 2.2 90/08/27 21:49:53 dbg
182 * Reflected changes in db_printsym()'s calling seq.
184 * Clear breakpoints only if inserted.
193 * Mach Operating System
194 * Copyright (c) 1991,1990 Carnegie Mellon University
195 * All Rights Reserved.
197 * Permission to use, copy, modify and distribute this software and its
198 * documentation is hereby granted, provided that both the copyright
199 * notice and this permission notice appear in all copies of the
200 * software, derivative works or modified versions, and any portions
201 * thereof, and that both notices appear in supporting documentation.
203 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
204 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
205 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
207 * Carnegie Mellon requests users of this software to return to
209 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
210 * School of Computer Science
211 * Carnegie Mellon University
212 * Pittsburgh PA 15213-3890
214 * any improvements or extensions that they make and grant Carnegie Mellon
215 * the rights to redistribute these changes.
220 * Author: David B. Golub, Carnegie Mellon University
227 #include <mach/boolean.h>
228 #include <machine/db_machdep.h>
229 #include <ddb/db_lex.h>
230 #include <ddb/db_break.h>
231 #include <ddb/db_access.h>
232 #include <ddb/db_sym.h>
233 #include <ddb/db_variables.h>
234 #include <ddb/db_command.h>
235 #include <ddb/db_cond.h>
236 #include <ddb/db_expr.h>
237 #include <ddb/db_output.h> /* For db_printf() */
238 #include <ddb/db_task_thread.h>
241 #define NBREAKPOINTS 100
242 #define NTHREAD_LIST (NBREAKPOINTS*3)
244 struct db_breakpoint db_break_table
[NBREAKPOINTS
];
245 db_breakpoint_t db_next_free_breakpoint
= &db_break_table
[0];
246 db_breakpoint_t db_free_breakpoints
= 0;
247 db_breakpoint_t db_breakpoint_list
= 0;
249 static struct db_thread_breakpoint db_thread_break_list
[NTHREAD_LIST
];
250 static db_thread_breakpoint_t db_free_thread_break_list
= 0;
251 static boolean_t db_thread_break_init
= FALSE
;
252 static int db_breakpoint_number
= 0;
254 /* Prototypes for functions local to this file. XXX -- should be static!
256 static int db_add_thread_breakpoint(
257 register db_breakpoint_t bkpt
,
258 vm_offset_t task_thd
,
262 static int db_delete_thread_breakpoint(
263 register db_breakpoint_t bkpt
,
264 vm_offset_t task_thd
);
266 static db_thread_breakpoint_t
db_find_thread_breakpoint(
267 db_breakpoint_t bkpt
,
268 thread_act_t thr_act
);
270 static void db_force_delete_breakpoint(
271 db_breakpoint_t bkpt
,
272 vm_offset_t task_thd
,
275 db_breakpoint_t
db_breakpoint_alloc(void);
277 void db_breakpoint_free(register db_breakpoint_t bkpt
);
279 void db_delete_breakpoint(
282 vm_offset_t task_thd
);
285 db_delete_all_breakpoints(
288 void db_list_breakpoints(void);
293 db_breakpoint_alloc(void)
295 register db_breakpoint_t bkpt
;
297 if ((bkpt
= db_free_breakpoints
) != 0) {
298 db_free_breakpoints
= bkpt
->link
;
301 if (db_next_free_breakpoint
== &db_break_table
[NBREAKPOINTS
]) {
302 db_printf("All breakpoints used.\n");
305 bkpt
= db_next_free_breakpoint
;
306 db_next_free_breakpoint
++;
312 db_breakpoint_free(register db_breakpoint_t bkpt
)
314 bkpt
->link
= db_free_breakpoints
;
315 db_free_breakpoints
= bkpt
;
319 db_add_thread_breakpoint(
320 register db_breakpoint_t bkpt
,
321 vm_offset_t task_thd
,
325 register db_thread_breakpoint_t tp
;
327 if (db_thread_break_init
== FALSE
) {
328 for (tp
= db_thread_break_list
;
329 tp
< &db_thread_break_list
[NTHREAD_LIST
-1]; tp
++)
332 db_free_thread_break_list
= db_thread_break_list
;
333 db_thread_break_init
= TRUE
;
335 if (db_free_thread_break_list
== 0)
337 tp
= db_free_thread_break_list
;
338 db_free_thread_break_list
= tp
->tb_next
;
339 tp
->tb_is_task
= task_bpt
;
340 tp
->tb_task_thd
= task_thd
;
341 tp
->tb_count
= count
;
342 tp
->tb_init_count
= count
;
344 tp
->tb_number
= ++db_breakpoint_number
;
345 tp
->tb_next
= bkpt
->threads
;
351 db_delete_thread_breakpoint(
352 register db_breakpoint_t bkpt
,
353 vm_offset_t task_thd
)
355 register db_thread_breakpoint_t tp
;
356 register db_thread_breakpoint_t
*tpp
;
359 /* delete all the thread-breakpoints */
361 for (tpp
= &bkpt
->threads
; (tp
= *tpp
) != 0; tpp
= &tp
->tb_next
)
364 *tpp
= db_free_thread_break_list
;
365 db_free_thread_break_list
= bkpt
->threads
;
369 /* delete the specified thread-breakpoint */
371 for (tpp
= &bkpt
->threads
; (tp
= *tpp
) != 0; tpp
= &tp
->tb_next
)
372 if (tp
->tb_task_thd
== task_thd
) {
375 tp
->tb_next
= db_free_thread_break_list
;
376 db_free_thread_break_list
= tp
;
380 return -1; /* not found */
384 static db_thread_breakpoint_t
385 db_find_thread_breakpoint(
386 db_breakpoint_t bkpt
,
387 thread_act_t thr_act
)
389 register db_thread_breakpoint_t tp
;
390 register task_t task
=
391 (thr_act
== THR_ACT_NULL
|| thr_act
->kernel_loaded
)
392 ? TASK_NULL
: thr_act
->task
;
394 for (tp
= bkpt
->threads
; tp
; tp
= tp
->tb_next
) {
395 if (tp
->tb_is_task
) {
396 if (tp
->tb_task_thd
== (vm_offset_t
)task
)
400 if (tp
->tb_task_thd
== (vm_offset_t
)thr_act
|| tp
->tb_task_thd
== 0)
406 db_thread_breakpoint_t
407 db_find_thread_breakpoint_here(
411 db_breakpoint_t bkpt
;
413 bkpt
= db_find_breakpoint(task
, (db_addr_t
)addr
);
416 return(db_find_thread_breakpoint(bkpt
, current_act()));
419 db_thread_breakpoint_t
420 db_find_breakpoint_number(
422 db_breakpoint_t
*bkptp
)
424 register db_thread_breakpoint_t tp
;
425 register db_breakpoint_t bkpt
;
427 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
428 for (tp
= bkpt
->threads
; tp
; tp
= tp
->tb_next
) {
429 if (tp
->tb_number
== num
) {
440 db_force_delete_breakpoint(
441 db_breakpoint_t bkpt
,
442 vm_offset_t task_thd
,
445 db_printf("deleted a stale breakpoint at ");
446 if (bkpt
->task
== TASK_NULL
|| db_lookup_task(bkpt
->task
) >= 0)
447 db_task_printsym(bkpt
->address
, DB_STGY_PROC
, bkpt
->task
);
449 db_printf("%#X", bkpt
->address
);
451 db_printf(" in task %X", bkpt
->task
);
453 db_printf(" for %s %X", (is_task
)? "task": "thr_act", task_thd
);
455 db_delete_thread_breakpoint(bkpt
, task_thd
);
459 db_check_breakpoint_valid(void)
461 register db_thread_breakpoint_t tbp
, tbp_next
;
462 register db_breakpoint_t bkpt
, *bkptp
;
464 bkptp
= &db_breakpoint_list
;
465 for (bkpt
= *bkptp
; bkpt
; bkpt
= *bkptp
) {
466 if (bkpt
->task
!= TASK_NULL
) {
467 if (db_lookup_task(bkpt
->task
) < 0) {
468 db_force_delete_breakpoint(bkpt
, 0, FALSE
);
470 db_breakpoint_free(bkpt
);
474 for (tbp
= bkpt
->threads
; tbp
; tbp
= tbp_next
) {
475 tbp_next
= tbp
->tb_next
;
476 if (tbp
->tb_task_thd
== 0)
478 if ((tbp
->tb_is_task
&&
479 db_lookup_task((task_t
)(tbp
->tb_task_thd
)) < 0) ||
481 db_lookup_act((thread_act_t
)(tbp
->tb_task_thd
)) < 0)) {
482 db_force_delete_breakpoint(bkpt
,
483 tbp
->tb_task_thd
, tbp
->tb_is_task
);
486 if (bkpt
->threads
== 0) {
487 db_put_task_value(bkpt
->address
, BKPT_SIZE
,
488 bkpt
->bkpt_inst
, bkpt
->task
);
490 db_breakpoint_free(bkpt
);
503 thread_act_t thr_act
,
506 register db_breakpoint_t bkpt
;
507 db_breakpoint_t alloc_bkpt
= 0;
508 vm_offset_t task_thd
;
510 bkpt
= db_find_breakpoint(task
, addr
);
512 if (thr_act
== THR_ACT_NULL
513 || db_find_thread_breakpoint(bkpt
, thr_act
)) {
514 db_printf("Already set.\n");
518 if (!DB_CHECK_ACCESS(addr
, BKPT_SIZE
, task
)) {
520 db_printf("Warning: non-resident page for breakpoint at %lX",
522 db_printf(" in task %lX.\n", task
);
524 db_printf("Cannot set breakpoint at %lX in kernel space.\n",
529 alloc_bkpt
= bkpt
= db_breakpoint_alloc();
531 db_printf("Too many breakpoints.\n");
535 bkpt
->flags
= (task
&& thr_act
== THR_ACT_NULL
)?
536 (BKPT_USR_GLOBAL
|BKPT_1ST_SET
): 0;
537 bkpt
->address
= addr
;
540 if (db_breakpoint_list
== 0)
541 db_breakpoint_number
= 0;
542 task_thd
= (task_bpt
) ? (vm_offset_t
)(thr_act
->task
)
543 : (vm_offset_t
)thr_act
;
544 if (db_add_thread_breakpoint(bkpt
, task_thd
, count
, task_bpt
) < 0) {
546 db_breakpoint_free(alloc_bkpt
);
547 db_printf("Too many thread_breakpoints.\n");
549 db_printf("set breakpoint #%x\n", db_breakpoint_number
);
551 bkpt
->link
= db_breakpoint_list
;
552 db_breakpoint_list
= bkpt
;
558 db_delete_breakpoint(
561 vm_offset_t task_thd
)
563 register db_breakpoint_t bkpt
;
564 register db_breakpoint_t
*prev
;
566 for (prev
= &db_breakpoint_list
; (bkpt
= *prev
) != 0;
567 prev
= &bkpt
->link
) {
568 if ((bkpt
->task
== task
569 || (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
)))
570 && bkpt
->address
== addr
)
573 if (bkpt
&& (bkpt
->flags
& BKPT_SET_IN_MEM
)) {
574 db_printf("cannot delete it now.\n");
578 || db_delete_thread_breakpoint(bkpt
, task_thd
) < 0) {
579 db_printf("Not set.\n");
582 if (bkpt
->threads
== 0) {
584 db_breakpoint_free(bkpt
);
593 register db_breakpoint_t bkpt
;
595 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
596 if ((bkpt
->task
== task
597 || (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
)))
598 && bkpt
->address
== addr
)
605 db_find_breakpoint_here(
609 register db_breakpoint_t bkpt
;
611 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
612 if ((bkpt
->task
== task
613 || (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
)))
614 && bkpt
->address
== addr
)
616 if ((bkpt
->flags
& BKPT_USR_GLOBAL
) == 0 &&
617 DB_PHYS_EQ(task
, addr
, bkpt
->task
, bkpt
->address
))
623 boolean_t db_breakpoints_inserted
= TRUE
;
626 db_set_breakpoints(void)
628 register db_breakpoint_t bkpt
;
629 register task_t task
;
631 thread_act_t cur_act
= current_act();
633 (cur_act
&& !cur_act
->kernel_loaded
) ?
634 cur_act
->task
: TASK_NULL
;
635 boolean_t inserted
= TRUE
;
637 if (!db_breakpoints_inserted
) {
638 for (bkpt
= db_breakpoint_list
; bkpt
!= 0; bkpt
= bkpt
->link
) {
639 if (bkpt
->flags
& BKPT_SET_IN_MEM
)
642 if (bkpt
->flags
& BKPT_USR_GLOBAL
) {
643 if ((bkpt
->flags
& BKPT_1ST_SET
) == 0) {
644 if (cur_task
== TASK_NULL
)
648 bkpt
->flags
&= ~BKPT_1ST_SET
;
650 if (DB_CHECK_ACCESS(bkpt
->address
, BKPT_SIZE
, task
)) {
651 inst
= db_get_task_value(bkpt
->address
, BKPT_SIZE
, FALSE
,
653 if (inst
== BKPT_SET(inst
))
655 bkpt
->bkpt_inst
= inst
;
656 db_put_task_value(bkpt
->address
,
658 BKPT_SET(bkpt
->bkpt_inst
), task
);
659 bkpt
->flags
|= BKPT_SET_IN_MEM
;
664 db_breakpoints_inserted
= inserted
;
669 db_clear_breakpoints(void)
671 register db_breakpoint_t bkpt
, *bkptp
;
672 register task_t task
;
674 thread_act_t cur_act
= current_act();
675 task_t cur_task
= (cur_act
&& !cur_act
->kernel_loaded
) ?
676 cur_act
->task
: TASK_NULL
;
678 if (db_breakpoints_inserted
) {
679 bkptp
= &db_breakpoint_list
;
680 for (bkpt
= *bkptp
; bkpt
; bkpt
= *bkptp
) {
682 if (bkpt
->flags
& BKPT_USR_GLOBAL
) {
683 if (cur_task
== TASK_NULL
) {
689 if ((bkpt
->flags
& BKPT_SET_IN_MEM
)
690 && DB_CHECK_ACCESS(bkpt
->address
, BKPT_SIZE
, task
)) {
691 inst
= db_get_task_value(bkpt
->address
, BKPT_SIZE
, FALSE
,
693 if (inst
!= BKPT_SET(inst
)) {
694 if (bkpt
->flags
& BKPT_USR_GLOBAL
) {
698 db_force_delete_breakpoint(bkpt
, 0, FALSE
);
700 db_breakpoint_free(bkpt
);
703 db_put_task_value(bkpt
->address
, BKPT_SIZE
,
704 bkpt
->bkpt_inst
, task
);
705 bkpt
->flags
&= ~BKPT_SET_IN_MEM
;
709 db_breakpoints_inserted
= FALSE
;
714 * Set a temporary breakpoint.
715 * The instruction is changed immediately,
716 * so the breakpoint does not have to be on the breakpoint list.
719 db_set_temp_breakpoint(
723 register db_breakpoint_t bkpt
;
725 bkpt
= db_breakpoint_alloc();
727 db_printf("Too many breakpoints.\n");
731 bkpt
->address
= addr
;
732 bkpt
->flags
= BKPT_TEMP
;
734 if (db_add_thread_breakpoint(bkpt
, 0, 1, FALSE
) < 0) {
736 db_breakpoint_free(bkpt
);
737 db_printf("Too many thread_breakpoints.\n");
740 bkpt
->bkpt_inst
= db_get_task_value(bkpt
->address
, BKPT_SIZE
,
742 db_put_task_value(bkpt
->address
, BKPT_SIZE
,
743 BKPT_SET(bkpt
->bkpt_inst
), task
);
748 db_delete_temp_breakpoint(
750 db_breakpoint_t bkpt
)
752 db_put_task_value(bkpt
->address
, BKPT_SIZE
, bkpt
->bkpt_inst
, task
);
753 db_delete_thread_breakpoint(bkpt
, 0);
754 db_breakpoint_free(bkpt
);
761 db_list_breakpoints(void)
763 register db_breakpoint_t bkpt
;
765 if (db_breakpoint_list
== 0) {
766 db_printf("No breakpoints set\n");
770 db_printf(" No Space Task.Act Cnt Address(Cond)\n");
771 for (bkpt
= db_breakpoint_list
;
775 register db_thread_breakpoint_t tp
;
780 for (tp
= bkpt
->threads
; tp
; tp
= tp
->tb_next
) {
781 db_printf("%3d ", tp
->tb_number
);
782 if (bkpt
->flags
& BKPT_USR_GLOBAL
)
784 else if (bkpt
->task
== TASK_NULL
)
785 db_printf("kernel ");
786 else if ((task_id
= db_lookup_task(bkpt
->task
)) < 0)
787 db_printf("%0*X ", 2*sizeof(vm_offset_t
), bkpt
->task
);
789 db_printf("task%-3d ", task_id
);
790 if (tp
->tb_task_thd
== 0) {
793 if (tp
->tb_is_task
) {
794 task_id
= db_lookup_task((task_t
)(tp
->tb_task_thd
));
796 db_printf("%0*X ", 2*sizeof(vm_offset_t
),
799 db_printf("task%03d ", task_id
);
801 thread_act_t thd
= (thread_act_t
)(tp
->tb_task_thd
);
802 task_id
= db_lookup_task(thd
->task
);
803 act_id
= db_lookup_task_act(thd
->task
, thd
);
804 if (task_id
< 0 || act_id
< 0)
805 db_printf("%0*X ", 2*sizeof(vm_offset_t
),
808 db_printf("task%03d.%-3d ", task_id
, act_id
);
811 db_printf("%3d ", tp
->tb_init_count
);
812 db_task_printsym(bkpt
->address
, DB_STGY_PROC
, bkpt
->task
);
813 if (tp
->tb_cond
> 0) {
821 if (bkpt
->task
== TASK_NULL
)
822 db_printf(" ? kernel ");
824 db_printf("%*X ", 2*sizeof(vm_offset_t
), bkpt
->task
);
826 db_task_printsym(bkpt
->address
, DB_STGY_PROC
, bkpt
->task
);
833 db_delete_all_breakpoints(
836 register db_breakpoint_t bkpt
;
838 bkpt
= db_breakpoint_list
;
839 while ( bkpt
!= 0 ) {
840 if (bkpt
->task
== task
||
841 (task
!= TASK_NULL
&& (bkpt
->flags
& BKPT_USR_GLOBAL
))) {
842 db_delete_breakpoint(task
, bkpt
->address
, 0);
843 bkpt
= db_breakpoint_list
;
851 /* Delete breakpoint */
856 thread_act_t thr_act
;
857 vm_offset_t task_thd
;
858 boolean_t user_global
= FALSE
;
859 boolean_t task_bpt
= FALSE
;
860 boolean_t user_space
= FALSE
;
861 boolean_t thd_bpt
= FALSE
;
869 db_printf("Bad modifier \"%s\"\n", db_tok_string
);
872 user_global
= db_option(db_tok_string
, 'U');
873 user_space
= (user_global
)? TRUE
: db_option(db_tok_string
, 'u');
874 task_bpt
= db_option(db_tok_string
, 'T');
875 thd_bpt
= db_option(db_tok_string
, 't');
876 if (task_bpt
&& user_global
)
877 db_error("Cannot specify both 'T' and 'U' option\n");
882 db_printf("Delete ALL breakpoints\n");
883 db_delete_all_breakpoints( (task_t
)task_bpt
);
888 db_thread_breakpoint_t tbp
;
889 db_breakpoint_t bkpt
;
891 if (db_read_token() != tNUMBER
) {
892 db_printf("Bad break point number #%s\n", db_tok_string
);
895 if ((tbp
= db_find_breakpoint_number(db_tok_number
, &bkpt
)) == 0) {
896 db_printf("No such break point #%d\n", db_tok_number
);
899 db_delete_breakpoint(bkpt
->task
, bkpt
->address
, tbp
->tb_task_thd
);
903 if (!db_expression(&addr
)) {
905 * We attempt to pick up the user_space indication from db_dot,
906 * so that a plain "d" always works.
908 addr
= (db_expr_t
)db_dot
;
909 if (!user_space
&& !DB_VALID_ADDRESS(addr
, FALSE
))
912 if (!DB_VALID_ADDRESS(addr
, user_space
)) {
913 db_printf("Address %#X is not in %s space\n", addr
,
914 (user_space
)? "user": "kernel");
917 if (thd_bpt
|| task_bpt
) {
918 for (n
= 0; db_get_next_act(&thr_act
, n
); n
++) {
919 if (thr_act
== THR_ACT_NULL
)
920 db_error("No active thr_act\n");
922 if (thr_act
->task
== TASK_NULL
)
923 db_error("No task\n");
924 task_thd
= (vm_offset_t
) (thr_act
->task
);
926 task_thd
= (user_global
)? 0: (vm_offset_t
) thr_act
;
927 db_delete_breakpoint(db_target_space(thr_act
, user_space
),
928 (db_addr_t
)addr
, task_thd
);
931 db_delete_breakpoint(db_target_space(THR_ACT_NULL
, user_space
),
936 /* Set breakpoint with skip count */
937 #include <mach/machine/vm_param.h>
947 thread_act_t thr_act
;
948 boolean_t user_global
= db_option(modif
, 'U');
949 boolean_t task_bpt
= db_option(modif
, 'T');
950 boolean_t user_space
;
955 if (!task_bpt
&& db_option(modif
,'t'))
959 if (task_bpt
&& user_global
)
960 db_error("Cannot specify both 'T' and 'U'\n");
961 user_space
= (user_global
)? TRUE
: db_option(modif
, 'u');
962 if (user_space
&& db_access_level
< DB_ACCESS_CURRENT
)
963 db_error("User space break point is not supported\n");
964 if ((!task_bpt
|| !user_space
) &&
965 !DB_VALID_ADDRESS(addr
, user_space
)) {
966 /* if the user has explicitly specified user space,
967 do not insert a breakpoint into the kernel */
969 db_error("Invalid user space address\n");
971 db_printf("%#X is in user space\n", addr
);
972 db_printf("kernel is from %#X to %#x\n", VM_MIN_KERNEL_ADDRESS
, VM_MAX_KERNEL_ADDRESS
);
974 if (db_option(modif
, 't') || task_bpt
) {
975 for (n
= 0; db_get_next_act(&thr_act
, n
); n
++) {
976 if (thr_act
== THR_ACT_NULL
)
977 db_error("No active thr_act\n");
978 if (task_bpt
&& thr_act
->task
== TASK_NULL
)
979 db_error("No task\n");
980 if (db_access_level
<= DB_ACCESS_CURRENT
&& user_space
981 && thr_act
->task
!= db_current_space())
982 db_error("Cannot set break point in inactive user space\n");
983 db_set_breakpoint(db_target_space(thr_act
, user_space
),
984 (db_addr_t
)addr
, count
,
985 (user_global
)? THR_ACT_NULL
: thr_act
,
989 db_set_breakpoint(db_target_space(THR_ACT_NULL
, user_space
),
991 count
, THR_ACT_NULL
, FALSE
);
995 /* list breakpoints */
997 db_listbreak_cmd(void)
999 db_list_breakpoints();