_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, ®ion); ip = get_ip_from_context (uw_context); db_region_for (®ion, 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, ®ion, &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; }
_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, ®ion); db_region_for (®ion, 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, ®ion, &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; }