2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 #include <mach/mach_types.h>
29 #include <mach/vm_attributes.h>
30 #include <mach/vm_param.h>
31 #include <libsa/types.h>
33 #include <kdp/kdp_core.h>
34 #include <kdp/kdp_internal.h>
35 #include <kdp/ml/i386/kdp_x86_common.h>
36 #include <mach-o/loader.h>
37 #include <mach/thread_status.h>
38 #include <i386/thread.h>
40 int kdp_dump_trap(int type
, x86_saved_state64_t
*regs
);
42 static const x86_state_hdr_t thread_flavor_array
[] = {
43 {x86_THREAD_STATE64
, x86_THREAD_STATE64_COUNT
}
47 kern_collectth_state_size(uint64_t * tstate_count
, uint64_t * ptstate_size
)
50 uint64_t tstate_size
= 0;
52 for (i
= 0; i
< sizeof(thread_flavor_array
) / sizeof(thread_flavor_array
[0]); i
++) {
53 tstate_size
+= sizeof(x86_state_hdr_t
) +
54 (thread_flavor_array
[i
].count
* sizeof(int));
58 *ptstate_size
= sizeof(struct thread_command
) + tstate_size
;
62 kern_collectth_state(thread_t thread
, void *buffer
, uint64_t size
, void ** iter
)
65 uint64_t tstate_size
, tstate_count
;
67 struct thread_command
*tc
;
72 * Fill in thread command structure.
76 if (hoffset
+ sizeof(struct thread_command
) > size
) {
80 kern_collectth_state_size(&tstate_count
, &tstate_size
);
81 tc
= (struct thread_command
*) ((uintptr_t)buffer
+ hoffset
);
83 tc
->cmdsize
= (uint32_t) tstate_size
;
84 hoffset
+= sizeof(struct thread_command
);
86 * Follow with a struct thread_state_flavor and
87 * the appropriate thread state struct for each
88 * thread state flavor.
90 for (i
= 0; i
< sizeof(thread_flavor_array
) / sizeof(thread_flavor_array
[0]); i
++) {
91 if (hoffset
+ sizeof(x86_state_hdr_t
) > size
) {
95 *(x86_state_hdr_t
*)((uintptr_t)buffer
+ hoffset
) =
96 thread_flavor_array
[i
];
97 hoffset
+= sizeof(x86_state_hdr_t
);
100 if (hoffset
+ thread_flavor_array
[i
].count
* sizeof(int) > size
) {
104 /* Locate and obtain the non-volatile register context
105 * for this kernel thread. This should ideally be
106 * encapsulated in machine_thread_get_kern_state().
108 if (thread_flavor_array
[i
].flavor
== x86_THREAD_STATE64
) {
109 x86_thread_state64_t
*tstate
= (x86_thread_state64_t
*) ((uintptr_t)buffer
+ hoffset
);
111 x86_saved_state64_t
*cpstate
= current_cpu_datap()->cpu_fatal_trap_state
;
113 bzero(tstate
, x86_THREAD_STATE64_COUNT
* sizeof(int));
114 if ((current_thread() == thread
) && (cpstate
!= NULL
)) {
115 tstate
->rax
= cpstate
->rax
;
116 tstate
->rbx
= cpstate
->rbx
;
117 tstate
->rcx
= cpstate
->rcx
;
118 tstate
->rdx
= cpstate
->rdx
;
119 tstate
->rdi
= cpstate
->rdi
;
120 tstate
->rsi
= cpstate
->rsi
;
121 tstate
->rbp
= cpstate
->rbp
;
122 tstate
->r8
= cpstate
->r8
;
123 tstate
->r9
= cpstate
->r9
;
124 tstate
->r10
= cpstate
->r10
;
125 tstate
->r11
= cpstate
->r11
;
126 tstate
->r12
= cpstate
->r12
;
127 tstate
->r13
= cpstate
->r13
;
128 tstate
->r14
= cpstate
->r14
;
129 tstate
->r15
= cpstate
->r15
;
130 tstate
->rip
= cpstate
->isf
.rip
;
131 tstate
->rsp
= cpstate
->isf
.rsp
;
132 tstate
->rflags
= cpstate
->isf
.rflags
;
133 tstate
->cs
= cpstate
->isf
.cs
;
134 tstate
->fs
= cpstate
->fs
;
135 tstate
->gs
= cpstate
->gs
;
136 } else if ((kstack
= thread
->kernel_stack
) != 0) {
137 struct x86_kernel_state
*iks
= STACK_IKS(kstack
);
138 tstate
->rbx
= iks
->k_rbx
;
139 tstate
->rsp
= iks
->k_rsp
;
140 tstate
->rbp
= iks
->k_rbp
;
141 tstate
->r12
= iks
->k_r12
;
142 tstate
->r13
= iks
->k_r13
;
143 tstate
->r14
= iks
->k_r14
;
144 tstate
->r15
= iks
->k_r15
;
145 tstate
->rip
= iks
->k_rip
;
148 void *tstate
= (void *)((uintptr_t)buffer
+ hoffset
);
150 bzero(tstate
, thread_flavor_array
[i
].count
* sizeof(int));
153 hoffset
+= thread_flavor_array
[i
].count
* sizeof(int);
157 /* Intended to be called from the kernel trap handler if an unrecoverable fault
158 * occurs during a crashdump (which shouldn't happen since we validate mappings
159 * and so on). This should be reworked to attempt some form of recovery.
164 __unused x86_saved_state64_t
*saved_state
)
166 printf("An unexpected trap (type %d) occurred during the system dump, terminating.\n", type
);
167 kdp_send_crashdump_pkt(KDP_EOF
, NULL
, 0, ((void *) 0));
168 abort_panic_transfer();
169 kdp_flag
&= ~KDP_PANIC_DUMP_ENABLED
;
170 kdp_flag
&= ~PANIC_CORE_ON_NMI
;
171 kdp_flag
&= ~PANIC_LOG_DUMP
;
175 kdp_raise_exception(EXC_BAD_ACCESS
, 0, 0, kdp
.saved_state
);
180 * kdp_core_start_addr
182 * return the address where the kernel core file starts
186 kdp_core_start_addr()
188 return VM_MIN_KERNEL_AND_KEXT_ADDRESS
;