static const __shim_type_info* get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, uint8_t ttypeEncoding, bool native_exception, _Unwind_Exception* unwind_exception) { if (classInfo == 0) { // this should not happen. Indicates corrupted eh_table. call_terminate(native_exception, unwind_exception); } switch (ttypeEncoding & 0x0F) { case DW_EH_PE_absptr: ttypeIndex *= sizeof(void*); break; case DW_EH_PE_udata2: case DW_EH_PE_sdata2: ttypeIndex *= 2; break; case DW_EH_PE_udata4: case DW_EH_PE_sdata4: ttypeIndex *= 4; break; case DW_EH_PE_udata8: case DW_EH_PE_sdata8: ttypeIndex *= 8; break; default: // this should not happen. Indicates corrupted eh_table. call_terminate(native_exception, unwind_exception); } classInfo -= ttypeIndex; return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding); }
/* This is checking a thrown exception type, excpType, against a possibly empty list of catchType's which make up an exception spec. An exception spec acts like a catch handler, but in reverse. This "catch handler" will catch an excpType if and only if none of the catchType's in the list will catch a excpType. If any catchType in the list can catch an excpType, then this exception spec does not catch the excpType. */ static bool exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, uint8_t ttypeEncoding, const __shim_type_info* excpType, void* adjustedPtr, _Unwind_Exception* unwind_exception) { if (classInfo == 0) { // this should not happen. Indicates corrupted eh_table. call_terminate(false, unwind_exception); } // specIndex is negative of 1-based byte offset into classInfo; specIndex = -specIndex; --specIndex; const uint8_t* temp = classInfo + specIndex; // If any type in the spec list can catch excpType, return false, else return true // adjustments to adjustedPtr are ignored. while (true) { uint64_t ttypeIndex = readULEB128(&temp); if (ttypeIndex == 0) break; const __shim_type_info* catchType = get_shim_type_info(ttypeIndex, classInfo, ttypeEncoding, true, unwind_exception); void* tempPtr = adjustedPtr; if (catchType->can_catch(excpType, tempPtr)) return false; } return true; }
int event_handler(int msg_type, int charging_type, int cid, char *subscriber, int crdtonce, int crdtpsec, int crdtpMb) { AAAMessage *acr; //Offline charging AAAMessage *ccr; //Online charging int sesid = cid; str user_subscriber; user_subscriber.s = subscriber; user_subscriber.len = strlen(user_subscriber.s); //sprintf(buf,"%d",cid); //str sesid; sesid.s = cid;sesid.len = strlen(sesid.s); str ohost; ohost.s = "iptv.open-ims.test"; ohost.len = strlen(ohost.s); str orealm; orealm.s = "open-ims.test"; orealm.len = strlen(orealm.s); str drealm; drealm.s = "open-ims.test"; drealm.len = strlen(drealm.s); str dhost; dhost.s = "cdf.open-ims.test"; dhost.len = strlen(dhost.s); str dhost1; dhost1.s = "ocf.open-ims.test"; dhost1.len = strlen(dhost1.s); str acctype; acctype.s ="START"; acctype.len = strlen(acctype.s); str accnumber; accnumber.s = "10"; accnumber.len = strlen(accnumber.s); str auth_app_id; auth_app_id.s = "100"; auth_app_id.len = strlen(auth_app_id.s); str service_context_id; service_context_id.s = "100"; service_context_id.len = strlen(service_context_id.s); str cc_type; cc_type.s ="START"; cc_type.len = strlen(cc_type.s); str cc_number; cc_number.s = "10"; cc_number.len = strlen(cc_number.s); switch (msg_type) { case START: if (charging_type == 0) { LOG(L_INFO,"INFO: event_handler - Invoking offline charging\n"); lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler START - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler START - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler START - Found client %s call ID %d\n",client->subscriber,client->call_id); lock_release(list_of_clients->lock); LOG(L_INFO,"event_handler START - ACR (INITIAL_REQUEST).\n"); acr = Rf_ACR(sesid,user_subscriber,ohost,orealm,drealm,START,accnumber,dhost,0,0,0); if(acr==0) return 0; } else if (charging_type == 1) { LOG(L_INFO,"INFO: event_handler - START - Invoking online charging\n"); lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler START - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler START - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler START - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler START - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); lock_release(list_of_clients->lock); LOG(L_INFO,"event_handler START - CCR (INITIAL_REQUEST).\n"); ccr = Ro_CCR(sesid,user_subscriber,ohost,orealm,auth_app_id,service_context_id,START,cc_number,dhost1,0,0,0); if(ccr==0) return 0; } break; case INTERIM: if(charging_type == 0) { lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler INTERIM - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler INTERIM - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler INTERIM - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler INTERIM - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); lock_release(list_of_clients->lock); LOG(L_INFO,"event_handler INTERIM - Sending ACR(UPDATE_REQUEST).\n"); acr = Rf_ACR(sesid,user_subscriber,ohost,orealm,drealm,INTERIM,accnumber,dhost,crdtonce,crdtpsec,crdtpMb); if(acr==0) return 0; } else if(charging_type == 1) { lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler INTERIM - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler INTERIM - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler INTERIM - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler INTERIM - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); lock_release(list_of_clients->lock); LOG(L_INFO,"event_handler INTERIM - Sending CCR(UPDATE_REQUEST).\n"); ccr = Ro_CCR(sesid,user_subscriber,ohost,orealm,auth_app_id,service_context_id,INTERIM,cc_number,dhost1,crdtonce,crdtpsec,crdtpMb); if(ccr==0) return 0; } break; case STOP: if(charging_type == 0) { lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler STOP - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler STOP - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler STOP - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler STOP - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); lock_release(list_of_clients->lock); LOG(L_INFO,"event_handler STOP - Sending ACR(TERMINATE_REQUEST).\n"); acr = Rf_ACR(sesid,user_subscriber,ohost,orealm,drealm,STOP,accnumber,dhost,crdtonce,crdtpsec,crdtpMb); if(acr==0) return 0; del_client(cid); } else if(charging_type == 1) { lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler STOP - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler STOP - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler STOP - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler STOP - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); lock_release(list_of_clients->lock); LOG(L_INFO,"event_handler STOP - Sending CCR(TERMINATE_REQUEST).\n"); ccr = Ro_CCR(sesid,user_subscriber,ohost,orealm,auth_app_id,service_context_id,STOP,cc_number,dhost1,crdtonce,crdtpsec,crdtpMb); if(ccr==0) return 0; call_terminate(client->call_id,client->call_did); del_client(cid); } break; case EVENT: //Not yet used lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler EVENT - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler EVENT - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } LOG(L_DBG,"event_handler EVENT - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler EVENT - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); client->events = Event; lock_release(list_of_clients->lock); break; case YES: lock_get(list_of_clients->lock); if(!list_of_clients->head){ LOG(L_DBG,"event_handler YES - No clients Found on list.\n"); lock_release(list_of_clients->lock); return 0; } client = list_of_clients->head; while(client->call_id != cid && client->next !=0){ client=client->next; } if(client->call_id != cid && client->next == 0){ LOG(L_ERR,"event_handler YES - Client not found.\n"); lock_release(list_of_clients->lock); return 0; } client->subscriber = subscriber;//Temporary hack LOG(L_DBG,"event_handler YES - Found client %s call ID %d\n",client->subscriber,client->call_id); LOG(L_DBG,"event_handler YES - Found %s callID %d and credits %d.\n",client->subscriber,client->call_id,client->onceoff_credit + client->persec_credit + client->perMbyte_credit); LOG(L_DBG,"event_handler YES - Credits received for %s client ID: %d\tonce: %d\tTime: %d\tVol: %d\n",client->subscriber,client->call_id,crdtonce,crdtpsec,crdtpMb); if(client->charge_type == 1){ client->onceoff_credit = client->onceoff_credit + crdtonce; client->persec_credit = client->persec_credit + crdtpsec; client->perMbyte_credit = client->perMbyte_credit + crdtpMb; client->used_crtdonce = client->onceoff_credit; client->onceoff_credit = 0; }else{ client->onceoff_credit = crdtonce; client->persec_credit = crdtpsec; client->perMbyte_credit = crdtpMb; } client->feedback = Yes; lock_release(list_of_clients->lock); break; case NO: //Not used break; } return 1; }
void __cxa_call_unexpected(void* arg) { _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg); if (unwind_exception == 0) call_terminate(false, unwind_exception); __cxa_begin_catch(unwind_exception); bool native_old_exception = (reinterpret_cast<uint64_t>(unwind_exception->exception_class) & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); std::unexpected_handler u_handler; std::terminate_handler t_handler; __cxa_exception* old_exception_header = 0; int64_t ttypeIndex; const uint8_t* lsda; if (native_old_exception) { old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; t_handler = old_exception_header->terminateHandler; u_handler = old_exception_header->unexpectedHandler; // If std::__unexpected(u_handler) rethrows the same exception, // these values get overwritten by the rethrow. So save them now: #ifndef __ARM_EABI_UNWINDER__ ttypeIndex = old_exception_header->handlerSwitchValue; lsda = old_exception_header->languageSpecificData; #endif } else { t_handler = std::get_terminate(); u_handler = std::get_unexpected(); } try { std::__unexpected(u_handler); } catch (...) { // If the old exception is foreign, then all we can do is terminate. // We have no way to recover the needed old exception spec. There's // no way to pass that information here. And the personality routine // can't call us directly and do anything but terminate() if we throw // from here. if (native_old_exception) { // Have: // old_exception_header->languageSpecificData // old_exception_header->actionRecord // Need // const uint8_t* classInfo // uint8_t ttypeEncoding uint8_t lpStartEncoding = *lsda++; const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); (void)lpStart; // purposefully unused. Just needed to increment lsda. uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding == DW_EH_PE_omit) std::__terminate(t_handler); uintptr_t classInfoOffset = readULEB128(&lsda); const uint8_t* classInfo = lsda + classInfoOffset; // Is this new exception catchable by the exception spec at ttypeIndex? // The answer is obviously yes if the new and old exceptions are the same exception // If no // throw; __cxa_eh_globals* globals = __cxa_get_globals_fast(); __cxa_exception* new_exception_header = globals->caughtExceptions; if (new_exception_header == 0) // This shouldn't be able to happen! std::__terminate(t_handler); bool native_new_exception = (reinterpret_cast<uint64_t>(new_exception_header->unwindHeader.exception_class) & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); void* adjustedPtr; if (native_new_exception && (new_exception_header != old_exception_header)) { const __shim_type_info* excpType = static_cast<const __shim_type_info*>(new_exception_header->exceptionType); adjustedPtr = reinterpret_cast<uint64_t>(new_exception_header->unwindHeader.exception_class) == kOurDependentExceptionClass ? ((__cxa_dependent_exception*)new_exception_header)->primaryException : new_exception_header + 1; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // We need to __cxa_end_catch, but for the old exception, // not the new one. This is a little tricky ... // Disguise new_exception_header as a rethrown exception, but // don't actually rethrow it. This means you can temporarily // end the catch clause enclosing new_exception_header without // __cxa_end_catch destroying new_exception_header. new_exception_header->handlerCount = -new_exception_header->handlerCount; globals->uncaughtExceptions += 1; // Call __cxa_end_catch for new_exception_header __cxa_end_catch(); // Call __cxa_end_catch for old_exception_header __cxa_end_catch(); // Renter this catch clause with new_exception_header __cxa_begin_catch(&new_exception_header->unwindHeader); // Rethrow new_exception_header throw; } } // Will a std::bad_exception be catchable by the exception spec at // ttypeIndex? // If no // throw std::bad_exception(); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(&typeid(std::bad_exception)); std::bad_exception be; adjustedPtr = &be; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // We need to __cxa_end_catch for both the old exception and the // new exception. Technically we should do it in that order. // But it is expedient to do it in the opposite order: // Call __cxa_end_catch for new_exception_header __cxa_end_catch(); // Throw std::bad_exception will __cxa_end_catch for // old_exception_header throw be; } } } std::__terminate(t_handler); }
_Unwind_Reason_Code #if __arm__ __gxx_personality_sj0 #else __gxx_personality_v0 #endif (int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { if (version != 1 || unwind_exception == 0 || context == 0) return _URC_FATAL_PHASE1_ERROR; bool native_exception = (exceptionClass & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); scan_results results; if (actions & _UA_SEARCH_PHASE) { // Phase 1 search: All we're looking for in phase 1 is a handler that // halts unwinding scan_eh_tab(results, actions, native_exception, unwind_exception, context); if (results.reason == _URC_HANDLER_FOUND) { // Found one. Can we cache the results somewhere to optimize phase 2? if (native_exception) { #ifndef __ARM_EABI_UNWINDER__ __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex); exception_header->actionRecord = results.actionRecord; exception_header->languageSpecificData = results.languageSpecificData; exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad); exception_header->adjustedPtr = results.adjustedPtr; #endif } return _URC_HANDLER_FOUND; } // Did not find a catching-handler. Return the results of the scan // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR // if we were called improperly). return results.reason; } if (actions & _UA_CLEANUP_PHASE) { // Phase 2 search: // Did we find a catching handler in phase 1? if (actions & _UA_HANDLER_FRAME) { // Yes, phase 1 said we have a catching handler here. // Did we cache the results of the scan? if (native_exception) { #ifndef __ARM_EABI_UNWINDER__ // Yes, reload the results from the cache. __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; results.ttypeIndex = exception_header->handlerSwitchValue; results.actionRecord = exception_header->actionRecord; results.languageSpecificData = exception_header->languageSpecificData; results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp); results.adjustedPtr = exception_header->adjustedPtr; #endif } else { // No, do the scan again to reload the results. scan_eh_tab(results, actions, native_exception, unwind_exception, context); // Phase 1 told us we would find a handler. Now in Phase 2 we // didn't find a handler. The eh table should not be changing! if (results.reason != _URC_HANDLER_FOUND) call_terminate(native_exception, unwind_exception); } // Jump to the handler set_registers(unwind_exception, context, results); return _URC_INSTALL_CONTEXT; } // Either we didn't do a phase 1 search (due to forced unwinding), or // phase 1 reported no catching-handlers. // Search for a (non-catching) cleanup scan_eh_tab(results, actions, native_exception, unwind_exception, context); if (results.reason == _URC_HANDLER_FOUND) { // Found a non-catching handler. Jump to it: set_registers(unwind_exception, context, results); return _URC_INSTALL_CONTEXT; } // Did not find a cleanup. Return the results of the scan // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR // if we were called improperly). return results.reason; } // We were called improperly: neither a phase 1 or phase 2 search return _URC_FATAL_PHASE1_ERROR; }
static void scan_eh_tab(scan_results& results, _Unwind_Action actions, bool native_exception, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { // Initialize results to found nothing but an error results.ttypeIndex = 0; results.actionRecord = 0; results.languageSpecificData = 0; results.landingPad = 0; results.adjustedPtr = 0; results.reason = _URC_FATAL_PHASE1_ERROR; // Check for consistent actions if (actions & _UA_SEARCH_PHASE) { // Do Phase 1 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) { // None of these flags should be set during Phase 1 // Client error results.reason = _URC_FATAL_PHASE1_ERROR; return; } } else if (actions & _UA_CLEANUP_PHASE) { if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) { // _UA_HANDLER_FRAME should only be set if phase 1 found a handler. // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened. // Client error results.reason = _URC_FATAL_PHASE2_ERROR; return; } } else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set { // One of these should be set. // Client error results.reason = _URC_FATAL_PHASE1_ERROR; return; } // Start scan by getting exception table address const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context); if (lsda == 0) { // There is no exception table results.reason = _URC_CONTINUE_UNWIND; return; } results.languageSpecificData = lsda; // Get the current instruction pointer and offset it before next // instruction in the current frame which threw the exception. uintptr_t ip = _Unwind_GetIP(context) - 1; // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); #if __arm__ if (ip == uintptr_t(-1)) { // no action results.reason = _URC_CONTINUE_UNWIND; return; } else if (ip == 0) call_terminate(native_exception, unwind_exception); // ip is 1-based index into call site table #else // __arm__ uintptr_t ipOffset = ip - funcStart; #endif // __arm__ const uint8_t* classInfo = NULL; // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission // Parse LSDA header. uint8_t lpStartEncoding = *lsda++; const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); if (lpStart == 0) lpStart = (const uint8_t*)funcStart; uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding != DW_EH_PE_omit) { // Calculate type info locations in emitted dwarf code which // were flagged by type info arguments to llvm.eh.selector // intrinsic uintptr_t classInfoOffset = readULEB128(&lsda); classInfo = lsda + classInfoOffset; } // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; #if __arm__ (void)callSiteEncoding; // On arm callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); const uint8_t* callSiteTableStart = lsda; const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t* actionTableStart = callSiteTableEnd; const uint8_t* callSitePtr = callSiteTableStart; while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. #if !__arm__ // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) #else // __arm__ // ip is 1-based index into this table uintptr_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) #endif // __arm__ { // Found the call site containing ip. #if !__arm__ if (landingPad == 0) { // No handler here results.reason = _URC_CONTINUE_UNWIND; return; } landingPad = (uintptr_t)lpStart + landingPad; #else // __arm__ ++landingPad; #endif // __arm__ if (actionEntry == 0) { // Found a cleanup // If this is a type 1 or type 2 search, there are no handlers // If this is a type 3 search, you want to install the cleanup. if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) { results.ttypeIndex = 0; // Redundant but clarifying results.landingPad = landingPad; results.reason = _URC_HANDLER_FOUND; return; } // No handler here results.reason = _URC_CONTINUE_UNWIND; return; } // Convert 1-based byte offset into const uint8_t* action = actionTableStart + (actionEntry - 1); // Scan action entries until you find a matching handler, cleanup, or the end of action list while (true) { const uint8_t* actionRecord = action; int64_t ttypeIndex = readSLEB128(&action); if (ttypeIndex > 0) { // Found a catch, does it actually catch? // First check for catch (...) const __shim_type_info* catchType = get_shim_type_info(static_cast<uint64_t>(ttypeIndex), classInfo, ttypeEncoding, native_exception, unwind_exception); if (catchType == 0) { // Found catch (...) catches everything, including foreign exceptions // If this is a type 1 search save state and return _URC_HANDLER_FOUND // If this is a type 2 search save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } // Else this is a catch (T) clause and will never // catch a foreign exception else if (native_exception) { __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(exception_header->exceptionType); if (adjustedPtr == 0 || excpType == 0) { // Something very bad happened call_terminate(native_exception, unwind_exception); } if (catchType->can_catch(excpType, adjustedPtr)) { // Found a matching handler // If this is a type 1 search save state and return _URC_HANDLER_FOUND // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan if (actions & _UA_SEARCH_PHASE) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } } // Scan next action ... } else if (ttypeIndex < 0) { // Found an exception spec. If this is a foreign exception, // it is always caught. if (native_exception) { // Does the exception spec catch this native exception? __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(exception_header->exceptionType); if (adjustedPtr == 0 || excpType == 0) { // Something very bad happened call_terminate(native_exception, unwind_exception); } if (exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // native exception caught by exception spec // If this is a type 1 search, save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if (actions & _UA_SEARCH_PHASE) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } } else { // foreign exception caught by exception spec // If this is a type 1 search, save state and return _URC_HANDLER_FOUND // If this is a type 2 search, save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } // Scan next action ... } else // ttypeIndex == 0 { // Found a cleanup // If this is a type 1 search, ignore it and continue scan // If this is a type 2 search, ignore it and continue scan // If this is a type 3 search, save state and return _URC_HANDLER_FOUND if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } } const uint8_t* temp = action; int64_t actionOffset = readSLEB128(&temp); if (actionOffset == 0) { // End of action list, no matching handler or cleanup found results.reason = _URC_CONTINUE_UNWIND; return; } // Go to next action action += actionOffset; } // there is no break out of this loop, only return } #if !__arm__ else if (ipOffset < start) { // There is no call site for this ip // Something bad has happened. We should never get here. // Possible stack corruption. call_terminate(native_exception, unwind_exception); } #endif // !__arm__ } // there might be some tricky cases which break out of this loop // It is possible that no eh table entry specify how to handle // this exception. By spec, terminate it immediately. call_terminate(native_exception, unwind_exception); }