]>
Commit | Line | Data |
---|---|---|
b0d623f7 A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
0a7de745 | 5 | * |
b0d623f7 A |
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. | |
0a7de745 | 14 | * |
b0d623f7 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
0a7de745 | 17 | * |
b0d623f7 A |
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. | |
0a7de745 | 25 | * |
b0d623f7 A |
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 | ||
0a7de745 | 40 | int kdp_dump_trap(int type, x86_saved_state64_t *regs); |
b0d623f7 | 41 | |
0a7de745 | 42 | static const x86_state_hdr_t thread_flavor_array[] = { |
b0d623f7 A |
43 | {x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT} |
44 | }; | |
45 | ||
3e170ce0 | 46 | void |
5ba3f43e | 47 | kern_collectth_state_size(uint64_t * tstate_count, uint64_t * ptstate_size) |
316670eb A |
48 | { |
49 | unsigned int i; | |
5ba3f43e | 50 | uint64_t tstate_size = 0; |
b0d623f7 | 51 | |
0a7de745 | 52 | for (i = 0; i < sizeof(thread_flavor_array) / sizeof(thread_flavor_array[0]); i++) { |
316670eb A |
53 | tstate_size += sizeof(x86_state_hdr_t) + |
54 | (thread_flavor_array[i].count * sizeof(int)); | |
0a7de745 | 55 | } |
b0d623f7 | 56 | |
3e170ce0 A |
57 | *tstate_count = 1; |
58 | *ptstate_size = sizeof(struct thread_command) + tstate_size; | |
316670eb | 59 | } |
b0d623f7 | 60 | |
316670eb | 61 | void |
5ba3f43e | 62 | kern_collectth_state(thread_t thread, void *buffer, uint64_t size, void ** iter) |
b0d623f7 | 63 | { |
0a7de745 A |
64 | size_t hoffset; |
65 | uint64_t tstate_size, tstate_count; | |
66 | unsigned int i; | |
67 | struct thread_command *tc; | |
68 | ||
316670eb | 69 | |
3e170ce0 | 70 | *iter = NULL; |
b0d623f7 A |
71 | /* |
72 | * Fill in thread command structure. | |
73 | */ | |
316670eb | 74 | hoffset = 0; |
0a7de745 A |
75 | |
76 | if (hoffset + sizeof(struct thread_command) > size) { | |
316670eb | 77 | return; |
0a7de745 | 78 | } |
316670eb | 79 | |
3e170ce0 | 80 | kern_collectth_state_size(&tstate_count, &tstate_size); |
316670eb | 81 | tc = (struct thread_command *) ((uintptr_t)buffer + hoffset); |
b0d623f7 | 82 | tc->cmd = LC_THREAD; |
3e170ce0 | 83 | tc->cmdsize = (uint32_t) tstate_size; |
316670eb | 84 | hoffset += sizeof(struct thread_command); |
b0d623f7 A |
85 | /* |
86 | * Follow with a struct thread_state_flavor and | |
87 | * the appropriate thread state struct for each | |
88 | * thread state flavor. | |
89 | */ | |
0a7de745 A |
90 | for (i = 0; i < sizeof(thread_flavor_array) / sizeof(thread_flavor_array[0]); i++) { |
91 | if (hoffset + sizeof(x86_state_hdr_t) > size) { | |
316670eb | 92 | return; |
0a7de745 | 93 | } |
316670eb A |
94 | |
95 | *(x86_state_hdr_t *)((uintptr_t)buffer + hoffset) = | |
96 | thread_flavor_array[i]; | |
97 | hoffset += sizeof(x86_state_hdr_t); | |
98 | ||
99 | ||
0a7de745 | 100 | if (hoffset + thread_flavor_array[i].count * sizeof(int) > size) { |
316670eb | 101 | return; |
0a7de745 | 102 | } |
316670eb | 103 | |
b0d623f7 A |
104 | /* Locate and obtain the non-volatile register context |
105 | * for this kernel thread. This should ideally be | |
a39ff7e2 | 106 | * encapsulated in machine_thread_get_kern_state(). |
b0d623f7 | 107 | */ |
316670eb A |
108 | if (thread_flavor_array[i].flavor == x86_THREAD_STATE64) { |
109 | x86_thread_state64_t *tstate = (x86_thread_state64_t *) ((uintptr_t)buffer + hoffset); | |
b0d623f7 | 110 | vm_offset_t kstack; |
6d2010ae | 111 | x86_saved_state64_t *cpstate = current_cpu_datap()->cpu_fatal_trap_state; |
316670eb | 112 | |
b0d623f7 | 113 | bzero(tstate, x86_THREAD_STATE64_COUNT * sizeof(int)); |
6d2010ae A |
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; | |
0a7de745 | 136 | } else if ((kstack = thread->kernel_stack) != 0) { |
b0d623f7 A |
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; | |
6d2010ae | 146 | } |
316670eb A |
147 | } else { |
148 | void *tstate = (void *)((uintptr_t)buffer + hoffset); | |
149 | ||
0a7de745 | 150 | bzero(tstate, thread_flavor_array[i].count * sizeof(int)); |
b0d623f7 | 151 | } |
b0d623f7 | 152 | |
0a7de745 | 153 | hoffset += thread_flavor_array[i].count * sizeof(int); |
316670eb | 154 | } |
b0d623f7 A |
155 | } |
156 | ||
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. | |
160 | */ | |
161 | int | |
162 | kdp_dump_trap( | |
163 | int type, | |
0a7de745 | 164 | __unused x86_saved_state64_t *saved_state) |
b0d623f7 | 165 | { |
0a7de745 A |
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)); | |
b0d623f7 A |
168 | abort_panic_transfer(); |
169 | kdp_flag &= ~KDP_PANIC_DUMP_ENABLED; | |
170 | kdp_flag &= ~PANIC_CORE_ON_NMI; | |
171 | kdp_flag &= ~PANIC_LOG_DUMP; | |
172 | ||
173 | kdp_reset(); | |
174 | ||
175 | kdp_raise_exception(EXC_BAD_ACCESS, 0, 0, kdp.saved_state); | |
0a7de745 | 176 | return 0; |
b0d623f7 | 177 | } |