| 1 | /* |
| 2 | * Copyright (c) 2018 Apple Inc. All rights reserved. |
| 3 | * |
| 4 | * @APPLE_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. Please obtain a copy of the License at |
| 10 | * http://www.opensource.apple.com/apsl/ and read it before using this |
| 11 | * file. |
| 12 | * |
| 13 | * The Original Code and all software distributed under the License are |
| 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
| 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
| 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
| 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
| 18 | * Please see the License for the specific language governing rights and |
| 19 | * limitations under the License. |
| 20 | * |
| 21 | * @APPLE_LICENSE_HEADER_END@ |
| 22 | */ |
| 23 | |
| 24 | /*! |
| 25 | * @header |
| 26 | * Darwin-specific interfaces for manipulating Mach exception handling |
| 27 | * properties of a task. |
| 28 | */ |
| 29 | #ifndef __DARWIN_EXCEPTION_H |
| 30 | #define __DARWIN_EXCEPTION_H |
| 31 | |
| 32 | #include <os/base.h> |
| 33 | #include <os/api.h> |
| 34 | |
| 35 | #include <sys/cdefs.h> |
| 36 | #include <spawn.h> |
| 37 | |
| 38 | #include <mach/mach.h> |
| 39 | #include <mach/port.h> |
| 40 | #include <mach/mach_port.h> |
| 41 | #include <mach/kern_return.h> |
| 42 | |
| 43 | __BEGIN_DECLS; |
| 44 | |
| 45 | /*! |
| 46 | * @typedef os_crash_flags_t |
| 47 | * A flagset describing crash handling behaviors. |
| 48 | * |
| 49 | * @param OS_CRASH_FLAG_INIT |
| 50 | * Handle no exceptions. |
| 51 | * |
| 52 | * @param OS_CRASH_FLAG_CRASH |
| 53 | * Handle exceptions due to crashing conditions (e.g. segmentation violations, |
| 54 | * signals raise(3)ed manually, etc.). These exceptions will suspend the subject |
| 55 | * task until the exception handler has returned. |
| 56 | * |
| 57 | * @param OS_CRASH_FLAG_GUARD |
| 58 | * Handle exceptions due to the subject task violating guarded kernel handles |
| 59 | * (e.g. guarded mach port rights and file descriptors). |
| 60 | * |
| 61 | * @param OS_CRASH_FLAG_RESOURCE |
| 62 | * Handle exceptions due to the subject task exceeding resource usage limits |
| 63 | * (e.g. CPU spins, memory growth, etc.). |
| 64 | * |
| 65 | * @param OS_CRASH_FLAG_CORPSE |
| 66 | * Handle exceptions which create corpses. The subject task of these exceptions |
| 67 | * is a corpse of the original task, which is torn down asynchronously. Corpses |
| 68 | * are a limited representation of the original task that is suitable for most |
| 69 | * introspection needs. |
| 70 | * |
| 71 | * This flag is mutually exclusive with {@link OS_CRASH_FLAG_CRASH}, and if both |
| 72 | * are present, this flag will be preferred. |
| 73 | * |
| 74 | * @discussion |
| 75 | * There are other Mach exception types than the ones enumerated by these flags, |
| 76 | * but they are almost exclusively handled internally by the kernel, and |
| 77 | * therefore are of little interest to userspace. Those that are not handled by |
| 78 | * the kernel are only relevant to debuggers. |
| 79 | */ |
| 80 | OS_ENUM(os_crash_flags, uint32_t, |
| 81 | OS_CRASH_FLAG_INIT = 0, |
| 82 | OS_CRASH_FLAG_CRASH = (1 << 0), |
| 83 | OS_CRASH_FLAG_GUARD = (1 << 1), |
| 84 | OS_CRASH_FLAG_RESOURCE = (1 << 2), |
| 85 | OS_CRASH_FLAG_CORPSE = (1 << 3), |
| 86 | ); |
| 87 | |
| 88 | /*! |
| 89 | * @enum os_crash_type_t |
| 90 | * A type describing exception types relevant to userspace crash reporters. |
| 91 | * These values serve as indexes into a {@link os_crash_port_array_t}. |
| 92 | * |
| 93 | * @const OS_CRASH_NONE |
| 94 | * No exception type. |
| 95 | * |
| 96 | * @const OS_CRASH_CRASH |
| 97 | * A crashing exception with the behavior described in {@link OS_CRASH_FLAG_CRASH}. |
| 98 | * |
| 99 | * @const OS_CRASH_GUARD |
| 100 | * A guard exception with the behavior described in {@link OS_CRASH_FLAG_GUARD}. |
| 101 | * |
| 102 | * @const OS_CRASH_RESOURCE |
| 103 | * A resource exception with the behavior described in {@link OS_CRASH_FLAG_RESOURCE}. |
| 104 | * |
| 105 | * @const OS_CRASH_CORPSE |
| 106 | * A corpse exception with the behavior described in {@link OS_CRASH_FLAG_CORPSE}. |
| 107 | */ |
| 108 | OS_ENUM(os_crash_type, uint32_t, |
| 109 | OS_CRASH_NONE, |
| 110 | OS_CRASH_CRASH, |
| 111 | OS_CRASH_GUARD, |
| 112 | OS_CRASH_RESOURCE, |
| 113 | OS_CRASH_CORPSE, |
| 114 | _OS_CRASH_LAST, |
| 115 | ); |
| 116 | |
| 117 | /*! |
| 118 | * struct os_crash_port_t |
| 119 | * A type describing an exception port and the exception it handles. |
| 120 | * |
| 121 | * @property oep_type |
| 122 | * The type of exception handled by the port. |
| 123 | * |
| 124 | * @property oep_port |
| 125 | * A handle representing a send right to the exception port. |
| 126 | */ |
| 127 | DARWIN_API_AVAILABLE_20170407 |
| 128 | typedef struct _os_crash_port { |
| 129 | os_crash_type_t oep_type; |
| 130 | mach_port_t oep_port; |
| 131 | } os_crash_port_t; |
| 132 | |
| 133 | /*! |
| 134 | * @define DARWIN_EXCEPTION_PORT_ARRAY_COUNT |
| 135 | * The maximum number of exception ports that an exception port array can |
| 136 | * accommodate. |
| 137 | */ |
| 138 | #define OS_CRASH_PORT_ARRAY_COUNT (16lu) |
| 139 | |
| 140 | /*! |
| 141 | * @typedef os_crash_port_array_t |
| 142 | * An array of exception ports. This array can accommodate all exception types |
| 143 | * described in the {@link os_crash_type_t} type and is sized to |
| 144 | * accommodate future exception types. |
| 145 | */ |
| 146 | DARWIN_API_AVAILABLE_20170407 |
| 147 | typedef os_crash_port_t os_crash_port_array_t[OS_CRASH_PORT_ARRAY_COUNT]; |
| 148 | |
| 149 | /*! |
| 150 | * @function os_crash_set_reporter_port |
| 151 | * Routine to set the exception handler port for the exceptions given. |
| 152 | * |
| 153 | * @param where |
| 154 | * The task port or host port for which to set the exception handler. This |
| 155 | * routine will internally choose the proper method of setting the exception |
| 156 | * port based on whether this parameter represents the host or not. |
| 157 | * |
| 158 | * @param flags |
| 159 | * Flags describing which exceptions are to be handled by the port. |
| 160 | * |
| 161 | * @param p |
| 162 | * A send right to the desired exception handler port. |
| 163 | * |
| 164 | * @result |
| 165 | * A kernel return code. |
| 166 | * |
| 167 | * @discussion |
| 168 | * This routine automatically chooses the most expressive thread state to |
| 169 | * deliver in the exception message based on the current architecture. |
| 170 | */ |
| 171 | DARWIN_API_AVAILABLE_20170407 |
| 172 | OS_EXPORT OS_WARN_RESULT |
| 173 | kern_return_t |
| 174 | os_crash_set_reporter_port(mach_port_t where, |
| 175 | os_crash_flags_t flags, mach_port_t p); |
| 176 | |
| 177 | /*! |
| 178 | * @function os_crash_get_reporter_port_array |
| 179 | * Routine to get the ports which handle exceptions for all enumerated exception |
| 180 | * types in {@link os_crash_flags_t}. |
| 181 | * |
| 182 | * @param where |
| 183 | * The task port or host port for which to retrieve exception handler ports. |
| 184 | * This routine will internally choose the proper method of obtaining the |
| 185 | * exception ports based on whether this parameter represents the host or not. |
| 186 | * |
| 187 | * @param array |
| 188 | * An array describing the exception ports for the target host or task. This |
| 189 | * array must be disposed of with {@link os_crash_port_array_deallocate} |
| 190 | * when it is no longer needed. |
| 191 | * |
| 192 | * @result |
| 193 | * A kernel return code. |
| 194 | */ |
| 195 | DARWIN_API_AVAILABLE_20170407 |
| 196 | OS_EXPORT OS_WARN_RESULT OS_NONNULL2 |
| 197 | kern_return_t |
| 198 | os_crash_get_reporter_port_array(mach_port_t where, |
| 199 | os_crash_port_array_t array); |
| 200 | |
| 201 | /*! |
| 202 | * @function os_crash_port_array_deallocate |
| 203 | * Routine to deallocate an array of exception port descriptors. |
| 204 | * |
| 205 | * @param array |
| 206 | * The array which is to be disposed of. |
| 207 | * |
| 208 | * @discussion |
| 209 | * This routine disposes of the resources represented by the kernel handles in |
| 210 | * the array. It does not manipulate the array's memory. The expectation is that |
| 211 | * the caller allocates {@link os_crash_port_array_t} from the stack. |
| 212 | */ |
| 213 | DARWIN_API_AVAILABLE_20170407 |
| 214 | OS_EXPORT OS_NONNULL1 |
| 215 | void |
| 216 | os_crash_port_array_deallocate(os_crash_port_array_t array); |
| 217 | |
| 218 | /*! |
| 219 | * @function os_crash_spawnattr_set_reporter_port |
| 220 | * Routine to set the exception handler port for the exceptions given in a |
| 221 | * posix_spawn(2) attributes structure. |
| 222 | * |
| 223 | * @param psattr |
| 224 | * The spawn attributes for which the exception port should be set. |
| 225 | * |
| 226 | * @param flags |
| 227 | * Flags describing which exceptions are to be handled by the port. |
| 228 | * |
| 229 | * @param p |
| 230 | * A send right to the desired exception handler port. |
| 231 | * |
| 232 | * @result |
| 233 | * A kernel return code. This routine will only fail if the port name given was |
| 234 | * invalid. |
| 235 | */ |
| 236 | DARWIN_API_AVAILABLE_20170407 |
| 237 | OS_EXPORT OS_WARN_RESULT OS_NONNULL1 |
| 238 | kern_return_t |
| 239 | os_crash_spawnattr_set_reporter_port(posix_spawnattr_t *psattr, |
| 240 | os_crash_flags_t flags, mach_port_t p); |
| 241 | |
| 242 | __END_DECLS; |
| 243 | |
| 244 | #endif // __DARWIN_EXCEPTION_H |