Пример #1
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;
}
Пример #2
0
static _Unwind_Reason_Code
unwind_phase1(struct _Unwind_Exception *exception_object) {
  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
  _LIBUNWIND_TRACE_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) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
                                 "bottom => _URC_END_OF_STACK\n",
                                  exception_object);
      return _URC_END_OF_STACK;
    }

    _LIBUNWIND_TRACE_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) {
      _LIBUNWIND_TRACE_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;
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
                                   "_URC_HANDLER_FOUND\n", exception_object);
        return _URC_NO_REASON;

      case _URC_CONTINUE_UNWIND:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
                                   "_URC_CONTINUE_UNWIND\n", exception_object);
        // continue unwinding
        break;

      default:
        // something went wrong
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
            exception_object);
        return _URC_FATAL_PHASE1_ERROR;
      }
    }
  }
  return _URC_NO_REASON;
}
Пример #3
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;
}
Пример #4
0
/// Called at start of each function that catches exceptions
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
  fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
  __Unwind_SjLj_SetTopOfFunctionStack(fc);
}