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 |