Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: util/mach/exc_server_variants.cc

Issue 545053003: Add exc_server_variants including UniversalMachExcServer and its test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Include live tests of crashing children Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/mach/exc_server_variants.h"
16
17 #include <algorithm>
18 #include <vector>
19
20 #include "base/basictypes.h"
21 #include "base/logging.h"
22 #include "util/mach/exc.h"
23 #include "util/mach/excServer.h"
24 #include "util/mach/mach_exc.h"
25 #include "util/mach/mach_excServer.h"
26
27 extern "C" {
28
29 // These six functions are not used, and are in fact obsoleted by the other
30 // functionality implemented in this file. The standard MIG-generated exc_server
31 // (in excServer.c) and mach_exc_server (in mach_excServer.c) server dispatch
32 // routines usable with the standard mach_msg_server() function call out to
33 // these functions. exc_server() and mach_exc_server() are unused and are
34 // replaced by the more flexible ExcServer and MachExcServer, but the linker
35 // still needs to see these six function definitions.
36
37 kern_return_t catch_exception_raise(exception_handler_t exception_port,
38 thread_t thread,
39 task_t task,
40 exception_type_t exception,
41 exception_data_t code,
42 mach_msg_type_number_t code_count) {
43 NOTREACHED();
44 return KERN_FAILURE;
45 }
46
47 kern_return_t catch_exception_raise_state(
48 exception_handler_t exception_port,
49 exception_type_t exception,
50 exception_data_t code,
51 mach_msg_type_number_t code_count,
52 thread_state_flavor_t* flavor,
53 thread_state_t old_state,
54 mach_msg_type_number_t old_state_count,
55 thread_state_t new_state,
56 mach_msg_type_number_t* new_state_count) {
57 NOTREACHED();
58 return KERN_FAILURE;
59 }
60
61 kern_return_t catch_exception_raise_state_identity(
62 exception_handler_t exception_port,
63 thread_t thread,
64 task_t task,
65 exception_type_t exception,
66 exception_data_t code,
67 mach_msg_type_number_t code_count,
68 thread_state_flavor_t* flavor,
69 thread_state_t old_state,
70 mach_msg_type_number_t old_state_count,
71 thread_state_t new_state,
72 mach_msg_type_number_t* new_state_count) {
73 NOTREACHED();
74 return KERN_FAILURE;
75 }
76
77 kern_return_t catch_mach_exception_raise(exception_handler_t exception_port,
78 thread_t thread,
79 task_t task,
80 exception_type_t exception,
81 mach_exception_data_t code,
82 mach_msg_type_number_t code_count) {
83 NOTREACHED();
84 return KERN_FAILURE;
85 }
86
87 kern_return_t catch_mach_exception_raise_state(
88 exception_handler_t exception_port,
89 exception_type_t exception,
90 mach_exception_data_t code,
91 mach_msg_type_number_t code_count,
92 thread_state_flavor_t* flavor,
93 thread_state_t old_state,
94 mach_msg_type_number_t old_state_count,
95 thread_state_t new_state,
96 mach_msg_type_number_t* new_state_count) {
97 NOTREACHED();
98 return KERN_FAILURE;
99 }
100
101 kern_return_t catch_mach_exception_raise_state_identity(
102 exception_handler_t exception_port,
103 thread_t thread,
104 task_t task,
105 exception_type_t exception,
106 mach_exception_data_t code,
107 mach_msg_type_number_t code_count,
108 thread_state_flavor_t* flavor,
109 thread_state_t old_state,
110 mach_msg_type_number_t old_state_count,
111 thread_state_t new_state,
112 mach_msg_type_number_t* new_state_count) {
113 NOTREACHED();
114 return KERN_FAILURE;
115 }
116
117 } // extern "C"
118
119 namespace {
120
121 void PrepareReplyFromRequest(const mach_msg_header_t* in_header,
122 mach_msg_header_t* out_header) {
123 out_header->msgh_bits =
124 MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(in_header->msgh_bits), 0);
125 out_header->msgh_remote_port = in_header->msgh_remote_port;
126 out_header->msgh_size = sizeof(mig_reply_error_t);
127 out_header->msgh_local_port = MACH_PORT_NULL;
128 out_header->msgh_id = in_header->msgh_id + 100;
129 reinterpret_cast<mig_reply_error_t*>(out_header)->NDR = NDR_record;
130 }
131
132 void SetReplyError(mach_msg_header_t* out_header, kern_return_t error) {
133 reinterpret_cast<mig_reply_error_t*>(out_header)->RetCode = error;
134 }
135
136 // There are no predefined constants for these.
137 enum MachMessageID : mach_msg_id_t {
138 kMachMessageIDExceptionRaise = 2401,
139 kMachMessageIDExceptionRaiseState = 2402,
140 kMachMessageIDExceptionRaiseStateIdentity = 2403,
141 kMachMessageIDMachExceptionRaise = 2405,
142 kMachMessageIDMachExceptionRaiseState = 2406,
143 kMachMessageIDMachExceptionRaiseStateIdentity = 2407,
144 };
145
146 } // namespace
147
148 namespace crashpad {
149
150 ExcServer::ExcServer(ExcServer::Interface* interface)
151 : MachMessageServer::Interface(),
152 interface_(interface) {
153 }
154
155 bool ExcServer::MachMessageServerFunction(mach_msg_header_t* in_header,
156 mach_msg_header_t* out_header,
157 bool* destroy_complex_request) {
158 PrepareReplyFromRequest(in_header, out_header);
159
160 switch (in_header->msgh_id) {
161 case kMachMessageIDExceptionRaise: {
162 // exception_raise(), catch_exception_raise().
163 typedef __Request__exception_raise_t Request;
164 Request* in_request = reinterpret_cast<Request*>(in_header);
165 kern_return_t kr = __MIG_check__Request__exception_raise_t(in_request);
166 if (kr != MACH_MSG_SUCCESS) {
167 SetReplyError(out_header, kr);
168 return true;
169 }
170
171 typedef __Reply__exception_raise_t Reply;
172 Reply* out_reply = reinterpret_cast<Reply*>(out_header);
173 out_reply->RetCode =
Robert Sesek 2014/09/10 16:44:41 Is out_reply->msgh_size correct here? (Right now i
Mark Mentovai 2014/09/10 20:12:56 rsesek wrote:
174 interface_->CatchExceptionRaise(in_header->msgh_local_port,
175 in_request->thread.name,
176 in_request->task.name,
177 in_request->exception,
178 in_request->code,
179 in_request->codeCnt,
180 destroy_complex_request);
181 return true;
182 }
183
184 case kMachMessageIDExceptionRaiseState: {
185 // exception_raise_state(), catch_exception_raise_state().
186 typedef __Request__exception_raise_state_t Request;
187 Request* in_request = reinterpret_cast<Request*>(in_header);
188 Request* in_request_1;
Robert Sesek 2014/09/10 16:44:41 Don't really know what in_request_1 is.
189 kern_return_t kr = __MIG_check__Request__exception_raise_state_t(
190 in_request, &in_request_1);
191 if (kr != MACH_MSG_SUCCESS) {
192 SetReplyError(out_header, kr);
193 return true;
194 }
195
196 typedef __Reply__exception_raise_state_t Reply;
197 Reply* out_reply = reinterpret_cast<Reply*>(out_header);
198 out_reply->new_stateCnt = arraysize(out_reply->new_state);
199 out_reply->RetCode =
200 interface_->CatchExceptionRaiseState(in_header->msgh_local_port,
201 in_request->exception,
202 in_request->code,
203 in_request->codeCnt,
204 &in_request_1->flavor,
205 in_request_1->old_state,
206 in_request_1->old_stateCnt,
207 out_reply->new_state,
208 &out_reply->new_stateCnt);
209 if (out_reply->RetCode != KERN_SUCCESS) {
210 return true;
211 }
212
213 out_reply->flavor = in_request_1->flavor;
214 out_header->msgh_size =
215 sizeof(*out_reply) - sizeof(out_reply->new_state) +
216 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
217 return true;
218 }
219
220 case kMachMessageIDExceptionRaiseStateIdentity: {
221 // exception_raise_state_identity(),
222 // catch_exception_raise_state_identity().
223 typedef __Request__exception_raise_state_identity_t Request;
224 Request* in_request = reinterpret_cast<Request*>(in_header);
225 Request* in_request_1;
226 kern_return_t kr = __MIG_check__Request__exception_raise_state_identity_t(
227 in_request, &in_request_1);
228 if (kr != MACH_MSG_SUCCESS) {
229 SetReplyError(out_header, kr);
230 return true;
231 }
232
233 typedef __Reply__exception_raise_state_identity_t Reply;
234 Reply* out_reply = reinterpret_cast<Reply*>(out_header);
235 out_reply->new_stateCnt = arraysize(out_reply->new_state);
236 out_reply->RetCode = interface_->CatchExceptionRaiseStateIdentity(
237 in_header->msgh_local_port,
238 in_request->thread.name,
239 in_request->task.name,
240 in_request->exception,
241 in_request->code,
242 in_request->codeCnt,
243 &in_request_1->flavor,
244 in_request_1->old_state,
245 in_request_1->old_stateCnt,
246 out_reply->new_state,
247 &out_reply->new_stateCnt,
248 destroy_complex_request);
249 if (out_reply->RetCode != KERN_SUCCESS) {
250 return true;
251 }
252
253 out_reply->flavor = in_request_1->flavor;
254 out_header->msgh_size =
255 sizeof(*out_reply) - sizeof(out_reply->new_state) +
256 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
257 return true;
258 }
259 }
260
261 SetReplyError(out_header, MIG_BAD_ID);
262 return false;
263 }
264
265 mach_msg_size_t ExcServer::MachMessageServerRequestSize() {
266 return sizeof(__RequestUnion__exc_subsystem);
267 }
268
269 mach_msg_size_t ExcServer::MachMessageServerReplySize() {
270 return sizeof(__ReplyUnion__exc_subsystem);
271 }
272
273 MachExcServer::MachExcServer(MachExcServer::Interface* interface)
274 : MachMessageServer::Interface(),
275 interface_(interface) {
276 }
277
278 bool MachExcServer::MachMessageServerFunction(mach_msg_header_t* in_header,
279 mach_msg_header_t* out_header,
280 bool* destroy_complex_request) {
281 PrepareReplyFromRequest(in_header, out_header);
282
283 switch (in_header->msgh_id) {
284 case kMachMessageIDMachExceptionRaise: {
285 // mach_exception_raise(), catch_mach_exception_raise().
286 typedef __Request__mach_exception_raise_t Request;
287 Request* in_request = reinterpret_cast<Request*>(in_header);
288 kern_return_t kr =
289 __MIG_check__Request__mach_exception_raise_t(in_request);
290 if (kr != MACH_MSG_SUCCESS) {
291 SetReplyError(out_header, kr);
292 return true;
293 }
294
295 typedef __Reply__mach_exception_raise_t Reply;
296 Reply* out_reply = reinterpret_cast<Reply*>(out_header);
297 out_reply->RetCode =
298 interface_->CatchMachExceptionRaise(in_header->msgh_local_port,
299 in_request->thread.name,
300 in_request->task.name,
301 in_request->exception,
302 in_request->code,
303 in_request->codeCnt,
304 destroy_complex_request);
305 return true;
306 }
307
308 case kMachMessageIDMachExceptionRaiseState: {
309 // mach_exception_raise_state(), catch_mach_exception_raise_state().
310 typedef __Request__mach_exception_raise_state_t Request;
311 Request* in_request = reinterpret_cast<Request*>(in_header);
312 Request* in_request_1;
313 kern_return_t kr = __MIG_check__Request__mach_exception_raise_state_t(
314 in_request, &in_request_1);
315 if (kr != MACH_MSG_SUCCESS) {
316 SetReplyError(out_header, kr);
317 return true;
318 }
319
320 typedef __Reply__mach_exception_raise_state_t Reply;
321 Reply* out_reply = reinterpret_cast<Reply*>(out_header);
322 out_reply->new_stateCnt = arraysize(out_reply->new_state);
323 out_reply->RetCode =
324 interface_->CatchMachExceptionRaiseState(in_header->msgh_local_port,
325 in_request->exception,
326 in_request->code,
327 in_request->codeCnt,
328 &in_request_1->flavor,
329 in_request_1->old_state,
330 in_request_1->old_stateCnt,
331 out_reply->new_state,
332 &out_reply->new_stateCnt);
333 if (out_reply->RetCode != KERN_SUCCESS) {
334 return true;
335 }
336
337 out_reply->flavor = in_request_1->flavor;
338 out_header->msgh_size =
339 sizeof(*out_reply) - sizeof(out_reply->new_state) +
340 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
341 return true;
342 }
343
344 case kMachMessageIDMachExceptionRaiseStateIdentity: {
345 // mach_exception_raise_state_identity(),
346 // catch_mach_exception_raise_state_identity().
347 typedef __Request__mach_exception_raise_state_identity_t Request;
348 Request* in_request = reinterpret_cast<Request*>(in_header);
349 Request* in_request_1;
350 kern_return_t kr =
351 __MIG_check__Request__mach_exception_raise_state_identity_t(
352 in_request, &in_request_1);
353 if (kr != MACH_MSG_SUCCESS) {
354 SetReplyError(out_header, kr);
355 return true;
356 }
357
358 typedef __Reply__mach_exception_raise_state_identity_t Reply;
359 Reply* out_reply = reinterpret_cast<Reply*>(out_header);
360 out_reply->new_stateCnt = arraysize(out_reply->new_state);
361 out_reply->RetCode = interface_->CatchMachExceptionRaiseStateIdentity(
362 in_header->msgh_local_port,
363 in_request->thread.name,
364 in_request->task.name,
365 in_request->exception,
366 in_request->code,
367 in_request->codeCnt,
368 &in_request_1->flavor,
369 in_request_1->old_state,
370 in_request_1->old_stateCnt,
371 out_reply->new_state,
372 &out_reply->new_stateCnt,
373 destroy_complex_request);
374 if (out_reply->RetCode != KERN_SUCCESS) {
375 return true;
376 }
377
378 out_reply->flavor = in_request_1->flavor;
379 out_header->msgh_size =
380 sizeof(*out_reply) - sizeof(out_reply->new_state) +
381 sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
382 return true;
383 }
384 }
385
386 SetReplyError(out_header, MIG_BAD_ID);
387 return false;
388 }
389
390 mach_msg_size_t MachExcServer::MachMessageServerRequestSize() {
391 return sizeof(__RequestUnion__mach_exc_subsystem);
392 }
393
394 mach_msg_size_t MachExcServer::MachMessageServerReplySize() {
395 return sizeof(__ReplyUnion__mach_exc_subsystem);
396 }
397
398 SimplifiedExcServer::SimplifiedExcServer(
399 SimplifiedExcServer::Interface* interface)
400 : ExcServer(this),
401 ExcServer::Interface(),
402 interface_(interface) {
403 }
404
405 kern_return_t SimplifiedExcServer::CatchExceptionRaise(
406 exception_handler_t exception_port,
407 thread_t thread,
408 task_t task,
409 exception_type_t exception,
410 const exception_data_type_t* code,
411 mach_msg_type_number_t code_count,
412 bool* destroy_request) {
413 thread_state_flavor_t flavor = THREAD_STATE_NONE;
414 mach_msg_type_number_t new_state_count = 0;
415 return interface_->CatchException(EXCEPTION_DEFAULT,
416 exception_port,
417 thread,
418 task,
419 exception,
420 code,
421 code_count,
422 &flavor,
423 NULL,
424 0,
425 NULL,
426 &new_state_count,
427 destroy_request);
428 }
429
430 kern_return_t SimplifiedExcServer::CatchExceptionRaiseState(
431 exception_handler_t exception_port,
432 exception_type_t exception,
433 const exception_data_type_t* code,
434 mach_msg_type_number_t code_count,
435 thread_state_flavor_t* flavor,
436 const natural_t* old_state,
437 mach_msg_type_number_t old_state_count,
438 thread_state_t new_state,
439 mach_msg_type_number_t* new_state_count) {
440 bool destroy_complex_request = false;
441 return interface_->CatchException(EXCEPTION_STATE,
442 exception_port,
443 MACH_PORT_NULL,
444 MACH_PORT_NULL,
445 exception,
446 code,
447 code_count,
448 flavor,
449 old_state,
450 old_state_count,
451 new_state,
452 new_state_count,
453 &destroy_complex_request);
454 }
455
456 kern_return_t SimplifiedExcServer::CatchExceptionRaiseStateIdentity(
457 exception_handler_t exception_port,
458 thread_t thread,
459 task_t task,
460 exception_type_t exception,
461 const exception_data_type_t* code,
462 mach_msg_type_number_t code_count,
463 thread_state_flavor_t* flavor,
464 const natural_t* old_state,
465 mach_msg_type_number_t old_state_count,
466 thread_state_t new_state,
467 mach_msg_type_number_t* new_state_count,
468 bool* destroy_request) {
469 return interface_->CatchException(EXCEPTION_STATE_IDENTITY,
470 exception_port,
471 thread,
472 task,
473 exception,
474 code,
475 code_count,
476 flavor,
477 old_state,
478 old_state_count,
479 new_state,
480 new_state_count,
481 destroy_request);
482 }
483
484 SimplifiedMachExcServer::SimplifiedMachExcServer(
485 SimplifiedMachExcServer::Interface* interface)
486 : MachExcServer(this),
487 MachExcServer::Interface(),
488 interface_(interface) {
489 }
490
491 kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaise(
492 exception_handler_t exception_port,
493 thread_t thread,
494 task_t task,
495 exception_type_t exception,
496 const mach_exception_data_type_t* code,
497 mach_msg_type_number_t code_count,
498 bool* destroy_request) {
499 thread_state_flavor_t flavor = THREAD_STATE_NONE;
500 mach_msg_type_number_t new_state_count = 0;
501 return interface_->CatchMachException(
502 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
503 exception_port,
504 thread,
505 task,
506 exception,
507 code,
508 code_count,
509 &flavor,
510 NULL,
511 0,
512 NULL,
513 &new_state_count,
514 destroy_request);
515 }
516
517 kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseState(
518 exception_handler_t exception_port,
519 exception_type_t exception,
520 const mach_exception_data_type_t* code,
521 mach_msg_type_number_t code_count,
522 thread_state_flavor_t* flavor,
523 const natural_t* old_state,
524 mach_msg_type_number_t old_state_count,
525 thread_state_t new_state,
526 mach_msg_type_number_t* new_state_count) {
527 bool destroy_complex_request = false;
528 return interface_->CatchMachException(EXCEPTION_STATE | MACH_EXCEPTION_CODES,
529 exception_port,
530 MACH_PORT_NULL,
531 MACH_PORT_NULL,
532 exception,
533 code,
534 code_count,
535 flavor,
536 old_state,
537 old_state_count,
538 new_state,
539 new_state_count,
540 &destroy_complex_request);
541 }
542
543 kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseStateIdentity(
544 exception_handler_t exception_port,
545 thread_t thread,
546 task_t task,
547 exception_type_t exception,
548 const mach_exception_data_type_t* code,
549 mach_msg_type_number_t code_count,
550 thread_state_flavor_t* flavor,
551 const natural_t* old_state,
552 mach_msg_type_number_t old_state_count,
553 thread_state_t new_state,
554 mach_msg_type_number_t* new_state_count,
555 bool* destroy_request) {
556 return interface_->CatchMachException(
557 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
558 exception_port,
559 thread,
560 task,
561 exception,
562 code,
563 code_count,
564 flavor,
565 old_state,
566 old_state_count,
567 new_state,
568 new_state_count,
569 destroy_request);
570 }
571
572 UniversalMachExcServer::UniversalMachExcServer()
573 : MachMessageServer::Interface(),
574 SimplifiedExcServer::Interface(),
575 SimplifiedMachExcServer::Interface(),
576 exc_server_(this),
577 mach_exc_server_(this) {
578 }
579
580 bool UniversalMachExcServer::MachMessageServerFunction(
581 mach_msg_header_t* in_header,
582 mach_msg_header_t* out_header,
583 bool* destroy_complex_request) {
584 switch (in_header->msgh_id) {
585 case kMachMessageIDMachExceptionRaise:
586 case kMachMessageIDMachExceptionRaiseState:
587 case kMachMessageIDMachExceptionRaiseStateIdentity:
588 return mach_exc_server_.MachMessageServerFunction(
589 in_header, out_header, destroy_complex_request);
590 case kMachMessageIDExceptionRaise:
591 case kMachMessageIDExceptionRaiseState:
592 case kMachMessageIDExceptionRaiseStateIdentity:
593 return exc_server_.MachMessageServerFunction(
594 in_header, out_header, destroy_complex_request);
595 }
596
597 // Do what the MIG-generated server routines do when they can’t dispatch a
598 // message.
599 PrepareReplyFromRequest(in_header, out_header);
600 SetReplyError(out_header, MIG_BAD_ID);
601 return false;
602 }
603
604 mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() {
605 return std::max(mach_exc_server_.MachMessageServerRequestSize(),
606 exc_server_.MachMessageServerRequestSize());
607 }
608
609 mach_msg_size_t UniversalMachExcServer::MachMessageServerReplySize() {
610 return std::max(mach_exc_server_.MachMessageServerReplySize(),
611 exc_server_.MachMessageServerReplySize());
612 }
613
614 kern_return_t UniversalMachExcServer::CatchException(
615 exception_behavior_t behavior,
616 exception_handler_t exception_port,
617 thread_t thread,
618 task_t task,
619 exception_type_t exception,
620 const 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 bool* destroy_complex_request) {
628 std::vector<mach_exception_data_type_t> mach_codes;
Robert Sesek 2014/09/10 16:44:41 Reserve code_count space?
629 for (size_t index = 0; index < code_count; ++index) {
630 mach_codes.push_back(code[index]);
631 }
632
633 return CatchMachException(behavior,
634 exception_port,
635 thread,
636 task,
637 exception,
638 code_count ? &mach_codes[0] : NULL,
639 code_count,
640 flavor,
641 old_state,
642 old_state_count,
643 new_state,
644 new_state_count,
645 destroy_complex_request);
646 }
647
648 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698