3333static void * FIRCLSMachExceptionServer (void * argument );
3434static bool FIRCLSMachExceptionThreadStart (FIRCLSMachExceptionReadContext * context );
3535static bool FIRCLSMachExceptionReadMessage (FIRCLSMachExceptionReadContext * context ,
36- MachExceptionMessage * message );
36+ MachExceptionProtectedMessage * message );
3737static kern_return_t FIRCLSMachExceptionDispatchMessage (FIRCLSMachExceptionReadContext * context ,
38- MachExceptionMessage * message );
38+ MachExceptionProtectedMessage * message );
3939static bool FIRCLSMachExceptionReply (FIRCLSMachExceptionReadContext * context ,
40- MachExceptionMessage * message ,
40+ MachExceptionProtectedMessage * message ,
4141 kern_return_t result );
4242static bool FIRCLSMachExceptionRegister (FIRCLSMachExceptionReadContext * context );
4343static bool FIRCLSMachExceptionUnregister (FIRCLSMachExceptionOriginalPorts * originalPorts ,
4444 exception_mask_t mask );
4545static bool FIRCLSMachExceptionRecord (FIRCLSMachExceptionReadContext * context ,
46- MachExceptionMessage * message );
47-
46+ MachExceptionProtectedMessage * message );
47+ static void FIRCLSCrashedThreadLookup ( MachExceptionProtectedMessage * message , thread_t * crashedThread );
4848#pragma mark - Initialization
4949void FIRCLSMachExceptionInit (FIRCLSMachExceptionReadContext * context ) {
5050 if (!FIRCLSUnlinkIfExists (context -> path )) {
@@ -166,7 +166,7 @@ static void* FIRCLSMachExceptionServer(void* argument) {
166166 pthread_setname_np ("com.google.firebase.crashlytics.MachExceptionServer" );
167167
168168 while (1 ) {
169- MachExceptionMessage message ;
169+ MachExceptionProtectedMessage message ;
170170
171171 // read the exception message
172172 if (!FIRCLSMachExceptionReadMessage (context , & message )) {
@@ -188,12 +188,12 @@ static void* FIRCLSMachExceptionServer(void* argument) {
188188}
189189
190190static bool FIRCLSMachExceptionReadMessage (FIRCLSMachExceptionReadContext * context ,
191- MachExceptionMessage * message ) {
191+ MachExceptionProtectedMessage * message ) {
192192 mach_msg_return_t r ;
193193
194- memset (message , 0 , sizeof (MachExceptionMessage ));
194+ memset (message , 0 , sizeof (MachExceptionProtectedMessage ));
195195
196- r = mach_msg (& message -> head , MACH_RCV_MSG | MACH_RCV_LARGE , 0 , sizeof (MachExceptionMessage ),
196+ r = mach_msg (& message -> head , MACH_RCV_MSG | MACH_RCV_LARGE , 0 , sizeof (MachExceptionProtectedMessage ),
197197 context -> port , MACH_MSG_TIMEOUT_NONE , MACH_PORT_NULL );
198198 if (r != MACH_MSG_SUCCESS ) {
199199 FIRCLSSDKLog ("Error receiving mach_msg (%d)\n" , r );
@@ -206,14 +206,27 @@ static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* conte
206206}
207207
208208static kern_return_t FIRCLSMachExceptionDispatchMessage (FIRCLSMachExceptionReadContext * context ,
209- MachExceptionMessage * message ) {
209+ MachExceptionProtectedMessage * message ) {
210210 FIRCLSSDKLog ("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n" , message -> exception ,
211211 message -> codeCnt , message -> codeCnt > 0 ? message -> code [0 ] : -1 ,
212212 message -> codeCnt > 1 ? message -> code [1 ] : -1 );
213213
214214 // This will happen if a child process raises an exception, as the exception ports are
215215 // inherited.
216- if (message -> task .name != mach_task_self ()) {
216+ mach_port_t actual_port ;
217+ 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 );
220+
221+ if (kr != KERN_SUCCESS ) {
222+ FIRCLSSDKLog ("Could not find task from task id token. returning failure\n" );
223+ return KERN_FAILURE ;
224+ }
225+
226+ const bool is_mismatch = (actual_port != mach_task_self ());
227+ mach_port_deallocate (mach_task_self (), actual_port );
228+
229+ if (is_mismatch ) {
217230 FIRCLSSDKLog ("Mach exception task mis-match, returning failure\n" );
218231 return KERN_FAILURE ;
219232 }
@@ -240,7 +253,7 @@ static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadC
240253}
241254
242255static bool FIRCLSMachExceptionReply (FIRCLSMachExceptionReadContext * context ,
243- MachExceptionMessage * message ,
256+ MachExceptionProtectedMessage * message ,
244257 kern_return_t result ) {
245258 MachExceptionReply reply ;
246259 mach_msg_return_t r ;
@@ -296,7 +309,7 @@ static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context)
296309
297310 // ORing with MACH_EXCEPTION_CODES will produce 64-bit exception data
298311 kr = task_swap_exception_ports (task , context -> mask , context -> port ,
299- EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES , THREAD_STATE_NONE ,
312+ EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES , THREAD_STATE_NONE ,
300313 context -> originalPorts .masks , & context -> originalPorts .count ,
301314 context -> originalPorts .ports , context -> originalPorts .behaviors ,
302315 context -> originalPorts .flavors );
@@ -333,7 +346,7 @@ static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* orig
333346
334347 // Finally, mark any masks we registered for that do not have an original port as unused.
335348 kr = task_set_exception_ports (mach_task_self (), mask , MACH_PORT_NULL ,
336- EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES , THREAD_STATE_NONE );
349+ EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES , THREAD_STATE_NONE );
337350 if (kr != KERN_SUCCESS ) {
338351 FIRCLSSDKLog ("unable to unset unregistered mask: 0x%x" , mask );
339352 return false;
@@ -472,7 +485,7 @@ void FIRCLSMachExceptionNameLookup(exception_type_t number,
472485}
473486
474487static bool FIRCLSMachExceptionRecord (FIRCLSMachExceptionReadContext * context ,
475- MachExceptionMessage * message ) {
488+ MachExceptionProtectedMessage * message ) {
476489 if (!context || !message ) {
477490 return false;
478491 }
@@ -520,13 +533,52 @@ static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context,
520533
521534 FIRCLSFileWriteSectionEnd (& file );
522535
523- FIRCLSHandler (& file , message -> thread .name , NULL , true);
524-
536+ thread_t crashedThread = THREAD_NULL ;
537+ FIRCLSCrashedThreadLookup (message , & crashedThread );
538+ FIRCLSSDKLog ("Crashed threads: %d\n" , crashedThread );
539+ FIRCLSHandler (& file , crashedThread , NULL , true);
540+ if (crashedThread != THREAD_NULL ) {
541+ mach_port_deallocate (mach_task_self (), crashedThread );
542+ }
525543 FIRCLSFileClose (& file );
526544
527545 return true;
528546}
529547
548+ static void FIRCLSCrashedThreadLookup (MachExceptionProtectedMessage * message , thread_t * crashedThread ) {
549+ thread_act_array_t threadList ;
550+ mach_msg_type_number_t threadCount ;
551+
552+ kern_return_t kr = task_threads (mach_task_self (), & threadList , & threadCount );
553+ if (kr != KERN_SUCCESS ) {
554+ FIRCLSSDKLogError ("Failed to get threads: %d\n" , kr );
555+ return ;
556+ }
557+
558+ // Find the crashed thread.
559+ for (int i = 0 ; i < threadCount ; i ++ ) {
560+ thread_identifier_info_data_t identifierInfo ;
561+ mach_msg_type_number_t infoCount = THREAD_IDENTIFIER_INFO_COUNT ;
562+
563+ kr = thread_info (threadList [i ], THREAD_IDENTIFIER_INFO , (thread_info_t )& identifierInfo , & infoCount );
564+
565+ if (kr == KERN_SUCCESS ) {
566+ FIRCLSSDKLog ("Thread %d: Thread port: %d, thread id: %llx\n" , i , threadList [i ], identifierInfo .thread_id );
567+ if (message -> thread_id == identifierInfo .thread_id ) {
568+ FIRCLSSDKLog ("Find crashed thread: %d\n" , threadList [i ]);
569+ * crashedThread = threadList [i ];
570+ break ;
571+ }
572+ }
573+ }
574+ for (int i = 0 ; i < threadCount ; i ++ ) {
575+ if (threadList [i ] != * crashedThread ) {
576+ mach_port_deallocate (mach_task_self (), threadList [i ]);
577+ }
578+ }
579+ vm_deallocate (mach_task_self (), (vm_address_t )threadList , threadCount * sizeof (thread_t ));
580+ }
581+
530582#else
531583
532584INJECT_STRIP_SYMBOL (cls_mach_exception )
0 commit comments