]>
Commit | Line | Data |
---|---|---|
b0d623f7 A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
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. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
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. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | #include <mach/mach_types.h> | |
29 | #include <mach/vm_attributes.h> | |
30 | #include <mach/vm_param.h> | |
31 | #include <libsa/types.h> | |
32 | ||
b0d623f7 A |
33 | #include <kdp/kdp_core.h> |
34 | #include <kdp/kdp_internal.h> | |
316670eb | 35 | #include <kdp/ml/i386/kdp_x86_common.h> |
b0d623f7 | 36 | #include <mach-o/loader.h> |
b0d623f7 A |
37 | #include <mach/thread_status.h> |
38 | #include <i386/thread.h> | |
39 | ||
b0d623f7 A |
40 | int kdp_dump_trap(int type, x86_saved_state64_t *regs); |
41 | ||
316670eb | 42 | static const x86_state_hdr_t thread_flavor_array [] = { |
b0d623f7 A |
43 | {x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT} |
44 | }; | |
45 | ||
316670eb A |
46 | size_t |
47 | kern_collectth_state_size(void) | |
48 | { | |
49 | unsigned int i; | |
50 | size_t tstate_size = 0; | |
b0d623f7 | 51 | |
316670eb A |
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)); | |
b0d623f7 | 55 | |
316670eb A |
56 | return tstate_size; |
57 | } | |
b0d623f7 | 58 | |
316670eb A |
59 | void |
60 | kern_collectth_state(thread_t thread, void *buffer, size_t size) | |
b0d623f7 | 61 | { |
316670eb A |
62 | size_t hoffset; |
63 | unsigned int i; | |
b0d623f7 | 64 | struct thread_command *tc; |
316670eb | 65 | |
b0d623f7 A |
66 | /* |
67 | * Fill in thread command structure. | |
68 | */ | |
316670eb | 69 | hoffset = 0; |
b0d623f7 | 70 | |
316670eb A |
71 | if (hoffset + sizeof(struct thread_command) > size) |
72 | return; | |
73 | ||
74 | tc = (struct thread_command *) ((uintptr_t)buffer + hoffset); | |
b0d623f7 | 75 | tc->cmd = LC_THREAD; |
316670eb A |
76 | tc->cmdsize = (uint32_t)(sizeof(struct thread_command) + kern_collectth_state_size()); |
77 | hoffset += sizeof(struct thread_command); | |
b0d623f7 A |
78 | /* |
79 | * Follow with a struct thread_state_flavor and | |
80 | * the appropriate thread state struct for each | |
81 | * thread state flavor. | |
82 | */ | |
316670eb A |
83 | for (i = 0; i < sizeof(thread_flavor_array)/sizeof(thread_flavor_array[0]); i++) { |
84 | ||
85 | if (hoffset + sizeof(x86_state_hdr_t) > size) | |
86 | return; | |
87 | ||
88 | *(x86_state_hdr_t *)((uintptr_t)buffer + hoffset) = | |
89 | thread_flavor_array[i]; | |
90 | hoffset += sizeof(x86_state_hdr_t); | |
91 | ||
92 | ||
93 | if (hoffset + thread_flavor_array[i].count*sizeof(int) > size) | |
94 | return; | |
95 | ||
b0d623f7 A |
96 | /* Locate and obtain the non-volatile register context |
97 | * for this kernel thread. This should ideally be | |
98 | * encapsulated in machine_thread_get_kern_state() | |
99 | * but that routine appears to have been co-opted | |
100 | * by CHUD to obtain pre-interrupt state. | |
101 | */ | |
316670eb A |
102 | if (thread_flavor_array[i].flavor == x86_THREAD_STATE64) { |
103 | x86_thread_state64_t *tstate = (x86_thread_state64_t *) ((uintptr_t)buffer + hoffset); | |
b0d623f7 | 104 | vm_offset_t kstack; |
6d2010ae | 105 | x86_saved_state64_t *cpstate = current_cpu_datap()->cpu_fatal_trap_state; |
316670eb | 106 | |
b0d623f7 | 107 | bzero(tstate, x86_THREAD_STATE64_COUNT * sizeof(int)); |
6d2010ae A |
108 | if ((current_thread() == thread) && (cpstate != NULL)) { |
109 | tstate->rax = cpstate->rax; | |
110 | tstate->rbx = cpstate->rbx; | |
111 | tstate->rcx = cpstate->rcx; | |
112 | tstate->rdx = cpstate->rdx; | |
113 | tstate->rdi = cpstate->rdi; | |
114 | tstate->rsi = cpstate->rsi; | |
115 | tstate->rbp = cpstate->rbp; | |
116 | tstate->r8 = cpstate->r8; | |
117 | tstate->r9 = cpstate->r9; | |
118 | tstate->r10 = cpstate->r10; | |
119 | tstate->r11 = cpstate->r11; | |
120 | tstate->r12 = cpstate->r12; | |
121 | tstate->r13 = cpstate->r13; | |
122 | tstate->r14 = cpstate->r14; | |
123 | tstate->r15 = cpstate->r15; | |
124 | tstate->rip = cpstate->isf.rip; | |
125 | tstate->rsp = cpstate->isf.rsp; | |
126 | tstate->rflags = cpstate->isf.rflags; | |
127 | tstate->cs = cpstate->isf.cs; | |
128 | tstate->fs = cpstate->fs; | |
129 | tstate->gs = cpstate->gs; | |
130 | } else if ((kstack = thread->kernel_stack) != 0){ | |
b0d623f7 A |
131 | struct x86_kernel_state *iks = STACK_IKS(kstack); |
132 | tstate->rbx = iks->k_rbx; | |
133 | tstate->rsp = iks->k_rsp; | |
134 | tstate->rbp = iks->k_rbp; | |
135 | tstate->r12 = iks->k_r12; | |
136 | tstate->r13 = iks->k_r13; | |
137 | tstate->r14 = iks->k_r14; | |
138 | tstate->r15 = iks->k_r15; | |
139 | tstate->rip = iks->k_rip; | |
6d2010ae | 140 | } |
316670eb A |
141 | } else { |
142 | void *tstate = (void *)((uintptr_t)buffer + hoffset); | |
143 | ||
144 | bzero(tstate, thread_flavor_array[i].count*sizeof(int)); | |
b0d623f7 | 145 | } |
b0d623f7 | 146 | |
316670eb A |
147 | hoffset += thread_flavor_array[i].count*sizeof(int); |
148 | } | |
b0d623f7 A |
149 | } |
150 | ||
151 | /* Intended to be called from the kernel trap handler if an unrecoverable fault | |
152 | * occurs during a crashdump (which shouldn't happen since we validate mappings | |
153 | * and so on). This should be reworked to attempt some form of recovery. | |
154 | */ | |
155 | int | |
156 | kdp_dump_trap( | |
157 | int type, | |
158 | __unused x86_saved_state64_t *saved_state) | |
159 | { | |
160 | printf ("An unexpected trap (type %d) occurred during the system dump, terminating.\n", type); | |
161 | kdp_send_crashdump_pkt (KDP_EOF, NULL, 0, ((void *) 0)); | |
162 | abort_panic_transfer(); | |
163 | kdp_flag &= ~KDP_PANIC_DUMP_ENABLED; | |
164 | kdp_flag &= ~PANIC_CORE_ON_NMI; | |
165 | kdp_flag &= ~PANIC_LOG_DUMP; | |
166 | ||
167 | kdp_reset(); | |
168 | ||
169 | kdp_raise_exception(EXC_BAD_ACCESS, 0, 0, kdp.saved_state); | |
170 | return( 0 ); | |
171 | } |