Beispiel #1
0
_Unwind_Reason_Code
PERSONALITY_FUNCTION (version_arg_t version_arg,
                      phases_arg_t phases_arg,
                      _Unwind_Exception_Class uw_exception_class
		         ATTRIBUTE_UNUSED,
                      _Unwind_Exception *uw_exception,
                      _Unwind_Context *uw_context)
{
  /* Fetch the version and phases args with their nominal ABI types for later
     use. This is a noop everywhere except on ia64-vms when called from the
     Condition Handling Facility.  */
  int uw_version = (int) version_arg;
  _Unwind_Action uw_phases = (_Unwind_Action) phases_arg;
  region_descriptor region;
  action_descriptor action;
  _Unwind_Ptr ip;

  /* Check that we're called from the ABI context we expect, with a major
     possible variation on VMS for IA64.  */
  if (uw_version != 1)
    {
#if defined (VMS) && defined (__IA64)

      /* Assume we're called with sigargs/mechargs arguments if really
	 unexpected bits are set in our first two formals.  Redirect to the
	 GNAT condition handling code in this case.  */

      extern long __gnat_handle_vms_condition (void *, void *);

      unsigned int version_unexpected_bits_mask = 0xffffff00U;
      unsigned int phases_unexpected_bits_mask  = 0xffffff00U;

      if ((unsigned int)uw_version & version_unexpected_bits_mask
	  && (unsigned int)uw_phases & phases_unexpected_bits_mask)
	return __gnat_handle_vms_condition (version_arg, phases_arg);
#endif

      return _URC_FATAL_PHASE1_ERROR;
    }

  db_indent (DB_INDENT_RESET);
  db_phases (uw_phases);
  db_indent (DB_INDENT_INCREASE);

  /* Get the region description for the context we were provided with. This
     will tell us if there is some lsda, call_site, action and/or ttype data
     for the associated ip.  */
  get_region_description_for (uw_context, &region);
  ip = get_ip_from_context (uw_context);
  db_region_for (&region, ip);

  /* No LSDA => no handlers or cleanups => we shall unwind further up.  */
  if (! region.lsda)
    return _URC_CONTINUE_UNWIND;

  /* Search the call-site and action-record tables for the action associated
     with this IP.  */
  get_action_description_for (ip, uw_exception, uw_phases, &region, &action);
  db_action_for (&action, ip);

  /* Whatever the phase, if there is nothing relevant in this frame,
     unwinding should just go on.  */
  if (action.kind == nothing)
    return _URC_CONTINUE_UNWIND;

  /* If we found something in search phase, we should return a code indicating
     what to do next depending on what we found. If we only have cleanups
     around, we shall try to unwind further up to find a handler, otherwise,
     tell we have a handler, which will trigger the second phase.  */
  if (uw_phases & _UA_SEARCH_PHASE)
    {
      if (action.kind == cleanup)
	{
	  return _URC_CONTINUE_UNWIND;
	}
      else
	{
	  struct Exception_Occurrence *excep;

	  /* Trigger the appropriate notification routines before the second
	     phase starts, which ensures the stack is still intact.
             First, setup the Ada occurrence.  */
          excep = __gnat_setup_current_excep (uw_exception);
	  if (action.kind == unhandler)
	    __gnat_notify_unhandled_exception (excep);
	  else
	    __gnat_notify_handled_exception (excep);

	  return _URC_HANDLER_FOUND;
	}
    }

  /* We found something in cleanup/handler phase, which might be the handler
     or a cleanup for a handled occurrence, or a cleanup for an unhandled
     occurrence (we are in a FORCED_UNWIND phase in this case). Install the
     context to get there.  */

  setup_to_install
    (uw_context, uw_exception, action.landing_pad, action.ttype_filter);

  /* Write current exception, so that it can be retrieved from Ada.  */
  __gnat_setup_current_excep (uw_exception);

  return _URC_INSTALL_CONTEXT;
}
Beispiel #2
0
_Unwind_Reason_Code
__gnat_eh_personality (int uw_version,
                       _Unwind_Action uw_phases,
                       _Unwind_Exception_Class uw_exception_class,
                       _Unwind_Exception *uw_exception,
                       _Unwind_Context *uw_context)
{
  _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception;

  region_descriptor region;
  action_descriptor action;

  if (uw_version != 1)
    return _URC_FATAL_PHASE1_ERROR;

  db_indent (DB_INDENT_RESET);
  db_phases (uw_phases);
  db_indent (DB_INDENT_INCREASE);

  /* Get the region description for the context we were provided with. This
     will tell us if there is some lsda, call_site, action and/or ttype data
     for the associated ip.  */
  get_region_description_for (uw_context, &region);
  db_region_for (&region, uw_context);

  /* No LSDA => no handlers or cleanups => we shall unwind further up.  */
  if (! region.lsda)
    return _URC_CONTINUE_UNWIND;

  /* Search the call-site and action-record tables for the action associated
     with this IP.  */
  get_action_description_for (uw_context, uw_exception, &region, &action);
  db_action_for (&action, uw_context);

  /* Whatever the phase, if there is nothing relevant in this frame,
     unwinding should just go on.  */
  if (action.kind == nothing)
    return _URC_CONTINUE_UNWIND;

  /* If we found something in search phase, we should return a code indicating
     what to do next depending on what we found. If we only have cleanups
     around, we shall try to unwind further up to find a handler, otherwise,
     tell we have a handler, which will trigger the second phase.  */
  if (uw_phases & _UA_SEARCH_PHASE)
    {
      if (action.kind == cleanup)
	{
	  gnat_exception->n_cleanups_to_trigger ++;
	  return _URC_CONTINUE_UNWIND;
	}
      else
	{
	  /* Trigger the appropriate notification routines before the second
	     phase starts, which ensures the stack is still intact. */
	  __gnat_notify_handled_exception ();

	  return _URC_HANDLER_FOUND;
	}
    }

  /* We found something in cleanup/handler phase, which might be the handler
     or a cleanup for a handled occurrence, or a cleanup for an unhandled
     occurrence (we are in a FORCED_UNWIND phase in this case). Install the
     context to get there.  */

  /* If we are going to install a cleanup context, decrement the cleanup
     count.  This is required in a FORCED_UNWINDing phase (for an unhandled
     exception), as this is used from the forced unwinding handler in
     Ada.Exceptions.Exception_Propagation to decide wether unwinding should
     proceed further or Unhandled_Exception_Terminate should be called.  */
  if (action.kind == cleanup)
    gnat_exception->n_cleanups_to_trigger --;

  setup_to_install
    (uw_context, uw_exception, action.landing_pad, action.ttype_filter);

  return _URC_INSTALL_CONTEXT;
}