Example #1
0
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);
}
Example #2
0
/*
    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;
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
0
_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;
}
Example #6
0
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);
}