3333static void * FIRCLSMachExceptionServer (void * argument );
3434static bool FIRCLSMachExceptionThreadStart (FIRCLSMachExceptionReadContext * context );
3535static bool FIRCLSMachExceptionReadMessage (FIRCLSMachExceptionReadContext * context ,
36- MachExceptionProtectedMessage * message );
36+ union MachExceptionMessage * message );
3737static kern_return_t FIRCLSMachExceptionDispatchMessage (FIRCLSMachExceptionReadContext * context ,
38- MachExceptionProtectedMessage * message );
38+ union MachExceptionMessage * message );
3939static bool FIRCLSMachExceptionReply (FIRCLSMachExceptionReadContext * context ,
40- MachExceptionProtectedMessage * message ,
40+ union MachExceptionMessage * message ,
4141 kern_return_t result );
4242static bool FIRCLSMachExceptionRegister (FIRCLSMachExceptionReadContext * context );
4343static bool FIRCLSMachExceptionUnregister (FIRCLSMachExceptionOriginalPorts * originalPorts ,
44- exception_mask_t mask );
44+ exception_mask_t mask ,
45+ exception_behavior_t behavior );
4546static bool FIRCLSMachExceptionRecord (FIRCLSMachExceptionReadContext * context ,
46- MachExceptionProtectedMessage * message );
47- static void FIRCLSCrashedThreadLookup (MachExceptionProtectedMessage * message , thread_t * crashedThread );
47+ union MachExceptionMessage * message );
48+ static void FIRCLSCrashedThreadLookup (union MachExceptionMessage * message , thread_t * crashedThread );
4849#pragma mark - Initialization
4950void FIRCLSMachExceptionInit (FIRCLSMachExceptionReadContext * context ) {
5051 if (!FIRCLSUnlinkIfExists (context -> path )) {
@@ -58,7 +59,7 @@ void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context) {
5859
5960 if (!FIRCLSMachExceptionThreadStart (context )) {
6061 FIRCLSSDKLog ("Unable to start thread\n" );
61- FIRCLSMachExceptionUnregister (& context -> originalPorts , context -> mask );
62+ FIRCLSMachExceptionUnregister (& context -> originalPorts , context -> mask , context -> behavior );
6263 }
6364}
6465
@@ -166,7 +167,7 @@ static void* FIRCLSMachExceptionServer(void* argument) {
166167 pthread_setname_np ("com.google.firebase.crashlytics.MachExceptionServer" );
167168
168169 while (1 ) {
169- MachExceptionProtectedMessage message ;
170+ union MachExceptionMessage message ;
170171
171172 // read the exception message
172173 if (!FIRCLSMachExceptionReadMessage (context , & message )) {
@@ -188,13 +189,15 @@ static void* FIRCLSMachExceptionServer(void* argument) {
188189}
189190
190191static bool FIRCLSMachExceptionReadMessage (FIRCLSMachExceptionReadContext * context ,
191- MachExceptionProtectedMessage * message ) {
192+ union MachExceptionMessage * message ) {
192193 mach_msg_return_t r ;
193194
194- memset (message , 0 , sizeof (MachExceptionProtectedMessage ));
195+ memset (message , 0 , sizeof (union MachExceptionMessage ));
195196
196- r = mach_msg (& message -> head , MACH_RCV_MSG | MACH_RCV_LARGE , 0 , sizeof (MachExceptionProtectedMessage ),
197+ // no need if condition here since head structure for union MachExceptionMessage is the same.
198+ r = mach_msg (& message -> default_message .head , MACH_RCV_MSG | MACH_RCV_LARGE , 0 , sizeof (union MachExceptionMessage ),
197199 context -> port , MACH_MSG_TIMEOUT_NONE , MACH_PORT_NULL );
200+
198201 if (r != MACH_MSG_SUCCESS ) {
199202 FIRCLSSDKLog ("Error receiving mach_msg (%d)\n" , r );
200203 return false;
@@ -206,33 +209,43 @@ static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* conte
206209}
207210
208211static kern_return_t FIRCLSMachExceptionDispatchMessage (FIRCLSMachExceptionReadContext * context ,
209- MachExceptionProtectedMessage * message ) {
210- FIRCLSSDKLog ("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n" , message -> exception ,
211- message -> codeCnt , message -> codeCnt > 0 ? message -> code [0 ] : -1 ,
212- message -> codeCnt > 1 ? message -> code [1 ] : -1 );
213-
214- // This will happen if a child process raises an exception, as the exception ports are
215- // inherited.
216- mach_port_t actual_port ;
212+ union MachExceptionMessage * message ) {
217213 kern_return_t kr ;
218- task_id_token_t token = message -> task_id_token_t .name ;
219- kr = task_identity_token_get_task_port (token , TASK_FLAVOR_CONTROL , & actual_port );
220214
221- if (kr != KERN_SUCCESS ) {
222- FIRCLSSDKLog ("Could not find task from task id token. returning failure\n" );
223- return KERN_FAILURE ;
224- }
215+ if (context -> behavior == EXCEPTION_DEFAULT ) {
216+ FIRCLSSDKLog ("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n" , message -> default_message .exception ,
217+ message -> default_message .codeCnt , message -> default_message .codeCnt > 0 ? message -> default_message .code [0 ] : -1 ,
218+ message -> default_message .codeCnt > 1 ? message -> default_message .code [1 ] : -1 );
219+ if (message -> default_message .task .name != mach_task_self ()) {
220+ FIRCLSSDKLog ("Mach exception task mis-match, returning failure\n" );
221+ return KERN_FAILURE ;
222+ }
223+ } else {
224+ FIRCLSSDKLog ("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n" , message -> protected_message .exception ,
225+ message -> protected_message .codeCnt , message -> protected_message .codeCnt > 0 ? message -> protected_message .code [0 ] : -1 ,
226+ message -> protected_message .codeCnt > 1 ? message -> protected_message .code [1 ] : -1 );
225227
226- const bool is_mismatch = (actual_port != mach_task_self ());
227- mach_port_deallocate (mach_task_self (), actual_port );
228+ // This will happen if a child process raises an exception, as the exception ports are
229+ // inherited.
230+ mach_port_t actual_port ;
231+ task_id_token_t token = message -> protected_message .task_id_token_t .name ;
232+ kr = task_identity_token_get_task_port (token , TASK_FLAVOR_CONTROL , & actual_port );
228233
229- if (is_mismatch ) {
230- FIRCLSSDKLog ("Mach exception task mis-match, returning failure\n" );
231- return KERN_FAILURE ;
234+ if (kr != KERN_SUCCESS ) {
235+ FIRCLSSDKLog ("Could not find task from task id token. returning failure\n" );
236+ return KERN_FAILURE ;
237+ }
238+ const bool is_mismatch = (actual_port != mach_task_self ());
239+ mach_port_deallocate (mach_task_self (), actual_port );
240+
241+ if (is_mismatch ) {
242+ FIRCLSSDKLog ("Mach exception task mis-match, returning failure\n" );
243+ return KERN_FAILURE ;
244+ }
232245 }
233246
234247 FIRCLSSDKLog ("Unregistering handler\n" );
235- if (!FIRCLSMachExceptionUnregister (& context -> originalPorts , context -> mask )) {
248+ if (!FIRCLSMachExceptionUnregister (& context -> originalPorts , context -> mask , context -> behavior )) {
236249 FIRCLSSDKLog ("Failed to unregister\n" );
237250 return KERN_FAILURE ;
238251 }
@@ -253,17 +266,17 @@ static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadC
253266}
254267
255268static bool FIRCLSMachExceptionReply (FIRCLSMachExceptionReadContext * context ,
256- MachExceptionProtectedMessage * message ,
269+ union MachExceptionMessage * message ,
257270 kern_return_t result ) {
258271 MachExceptionReply reply ;
259272 mach_msg_return_t r ;
260273
261274 // prepare the reply
262- reply .head .msgh_bits = MACH_MSGH_BITS (MACH_MSGH_BITS_REMOTE (message -> head .msgh_bits ), 0 );
263- reply .head .msgh_remote_port = message -> head .msgh_remote_port ;
275+ reply .head .msgh_bits = MACH_MSGH_BITS (MACH_MSGH_BITS_REMOTE (message -> default_message . head .msgh_bits ), 0 );
276+ reply .head .msgh_remote_port = message -> default_message . head .msgh_remote_port ;
264277 reply .head .msgh_size = (mach_msg_size_t )sizeof (MachExceptionReply );
265278 reply .head .msgh_local_port = MACH_PORT_NULL ;
266- reply .head .msgh_id = message -> head .msgh_id + 100 ;
279+ reply .head .msgh_id = message -> default_message . head .msgh_id + 100 ;
267280
268281 reply .NDR = NDR_record ;
269282
@@ -309,7 +322,7 @@ static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context)
309322
310323 // ORing with MACH_EXCEPTION_CODES will produce 64-bit exception data
311324 kr = task_swap_exception_ports (task , context -> mask , context -> port ,
312- EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES , THREAD_STATE_NONE ,
325+ context -> behavior | MACH_EXCEPTION_CODES , THREAD_STATE_NONE ,
313326 context -> originalPorts .masks , & context -> originalPorts .count ,
314327 context -> originalPorts .ports , context -> originalPorts .behaviors ,
315328 context -> originalPorts .flavors );
@@ -328,7 +341,8 @@ static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context)
328341}
329342
330343static bool FIRCLSMachExceptionUnregister (FIRCLSMachExceptionOriginalPorts * originalPorts ,
331- exception_mask_t mask ) {
344+ exception_mask_t mask ,
345+ exception_behavior_t behavior ) {
332346 kern_return_t kr ;
333347
334348 // Re-register all the old ports.
@@ -346,7 +360,7 @@ static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* orig
346360
347361 // Finally, mark any masks we registered for that do not have an original port as unused.
348362 kr = task_set_exception_ports (mach_task_self (), mask , MACH_PORT_NULL ,
349- EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES , THREAD_STATE_NONE );
363+ behavior | MACH_EXCEPTION_CODES , THREAD_STATE_NONE );
350364 if (kr != KERN_SUCCESS ) {
351365 FIRCLSSDKLog ("unable to unset unregistered mask: 0x%x" , mask );
352366 return false;
@@ -485,7 +499,7 @@ void FIRCLSMachExceptionNameLookup(exception_type_t number,
485499}
486500
487501static bool FIRCLSMachExceptionRecord (FIRCLSMachExceptionReadContext * context ,
488- MachExceptionProtectedMessage * message ) {
502+ union MachExceptionMessage * message ) {
489503 if (!context || !message ) {
490504 return false;
491505 }
@@ -507,21 +521,34 @@ static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
507521
508522 FIRCLSFileWriteHashStart (& file );
509523
510- FIRCLSFileWriteHashEntryUint64 (& file , "exception" , message -> exception );
524+ exception_type_t exception ;
525+ mach_msg_type_number_t codeCnt ;
526+ mach_exception_data_type_t * code ;
527+
528+ if (context -> behavior == EXCEPTION_DEFAULT ) {
529+ exception = message -> default_message .exception ;
530+ codeCnt = message -> default_message .codeCnt ;
531+ code = message -> default_message .code ;
532+ } else {
533+ exception = message -> protected_message .exception ;
534+ codeCnt = message -> protected_message .codeCnt ;
535+ code = message -> protected_message .code ;
536+ }
537+
538+ FIRCLSFileWriteHashEntryUint64 (& file , "exception" , exception );
511539
512540 // record the codes
513541 FIRCLSFileWriteHashKey (& file , "codes" );
514542 FIRCLSFileWriteArrayStart (& file );
515- for (mach_msg_type_number_t i = 0 ; i < message -> codeCnt ; ++ i ) {
516- FIRCLSFileWriteArrayEntryUint64 (& file , message -> code [i ]);
543+ for (mach_msg_type_number_t i = 0 ; i < codeCnt ; ++ i ) {
544+ FIRCLSFileWriteArrayEntryUint64 (& file , code [i ]);
517545 }
518546 FIRCLSFileWriteArrayEnd (& file );
519547
520548 const char * name = NULL ;
521549 const char * codeName = NULL ;
522550
523- FIRCLSMachExceptionNameLookup (message -> exception , message -> codeCnt > 0 ? message -> code [0 ] : 0 ,
524- & name , & codeName );
551+ FIRCLSMachExceptionNameLookup (exception , codeCnt > 0 ? code [0 ] : 0 , & name , & codeName );
525552
526553 FIRCLSFileWriteHashEntryString (& file , "name" , name );
527554 FIRCLSFileWriteHashEntryString (& file , "code_name" , codeName );
@@ -534,7 +561,11 @@ static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
534561 FIRCLSFileWriteSectionEnd (& file );
535562
536563 thread_t crashedThread = THREAD_NULL ;
537- FIRCLSCrashedThreadLookup (message , & crashedThread );
564+ if (context -> behavior == EXCEPTION_DEFAULT ) {
565+ crashedThread = message -> default_message .thread .name ;
566+ } else {
567+ FIRCLSCrashedThreadLookup (message , & crashedThread );
568+ }
538569 FIRCLSSDKLog ("Crashed threads: %d\n" , crashedThread );
539570 FIRCLSHandler (& file , crashedThread , NULL , true);
540571 if (crashedThread != THREAD_NULL ) {
@@ -545,7 +576,7 @@ static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
545576 return true;
546577}
547578
548- static void FIRCLSCrashedThreadLookup (MachExceptionProtectedMessage * message , thread_t * crashedThread ) {
579+ static void FIRCLSCrashedThreadLookup (union MachExceptionMessage * message , thread_t * crashedThread ) {
549580 thread_act_array_t threadList ;
550581 mach_msg_type_number_t threadCount ;
551582
@@ -564,7 +595,7 @@ static void FIRCLSCrashedThreadLookup(MachExceptionProtectedMessage* message, th
564595
565596 if (kr == KERN_SUCCESS ) {
566597 FIRCLSSDKLog ("Thread %d: Thread port: %d, thread id: %llx\n" , i , threadList [i ], identifierInfo .thread_id );
567- if (message -> thread_id == identifierInfo .thread_id ) {
598+ if (message -> protected_message . thread_id == identifierInfo .thread_id ) {
568599 FIRCLSSDKLog ("Find crashed thread: %d\n" , threadList [i ]);
569600 * crashedThread = threadList [i ];
570601 break ;
0 commit comments