2 * Copyright (c) 2000-2005 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@
26 * Mach Operating System
27 * Copyright (c) 1991,1990 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
55 #include <mach/boolean.h>
56 #include <vm/vm_map.h>
57 #include <kern/thread.h>
58 #include <kern/task.h>
60 #include <machine/asm.h>
61 #include <machine/db_machdep.h>
62 #include <machine/setjmp.h>
63 #include <mach/machine.h>
64 #include <mach/kmod.h>
68 #include <i386/cpuid.h>
69 #include <i386/proc_reg.h>
70 #include <i386/machine_routines.h>
72 #include <ddb/db_access.h>
73 #include <ddb/db_sym.h>
74 #include <ddb/db_variables.h>
75 #include <ddb/db_command.h>
76 #include <ddb/db_task_thread.h>
77 #include <ddb/db_output.h>
79 extern jmp_buf_t
*db_recover
;
80 struct x86_kernel_state32 ddb_null_kregs
;
81 extern kmod_info_t
*kmod
;
88 #define INKERNELSTACK(va, th) 1
90 #define DB_NUMARGS_MAX 5
93 struct i386_frame
*f_frame
;
102 db_addr_t db_user_trap_symbol_value
= 0;
103 db_addr_t db_kernel_trap_symbol_value
= 0;
104 db_addr_t db_interrupt_symbol_value
= 0;
105 db_addr_t db_return_to_iret_symbol_value
= 0;
106 db_addr_t db_syscall_symbol_value
= 0;
107 boolean_t db_trace_symbols_found
= FALSE
;
113 { "ebx", (unsigned int)(&((struct x86_kernel_state32
*)0)->k_ebx
) },
114 { "esp", (unsigned int)(&((struct x86_kernel_state32
*)0)->k_esp
) },
115 { "ebp", (unsigned int)(&((struct x86_kernel_state32
*)0)->k_ebp
) },
116 { "edi", (unsigned int)(&((struct x86_kernel_state32
*)0)->k_edi
) },
117 { "esi", (unsigned int)(&((struct x86_kernel_state32
*)0)->k_esi
) },
118 { "eip", (unsigned int)(&((struct x86_kernel_state32
*)0)->k_eip
) },
124 extern unsigned int * db_lookup_i386_kreg(
127 extern int db_i386_reg_value(
128 struct db_variable
* vp
,
131 db_var_aux_param_t ap
);
132 extern void db_find_trace_symbols(void);
133 extern int db_numargs(
134 struct i386_frame
*fp
,
136 extern void db_nextframe(
137 struct i386_frame
**lfp
,
138 struct i386_frame
**fp
,
146 * Machine register set.
148 struct db_variable db_regs
[] = {
149 { "cs", (unsigned int *)&ddb_regs
.cs
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
150 { "ds", (unsigned int *)&ddb_regs
.ds
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
151 { "es", (unsigned int *)&ddb_regs
.es
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
152 { "fs", (unsigned int *)&ddb_regs
.fs
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
153 { "gs", (unsigned int *)&ddb_regs
.gs
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
154 { "ss", (unsigned int *)&ddb_regs
.ss
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
155 { "eax",(unsigned int *)&ddb_regs
.eax
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
156 { "ecx",(unsigned int *)&ddb_regs
.ecx
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
157 { "edx",(unsigned int *)&ddb_regs
.edx
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
158 { "ebx",(unsigned int *)&ddb_regs
.ebx
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
159 { "esp",(unsigned int *)&ddb_regs
.uesp
,db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
160 { "ebp",(unsigned int *)&ddb_regs
.ebp
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
161 { "esi",(unsigned int *)&ddb_regs
.esi
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
162 { "edi",(unsigned int *)&ddb_regs
.edi
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
163 { "eip",(unsigned int *)&ddb_regs
.eip
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 },
164 { "efl",(unsigned int *)&ddb_regs
.efl
, db_i386_reg_value
, 0, 0, 0, 0, TRUE
, 0, 0, (int *)0, 0 }
166 struct db_variable
*db_eregs
= db_regs
+ sizeof(db_regs
)/sizeof(db_regs
[0]);
173 register struct i386_kregs
*kp
;
175 for (kp
= i386_kregs
; kp
->name
; kp
++) {
176 if (strcmp(name
, kp
->name
) == 0)
177 return((unsigned int *)((int)kregp
+ kp
->offset
));
184 struct db_variable
*vp
,
187 db_var_aux_param_t ap
)
190 unsigned int *dp
= 0;
191 db_expr_t null_reg
= 0;
192 register thread_t thr_act
= ap
->thr_act
;
194 if (db_option(ap
->modif
, 'u')) {
195 if (thr_act
== THREAD_NULL
) {
196 if ((thr_act
= current_thread()) == THREAD_NULL
)
197 db_error("no user registers\n");
199 if (thr_act
== current_thread()) {
200 if (IS_USER_TRAP(&ddb_regs
, &etext
))
204 if (thr_act
== THREAD_NULL
|| thr_act
== current_thread()) {
208 (thr_act
->continuation
!= THREAD_CONTINUE_NULL
) &&
209 thr_act
->kernel_stack
) {
212 for (cpu
= 0; cpu
< real_ncpus
; cpu
++) {
213 if (cpu_datap(cpu
)->cpu_running
== TRUE
&&
214 cpu_datap(cpu
)->cpu_active_thread
== thr_act
&& cpu_datap(cpu
)->cpu_kdb_saved_state
) {
215 dp
= (unsigned int *) (((unsigned int)cpu_datap(cpu
)->cpu_kdb_saved_state
) +
216 (((unsigned int) vp
->valuep
) -
217 (unsigned int) &ddb_regs
));
221 if (dp
== 0 && thr_act
)
222 dp
= db_lookup_i386_kreg(vp
->name
,
223 (unsigned int *)(STACK_IKS(thr_act
->kernel_stack
)));
226 } else if (thr_act
&&
227 (thr_act
->continuation
!= THREAD_CONTINUE_NULL
)) {
228 /* only EIP is valid */
229 if (vp
->valuep
== (unsigned int *) &ddb_regs
.eip
) {
230 dp
= (unsigned int *)(&thr_act
->continuation
);
240 if (!db_option(ap
->modif
, 'u')) {
241 for (cpu
= 0; cpu
< real_ncpus
; cpu
++) {
242 if (cpu_datap(cpu
)->cpu_running
== TRUE
&&
243 cpu_datap(cpu
)->cpu_active_thread
== thr_act
&& cpu_datap(cpu
)->cpu_kdb_saved_state
) {
244 dp
= (unsigned int *) (((unsigned int)cpu_datap(cpu
)->cpu_kdb_saved_state
) +
245 (((unsigned int) vp
->valuep
) -
246 (unsigned int) &ddb_regs
));
252 if (!thr_act
|| thr_act
->machine
.pcb
== 0)
253 db_error("no pcb\n");
254 dp
= (unsigned int *)((unsigned int)(thr_act
->machine
.pcb
->iss
) +
255 ((unsigned int)vp
->valuep
- (unsigned int)&ddb_regs
));
258 if (flag
== DB_VAR_SET
)
266 db_find_trace_symbols(void)
269 boolean_t found_some
;
272 if (db_value_of_name(CC_SYM_PREFIX
"user_trap", &value
)) {
273 db_user_trap_symbol_value
= (db_addr_t
) value
;
276 if (db_value_of_name(CC_SYM_PREFIX
"kernel_trap", &value
)) {
277 db_kernel_trap_symbol_value
= (db_addr_t
) value
;
280 if (db_value_of_name(CC_SYM_PREFIX
"interrupt", &value
)) {
281 db_interrupt_symbol_value
= (db_addr_t
) value
;
284 if (db_value_of_name(CC_SYM_PREFIX
"return_to_iret", &value
)) {
285 db_return_to_iret_symbol_value
= (db_addr_t
) value
;
288 if (db_value_of_name(CC_SYM_PREFIX
"syscall", &value
)) {
289 db_syscall_symbol_value
= (db_addr_t
) value
;
293 db_trace_symbols_found
= TRUE
;
297 * Figure out how many arguments were passed into the frame at "fp".
299 int db_numargs_default
= 5;
303 struct i386_frame
*fp
,
311 argp
= (int *)db_get_task_value((int)&fp
->f_retaddr
, 4, FALSE
, task
);
312 if (argp
< (int *)VM_MIN_KERNEL_ADDRESS
|| (char *)argp
> &etext
)
313 args
= db_numargs_default
;
314 else if (!DB_CHECK_ACCESS((int)argp
, 4, task
))
315 args
= db_numargs_default
;
317 inst
= db_get_task_value((int)argp
, 4, FALSE
, task
);
318 if ((inst
& 0xff) == 0x59) /* popl %ecx */
320 else if ((inst
& 0xffff) == 0xc483) /* addl %n, %esp */
321 args
= ((inst
>> 16) & 0xff) / 4;
323 args
= db_numargs_default
;
328 struct interrupt_frame
{
329 struct i386_frame
*if_frame
; /* point to next frame */
330 int if_retaddr
; /* return address to _interrupt */
331 int if_unit
; /* unit number */
332 int if_spl
; /* saved spl */
333 int if_iretaddr
; /* _return_to_{iret,iret_i} */
334 int if_edx
; /* old sp(iret) or saved edx(iret_i) */
335 int if_ecx
; /* saved ecx(iret_i) */
336 int if_eax
; /* saved eax(iret_i) */
337 int if_eip
; /* saved eip(iret_i) */
338 int if_cs
; /* saved cs(iret_i) */
339 int if_efl
; /* saved efl(iret_i) */
343 * Figure out the next frame up in the call stack.
344 * For trap(), we print the address of the faulting instruction and
345 * proceed with the calling frame. We return the ip that faulted.
346 * If the trap was caused by jumping through a bogus pointer, then
347 * the next line in the backtrace will list some random function as
348 * being called. It should get the argument list correct, though.
349 * It might be possible to dig out from the next frame up the name
350 * of the function that faulted, but that could get hairy.
354 struct i386_frame
**lfp
, /* in/out */
355 struct i386_frame
**fp
, /* in/out */
356 db_addr_t
*ip
, /* out */
357 int frame_type
, /* in */
358 thread_t thr_act
) /* in */
360 x86_saved_state32_t
*iss32
;
361 extern char * trap_type
[];
362 extern int TRAP_TYPES
;
364 struct interrupt_frame
*ifp
;
365 task_t task
= (thr_act
!= THREAD_NULL
)? thr_act
->task
: TASK_NULL
;
370 * We know that trap() has 1 argument and we know that
371 * it is an (x86_saved_state32_t *).
373 iss32
= (x86_saved_state32_t
*)
374 db_get_task_value((int)&((*fp
)->f_arg0
),4,FALSE
,task
);
376 if (iss32
->trapno
>= 0 && iss32
->trapno
< TRAP_TYPES
) {
377 db_printf(">>>>> %s trap at ",
378 trap_type
[iss32
->trapno
]);
380 db_printf(">>>>> trap (number %d) at ",
381 iss32
->trapno
& 0xffff);
383 db_task_printsym(iss32
->eip
, DB_STGY_PROC
, task
);
384 db_printf(" <<<<<\n");
385 *fp
= (struct i386_frame
*)iss32
->ebp
;
386 *ip
= (db_addr_t
)iss32
->eip
;
390 db_printf(">>>>> interrupt <<<<<\n");
393 db_printf(">>>>> interrupt at ");
394 ifp
= (struct interrupt_frame
*)(*lfp
);
396 if (ifp
->if_iretaddr
== db_return_to_iret_symbol_value
) {
397 *ip
= ((x86_saved_state32_t
*) ifp
->if_edx
)->eip
;
399 *ip
= (db_addr_t
) ifp
->if_eip
;
400 db_task_printsym(*ip
, DB_STGY_PROC
, task
);
401 db_printf(" <<<<<\n");
404 if (thr_act
!= THREAD_NULL
&& thr_act
->machine
.pcb
) {
405 iss32
= (x86_saved_state32_t
*)thr_act
->machine
.pcb
->iss
;
407 *ip
= (db_addr_t
)(iss32
->eip
);
408 *fp
= (struct i386_frame
*)(iss32
->ebp
);
411 /* falling down for unknown case */
415 db_get_task_value((int)&(*fp
)->f_retaddr
, 4, FALSE
, task
);
417 *fp
= (struct i386_frame
*)
418 db_get_task_value((int)&(*fp
)->f_frame
, 4, FALSE
, task
);
430 struct i386_frame
*frame
, *lastframe
;
431 x86_saved_state32_t
*iss32
;
433 db_addr_t callpc
, lastcallpc
;
435 boolean_t kernel_only
= TRUE
;
436 boolean_t trace_thread
= FALSE
;
437 boolean_t trace_all_threads
= FALSE
;
442 thread_t th
, top_act
;
446 jmp_buf_t db_jmp_buf
;
447 queue_entry_t act_list
;
449 if (!db_trace_symbols_found
)
450 db_find_trace_symbols();
453 register char *cp
= modif
;
456 while ((c
= *cp
++) != 0) {
460 trace_all_threads
= TRUE
;
468 if (trace_all_threads
) {
469 if (!have_addr
&& !trace_thread
) {
472 act_list
= &(current_task()->threads
);
473 addr
= (db_expr_t
) queue_first(act_list
);
474 } else if (trace_thread
) {
476 if (!db_check_act_address_valid((thread_t
)addr
)) {
477 if (db_lookup_task((task_t
)addr
) == -1)
479 act_list
= &(((task_t
)addr
)->threads
);
480 addr
= (db_expr_t
) queue_first(act_list
);
482 act_list
= &(((thread_t
)addr
)->task
->threads
);
483 thcount
= db_lookup_task_act(((thread_t
)addr
)->task
,
488 if (th
== THREAD_NULL
)
489 th
= current_thread();
490 if (th
== THREAD_NULL
) {
491 db_printf("no active thr_act\n");
495 act_list
= &th
->task
->threads
;
496 addr
= (db_expr_t
) queue_first(act_list
);
505 top_act
= THREAD_NULL
;
510 if (!have_addr
&& !trace_thread
) {
511 frame
= (struct i386_frame
*)ddb_regs
.ebp
;
512 callpc
= (db_addr_t
)ddb_regs
.eip
;
513 th
= current_thread();
514 task
= (th
!= THREAD_NULL
)? th
->task
: TASK_NULL
;
515 db_printf("thread 0x%x, current_thread() is 0x%x, ebp is 0x%x, eip is 0x%x\n", th
, current_thread(), ddb_regs
.ebp
, ddb_regs
.eip
);
516 } else if (trace_thread
) {
518 th
= (thread_t
) addr
;
519 if (!db_check_act_address_valid(th
)) {
524 if (th
== THREAD_NULL
)
525 th
= current_thread();
526 if (th
== THREAD_NULL
) {
527 db_printf("no active thread\n");
531 if (trace_all_threads
)
532 db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
533 addr
, thcount
, th
->task
->thread_count
);
537 // kprintf("th is %x, current_thread() is %x, ddb_regs.ebp is %x ddb_regs.eip is %x\n", th, current_thread(), ddb_regs.ebp, ddb_regs.eip);
539 if (th
== current_thread()) {
540 frame
= (struct i386_frame
*)ddb_regs
.ebp
;
541 callpc
= (db_addr_t
)ddb_regs
.eip
;
543 if (th
->machine
.pcb
== 0) {
544 db_printf("thread has no pcb\n");
548 db_printf("thread has no shuttle\n");
552 else if ( (th
->continuation
!= THREAD_CONTINUE_NULL
) ||
553 th
->kernel_stack
== 0) {
555 db_printf("Continuation ");
556 db_task_printsym((db_expr_t
)th
->continuation
,
560 iss32
= (x86_saved_state32_t
*)th
->machine
.pcb
->iss
;
562 frame
= (struct i386_frame
*) (iss32
->ebp
);
563 callpc
= (db_addr_t
) (iss32
->eip
);
568 for (cpu
= 0; cpu
< real_ncpus
; cpu
++) {
569 if (cpu_datap(cpu
)->cpu_running
== TRUE
&&
570 cpu_datap(cpu
)->cpu_active_thread
== th
&&
571 cpu_datap(cpu
)->cpu_kdb_saved_state
) {
575 if (top_act
!= THREAD_NULL
) {
577 * Trying to get the backtrace of an activation
578 * which is not the top_most one in the RPC chain:
579 * use the activation's pcb.
581 iss32
= (x86_saved_state32_t
*)th
->machine
.pcb
->iss
;
583 frame
= (struct i386_frame
*) (iss32
->ebp
);
584 callpc
= (db_addr_t
) (iss32
->eip
);
586 if (cpu
== real_ncpus
) {
587 register struct x86_kernel_state32
*iks
;
590 iks
= STACK_IKS(th
->kernel_stack
);
592 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
593 frame
= (struct i386_frame
*) (iks
->k_ebp
);
594 callpc
= (db_addr_t
) (iks
->k_eip
);
597 * The kernel stack has probably been
598 * paged out (swapped out activation).
601 if (r
== 2) /* 'q' from db_more() */
603 db_printf("<kernel stack (0x%x) error "
604 "(probably swapped out)>\n",
610 db_printf(">>>>> active on cpu %d <<<<<\n",
613 iss32
= (x86_saved_state32_t
*)cpu_datap(cpu
)->cpu_kdb_saved_state
;
615 frame
= (struct i386_frame
*) (iss32
->ebp
);
616 callpc
= (db_addr_t
) (iss32
->eip
);
622 frame
= (struct i386_frame
*)addr
;
623 th
= (db_default_act
)? db_default_act
: current_thread();
624 task
= (th
!= THREAD_NULL
)? th
->task
: TASK_NULL
;
625 callpc
= (db_addr_t
)db_get_task_value((int)&frame
->f_retaddr
,
628 (user_frame
) ? task
: 0);
631 if (!INKERNELSTACK((unsigned)frame
, th
)) {
632 db_printf(">>>>> user space <<<<<\n");
639 lastcallpc
= (db_addr_t
) 0;
640 while (frame_count
-- && frame
!= 0) {
641 int narg
= DB_NUMARGS_MAX
;
644 db_addr_t call_func
= 0;
648 db_symbol_values(NULL
,
649 db_search_task_symbol_and_line(
655 (user_frame
) ? task
: 0,
657 &name
, (db_expr_t
*)&call_func
);
659 db_find_task_sym_and_offset(callpc
,
660 &name
, &off
, (user_frame
) ? task
: 0);
661 offset
= (db_expr_t
) off
;
664 if (user_frame
== 0) {
665 if (call_func
&& call_func
== db_user_trap_symbol_value
||
666 call_func
== db_kernel_trap_symbol_value
) {
669 } else if (call_func
&&
670 call_func
== db_interrupt_symbol_value
) {
671 frame_type
= INTERRUPT
;
673 } else if (call_func
&& call_func
== db_syscall_symbol_value
) {
674 frame_type
= SYSCALL
;
679 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
681 narg
= db_numargs(frame
,
682 (user_frame
) ? task
: 0);
692 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
694 narg
= db_numargs(frame
,
695 (user_frame
) ? task
: 0);
703 if (name
== 0 || offset
> db_maxoff
) {
704 db_printf("0x%x 0x%x(", frame
, callpc
);
707 db_printf("0x%x %s(", frame
, name
);
709 argp
= &frame
->f_arg0
;
714 if ((r
= _setjmp(db_recover
= &db_jmp_buf
)) == 0) {
715 value
= db_get_task_value((int)argp
,
718 (user_frame
) ? task
: 0);
721 if (r
== 2) /* 'q' from db_more() */
723 db_printf("... <stack error>)");
725 db_printf("+%x", offset
);
727 db_printf(" [%s", filename
);
729 db_printf(":%d", linenum
);
736 db_printf("%x", value
);
745 db_printf("+%x", offset
);
748 db_printf(" [%s", filename
);
750 db_printf(":%d", linenum
);
757 db_nextframe(&lastframe
, &frame
, &callpc
, frame_type
,
758 (user_frame
) ? th
: THREAD_NULL
);
761 if (th
->task_threads
.prev
!= THREAD_NULL
) {
762 if (top_act
== THREAD_NULL
)
764 th
= th
->task_threads
.prev
;
765 db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
767 db_lookup_task(th
->task
),
768 db_lookup_task_act(th
->task
, th
));
769 goto next_activation
;
774 if (!INKERNELSTACK(lastframe
, th
) ||
775 !INKERNELSTACK((unsigned)frame
, th
))
777 if (user_frame
== 1) {
778 db_printf(">>>>> user space <<<<<\n");
782 if (frame
<= lastframe
) {
783 if ((INKERNELSTACK(lastframe
, th
) &&
784 !INKERNELSTACK(frame
, th
)))
786 db_printf("Bad frame pointer: 0x%x\n", frame
);
792 if (trace_all_threads
) {
793 if (top_act
!= THREAD_NULL
)
795 th
= (thread_t
) queue_next(&th
->task_threads
);
796 if (! queue_end(act_list
, (queue_entry_t
) th
)) {
798 addr
= (db_expr_t
) th
;
806 extern int kdp_vm_read(caddr_t
, caddr_t
, unsigned int );
807 extern boolean_t kdp_trans_off
;
809 * Print out 256 bytes of real storage
813 void db_display_real(db_expr_t addr
, __unused
int have_addr
, __unused db_expr_t count
, __unused
char * modif
) {
816 unsigned int xbuf
[8];
817 unsigned read_result
= 0;
818 /* Print 256 bytes */
821 /* Do a physical read using kdp_vm_read(), rather than replicating the same
825 read_result
= kdp_vm_read(addr
, &xbuf
[0], 32);
828 if (read_result
!= 32)
829 db_printf("Unable to read address\n");
831 db_printf("%016llX %08X %08X %08X %08X %08X %08X %08X %08X\n", addr
, /* Print a line */
832 xbuf
[0], xbuf
[1], xbuf
[2], xbuf
[3],
833 xbuf
[4], xbuf
[5], xbuf
[6], xbuf
[7]);
834 addr
= addr
+ 0x00000020; /* Point to next address */
840 * Displays all of the kmods in the system.
845 db_display_kmod(__unused db_expr_t addr
, __unused
int have_addr
, __unused db_expr_t count
, __unused
char *modif
)
849 unsigned int strt
, end
;
851 kmd
= kmod
; /* Start at the start */
853 db_printf("info addr start - end name ver\n");
855 while (kmd
) { /* Dump 'em all */
856 strt
= (unsigned int) kmd
->address
+ kmd
->hdr_size
;
857 end
= (unsigned int) kmd
->address
+ kmd
->size
;
858 db_printf("%08X %08X %08X - %08X: %s, %s\n",
859 kmd
, kmd
->address
, strt
, end
, kmd
->name
, kmd
->version
);