示例#1
0
static _Unwind_Reason_Code unwind_phase2(struct _Unwind_Exception* exception_object)
{
	DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); 
	
	// walk each frame until we reach where search phase said to stop
	_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
	while ( true ) {
		DEBUG_PRINT_UNWINDING("unwind_phase2s(ex_ojb=%p): function-context=%p\n", exception_object, c); 

		// check for no more frames
		if ( c == NULL ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
			return _URC_END_OF_STACK;
		}
		
		// if there is a personality routine, tell it we are unwinding
		if ( c->personality != NULL ) {
			_Unwind_Action action = _UA_CLEANUP_PHASE;
			if ( (uintptr_t)c == exception_object->private_2 )
				action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1
			_Unwind_Reason_Code personalityResult = (*c->personality)(1, action, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)c);
			switch ( personalityResult ) {
				case _URC_CONTINUE_UNWIND:
					// continue unwinding
					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
					if ( (uintptr_t)c == exception_object->private_2 ) {
						// phase 1 said we would stop at this frame, but we did not...
						ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here");
					}
					break;
				case _URC_INSTALL_CONTEXT:
					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT, will resume at landing pad %p\n", exception_object, c->jbuf[1]);
					// personality routine says to transfer control to landing pad
					// we may get control back if landing pad calls _Unwind_Resume()
					__Unwind_SjLj_SetTopOfFunctionStack(c);
					__builtin_longjmp(c->jbuf, 1);
					// unw_resume() only returns if there was an error
					return _URC_FATAL_PHASE2_ERROR;
				default:
					// something went wrong
					DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult);
					return _URC_FATAL_PHASE2_ERROR;
			}
		}
		c = c->prev;
	}

	// clean up phase did not resume at the frame that the search phase said it would
	return _URC_FATAL_PHASE2_ERROR;
}
示例#2
0
static _Unwind_Reason_Code unwind_phase2_forced(struct _Unwind_Exception* exception_object, 
												_Unwind_Stop_Fn stop, void* stop_parameter)
{
	// walk each frame until we reach where search phase said to stop
	_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
	while ( true ) {

		// get next frame (skip over first which is _Unwind_RaiseException)
		if ( c == NULL ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
			return _URC_END_OF_STACK;
		}
				
		// call stop function at each frame
		_Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE);
		_Unwind_Reason_Code stopResult = (*stop)(1, action, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)c, stop_parameter);
		DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult);
		if ( stopResult != _URC_NO_REASON ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object);
			return _URC_FATAL_PHASE2_ERROR;
		}
		
		// if there is a personality routine, tell it we are unwinding
		if ( c->personality != NULL ) {
			__personality_routine p = (__personality_routine)c->personality;
			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p);
			_Unwind_Reason_Code personalityResult = (*p)(1, action, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)c);
			switch ( personalityResult ) {
				case _URC_CONTINUE_UNWIND:
					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object);
					// destructors called, continue unwinding
					break;
				case _URC_INSTALL_CONTEXT:
					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object);
					// we may get control back if landing pad calls _Unwind_Resume()
					__Unwind_SjLj_SetTopOfFunctionStack(c);
					__builtin_longjmp(c->jbuf, 1);
					break;
				default:
					// something went wrong
					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n", 
						exception_object, personalityResult);
					return _URC_FATAL_PHASE2_ERROR;
			}
		}
		c = c->prev;
	}

	// call stop function one last time and tell it we've reached the end of the stack
	DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object);
	_Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK);
	(*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)c, stop_parameter);
	
	// clean up phase did not resume at the frame that the search phase said it would
	return _URC_FATAL_PHASE2_ERROR;
}
示例#3
0
static _Unwind_Reason_Code unwind_phase1(struct _Unwind_Exception* exception_object)
{
	_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
	DEBUG_PRINT_UNWINDING("unwind_phase1: initial function-context=%p\n", c); 

	// walk each frame looking for a place to stop
	for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {

		// check for no more frames
		if ( c == NULL ) {
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): reached bottom => _URC_END_OF_STACK\n", exception_object); 
			return _URC_END_OF_STACK;
		}
		
		DEBUG_PRINT_UNWINDING("unwind_phase1: function-context=%p\n", c); 
		// if there is a personality routine, ask it if it will want to stop at this frame
		if ( c->personality != NULL ) {
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, c->personality);
			_Unwind_Reason_Code personalityResult = (*c->personality)(1, _UA_SEARCH_PHASE, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)c);
			switch ( personalityResult ) {
				case _URC_HANDLER_FOUND:
					// found a catch clause or locals that need destructing in this frame
					// stop search and remember function context
					handlerNotFound = false;
					exception_object->private_2 = (uintptr_t)c;
					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object);
					return _URC_NO_REASON;
					
				case _URC_CONTINUE_UNWIND:
					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
					// continue unwinding
					break;
					
				default:
					// something went wrong
					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object);
					return _URC_FATAL_PHASE1_ERROR;
			}
		}
	}
	return _URC_NO_REASON;
}
示例#4
0
static _Unwind_Reason_Code unwind_phase1(unw_context_t* uc, struct _Unwind_Exception* exception_object)
{
	unw_cursor_t cursor1; 
	unw_init_local(&cursor1, uc);
	
	// walk each frame looking for a place to stop
	for (bool handlerNotFound = true; handlerNotFound; ) {

		// ask libuwind to get next frame (skip over first which is _Unwind_RaiseException)
		int stepResult = unw_step(&cursor1);
		if ( stepResult == 0 ) {
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
			return _URC_END_OF_STACK;
		}
		else if ( stepResult < 0 ) {
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); 
			return _URC_FATAL_PHASE1_ERROR;
		}
		
		// see if frame has code to run (has personality routine)
		unw_proc_info_t frameInfo;
		unw_word_t sp;
		if ( unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS ) {
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
			return _URC_FATAL_PHASE1_ERROR;
		}
		
		// debugging
		if ( DEBUG_PRINT_UNWINDING_TEST ) {
			char functionName[512];
			unw_word_t	offset;
			if ( (unw_get_proc_name(&cursor1, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
				strcpy(functionName, ".anonymous.");
			unw_word_t pc;
			unw_get_reg(&cursor1, UNW_REG_IP, &pc);
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n", 
							exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler);
		}
		
		// if there is a personality routine, ask it if it will want to stop at this frame
		if ( frameInfo.handler != 0 ) {
			__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
			DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, p);
			_Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)(&cursor1));
			switch ( personalityResult ) {
				case _URC_HANDLER_FOUND:
					// found a catch clause or locals that need destructing in this frame
					// stop search and remember stack pointer at the frame
					handlerNotFound = false;
					unw_get_reg(&cursor1, UNW_REG_SP, &sp);
					exception_object->private_2 = sp;
					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object);
					return _URC_NO_REASON;
					
				case _URC_CONTINUE_UNWIND:
					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
					// continue unwinding
					break;
					
				default:
					// something went wrong
					DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object);
					return _URC_FATAL_PHASE1_ERROR;
			}
		}
	}
	return _URC_NO_REASON;
}
示例#5
0
static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t* uc, struct _Unwind_Exception* exception_object, 
												_Unwind_Stop_Fn stop, void* stop_parameter)
{
	unw_cursor_t cursor2; 
	unw_init_local(&cursor2, uc);
	
	// walk each frame until we reach where search phase said to stop
	while ( unw_step(&cursor2) > 0 ) {
		
		// get info about this frame
		unw_proc_info_t frameInfo;
		if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step failed => _URC_END_OF_STACK\n", exception_object); 
			return _URC_FATAL_PHASE1_ERROR;
		}
		
		// debugging
		if ( DEBUG_PRINT_UNWINDING_TEST ) {
			char functionName[512];
			unw_word_t	offset;
			if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
				strcpy(functionName, ".anonymous.");
			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n", 
							exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler);
		}
		
		// call stop function at each frame
		_Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE);
		_Unwind_Reason_Code stopResult = (*stop)(1, action, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)(&cursor2), stop_parameter);
		DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult);
		if ( stopResult != _URC_NO_REASON ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object);
			return _URC_FATAL_PHASE2_ERROR;
		}
		
		// if there is a personality routine, tell it we are unwinding
		if ( frameInfo.handler != 0 ) {
			__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
			DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p);
			_Unwind_Reason_Code personalityResult = (*p)(1, action, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)(&cursor2));
			switch ( personalityResult ) {
				case _URC_CONTINUE_UNWIND:
					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object);
					// destructors called, continue unwinding
					break;
				case _URC_INSTALL_CONTEXT:
					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object);
					// we may get control back if landing pad calls _Unwind_Resume()
					unw_resume(&cursor2);
					break;
				default:
					// something went wrong
					DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n", 
						exception_object, personalityResult);
					return _URC_FATAL_PHASE2_ERROR;
			}
		}
	}

	// call stop function one last time and tell it we've reached the end of the stack
	DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object);
	_Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK);
	(*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)(&cursor2), stop_parameter);
	
	// clean up phase did not resume at the frame that the search phase said it would
	return _URC_FATAL_PHASE2_ERROR;
}
示例#6
0
static _Unwind_Reason_Code unwind_phase2(unw_context_t* uc, struct _Unwind_Exception* exception_object)
{
	unw_cursor_t cursor2; 
	unw_init_local(&cursor2, uc);
	
	DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); 
	
	// walk each frame until we reach where search phase said to stop
	while ( true ) {

		// ask libuwind to get next frame (skip over first which is _Unwind_RaiseException)
		int stepResult = unw_step(&cursor2);
		if ( stepResult == 0 ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); 
			return _URC_END_OF_STACK;
		}
		else if ( stepResult < 0 ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); 
			return _URC_FATAL_PHASE2_ERROR;
		}
		
		// get info about this frame
		unw_word_t sp;
		unw_proc_info_t frameInfo;
		unw_get_reg(&cursor2, UNW_REG_SP, &sp);
		if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) {
			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
			return _URC_FATAL_PHASE2_ERROR;
		}
		
		// debugging
		if ( DEBUG_PRINT_UNWINDING_TEST ) {
			char functionName[512];
			unw_word_t	offset;
			if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
				strcpy(functionName, ".anonymous.");
			DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, lsda=0x%llX, personality=0x%llX\n", 
							exception_object, frameInfo.start_ip, functionName, sp, frameInfo.lsda, frameInfo.handler);
		}
		
		// if there is a personality routine, tell it we are unwinding
		if ( frameInfo.handler != 0 ) {
			__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
			_Unwind_Action action = _UA_CLEANUP_PHASE;
			if ( sp == exception_object->private_2 )
				action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1
			_Unwind_Reason_Code personalityResult = (*p)(1, action, 
						exception_object->exception_class, exception_object, 
						(struct _Unwind_Context*)(&cursor2));
			switch ( personalityResult ) {
				case _URC_CONTINUE_UNWIND:
					// continue unwinding
					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
					if ( sp == exception_object->private_2 ) {
						// phase 1 said we would stop at this frame, but we did not...
						ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here");
					}
					break;
				case _URC_INSTALL_CONTEXT:
					DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", exception_object);
					// personality routine says to transfer control to landing pad
					// we may get control back if landing pad calls _Unwind_Resume()
					if ( DEBUG_PRINT_UNWINDING_TEST ) {
						unw_word_t pc;
						unw_word_t sp;
						unw_get_reg(&cursor2, UNW_REG_IP, &pc);
						unw_get_reg(&cursor2, UNW_REG_SP, &sp);
						DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering user code with ip=0x%llX, sp=0x%llX\n", exception_object, pc, sp);
					}
					unw_resume(&cursor2);
					// unw_resume() only returns if there was an error
					return _URC_FATAL_PHASE2_ERROR;
				default:
					// something went wrong
					DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult);
					return _URC_FATAL_PHASE2_ERROR;
			}
		}
	}

	// clean up phase did not resume at the frame that the search phase said it would
	return _URC_FATAL_PHASE2_ERROR;
}