OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #ifndef CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ |
| 16 #define CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ |
| 17 |
| 18 #include <mach/mach.h> |
| 19 |
| 20 #include "util/mach/mach_message_server.h" |
| 21 |
| 22 namespace crashpad { |
| 23 |
| 24 // Routines to provide a single unified front-end to the interfaces in |
| 25 // <mach/exc.defs> and <mach/mach_exc.defs>. The two interfaces are identical, |
| 26 // except that the latter allows for 64-bit exception codes, and is requested by |
| 27 // setting the MACH_EXCEPTION_CODES behavior bit associated with an exception |
| 28 // port. |
| 29 |
| 30 namespace internal { |
| 31 |
| 32 //! \brief A server interface for the `exc` Mach subsystem. |
| 33 class ExcServer : public MachMessageServer::Interface { |
| 34 public: |
| 35 //! \brief An interface that the different request messages that are a part of |
| 36 //! the `exc` Mach subsystem can be dispatched to. |
| 37 class Interface { |
| 38 public: |
| 39 //! \brief Handles exceptions raised by `exception_raise()`. |
| 40 //! |
| 41 //! This behaves equivalently to a `catch_exception_raise()` function used |
| 42 //! with `exc_server()`. |
| 43 //! |
| 44 //! \param[out] destroy_request `true` if the request message is to be |
| 45 //! destroyed even when this method returns success. See |
| 46 //! MachMessageServer::Interface. |
| 47 virtual kern_return_t CatchExceptionRaise( |
| 48 exception_handler_t exception_port, |
| 49 thread_t thread, |
| 50 task_t task, |
| 51 exception_type_t exception, |
| 52 const exception_data_type_t* code, |
| 53 mach_msg_type_number_t code_count, |
| 54 bool* destroy_request) = 0; |
| 55 |
| 56 //! \brief Handles exceptions raised by `exception_raise_state()`. |
| 57 //! |
| 58 //! This behaves equivalently to a `catch_exception_raise_state()` function |
| 59 //! used with `exc_server()`. |
| 60 //! |
| 61 //! There is no \a destroy_request parameter because, unlike |
| 62 //! CatchExceptionRaise() and CatchExceptionRaiseStateIdentity(), the |
| 63 //! request message is not complex (it does not carry the \a thread or \a |
| 64 //! task port rights) and thus there is nothing to destroy. |
| 65 virtual kern_return_t CatchExceptionRaiseState( |
| 66 exception_handler_t exception_port, |
| 67 exception_type_t exception, |
| 68 const exception_data_type_t* code, |
| 69 mach_msg_type_number_t code_count, |
| 70 thread_state_flavor_t* flavor, |
| 71 const natural_t* old_state, |
| 72 mach_msg_type_number_t old_state_count, |
| 73 thread_state_t new_state, |
| 74 mach_msg_type_number_t* new_state_count) = 0; |
| 75 |
| 76 //! \brief Handles exceptions raised by `exception_raise_state_identity()`. |
| 77 //! |
| 78 //! This behaves equivalently to a `catch_exception_raise_state_identity()` |
| 79 //! function used with `exc_server()`. |
| 80 //! |
| 81 //! \param[out] destroy_request `true` if the request message is to be |
| 82 //! destroyed even when this method returns success. See |
| 83 //! MachMessageServer::Interface. |
| 84 virtual kern_return_t CatchExceptionRaiseStateIdentity( |
| 85 exception_handler_t exception_port, |
| 86 thread_t thread, |
| 87 task_t task, |
| 88 exception_type_t exception, |
| 89 const exception_data_type_t* code, |
| 90 mach_msg_type_number_t code_count, |
| 91 thread_state_flavor_t* flavor, |
| 92 const natural_t* old_state, |
| 93 mach_msg_type_number_t old_state_count, |
| 94 thread_state_t new_state, |
| 95 mach_msg_type_number_t* new_state_count, |
| 96 bool* destroy_request) = 0; |
| 97 |
| 98 protected: |
| 99 ~Interface() {} |
| 100 }; |
| 101 |
| 102 explicit ExcServer(Interface* interface); |
| 103 |
| 104 // MachMessageServer::Interface: |
| 105 |
| 106 virtual bool MachMessageServerFunction( |
| 107 mach_msg_header_t* in_header, |
| 108 mach_msg_header_t* out_header, |
| 109 bool* destroy_complex_request) override; |
| 110 |
| 111 virtual mach_msg_size_t MachMessageServerRequestSize() override; |
| 112 virtual mach_msg_size_t MachMessageServerReplySize() override; |
| 113 |
| 114 private: |
| 115 Interface* interface_; // weak |
| 116 }; |
| 117 |
| 118 //! \brief A server interface for the `mach_exc` Mach subsystem. |
| 119 class MachExcServer : public MachMessageServer::Interface { |
| 120 public: |
| 121 //! \brief An interface that the different request messages that are a part of |
| 122 //! the `mach_exc` Mach subsystem can be dispatched to. |
| 123 class Interface { |
| 124 public: |
| 125 //! \brief Handles exceptions raised by `mach_exception_raise()`. |
| 126 //! |
| 127 //! This behaves equivalently to a `catch_mach_exception_raise()` function |
| 128 //! used with `mach_exc_server()`. |
| 129 //! |
| 130 //! \param[out] destroy_request `true` if the request message is to be |
| 131 //! destroyed even when this method returns success. See |
| 132 //! MachMessageServer::Interface. |
| 133 virtual kern_return_t CatchMachExceptionRaise( |
| 134 exception_handler_t exception_port, |
| 135 thread_t thread, |
| 136 task_t task, |
| 137 exception_type_t exception, |
| 138 const mach_exception_data_type_t* code, |
| 139 mach_msg_type_number_t code_count, |
| 140 bool* destroy_request) = 0; |
| 141 |
| 142 //! \brief Handles exceptions raised by `mach_exception_raise_state()`. |
| 143 //! |
| 144 //! This behaves equivalently to a `catch_mach_exception_raise_state()` |
| 145 //! function used with `mach_exc_server()`. |
| 146 //! |
| 147 //! There is no \a destroy_request parameter because, unlike |
| 148 //! CatchMachExceptionRaise() and CatchMachExceptionRaiseStateIdentity(), |
| 149 //! the request message is not complex (it does not carry the \a thread or |
| 150 //! \a task port rights) and thus there is nothing to destroy. |
| 151 virtual kern_return_t CatchMachExceptionRaiseState( |
| 152 exception_handler_t exception_port, |
| 153 exception_type_t exception, |
| 154 const mach_exception_data_type_t* code, |
| 155 mach_msg_type_number_t code_count, |
| 156 thread_state_flavor_t* flavor, |
| 157 const natural_t* old_state, |
| 158 mach_msg_type_number_t old_state_count, |
| 159 thread_state_t new_state, |
| 160 mach_msg_type_number_t* new_state_count) = 0; |
| 161 |
| 162 //! \brief Handles exceptions raised by |
| 163 //! `mach_exception_raise_state_identity()`. |
| 164 //! |
| 165 //! This behaves equivalently to a |
| 166 //! `catch_mach_exception_raise_state_identity()` function used with |
| 167 //! `mach_exc_server()`. |
| 168 //! |
| 169 //! \param[out] destroy_request `true` if the request message is to be |
| 170 //! destroyed even when this method returns success. See |
| 171 //! MachMessageServer::Interface. |
| 172 virtual kern_return_t CatchMachExceptionRaiseStateIdentity( |
| 173 exception_handler_t exception_port, |
| 174 thread_t thread, |
| 175 task_t task, |
| 176 exception_type_t exception, |
| 177 const mach_exception_data_type_t* code, |
| 178 mach_msg_type_number_t code_count, |
| 179 thread_state_flavor_t* flavor, |
| 180 const natural_t* old_state, |
| 181 mach_msg_type_number_t old_state_count, |
| 182 thread_state_t new_state, |
| 183 mach_msg_type_number_t* new_state_count, |
| 184 bool* destroy_request) = 0; |
| 185 |
| 186 protected: |
| 187 ~Interface() {} |
| 188 }; |
| 189 |
| 190 explicit MachExcServer(Interface* interface); |
| 191 |
| 192 // MachMessageServer::Interface: |
| 193 |
| 194 virtual bool MachMessageServerFunction( |
| 195 mach_msg_header_t* in_header, |
| 196 mach_msg_header_t* out_header, |
| 197 bool* destroy_complex_request) override; |
| 198 |
| 199 virtual mach_msg_size_t MachMessageServerRequestSize() override; |
| 200 virtual mach_msg_size_t MachMessageServerReplySize() override; |
| 201 |
| 202 private: |
| 203 Interface* interface_; // weak |
| 204 }; |
| 205 |
| 206 //! \brief A server interface for the `exc` Mach subsystem, simplified to have |
| 207 //! only a single interface method needing implementation. |
| 208 class SimplifiedExcServer : public ExcServer, public ExcServer::Interface { |
| 209 public: |
| 210 //! \brief An interface that the different request messages that are a part of |
| 211 //! the `exc` Mach subsystem can be dispatched to. |
| 212 class Interface { |
| 213 public: |
| 214 //! \brief Handles exceptions raised by `exception_raise()`, |
| 215 //! `exception_raise_state()`, and `exception_raise_state_identity()`. |
| 216 //! |
| 217 //! For convenience in implementation, these different “behaviors” of |
| 218 //! exception messages are all mapped to a single interface method. The |
| 219 //! exception’s original “behavior” is specified in the \a behavior |
| 220 //! parameter. Only parameters that were supplied in the request message |
| 221 //! are populated, other parameters are set to reasonable default values. |
| 222 //! |
| 223 //! The meanings of most parameters are identical to that of |
| 224 //! ExcServer::Interface::CatchExceptionRaiseStateIdentity(). |
| 225 //! |
| 226 //! \param[in] behavior `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or |
| 227 //! `EXCEPTION_STATE_IDENTITY`, identifying which exception request |
| 228 //! message was processed and thus which other parameters are valid. |
| 229 virtual kern_return_t CatchException( |
| 230 exception_behavior_t behavior, |
| 231 exception_handler_t exception_port, |
| 232 thread_t thread, |
| 233 task_t task, |
| 234 exception_type_t exception, |
| 235 const exception_data_type_t* code, |
| 236 mach_msg_type_number_t code_count, |
| 237 thread_state_flavor_t* flavor, |
| 238 const natural_t* old_state, |
| 239 mach_msg_type_number_t old_state_count, |
| 240 thread_state_t new_state, |
| 241 mach_msg_type_number_t* new_state_count, |
| 242 bool* destroy_complex_request) = 0; |
| 243 |
| 244 protected: |
| 245 ~Interface() {} |
| 246 }; |
| 247 |
| 248 explicit SimplifiedExcServer(Interface* interface); |
| 249 |
| 250 // ExcServer::Interface: |
| 251 |
| 252 virtual kern_return_t CatchExceptionRaise( |
| 253 exception_handler_t exception_port, |
| 254 thread_t thread, |
| 255 task_t task, |
| 256 exception_type_t exception, |
| 257 const exception_data_type_t* code, |
| 258 mach_msg_type_number_t code_count, |
| 259 bool* destroy_request) override; |
| 260 virtual kern_return_t CatchExceptionRaiseState( |
| 261 exception_handler_t exception_port, |
| 262 exception_type_t exception, |
| 263 const exception_data_type_t* code, |
| 264 mach_msg_type_number_t code_count, |
| 265 thread_state_flavor_t* flavor, |
| 266 const natural_t* old_state, |
| 267 mach_msg_type_number_t old_state_count, |
| 268 thread_state_t new_state, |
| 269 mach_msg_type_number_t* new_state_count) override; |
| 270 virtual kern_return_t CatchExceptionRaiseStateIdentity( |
| 271 exception_handler_t exception_port, |
| 272 thread_t thread, |
| 273 task_t task, |
| 274 exception_type_t exception, |
| 275 const exception_data_type_t* code, |
| 276 mach_msg_type_number_t code_count, |
| 277 thread_state_flavor_t* flavor, |
| 278 const natural_t* old_state, |
| 279 mach_msg_type_number_t old_state_count, |
| 280 thread_state_t new_state, |
| 281 mach_msg_type_number_t* new_state_count, |
| 282 bool* destroy_request) override; |
| 283 |
| 284 private: |
| 285 Interface* interface_; // weak |
| 286 }; |
| 287 |
| 288 //! \brief A server interface for the `mach_exc` Mach subsystem, simplified to |
| 289 //! have only a single interface method needing implementation. |
| 290 class SimplifiedMachExcServer : public MachExcServer, |
| 291 public MachExcServer::Interface { |
| 292 public: |
| 293 //! \brief An interface that the different request messages that are a part of |
| 294 //! the `mach_exc` Mach subsystem can be dispatched to. |
| 295 class Interface { |
| 296 public: |
| 297 //! \brief Handles exceptions raised by `mach_exception_raise()`, |
| 298 //! `mach_exception_raise_state()`, and |
| 299 //! `mach_exception_raise_state_identity()`. |
| 300 //! |
| 301 //! When used with UniversalMachExcServer, this also handles exceptions |
| 302 //! raised by `exception_raise()`, `exception_raise_state()`, and |
| 303 //! `exception_raise_state_identity()`. |
| 304 //! |
| 305 //! For convenience in implementation, these different “behaviors” of |
| 306 //! exception messages are all mapped to a single interface method. The |
| 307 //! exception’s original “behavior” is specified in the \a behavior |
| 308 //! parameter. Only parameters that were supplied in the request message |
| 309 //! are populated, other parameters are set to reasonable default values. |
| 310 //! |
| 311 //! The meanings of most parameters are identical to that of |
| 312 //! MachExcServer::Interface::CatchMachExceptionRaiseStateIdentity(). |
| 313 //! |
| 314 //! \param[in] behavior `MACH_EXCEPTION_CODES | EXCEPTION_DEFAULT`, |
| 315 //! `MACH_EXCEPTION_CODES | EXCEPTION_STATE`, or |
| 316 //! `MACH_EXCEPTION_CODES | EXCEPTION_STATE_IDENTITY`, identifying which |
| 317 //! exception request message was processed and thus which other |
| 318 //! parameters are valid. When used with UniversalMachExcServer, \a |
| 319 //! behavior can also be `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or |
| 320 //! `EXCEPTION_STATE_IDENTITY`. |
| 321 virtual kern_return_t CatchMachException( |
| 322 exception_behavior_t behavior, |
| 323 exception_handler_t exception_port, |
| 324 thread_t thread, |
| 325 task_t task, |
| 326 exception_type_t exception, |
| 327 const mach_exception_data_type_t* code, |
| 328 mach_msg_type_number_t code_count, |
| 329 thread_state_flavor_t* flavor, |
| 330 const natural_t* old_state, |
| 331 mach_msg_type_number_t old_state_count, |
| 332 thread_state_t new_state, |
| 333 mach_msg_type_number_t* new_state_count, |
| 334 bool* destroy_complex_request) = 0; |
| 335 |
| 336 protected: |
| 337 ~Interface() {} |
| 338 }; |
| 339 |
| 340 explicit SimplifiedMachExcServer(Interface* interface); |
| 341 |
| 342 // MachExcServer::Interface: |
| 343 |
| 344 virtual kern_return_t CatchMachExceptionRaise( |
| 345 exception_handler_t exception_port, |
| 346 thread_t thread, |
| 347 task_t task, |
| 348 exception_type_t exception, |
| 349 const mach_exception_data_type_t* code, |
| 350 mach_msg_type_number_t code_count, |
| 351 bool* destroy_request) override; |
| 352 virtual kern_return_t CatchMachExceptionRaiseState( |
| 353 exception_handler_t exception_port, |
| 354 exception_type_t exception, |
| 355 const mach_exception_data_type_t* code, |
| 356 mach_msg_type_number_t code_count, |
| 357 thread_state_flavor_t* flavor, |
| 358 const natural_t* old_state, |
| 359 mach_msg_type_number_t old_state_count, |
| 360 thread_state_t new_state, |
| 361 mach_msg_type_number_t* new_state_count) override; |
| 362 virtual kern_return_t CatchMachExceptionRaiseStateIdentity( |
| 363 exception_handler_t exception_port, |
| 364 thread_t thread, |
| 365 task_t task, |
| 366 exception_type_t exception, |
| 367 const mach_exception_data_type_t* code, |
| 368 mach_msg_type_number_t code_count, |
| 369 thread_state_flavor_t* flavor, |
| 370 const natural_t* old_state, |
| 371 mach_msg_type_number_t old_state_count, |
| 372 thread_state_t new_state, |
| 373 mach_msg_type_number_t* new_state_count, |
| 374 bool* destroy_request) override; |
| 375 |
| 376 private: |
| 377 Interface* interface_; // weak |
| 378 }; |
| 379 |
| 380 } // namespace internal |
| 381 |
| 382 //! \brief A server interface for the `exc` and `mach_exc` Mach subsystems, |
| 383 //! unified to handle exceptions delivered to either subsystem, and |
| 384 //! simplified to have only a single interface method needing |
| 385 //! implementation. |
| 386 //! |
| 387 //! UniversalMachExcServer operates by translating messages received in the |
| 388 //! `exc` subsystem to a variant that is compatible with the `mach_exc` |
| 389 //! subsystem. This involves changing the format of \a code, the exception code |
| 390 //! field, from `exception_data_type_t` to `mach_exception_data_type_t`. |
| 391 //! This is achieved by implementing SimplifiedExcServer::Interface and having |
| 392 //! it forward translated messages to SimplifiedMachExcServer::Interface, which |
| 393 //! is left unimplemented here so that users of this class can provide their own |
| 394 //! implementations. |
| 395 class UniversalMachExcServer |
| 396 : public MachMessageServer::Interface, |
| 397 public internal::SimplifiedExcServer::Interface, |
| 398 public internal::SimplifiedMachExcServer::Interface { |
| 399 public: |
| 400 UniversalMachExcServer(); |
| 401 |
| 402 // MachMessageServer::Interface: |
| 403 |
| 404 virtual bool MachMessageServerFunction( |
| 405 mach_msg_header_t* in_header, |
| 406 mach_msg_header_t* out_header, |
| 407 bool* destroy_complex_request) override; |
| 408 |
| 409 virtual mach_msg_size_t MachMessageServerRequestSize() override; |
| 410 virtual mach_msg_size_t MachMessageServerReplySize() override; |
| 411 |
| 412 // internal::SimplifiedExcServer::Interface: |
| 413 |
| 414 virtual kern_return_t CatchException( |
| 415 exception_behavior_t behavior, |
| 416 exception_handler_t exception_port, |
| 417 thread_t thread, |
| 418 task_t task, |
| 419 exception_type_t exception, |
| 420 const exception_data_type_t* code, |
| 421 mach_msg_type_number_t code_count, |
| 422 thread_state_flavor_t* flavor, |
| 423 const natural_t* old_state, |
| 424 mach_msg_type_number_t old_state_count, |
| 425 thread_state_t new_state, |
| 426 mach_msg_type_number_t* new_state_count, |
| 427 bool* destroy_complex_request) override; |
| 428 |
| 429 private: |
| 430 internal::SimplifiedExcServer exc_server_; |
| 431 internal::SimplifiedMachExcServer mach_exc_server_; |
| 432 }; |
| 433 |
| 434 } // namespace crashpad |
| 435 |
| 436 #endif // CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ |
OLD | NEW |