| OLD | NEW |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include "util/mach/exc_server_variants.h" | 15 #include "util/mach/exc_server_variants.h" |
| 16 | 16 |
| 17 #include <algorithm> | 17 #include <algorithm> |
| 18 #include <vector> | 18 #include <vector> |
| 19 | 19 |
| 20 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "util/mach/composite_mach_message_server.h" |
| 21 #include "util/mach/exc.h" | 22 #include "util/mach/exc.h" |
| 22 #include "util/mach/exception_behaviors.h" | 23 #include "util/mach/exception_behaviors.h" |
| 23 #include "util/mach/excServer.h" | 24 #include "util/mach/excServer.h" |
| 24 #include "util/mach/mach_exc.h" | 25 #include "util/mach/mach_exc.h" |
| 25 #include "util/mach/mach_excServer.h" | 26 #include "util/mach/mach_excServer.h" |
| 26 #include "util/mach/mach_message.h" | 27 #include "util/mach/mach_message.h" |
| 27 | 28 |
| 28 extern "C" { | 29 extern "C" { |
| 29 | 30 |
| 30 // These six functions are not used, and are in fact obsoleted by the other | 31 // These six functions are not used, and are in fact obsoleted by the other |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 thread_state_t old_state, | 111 thread_state_t old_state, |
| 111 mach_msg_type_number_t old_state_count, | 112 mach_msg_type_number_t old_state_count, |
| 112 thread_state_t new_state, | 113 thread_state_t new_state, |
| 113 mach_msg_type_number_t* new_state_count) { | 114 mach_msg_type_number_t* new_state_count) { |
| 114 NOTREACHED(); | 115 NOTREACHED(); |
| 115 return KERN_FAILURE; | 116 return KERN_FAILURE; |
| 116 } | 117 } |
| 117 | 118 |
| 118 } // extern "C" | 119 } // extern "C" |
| 119 | 120 |
| 121 namespace crashpad { |
| 122 |
| 120 namespace { | 123 namespace { |
| 121 | 124 |
| 122 // There are no predefined constants for these. | 125 // Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with |
| 123 enum MachMessageID : mach_msg_id_t { | 126 // the exc subsystem. |
| 124 kMachMessageIDExceptionRaise = 2401, | 127 struct ExcTraits { |
| 125 kMachMessageIDExceptionRaiseState = 2402, | 128 using ExceptionCode = exception_data_type_t; |
| 126 kMachMessageIDExceptionRaiseStateIdentity = 2403, | 129 |
| 127 kMachMessageIDMachExceptionRaise = 2405, | 130 using RequestUnion = __RequestUnion__exc_subsystem; |
| 128 kMachMessageIDMachExceptionRaiseState = 2406, | 131 using ReplyUnion = __ReplyUnion__exc_subsystem; |
| 129 kMachMessageIDMachExceptionRaiseStateIdentity = 2407, | 132 |
| 133 using ExceptionRaiseRequest = __Request__exception_raise_t; |
| 134 using ExceptionRaiseStateRequest = __Request__exception_raise_state_t; |
| 135 using ExceptionRaiseStateIdentityRequest = |
| 136 __Request__exception_raise_state_identity_t; |
| 137 |
| 138 using ExceptionRaiseReply = __Reply__exception_raise_t; |
| 139 using ExceptionRaiseStateReply = __Reply__exception_raise_state_t; |
| 140 using ExceptionRaiseStateIdentityReply = |
| 141 __Reply__exception_raise_state_identity_t; |
| 142 |
| 143 // The MIG-generated __MIG_check__Request__*() functions are not declared as |
| 144 // accepting const data, but they could have been because they in fact do not |
| 145 // modify the data. |
| 146 |
| 147 static kern_return_t MIGCheckRequestExceptionRaise( |
| 148 const ExceptionRaiseRequest* in_request) { |
| 149 return __MIG_check__Request__exception_raise_t( |
| 150 const_cast<ExceptionRaiseRequest*>(in_request)); |
| 151 } |
| 152 |
| 153 static kern_return_t MIGCheckRequestExceptionRaiseState( |
| 154 const ExceptionRaiseStateRequest* in_request, |
| 155 const ExceptionRaiseStateRequest** in_request_1) { |
| 156 using Request = __Request__exception_raise_state_t; |
| 157 return __MIG_check__Request__exception_raise_state_t( |
| 158 const_cast<ExceptionRaiseStateRequest*>(in_request), |
| 159 const_cast<ExceptionRaiseStateRequest**>(in_request_1)); |
| 160 } |
| 161 |
| 162 static kern_return_t MIGCheckRequestExceptionRaiseStateIdentity( |
| 163 const ExceptionRaiseStateIdentityRequest* in_request, |
| 164 const ExceptionRaiseStateIdentityRequest** in_request_1) { |
| 165 return __MIG_check__Request__exception_raise_state_identity_t( |
| 166 const_cast<ExceptionRaiseStateIdentityRequest*>(in_request), |
| 167 const_cast<ExceptionRaiseStateIdentityRequest**>(in_request_1)); |
| 168 } |
| 169 |
| 170 // There are no predefined constants for these. |
| 171 static const mach_msg_id_t kMachMessageIDExceptionRaise = 2401; |
| 172 static const mach_msg_id_t kMachMessageIDExceptionRaiseState = 2402; |
| 173 static const mach_msg_id_t kMachMessageIDExceptionRaiseStateIdentity = 2403; |
| 174 |
| 175 static const exception_behavior_t kExceptionBehavior = 0; |
| 130 }; | 176 }; |
| 131 | 177 |
| 132 // The MIG-generated __MIG_check__Request__*() functions are not declared as | 178 // Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with |
| 133 // accepting const data, but they could have been because they in fact do not | 179 // the mach_exc subsystem. |
| 134 // modify the data. These wrapper functions are provided to bridge the const gap | 180 struct MachExcTraits { |
| 135 // between the code in this file, which is const-correct and treats request | 181 using ExceptionCode = mach_exception_data_type_t; |
| 136 // message data as const, and those generated functions. | 182 |
| 137 | 183 using RequestUnion = __RequestUnion__mach_exc_subsystem; |
| 138 kern_return_t MIGCheckRequestExceptionRaise( | 184 using ReplyUnion = __ReplyUnion__mach_exc_subsystem; |
| 139 const __Request__exception_raise_t* in_request) { | 185 |
| 140 using Request = __Request__exception_raise_t; | 186 using ExceptionRaiseRequest = __Request__mach_exception_raise_t; |
| 141 return __MIG_check__Request__exception_raise_t( | 187 using ExceptionRaiseStateRequest = __Request__mach_exception_raise_state_t; |
| 142 const_cast<Request*>(in_request)); | 188 using ExceptionRaiseStateIdentityRequest = |
| 143 } | 189 __Request__mach_exception_raise_state_identity_t; |
| 144 | 190 |
| 145 kern_return_t MIGCheckRequestExceptionRaiseState( | 191 using ExceptionRaiseReply = __Reply__mach_exception_raise_t; |
| 146 const __Request__exception_raise_state_t* in_request, | 192 using ExceptionRaiseStateReply = __Reply__mach_exception_raise_state_t; |
| 147 const __Request__exception_raise_state_t** in_request_1) { | 193 using ExceptionRaiseStateIdentityReply = |
| 148 using Request = __Request__exception_raise_state_t; | 194 __Reply__mach_exception_raise_state_identity_t; |
| 149 return __MIG_check__Request__exception_raise_state_t( | 195 |
| 150 const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); | 196 // The MIG-generated __MIG_check__Request__*() functions are not declared as |
| 151 } | 197 // accepting const data, but they could have been because they in fact do not |
| 152 | 198 // modify the data. |
| 153 kern_return_t MIGCheckRequestExceptionRaiseStateIdentity( | 199 |
| 154 const __Request__exception_raise_state_identity_t* in_request, | 200 static kern_return_t MIGCheckRequestExceptionRaise( |
| 155 const __Request__exception_raise_state_identity_t** in_request_1) { | 201 const ExceptionRaiseRequest* in_request) { |
| 156 using Request = __Request__exception_raise_state_identity_t; | 202 return __MIG_check__Request__mach_exception_raise_t( |
| 157 return __MIG_check__Request__exception_raise_state_identity_t( | 203 const_cast<ExceptionRaiseRequest*>(in_request)); |
| 158 const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); | 204 } |
| 159 } | 205 |
| 160 | 206 static kern_return_t MIGCheckRequestExceptionRaiseState( |
| 161 kern_return_t MIGCheckRequestMachExceptionRaise( | 207 const ExceptionRaiseStateRequest* in_request, |
| 162 const __Request__mach_exception_raise_t* in_request) { | 208 const ExceptionRaiseStateRequest** in_request_1) { |
| 163 using Request = __Request__mach_exception_raise_t; | 209 using Request = __Request__exception_raise_state_t; |
| 164 return __MIG_check__Request__mach_exception_raise_t( | 210 return __MIG_check__Request__mach_exception_raise_state_t( |
| 165 const_cast<Request*>(in_request)); | 211 const_cast<ExceptionRaiseStateRequest*>(in_request), |
| 166 } | 212 const_cast<ExceptionRaiseStateRequest**>(in_request_1)); |
| 167 | 213 } |
| 168 kern_return_t MIGCheckRequestMachExceptionRaiseState( | 214 |
| 169 const __Request__mach_exception_raise_state_t* in_request, | 215 static kern_return_t MIGCheckRequestExceptionRaiseStateIdentity( |
| 170 const __Request__mach_exception_raise_state_t** in_request_1) { | 216 const ExceptionRaiseStateIdentityRequest* in_request, |
| 171 using Request = __Request__mach_exception_raise_state_t; | 217 const ExceptionRaiseStateIdentityRequest** in_request_1) { |
| 172 return __MIG_check__Request__mach_exception_raise_state_t( | 218 return __MIG_check__Request__mach_exception_raise_state_identity_t( |
| 173 const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); | 219 const_cast<ExceptionRaiseStateIdentityRequest*>(in_request), |
| 174 } | 220 const_cast<ExceptionRaiseStateIdentityRequest**>(in_request_1)); |
| 175 | 221 } |
| 176 kern_return_t MIGCheckRequestMachExceptionRaiseStateIdentity( | 222 |
| 177 const __Request__mach_exception_raise_state_identity_t* in_request, | 223 // There are no predefined constants for these. |
| 178 const __Request__mach_exception_raise_state_identity_t** in_request_1) { | 224 static const mach_msg_id_t kMachMessageIDExceptionRaise = 2405; |
| 179 using Request = __Request__mach_exception_raise_state_identity_t; | 225 static const mach_msg_id_t kMachMessageIDExceptionRaiseState = 2406; |
| 180 return __MIG_check__Request__mach_exception_raise_state_identity_t( | 226 static const mach_msg_id_t kMachMessageIDExceptionRaiseStateIdentity = 2407; |
| 181 const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); | 227 |
| 182 } | 228 static const exception_behavior_t kExceptionBehavior = MACH_EXCEPTION_CODES; |
| 183 | 229 }; |
| 184 } // namespace | 230 |
| 185 | 231 //! \brief A server interface for the `exc` or `mach_exc` Mach subsystems. |
| 186 namespace crashpad { | 232 template <typename Traits> |
| 187 namespace internal { | 233 class ExcServer : public MachMessageServer::Interface { |
| 188 | 234 public: |
| 189 ExcServer::ExcServer(ExcServer::Interface* interface) | 235 //! \brief An interface that the different request messages that are a part of |
| 190 : MachMessageServer::Interface(), | 236 //! the `exc` or `mach_exc` Mach subsystems can be dispatched to. |
| 191 interface_(interface) { | 237 class Interface { |
| 192 } | 238 public: |
| 193 | 239 //! \brief Handles exceptions raised by `exception_raise()` or |
| 194 bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header, | 240 //! `mach_exception_raise()`. |
| 195 mach_msg_header_t* out_header, | 241 //! |
| 196 bool* destroy_complex_request) { | 242 //! This behaves equivalently to a `catch_exception_raise()` function used |
| 243 //! with `exc_server()`, or a `catch_mach_exception_raise()` function used |
| 244 //! with `mach_exc_server()`. |
| 245 //! |
| 246 //! \param[in] trailer The trailer received with the request message. |
| 247 //! \param[out] destroy_request `true` if the request message is to be |
| 248 //! destroyed even when this method returns success. See |
| 249 //! MachMessageServer::Interface. |
| 250 virtual kern_return_t CatchExceptionRaise( |
| 251 exception_handler_t exception_port, |
| 252 thread_t thread, |
| 253 task_t task, |
| 254 exception_type_t exception, |
| 255 const typename Traits::ExceptionCode* code, |
| 256 mach_msg_type_number_t code_count, |
| 257 const mach_msg_trailer_t* trailer, |
| 258 bool* destroy_request) = 0; |
| 259 |
| 260 //! \brief Handles exceptions raised by `exception_raise_state()` or |
| 261 //! `mach_exception_raise_state()`. |
| 262 //! |
| 263 //! This behaves equivalently to a `catch_exception_raise_state()` function |
| 264 //! used with `exc_server()`, or a `catch_mach_exception_raise_state()` |
| 265 //! function used with `mach_exc_server()`. |
| 266 //! |
| 267 //! There is no \a destroy_request parameter because, unlike |
| 268 //! CatchExceptionRaise() and CatchExceptionRaiseStateIdentity(), the |
| 269 //! request message is not complex (it does not carry the \a thread or \a |
| 270 //! task port rights) and thus there is nothing to destroy. |
| 271 //! |
| 272 //! \param[in] trailer The trailer received with the request message. |
| 273 virtual kern_return_t CatchExceptionRaiseState( |
| 274 exception_handler_t exception_port, |
| 275 exception_type_t exception, |
| 276 const typename Traits::ExceptionCode* code, |
| 277 mach_msg_type_number_t code_count, |
| 278 thread_state_flavor_t* flavor, |
| 279 const natural_t* old_state, |
| 280 mach_msg_type_number_t old_state_count, |
| 281 thread_state_t new_state, |
| 282 mach_msg_type_number_t* new_state_count, |
| 283 const mach_msg_trailer_t* trailer) = 0; |
| 284 |
| 285 //! \brief Handles exceptions raised by `exception_raise_state_identity()` |
| 286 //! or `mach_exception_raise_state_identity()`. |
| 287 //! |
| 288 //! This behaves equivalently to a `catch_exception_raise_state_identity()` |
| 289 //! function used with `exc_server()`, or a |
| 290 //! `catch_mach_exception_raise_state_identity()` function used with |
| 291 //! `mach_exc_server()`. |
| 292 //! |
| 293 //! \param[in] trailer The trailer received with the request message. |
| 294 //! \param[out] destroy_request `true` if the request message is to be |
| 295 //! destroyed even when this method returns success. See |
| 296 //! MachMessageServer::Interface. |
| 297 virtual kern_return_t CatchExceptionRaiseStateIdentity( |
| 298 exception_handler_t exception_port, |
| 299 thread_t thread, |
| 300 task_t task, |
| 301 exception_type_t exception, |
| 302 const typename Traits::ExceptionCode* code, |
| 303 mach_msg_type_number_t code_count, |
| 304 thread_state_flavor_t* flavor, |
| 305 const natural_t* old_state, |
| 306 mach_msg_type_number_t old_state_count, |
| 307 thread_state_t new_state, |
| 308 mach_msg_type_number_t* new_state_count, |
| 309 const mach_msg_trailer_t* trailer, |
| 310 bool* destroy_request) = 0; |
| 311 |
| 312 protected: |
| 313 ~Interface() {} |
| 314 }; |
| 315 |
| 316 //! \brief Constructs an object of this class. |
| 317 //! |
| 318 //! \param[in] interface The interface to dispatch requests to. Weak. |
| 319 explicit ExcServer(Interface* interface) |
| 320 : MachMessageServer::Interface(), interface_(interface) {} |
| 321 |
| 322 // MachMessageServer::Interface: |
| 323 |
| 324 bool MachMessageServerFunction(const mach_msg_header_t* in_header, |
| 325 mach_msg_header_t* out_header, |
| 326 bool* destroy_complex_request) override; |
| 327 |
| 328 std::set<mach_msg_id_t> MachMessageServerRequestIDs() override { |
| 329 const mach_msg_id_t request_ids[] = { |
| 330 Traits::kMachMessageIDExceptionRaise, |
| 331 Traits::kMachMessageIDExceptionRaiseState, |
| 332 Traits::kMachMessageIDExceptionRaiseStateIdentity, |
| 333 }; |
| 334 return std::set<mach_msg_id_t>(&request_ids[0], |
| 335 &request_ids[arraysize(request_ids)]); |
| 336 } |
| 337 |
| 338 mach_msg_size_t MachMessageServerRequestSize() override { |
| 339 return sizeof(typename Traits::RequestUnion); |
| 340 } |
| 341 |
| 342 mach_msg_size_t MachMessageServerReplySize() override { |
| 343 return sizeof(typename Traits::ReplyUnion); |
| 344 } |
| 345 |
| 346 private: |
| 347 Interface* interface_; // weak |
| 348 |
| 349 DISALLOW_COPY_AND_ASSIGN(ExcServer); |
| 350 }; |
| 351 |
| 352 template <typename Traits> |
| 353 bool ExcServer<Traits>::MachMessageServerFunction( |
| 354 const mach_msg_header_t* in_header, |
| 355 mach_msg_header_t* out_header, |
| 356 bool* destroy_complex_request) { |
| 197 PrepareMIGReplyFromRequest(in_header, out_header); | 357 PrepareMIGReplyFromRequest(in_header, out_header); |
| 198 | 358 |
| 199 const mach_msg_trailer_t* in_trailer = | 359 const mach_msg_trailer_t* in_trailer = |
| 200 MachMessageTrailerFromHeader(in_header); | 360 MachMessageTrailerFromHeader(in_header); |
| 201 | 361 |
| 202 switch (in_header->msgh_id) { | 362 switch (in_header->msgh_id) { |
| 203 case kMachMessageIDExceptionRaise: { | 363 case Traits::kMachMessageIDExceptionRaise: { |
| 204 // exception_raise(), catch_exception_raise(). | 364 // exception_raise(), catch_exception_raise(), mach_exception_raise(), |
| 205 using Request = __Request__exception_raise_t; | 365 // catch_mach_exception_raise(). |
| 366 using Request = typename Traits::ExceptionRaiseRequest; |
| 206 const Request* in_request = reinterpret_cast<const Request*>(in_header); | 367 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 207 kern_return_t kr = MIGCheckRequestExceptionRaise(in_request); | 368 kern_return_t kr = Traits::MIGCheckRequestExceptionRaise(in_request); |
| 208 if (kr != MACH_MSG_SUCCESS) { | 369 if (kr != MACH_MSG_SUCCESS) { |
| 209 SetMIGReplyError(out_header, kr); | 370 SetMIGReplyError(out_header, kr); |
| 210 return true; | 371 return true; |
| 211 } | 372 } |
| 212 | 373 |
| 213 using Reply = __Reply__exception_raise_t; | 374 using Reply = typename Traits::ExceptionRaiseReply; |
| 214 Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 375 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 215 out_reply->RetCode = | 376 out_reply->RetCode = |
| 216 interface_->CatchExceptionRaise(in_header->msgh_local_port, | 377 interface_->CatchExceptionRaise(in_header->msgh_local_port, |
| 217 in_request->thread.name, | 378 in_request->thread.name, |
| 218 in_request->task.name, | 379 in_request->task.name, |
| 219 in_request->exception, | 380 in_request->exception, |
| 220 in_request->code, | 381 in_request->code, |
| 221 in_request->codeCnt, | 382 in_request->codeCnt, |
| 222 in_trailer, | 383 in_trailer, |
| 223 destroy_complex_request); | 384 destroy_complex_request); |
| 224 if (out_reply->RetCode != KERN_SUCCESS) { | 385 if (out_reply->RetCode != KERN_SUCCESS) { |
| 225 return true; | 386 return true; |
| 226 } | 387 } |
| 227 | 388 |
| 228 out_header->msgh_size = sizeof(*out_reply); | 389 out_header->msgh_size = sizeof(*out_reply); |
| 229 return true; | 390 return true; |
| 230 } | 391 } |
| 231 | 392 |
| 232 case kMachMessageIDExceptionRaiseState: { | 393 case Traits::kMachMessageIDExceptionRaiseState: { |
| 233 // exception_raise_state(), catch_exception_raise_state(). | 394 // exception_raise_state(), catch_exception_raise_state(), |
| 234 using Request = __Request__exception_raise_state_t; | 395 // mach_exception_raise_state(), catch_mach_exception_raise_state(). |
| 396 using Request = typename Traits::ExceptionRaiseStateRequest; |
| 235 const Request* in_request = reinterpret_cast<const Request*>(in_header); | 397 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 236 | 398 |
| 237 // in_request_1 is used for the portion of the request after the codes, | 399 // in_request_1 is used for the portion of the request after the codes, |
| 238 // which in theory can be variable-length. The check function will set it. | 400 // which in theory can be variable-length. The check function will set it. |
| 239 const Request* in_request_1; | 401 const Request* in_request_1; |
| 240 kern_return_t kr = | 402 kern_return_t kr = |
| 241 MIGCheckRequestExceptionRaiseState(in_request, &in_request_1); | 403 Traits::MIGCheckRequestExceptionRaiseState(in_request, &in_request_1); |
| 242 if (kr != MACH_MSG_SUCCESS) { | 404 if (kr != MACH_MSG_SUCCESS) { |
| 243 SetMIGReplyError(out_header, kr); | 405 SetMIGReplyError(out_header, kr); |
| 244 return true; | 406 return true; |
| 245 } | 407 } |
| 246 | 408 |
| 247 using Reply = __Reply__exception_raise_state_t; | 409 using Reply = typename Traits::ExceptionRaiseStateReply; |
| 248 Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 410 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 249 out_reply->flavor = in_request_1->flavor; | 411 out_reply->flavor = in_request_1->flavor; |
| 250 out_reply->new_stateCnt = arraysize(out_reply->new_state); | 412 out_reply->new_stateCnt = arraysize(out_reply->new_state); |
| 251 out_reply->RetCode = | 413 out_reply->RetCode = |
| 252 interface_->CatchExceptionRaiseState(in_header->msgh_local_port, | 414 interface_->CatchExceptionRaiseState(in_header->msgh_local_port, |
| 253 in_request->exception, | 415 in_request->exception, |
| 254 in_request->code, | 416 in_request->code, |
| 255 in_request->codeCnt, | 417 in_request->codeCnt, |
| 256 &out_reply->flavor, | 418 &out_reply->flavor, |
| 257 in_request_1->old_state, | 419 in_request_1->old_state, |
| 258 in_request_1->old_stateCnt, | 420 in_request_1->old_stateCnt, |
| 259 out_reply->new_state, | 421 out_reply->new_state, |
| 260 &out_reply->new_stateCnt, | 422 &out_reply->new_stateCnt, |
| 261 in_trailer); | 423 in_trailer); |
| 262 if (out_reply->RetCode != KERN_SUCCESS) { | 424 if (out_reply->RetCode != KERN_SUCCESS) { |
| 263 return true; | 425 return true; |
| 264 } | 426 } |
| 265 | 427 |
| 266 out_header->msgh_size = | 428 out_header->msgh_size = |
| 267 sizeof(*out_reply) - sizeof(out_reply->new_state) + | 429 sizeof(*out_reply) - sizeof(out_reply->new_state) + |
| 268 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; | 430 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; |
| 269 return true; | 431 return true; |
| 270 } | 432 } |
| 271 | 433 |
| 272 case kMachMessageIDExceptionRaiseStateIdentity: { | 434 case Traits::kMachMessageIDExceptionRaiseStateIdentity: { |
| 273 // exception_raise_state_identity(), | 435 // exception_raise_state_identity(), |
| 274 // catch_exception_raise_state_identity(). | 436 // catch_exception_raise_state_identity(), |
| 275 using Request = __Request__exception_raise_state_identity_t; | 437 // mach_exception_raise_state_identity(), |
| 438 // catch_mach_exception_raise_state_identity(). |
| 439 using Request = typename Traits::ExceptionRaiseStateIdentityRequest; |
| 276 const Request* in_request = reinterpret_cast<const Request*>(in_header); | 440 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 277 | 441 |
| 278 // in_request_1 is used for the portion of the request after the codes, | 442 // in_request_1 is used for the portion of the request after the codes, |
| 279 // which in theory can be variable-length. The check function will set it. | 443 // which in theory can be variable-length. The check function will set it. |
| 280 const Request* in_request_1; | 444 const Request* in_request_1; |
| 281 kern_return_t kr = | 445 kern_return_t kr = Traits::MIGCheckRequestExceptionRaiseStateIdentity( |
| 282 MIGCheckRequestExceptionRaiseStateIdentity(in_request, &in_request_1); | 446 in_request, &in_request_1); |
| 283 if (kr != MACH_MSG_SUCCESS) { | 447 if (kr != MACH_MSG_SUCCESS) { |
| 284 SetMIGReplyError(out_header, kr); | 448 SetMIGReplyError(out_header, kr); |
| 285 return true; | 449 return true; |
| 286 } | 450 } |
| 287 | 451 |
| 288 using Reply = __Reply__exception_raise_state_identity_t; | 452 using Reply = typename Traits::ExceptionRaiseStateIdentityReply; |
| 289 Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 453 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 290 out_reply->flavor = in_request_1->flavor; | 454 out_reply->flavor = in_request_1->flavor; |
| 291 out_reply->new_stateCnt = arraysize(out_reply->new_state); | 455 out_reply->new_stateCnt = arraysize(out_reply->new_state); |
| 292 out_reply->RetCode = interface_->CatchExceptionRaiseStateIdentity( | 456 out_reply->RetCode = interface_->CatchExceptionRaiseStateIdentity( |
| 293 in_header->msgh_local_port, | 457 in_header->msgh_local_port, |
| 294 in_request->thread.name, | 458 in_request->thread.name, |
| 295 in_request->task.name, | 459 in_request->task.name, |
| 296 in_request->exception, | 460 in_request->exception, |
| 297 in_request->code, | 461 in_request->code, |
| 298 in_request->codeCnt, | 462 in_request->codeCnt, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 311 sizeof(*out_reply) - sizeof(out_reply->new_state) + | 475 sizeof(*out_reply) - sizeof(out_reply->new_state) + |
| 312 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; | 476 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; |
| 313 return true; | 477 return true; |
| 314 } | 478 } |
| 315 } | 479 } |
| 316 | 480 |
| 317 SetMIGReplyError(out_header, MIG_BAD_ID); | 481 SetMIGReplyError(out_header, MIG_BAD_ID); |
| 318 return false; | 482 return false; |
| 319 } | 483 } |
| 320 | 484 |
| 321 std::set<mach_msg_id_t> ExcServer::MachMessageServerRequestIDs() { | 485 //! \brief A server interface for the `exc` or `mach_exc` Mach subsystems, |
| 322 const mach_msg_id_t request_ids[] = { | 486 //! simplified to have only a single interface method needing |
| 323 kMachMessageIDExceptionRaise, | 487 //! implementation. |
| 324 kMachMessageIDExceptionRaiseState, | 488 template <typename Traits> |
| 325 kMachMessageIDExceptionRaiseStateIdentity | 489 class SimplifiedExcServer final : public ExcServer<Traits>, |
| 490 public ExcServer<Traits>::Interface { |
| 491 public: |
| 492 //! \brief An interface that the different request messages that are a part of |
| 493 //! the `exc` or `mach_exc` Mach subsystems can be dispatched to. |
| 494 class Interface { |
| 495 public: |
| 496 //! \brief Handles exceptions raised by `exception_raise()`, |
| 497 //! `exception_raise_state()`, and `exception_raise_state_identity()`; |
| 498 //! or `mach_exception_raise()`, `mach_exception_raise_state()`, and |
| 499 //! `mach_exception_raise_state_identity()`. |
| 500 //! |
| 501 //! For convenience in implementation, these different “behaviors” of |
| 502 //! exception messages are all mapped to a single interface method. The |
| 503 //! exception’s original “behavior” is specified in the \a behavior |
| 504 //! parameter. Only parameters that were supplied in the request message |
| 505 //! are populated, other parameters are set to reasonable default values. |
| 506 //! |
| 507 //! The meanings of most parameters are identical to that of |
| 508 //! ExcServer<>::Interface::CatchExceptionRaiseStateIdentity(). |
| 509 //! |
| 510 //! \param[in] behavior `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or |
| 511 //! `EXCEPTION_STATE_IDENTITY`, identifying which exception request |
| 512 //! message was processed and thus which other parameters are valid. |
| 513 //! When used with the `mach_exc` subsystem, `MACH_EXCEPTION_CODES` will |
| 514 //! be ORed in to this parameter. |
| 515 virtual kern_return_t CatchException( |
| 516 exception_behavior_t behavior, |
| 517 exception_handler_t exception_port, |
| 518 thread_t thread, |
| 519 task_t task, |
| 520 exception_type_t exception, |
| 521 const typename Traits::ExceptionCode* code, |
| 522 mach_msg_type_number_t code_count, |
| 523 thread_state_flavor_t* flavor, |
| 524 const natural_t* old_state, |
| 525 mach_msg_type_number_t old_state_count, |
| 526 thread_state_t new_state, |
| 527 mach_msg_type_number_t* new_state_count, |
| 528 const mach_msg_trailer_t* trailer, |
| 529 bool* destroy_complex_request) = 0; |
| 530 |
| 531 protected: |
| 532 ~Interface() {} |
| 326 }; | 533 }; |
| 327 return std::set<mach_msg_id_t>( | 534 |
| 328 &request_ids[0], &request_ids[arraysize(request_ids)]); | 535 //! \brief Constructs an object of this class. |
| 329 } | 536 //! |
| 330 | 537 //! \param[in] interface The interface to dispatch requests to. Weak. |
| 331 mach_msg_size_t ExcServer::MachMessageServerRequestSize() { | 538 explicit SimplifiedExcServer(Interface* interface) |
| 332 return sizeof(__RequestUnion__exc_subsystem); | 539 : ExcServer<Traits>(this), |
| 333 } | 540 ExcServer<Traits>::Interface(), |
| 334 | 541 interface_(interface) {} |
| 335 mach_msg_size_t ExcServer::MachMessageServerReplySize() { | 542 |
| 336 return sizeof(__ReplyUnion__exc_subsystem); | 543 // ExcServer::Interface: |
| 337 } | 544 |
| 338 | 545 kern_return_t CatchExceptionRaise(exception_handler_t exception_port, |
| 339 MachExcServer::MachExcServer(MachExcServer::Interface* interface) | 546 thread_t thread, |
| 340 : MachMessageServer::Interface(), | 547 task_t task, |
| 341 interface_(interface) { | 548 exception_type_t exception, |
| 342 } | 549 const typename Traits::ExceptionCode* code, |
| 343 | 550 mach_msg_type_number_t code_count, |
| 344 bool MachExcServer::MachMessageServerFunction( | 551 const mach_msg_trailer_t* trailer, |
| 345 const mach_msg_header_t* in_header, | 552 bool* destroy_request) override { |
| 346 mach_msg_header_t* out_header, | 553 thread_state_flavor_t flavor = THREAD_STATE_NONE; |
| 347 bool* destroy_complex_request) { | 554 mach_msg_type_number_t new_state_count = 0; |
| 348 PrepareMIGReplyFromRequest(in_header, out_header); | 555 return interface_->CatchException( |
| 349 | 556 Traits::kExceptionBehavior | EXCEPTION_DEFAULT, |
| 350 const mach_msg_trailer_t* in_trailer = | 557 exception_port, |
| 351 MachMessageTrailerFromHeader(in_header); | 558 thread, |
| 352 | 559 task, |
| 353 switch (in_header->msgh_id) { | 560 exception, |
| 354 case kMachMessageIDMachExceptionRaise: { | 561 code_count ? code : nullptr, |
| 355 // mach_exception_raise(), catch_mach_exception_raise(). | 562 code_count, |
| 356 using Request = __Request__mach_exception_raise_t; | 563 &flavor, |
| 357 const Request* in_request = reinterpret_cast<const Request*>(in_header); | 564 nullptr, |
| 358 kern_return_t kr = MIGCheckRequestMachExceptionRaise(in_request); | 565 0, |
| 359 if (kr != MACH_MSG_SUCCESS) { | 566 nullptr, |
| 360 SetMIGReplyError(out_header, kr); | 567 &new_state_count, |
| 361 return true; | 568 trailer, |
| 362 } | 569 destroy_request); |
| 363 | 570 } |
| 364 using Reply = __Reply__mach_exception_raise_t; | 571 |
| 365 Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 572 kern_return_t CatchExceptionRaiseState( |
| 366 out_reply->RetCode = | 573 exception_handler_t exception_port, |
| 367 interface_->CatchMachExceptionRaise(in_header->msgh_local_port, | 574 exception_type_t exception, |
| 368 in_request->thread.name, | 575 const typename Traits::ExceptionCode* code, |
| 369 in_request->task.name, | 576 mach_msg_type_number_t code_count, |
| 370 in_request->exception, | 577 thread_state_flavor_t* flavor, |
| 371 in_request->code, | 578 const natural_t* old_state, |
| 372 in_request->codeCnt, | 579 mach_msg_type_number_t old_state_count, |
| 373 in_trailer, | 580 thread_state_t new_state, |
| 374 destroy_complex_request); | 581 mach_msg_type_number_t* new_state_count, |
| 375 if (out_reply->RetCode != KERN_SUCCESS) { | 582 const mach_msg_trailer_t* trailer) override { |
| 376 return true; | 583 bool destroy_complex_request = false; |
| 377 } | 584 return interface_->CatchException( |
| 378 | 585 Traits::kExceptionBehavior | EXCEPTION_STATE, |
| 379 out_header->msgh_size = sizeof(*out_reply); | 586 exception_port, |
| 380 return true; | 587 THREAD_NULL, |
| 588 TASK_NULL, |
| 589 exception, |
| 590 code_count ? code : nullptr, |
| 591 code_count, |
| 592 flavor, |
| 593 old_state_count ? old_state : nullptr, |
| 594 old_state_count, |
| 595 new_state_count ? new_state : nullptr, |
| 596 new_state_count, |
| 597 trailer, |
| 598 &destroy_complex_request); |
| 599 } |
| 600 |
| 601 kern_return_t CatchExceptionRaiseStateIdentity( |
| 602 exception_handler_t exception_port, |
| 603 thread_t thread, |
| 604 task_t task, |
| 605 exception_type_t exception, |
| 606 const typename Traits::ExceptionCode* code, |
| 607 mach_msg_type_number_t code_count, |
| 608 thread_state_flavor_t* flavor, |
| 609 const natural_t* old_state, |
| 610 mach_msg_type_number_t old_state_count, |
| 611 thread_state_t new_state, |
| 612 mach_msg_type_number_t* new_state_count, |
| 613 const mach_msg_trailer_t* trailer, |
| 614 bool* destroy_request) override { |
| 615 return interface_->CatchException( |
| 616 Traits::kExceptionBehavior | EXCEPTION_STATE_IDENTITY, |
| 617 exception_port, |
| 618 thread, |
| 619 task, |
| 620 exception, |
| 621 code_count ? code : nullptr, |
| 622 code_count, |
| 623 flavor, |
| 624 old_state_count ? old_state : nullptr, |
| 625 old_state_count, |
| 626 new_state_count ? new_state : nullptr, |
| 627 new_state_count, |
| 628 trailer, |
| 629 destroy_request); |
| 630 } |
| 631 |
| 632 private: |
| 633 Interface* interface_; // weak |
| 634 |
| 635 DISALLOW_COPY_AND_ASSIGN(SimplifiedExcServer); |
| 636 }; |
| 637 |
| 638 } // namespace |
| 639 |
| 640 namespace internal { |
| 641 |
| 642 class UniversalMachExcServerImpl final |
| 643 : public CompositeMachMessageServer, |
| 644 public SimplifiedExcServer<ExcTraits>::Interface, |
| 645 public SimplifiedExcServer<MachExcTraits>::Interface { |
| 646 public: |
| 647 explicit UniversalMachExcServerImpl( |
| 648 UniversalMachExcServer::Interface* interface) |
| 649 : CompositeMachMessageServer(), |
| 650 SimplifiedExcServer<ExcTraits>::Interface(), |
| 651 SimplifiedExcServer<MachExcTraits>::Interface(), |
| 652 exc_server_(this), |
| 653 mach_exc_server_(this), |
| 654 interface_(interface) { |
| 655 AddHandler(&exc_server_); |
| 656 AddHandler(&mach_exc_server_); |
| 657 } |
| 658 |
| 659 ~UniversalMachExcServerImpl() {} |
| 660 |
| 661 // SimplifiedExcServer<ExcTraits>::Interface: |
| 662 kern_return_t CatchException(exception_behavior_t behavior, |
| 663 exception_handler_t exception_port, |
| 664 thread_t thread, |
| 665 task_t task, |
| 666 exception_type_t exception, |
| 667 const exception_data_type_t* code, |
| 668 mach_msg_type_number_t code_count, |
| 669 thread_state_flavor_t* flavor, |
| 670 const natural_t* old_state, |
| 671 mach_msg_type_number_t old_state_count, |
| 672 thread_state_t new_state, |
| 673 mach_msg_type_number_t* new_state_count, |
| 674 const mach_msg_trailer_t* trailer, |
| 675 bool* destroy_complex_request) { |
| 676 std::vector<mach_exception_data_type_t> mach_codes; |
| 677 mach_codes.reserve(code_count); |
| 678 for (size_t index = 0; index < code_count; ++index) { |
| 679 mach_codes.push_back(code[index]); |
| 381 } | 680 } |
| 382 | 681 |
| 383 case kMachMessageIDMachExceptionRaiseState: { | 682 return interface_->CatchMachException(behavior, |
| 384 // mach_exception_raise_state(), catch_mach_exception_raise_state(). | 683 exception_port, |
| 385 using Request = __Request__mach_exception_raise_state_t; | 684 thread, |
| 386 const Request* in_request = reinterpret_cast<const Request*>(in_header); | 685 task, |
| 387 | 686 exception, |
| 388 // in_request_1 is used for the portion of the request after the codes, | 687 code_count ? &mach_codes[0] : nullptr, |
| 389 // which in theory can be variable-length. The check function will set it. | 688 code_count, |
| 390 const Request* in_request_1; | 689 flavor, |
| 391 kern_return_t kr = | 690 old_state_count ? old_state : nullptr, |
| 392 MIGCheckRequestMachExceptionRaiseState(in_request, &in_request_1); | 691 old_state_count, |
| 393 if (kr != MACH_MSG_SUCCESS) { | 692 new_state_count ? new_state : nullptr, |
| 394 SetMIGReplyError(out_header, kr); | 693 new_state_count, |
| 395 return true; | 694 trailer, |
| 396 } | 695 destroy_complex_request); |
| 397 | 696 } |
| 398 using Reply = __Reply__mach_exception_raise_state_t; | 697 |
| 399 Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 698 // SimplifiedExcServer<MachExcTraits>::Interface: |
| 400 out_reply->flavor = in_request_1->flavor; | 699 kern_return_t CatchException(exception_behavior_t behavior, |
| 401 out_reply->new_stateCnt = arraysize(out_reply->new_state); | 700 exception_handler_t exception_port, |
| 402 out_reply->RetCode = | 701 thread_t thread, |
| 403 interface_->CatchMachExceptionRaiseState(in_header->msgh_local_port, | 702 task_t task, |
| 404 in_request->exception, | 703 exception_type_t exception, |
| 405 in_request->code, | 704 const mach_exception_data_type_t* code, |
| 406 in_request->codeCnt, | 705 mach_msg_type_number_t code_count, |
| 407 &out_reply->flavor, | 706 thread_state_flavor_t* flavor, |
| 408 in_request_1->old_state, | 707 const natural_t* old_state, |
| 409 in_request_1->old_stateCnt, | 708 mach_msg_type_number_t old_state_count, |
| 410 out_reply->new_state, | 709 thread_state_t new_state, |
| 411 &out_reply->new_stateCnt, | 710 mach_msg_type_number_t* new_state_count, |
| 412 in_trailer); | 711 const mach_msg_trailer_t* trailer, |
| 413 if (out_reply->RetCode != KERN_SUCCESS) { | 712 bool* destroy_complex_request) { |
| 414 return true; | 713 return interface_->CatchMachException(behavior, |
| 415 } | 714 exception_port, |
| 416 | 715 thread, |
| 417 out_header->msgh_size = | 716 task, |
| 418 sizeof(*out_reply) - sizeof(out_reply->new_state) + | 717 exception, |
| 419 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; | 718 code_count ? code : nullptr, |
| 420 return true; | 719 code_count, |
| 421 } | 720 flavor, |
| 422 | 721 old_state_count ? old_state : nullptr, |
| 423 case kMachMessageIDMachExceptionRaiseStateIdentity: { | 722 old_state_count, |
| 424 // mach_exception_raise_state_identity(), | 723 new_state_count ? new_state : nullptr, |
| 425 // catch_mach_exception_raise_state_identity(). | 724 new_state_count, |
| 426 using Request = __Request__mach_exception_raise_state_identity_t; | 725 trailer, |
| 427 const Request* in_request = reinterpret_cast<const Request*>(in_header); | 726 destroy_complex_request); |
| 428 | 727 } |
| 429 // in_request_1 is used for the portion of the request after the codes, | 728 |
| 430 // which in theory can be variable-length. The check function will set it. | 729 private: |
| 431 const Request* in_request_1; | 730 SimplifiedExcServer<ExcTraits> exc_server_; |
| 432 kern_return_t kr = MIGCheckRequestMachExceptionRaiseStateIdentity( | 731 SimplifiedExcServer<MachExcTraits> mach_exc_server_; |
| 433 in_request, &in_request_1); | 732 UniversalMachExcServer::Interface* interface_; // weak |
| 434 if (kr != MACH_MSG_SUCCESS) { | 733 |
| 435 SetMIGReplyError(out_header, kr); | 734 DISALLOW_COPY_AND_ASSIGN(UniversalMachExcServerImpl); |
| 436 return true; | 735 }; |
| 437 } | |
| 438 | |
| 439 using Reply = __Reply__mach_exception_raise_state_identity_t; | |
| 440 Reply* out_reply = reinterpret_cast<Reply*>(out_header); | |
| 441 out_reply->flavor = in_request_1->flavor; | |
| 442 out_reply->new_stateCnt = arraysize(out_reply->new_state); | |
| 443 out_reply->RetCode = interface_->CatchMachExceptionRaiseStateIdentity( | |
| 444 in_header->msgh_local_port, | |
| 445 in_request->thread.name, | |
| 446 in_request->task.name, | |
| 447 in_request->exception, | |
| 448 in_request->code, | |
| 449 in_request->codeCnt, | |
| 450 &out_reply->flavor, | |
| 451 in_request_1->old_state, | |
| 452 in_request_1->old_stateCnt, | |
| 453 out_reply->new_state, | |
| 454 &out_reply->new_stateCnt, | |
| 455 in_trailer, | |
| 456 destroy_complex_request); | |
| 457 if (out_reply->RetCode != KERN_SUCCESS) { | |
| 458 return true; | |
| 459 } | |
| 460 | |
| 461 out_header->msgh_size = | |
| 462 sizeof(*out_reply) - sizeof(out_reply->new_state) + | |
| 463 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; | |
| 464 return true; | |
| 465 } | |
| 466 } | |
| 467 | |
| 468 SetMIGReplyError(out_header, MIG_BAD_ID); | |
| 469 return false; | |
| 470 } | |
| 471 | |
| 472 std::set<mach_msg_id_t> MachExcServer::MachMessageServerRequestIDs() { | |
| 473 const mach_msg_id_t request_ids[] = { | |
| 474 kMachMessageIDMachExceptionRaise, | |
| 475 kMachMessageIDMachExceptionRaiseState, | |
| 476 kMachMessageIDMachExceptionRaiseStateIdentity | |
| 477 }; | |
| 478 return std::set<mach_msg_id_t>( | |
| 479 &request_ids[0], &request_ids[arraysize(request_ids)]); | |
| 480 } | |
| 481 | |
| 482 mach_msg_size_t MachExcServer::MachMessageServerRequestSize() { | |
| 483 return sizeof(__RequestUnion__mach_exc_subsystem); | |
| 484 } | |
| 485 | |
| 486 mach_msg_size_t MachExcServer::MachMessageServerReplySize() { | |
| 487 return sizeof(__ReplyUnion__mach_exc_subsystem); | |
| 488 } | |
| 489 | |
| 490 SimplifiedExcServer::SimplifiedExcServer( | |
| 491 SimplifiedExcServer::Interface* interface) | |
| 492 : ExcServer(this), | |
| 493 ExcServer::Interface(), | |
| 494 interface_(interface) { | |
| 495 } | |
| 496 | |
| 497 kern_return_t SimplifiedExcServer::CatchExceptionRaise( | |
| 498 exception_handler_t exception_port, | |
| 499 thread_t thread, | |
| 500 task_t task, | |
| 501 exception_type_t exception, | |
| 502 const exception_data_type_t* code, | |
| 503 mach_msg_type_number_t code_count, | |
| 504 const mach_msg_trailer_t* trailer, | |
| 505 bool* destroy_request) { | |
| 506 thread_state_flavor_t flavor = THREAD_STATE_NONE; | |
| 507 mach_msg_type_number_t new_state_count = 0; | |
| 508 return interface_->CatchException(EXCEPTION_DEFAULT, | |
| 509 exception_port, | |
| 510 thread, | |
| 511 task, | |
| 512 exception, | |
| 513 code_count ? code : nullptr, | |
| 514 code_count, | |
| 515 &flavor, | |
| 516 nullptr, | |
| 517 0, | |
| 518 nullptr, | |
| 519 &new_state_count, | |
| 520 trailer, | |
| 521 destroy_request); | |
| 522 } | |
| 523 | |
| 524 kern_return_t SimplifiedExcServer::CatchExceptionRaiseState( | |
| 525 exception_handler_t exception_port, | |
| 526 exception_type_t exception, | |
| 527 const exception_data_type_t* code, | |
| 528 mach_msg_type_number_t code_count, | |
| 529 thread_state_flavor_t* flavor, | |
| 530 const natural_t* old_state, | |
| 531 mach_msg_type_number_t old_state_count, | |
| 532 thread_state_t new_state, | |
| 533 mach_msg_type_number_t* new_state_count, | |
| 534 const mach_msg_trailer_t* trailer) { | |
| 535 bool destroy_complex_request = false; | |
| 536 return interface_->CatchException(EXCEPTION_STATE, | |
| 537 exception_port, | |
| 538 THREAD_NULL, | |
| 539 TASK_NULL, | |
| 540 exception, | |
| 541 code_count ? code : nullptr, | |
| 542 code_count, | |
| 543 flavor, | |
| 544 old_state_count ? old_state : nullptr, | |
| 545 old_state_count, | |
| 546 new_state_count ? new_state : nullptr, | |
| 547 new_state_count, | |
| 548 trailer, | |
| 549 &destroy_complex_request); | |
| 550 } | |
| 551 | |
| 552 kern_return_t SimplifiedExcServer::CatchExceptionRaiseStateIdentity( | |
| 553 exception_handler_t exception_port, | |
| 554 thread_t thread, | |
| 555 task_t task, | |
| 556 exception_type_t exception, | |
| 557 const exception_data_type_t* code, | |
| 558 mach_msg_type_number_t code_count, | |
| 559 thread_state_flavor_t* flavor, | |
| 560 const natural_t* old_state, | |
| 561 mach_msg_type_number_t old_state_count, | |
| 562 thread_state_t new_state, | |
| 563 mach_msg_type_number_t* new_state_count, | |
| 564 const mach_msg_trailer_t* trailer, | |
| 565 bool* destroy_request) { | |
| 566 return interface_->CatchException(EXCEPTION_STATE_IDENTITY, | |
| 567 exception_port, | |
| 568 thread, | |
| 569 task, | |
| 570 exception, | |
| 571 code_count ? code : nullptr, | |
| 572 code_count, | |
| 573 flavor, | |
| 574 old_state_count ? old_state : nullptr, | |
| 575 old_state_count, | |
| 576 new_state_count ? new_state : nullptr, | |
| 577 new_state_count, | |
| 578 trailer, | |
| 579 destroy_request); | |
| 580 } | |
| 581 | |
| 582 SimplifiedMachExcServer::SimplifiedMachExcServer( | |
| 583 SimplifiedMachExcServer::Interface* interface) | |
| 584 : MachExcServer(this), | |
| 585 MachExcServer::Interface(), | |
| 586 interface_(interface) { | |
| 587 } | |
| 588 | |
| 589 kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaise( | |
| 590 exception_handler_t exception_port, | |
| 591 thread_t thread, | |
| 592 task_t task, | |
| 593 exception_type_t exception, | |
| 594 const mach_exception_data_type_t* code, | |
| 595 mach_msg_type_number_t code_count, | |
| 596 const mach_msg_trailer_t* trailer, | |
| 597 bool* destroy_request) { | |
| 598 thread_state_flavor_t flavor = THREAD_STATE_NONE; | |
| 599 mach_msg_type_number_t new_state_count = 0; | |
| 600 return interface_->CatchMachException( | |
| 601 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, | |
| 602 exception_port, | |
| 603 thread, | |
| 604 task, | |
| 605 exception, | |
| 606 code_count ? code : nullptr, | |
| 607 code_count, | |
| 608 &flavor, | |
| 609 nullptr, | |
| 610 0, | |
| 611 nullptr, | |
| 612 &new_state_count, | |
| 613 trailer, | |
| 614 destroy_request); | |
| 615 } | |
| 616 | |
| 617 kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseState( | |
| 618 exception_handler_t exception_port, | |
| 619 exception_type_t exception, | |
| 620 const mach_exception_data_type_t* code, | |
| 621 mach_msg_type_number_t code_count, | |
| 622 thread_state_flavor_t* flavor, | |
| 623 const natural_t* old_state, | |
| 624 mach_msg_type_number_t old_state_count, | |
| 625 thread_state_t new_state, | |
| 626 mach_msg_type_number_t* new_state_count, | |
| 627 const mach_msg_trailer_t* trailer) { | |
| 628 bool destroy_complex_request = false; | |
| 629 return interface_->CatchMachException(EXCEPTION_STATE | MACH_EXCEPTION_CODES, | |
| 630 exception_port, | |
| 631 THREAD_NULL, | |
| 632 TASK_NULL, | |
| 633 exception, | |
| 634 code_count ? code : nullptr, | |
| 635 code_count, | |
| 636 flavor, | |
| 637 old_state_count ? old_state : nullptr, | |
| 638 old_state_count, | |
| 639 new_state_count ? new_state : nullptr, | |
| 640 new_state_count, | |
| 641 trailer, | |
| 642 &destroy_complex_request); | |
| 643 } | |
| 644 | |
| 645 kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseStateIdentity( | |
| 646 exception_handler_t exception_port, | |
| 647 thread_t thread, | |
| 648 task_t task, | |
| 649 exception_type_t exception, | |
| 650 const mach_exception_data_type_t* code, | |
| 651 mach_msg_type_number_t code_count, | |
| 652 thread_state_flavor_t* flavor, | |
| 653 const natural_t* old_state, | |
| 654 mach_msg_type_number_t old_state_count, | |
| 655 thread_state_t new_state, | |
| 656 mach_msg_type_number_t* new_state_count, | |
| 657 const mach_msg_trailer_t* trailer, | |
| 658 bool* destroy_request) { | |
| 659 return interface_->CatchMachException( | |
| 660 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, | |
| 661 exception_port, | |
| 662 thread, | |
| 663 task, | |
| 664 exception, | |
| 665 code_count ? code : nullptr, | |
| 666 code_count, | |
| 667 flavor, | |
| 668 old_state_count ? old_state : nullptr, | |
| 669 old_state_count, | |
| 670 new_state_count ? new_state : nullptr, | |
| 671 new_state_count, | |
| 672 trailer, | |
| 673 destroy_request); | |
| 674 } | |
| 675 | 736 |
| 676 } // namespace internal | 737 } // namespace internal |
| 677 | 738 |
| 678 UniversalMachExcServer::UniversalMachExcServer( | 739 UniversalMachExcServer::UniversalMachExcServer( |
| 679 UniversalMachExcServer::Interface* interface) | 740 UniversalMachExcServer::Interface* interface) |
| 680 : MachMessageServer::Interface(), | 741 : MachMessageServer::Interface(), |
| 681 internal::SimplifiedExcServer::Interface(), | 742 impl_(new internal::UniversalMachExcServerImpl(interface)) { |
| 682 internal::SimplifiedMachExcServer::Interface(), | 743 } |
| 683 exc_server_(this), | 744 |
| 684 mach_exc_server_(this), | 745 UniversalMachExcServer::~UniversalMachExcServer() { |
| 685 interface_(interface) { | |
| 686 } | 746 } |
| 687 | 747 |
| 688 bool UniversalMachExcServer::MachMessageServerFunction( | 748 bool UniversalMachExcServer::MachMessageServerFunction( |
| 689 const mach_msg_header_t* in_header, | 749 const mach_msg_header_t* in_header, |
| 690 mach_msg_header_t* out_header, | 750 mach_msg_header_t* out_header, |
| 691 bool* destroy_complex_request) { | 751 bool* destroy_complex_request) { |
| 692 switch (in_header->msgh_id) { | 752 return impl_->MachMessageServerFunction( |
| 693 case kMachMessageIDMachExceptionRaise: | 753 in_header, out_header, destroy_complex_request); |
| 694 case kMachMessageIDMachExceptionRaiseState: | |
| 695 case kMachMessageIDMachExceptionRaiseStateIdentity: | |
| 696 return mach_exc_server_.MachMessageServerFunction( | |
| 697 in_header, out_header, destroy_complex_request); | |
| 698 case kMachMessageIDExceptionRaise: | |
| 699 case kMachMessageIDExceptionRaiseState: | |
| 700 case kMachMessageIDExceptionRaiseStateIdentity: | |
| 701 return exc_server_.MachMessageServerFunction( | |
| 702 in_header, out_header, destroy_complex_request); | |
| 703 } | |
| 704 | |
| 705 // Do what the MIG-generated server routines do when they can’t dispatch a | |
| 706 // message. | |
| 707 PrepareMIGReplyFromRequest(in_header, out_header); | |
| 708 SetMIGReplyError(out_header, MIG_BAD_ID); | |
| 709 return false; | |
| 710 } | 754 } |
| 711 | 755 |
| 712 std::set<mach_msg_id_t> UniversalMachExcServer::MachMessageServerRequestIDs() { | 756 std::set<mach_msg_id_t> UniversalMachExcServer::MachMessageServerRequestIDs() { |
| 713 std::set<mach_msg_id_t> request_ids = | 757 return impl_->MachMessageServerRequestIDs(); |
| 714 exc_server_.MachMessageServerRequestIDs(); | |
| 715 | |
| 716 std::set<mach_msg_id_t> mach_exc_request_ids = | |
| 717 mach_exc_server_.MachMessageServerRequestIDs(); | |
| 718 request_ids.insert(mach_exc_request_ids.begin(), mach_exc_request_ids.end()); | |
| 719 | |
| 720 return request_ids; | |
| 721 } | 758 } |
| 722 | 759 |
| 723 mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() { | 760 mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() { |
| 724 return std::max(mach_exc_server_.MachMessageServerRequestSize(), | 761 return impl_->MachMessageServerRequestSize(); |
| 725 exc_server_.MachMessageServerRequestSize()); | |
| 726 } | 762 } |
| 727 | 763 |
| 728 mach_msg_size_t UniversalMachExcServer::MachMessageServerReplySize() { | 764 mach_msg_size_t UniversalMachExcServer::MachMessageServerReplySize() { |
| 729 return std::max(mach_exc_server_.MachMessageServerReplySize(), | 765 return impl_->MachMessageServerReplySize(); |
| 730 exc_server_.MachMessageServerReplySize()); | |
| 731 } | |
| 732 | |
| 733 kern_return_t UniversalMachExcServer::CatchException( | |
| 734 exception_behavior_t behavior, | |
| 735 exception_handler_t exception_port, | |
| 736 thread_t thread, | |
| 737 task_t task, | |
| 738 exception_type_t exception, | |
| 739 const exception_data_type_t* code, | |
| 740 mach_msg_type_number_t code_count, | |
| 741 thread_state_flavor_t* flavor, | |
| 742 const natural_t* old_state, | |
| 743 mach_msg_type_number_t old_state_count, | |
| 744 thread_state_t new_state, | |
| 745 mach_msg_type_number_t* new_state_count, | |
| 746 const mach_msg_trailer_t* trailer, | |
| 747 bool* destroy_complex_request) { | |
| 748 std::vector<mach_exception_data_type_t> mach_codes; | |
| 749 mach_codes.reserve(code_count); | |
| 750 for (size_t index = 0; index < code_count; ++index) { | |
| 751 mach_codes.push_back(code[index]); | |
| 752 } | |
| 753 | |
| 754 return interface_->CatchMachException(behavior, | |
| 755 exception_port, | |
| 756 thread, | |
| 757 task, | |
| 758 exception, | |
| 759 code_count ? &mach_codes[0] : nullptr, | |
| 760 code_count, | |
| 761 flavor, | |
| 762 old_state_count ? old_state : nullptr, | |
| 763 old_state_count, | |
| 764 new_state_count ? new_state : nullptr, | |
| 765 new_state_count, | |
| 766 trailer, | |
| 767 destroy_complex_request); | |
| 768 } | |
| 769 | |
| 770 kern_return_t UniversalMachExcServer::CatchMachException( | |
| 771 exception_behavior_t behavior, | |
| 772 exception_handler_t exception_port, | |
| 773 thread_t thread, | |
| 774 task_t task, | |
| 775 exception_type_t exception, | |
| 776 const mach_exception_data_type_t* code, | |
| 777 mach_msg_type_number_t code_count, | |
| 778 thread_state_flavor_t* flavor, | |
| 779 const natural_t* old_state, | |
| 780 mach_msg_type_number_t old_state_count, | |
| 781 thread_state_t new_state, | |
| 782 mach_msg_type_number_t* new_state_count, | |
| 783 const mach_msg_trailer_t* trailer, | |
| 784 bool* destroy_complex_request) { | |
| 785 return interface_->CatchMachException(behavior, | |
| 786 exception_port, | |
| 787 thread, | |
| 788 task, | |
| 789 exception, | |
| 790 code_count ? code : nullptr, | |
| 791 code_count, | |
| 792 flavor, | |
| 793 old_state_count ? old_state : nullptr, | |
| 794 old_state_count, | |
| 795 new_state_count ? new_state : nullptr, | |
| 796 new_state_count, | |
| 797 trailer, | |
| 798 destroy_complex_request); | |
| 799 } | 766 } |
| 800 | 767 |
| 801 exception_type_t ExcCrashRecoverOriginalException( | 768 exception_type_t ExcCrashRecoverOriginalException( |
| 802 mach_exception_code_t code_0, | 769 mach_exception_code_t code_0, |
| 803 mach_exception_code_t* original_code_0, | 770 mach_exception_code_t* original_code_0, |
| 804 int* signal) { | 771 int* signal) { |
| 805 // 10.9.4 xnu-2422.110.17/bsd/kern/kern_exit.c proc_prepareexit() sets code[0] | 772 // 10.9.4 xnu-2422.110.17/bsd/kern/kern_exit.c proc_prepareexit() sets code[0] |
| 806 // based on the signal value, original exception type, and low 20 bits of the | 773 // based on the signal value, original exception type, and low 20 bits of the |
| 807 // original code[0] before calling xnu-2422.110.17/osfmk/kern/exception.c | 774 // original code[0] before calling xnu-2422.110.17/osfmk/kern/exception.c |
| 808 // task_exception_notify() to raise an EXC_CRASH. | 775 // task_exception_notify() to raise an EXC_CRASH. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 828 kern_return_t ExcServerSuccessfulReturnValue(exception_behavior_t behavior, | 795 kern_return_t ExcServerSuccessfulReturnValue(exception_behavior_t behavior, |
| 829 bool set_thread_state) { | 796 bool set_thread_state) { |
| 830 if (!set_thread_state && ExceptionBehaviorHasState(behavior)) { | 797 if (!set_thread_state && ExceptionBehaviorHasState(behavior)) { |
| 831 return MACH_RCV_PORT_DIED; | 798 return MACH_RCV_PORT_DIED; |
| 832 } | 799 } |
| 833 | 800 |
| 834 return KERN_SUCCESS; | 801 return KERN_SUCCESS; |
| 835 } | 802 } |
| 836 | 803 |
| 837 } // namespace crashpad | 804 } // namespace crashpad |
| OLD | NEW |