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 61extern zone_t ids_zone; 62 63kern_return_t 64machine_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 153kern_return_t 154machine_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 */ 236void 237machine_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 */ 261kern_return_t 262machine_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} 283