]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/machine_task.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / osfmk / i386 / machine_task.c
1 /*
2 * Copyright (c) 2000-2008 Apple 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 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56
57 #include <kern/task.h>
58 #include <kern/thread.h>
59 #include <i386/misc_protos.h>
60
61 extern zone_t ids_zone;
62
63 kern_return_t
64 machine_task_set_state(
65 task_t task,
66 int flavor,
67 thread_state_t state,
68 mach_msg_type_number_t state_count)
69 {
70 switch (flavor) {
71 case x86_DEBUG_STATE32:
72 {
73 x86_debug_state32_t *tstate = (x86_debug_state32_t*) state;
74 if ((task_has_64BitAddr(task)) ||
75 (state_count != x86_DEBUG_STATE32_COUNT) ||
76 (!debug_state_is_valid32(tstate))) {
77 return KERN_INVALID_ARGUMENT;
78 }
79
80 if (task->task_debug == NULL) {
81 task->task_debug = zalloc(ids_zone);
82 }
83
84 copy_debug_state32(tstate, (x86_debug_state32_t*) task->task_debug, FALSE);
85
86 return KERN_SUCCESS;
87 break;
88 }
89 case x86_DEBUG_STATE64:
90 {
91 x86_debug_state64_t *tstate = (x86_debug_state64_t*) state;
92
93 if ((!task_has_64BitAddr(task)) ||
94 (state_count != x86_DEBUG_STATE64_COUNT) ||
95 (!debug_state_is_valid64(tstate))) {
96 return KERN_INVALID_ARGUMENT;
97 }
98
99 if (task->task_debug == NULL) {
100 task->task_debug = zalloc(ids_zone);
101 }
102
103 copy_debug_state64(tstate, (x86_debug_state64_t*) task->task_debug, FALSE);
104
105 return KERN_SUCCESS;
106 break;
107 }
108 case x86_DEBUG_STATE:
109 {
110 x86_debug_state_t *tstate = (x86_debug_state_t*) state;
111
112 if (state_count != x86_DEBUG_STATE_COUNT) {
113 return KERN_INVALID_ARGUMENT;
114 }
115
116 if ((tstate->dsh.flavor == x86_DEBUG_STATE32) &&
117 (tstate->dsh.count == x86_DEBUG_STATE32_COUNT) &&
118 (!task_has_64BitAddr(task)) &&
119 debug_state_is_valid32(&tstate->uds.ds32)) {
120
121 if (task->task_debug == NULL) {
122 task->task_debug = zalloc(ids_zone);
123 }
124
125 copy_debug_state32(&tstate->uds.ds32, (x86_debug_state32_t*) task->task_debug, FALSE);
126 return KERN_SUCCESS;
127
128 } else if ((tstate->dsh.flavor == x86_DEBUG_STATE64) &&
129 (tstate->dsh.count == x86_DEBUG_STATE64_COUNT) &&
130 task_has_64BitAddr(task) &&
131 debug_state_is_valid64(&tstate->uds.ds64)) {
132
133 if (task->task_debug == NULL) {
134 task->task_debug = zalloc(ids_zone);
135 }
136
137 copy_debug_state64(&tstate->uds.ds64, (x86_debug_state64_t*) task->task_debug, FALSE);
138 return KERN_SUCCESS;
139 } else {
140 return KERN_INVALID_ARGUMENT;
141 }
142
143 break;
144 }
145 default:
146 {
147 return KERN_INVALID_ARGUMENT;
148 break;
149 }
150 }
151 }
152
153 kern_return_t
154 machine_task_get_state(task_t task,
155 int flavor,
156 thread_state_t state,
157 mach_msg_type_number_t *state_count)
158 {
159 switch (flavor) {
160 case x86_DEBUG_STATE32:
161 {
162 x86_debug_state32_t *tstate = (x86_debug_state32_t*) state;
163
164 if ((task_has_64BitAddr(task)) || (*state_count != x86_DEBUG_STATE32_COUNT)) {
165 return KERN_INVALID_ARGUMENT;
166 }
167
168 if (task->task_debug == NULL) {
169 bzero(state, sizeof(*tstate));
170 } else {
171 copy_debug_state32((x86_debug_state32_t*) task->task_debug, tstate, TRUE);
172 }
173
174 return KERN_SUCCESS;
175 break;
176 }
177 case x86_DEBUG_STATE64:
178 {
179 x86_debug_state64_t *tstate = (x86_debug_state64_t*) state;
180
181 if ((!task_has_64BitAddr(task)) || (*state_count != x86_DEBUG_STATE64_COUNT)) {
182 return KERN_INVALID_ARGUMENT;
183 }
184
185 if (task->task_debug == NULL) {
186 bzero(state, sizeof(*tstate));
187 } else {
188 copy_debug_state64((x86_debug_state64_t*) task->task_debug, tstate, TRUE);
189 }
190
191 return KERN_SUCCESS;
192 break;
193 }
194 case x86_DEBUG_STATE:
195 {
196 x86_debug_state_t *tstate = (x86_debug_state_t*)state;
197
198 if (*state_count != x86_DEBUG_STATE_COUNT)
199 return(KERN_INVALID_ARGUMENT);
200
201 if (task_has_64BitAddr(task)) {
202 tstate->dsh.flavor = x86_DEBUG_STATE64;
203 tstate->dsh.count = x86_DEBUG_STATE64_COUNT;
204
205 if (task->task_debug == NULL) {
206 bzero(&tstate->uds.ds64, sizeof(tstate->uds.ds64));
207 } else {
208 copy_debug_state64((x86_debug_state64_t*)task->task_debug, &tstate->uds.ds64, TRUE);
209 }
210 } else {
211 tstate->dsh.flavor = x86_DEBUG_STATE32;
212 tstate->dsh.count = x86_DEBUG_STATE32_COUNT;
213
214 if (task->task_debug == NULL) {
215 bzero(&tstate->uds.ds32, sizeof(tstate->uds.ds32));
216 } else {
217 copy_debug_state32((x86_debug_state32_t*)task->task_debug, &tstate->uds.ds32, TRUE);
218 }
219 }
220
221 return KERN_SUCCESS;
222 break;
223 }
224 default:
225 {
226 return KERN_INVALID_ARGUMENT;
227 break;
228 }
229 }
230 }
231
232 /*
233 * This is called when a task is terminated, and also on exec().
234 * Clear machine-dependent state that is stored on the task.
235 */
236 void
237 machine_task_terminate(task_t task)
238 {
239 if (task) {
240 user_ldt_t user_ldt;
241 void *task_debug;
242
243 user_ldt = task->i386_ldt;
244 if (user_ldt != 0) {
245 task->i386_ldt = 0;
246 user_ldt_free(user_ldt);
247 }
248
249 task_debug = task->task_debug;
250 if (task_debug != NULL) {
251 task->task_debug = NULL;
252 zfree(ids_zone, task_debug);
253 }
254 }
255 }
256
257 /*
258 * Set initial default state on a thread as stored in the MACHINE_TASK data.
259 * Note: currently only debug state is supported.
260 */
261 kern_return_t
262 machine_thread_inherit_taskwide(
263 thread_t thread,
264 task_t parent_task)
265 {
266 if (parent_task->task_debug) {
267 int flavor;
268 mach_msg_type_number_t count;
269
270 if (task_has_64BitAddr(parent_task)) {
271 flavor = x86_DEBUG_STATE64;
272 count = x86_DEBUG_STATE64_COUNT;
273 } else {
274 flavor = x86_DEBUG_STATE32;
275 count = x86_DEBUG_STATE32_COUNT;
276 }
277
278 return machine_thread_set_state(thread, flavor, parent_task->task_debug, count);
279 }
280
281 return KERN_SUCCESS;
282 }