Пример #1
0
static void
db_action_for (action_descriptor *action, _Unwind_Context *uw_context)
{
  _Unwind_Ptr ip = get_ip_from_context (uw_context);

  db (DB_ACTIONS, "For ip @ %p => ", (void *)ip);

  switch (action->kind)
     {
     case unknown:
       db (DB_ACTIONS, "lpad @ %p, record @ %p\n",
	   (void *) action->landing_pad, action->table_entry);
       break;

     case nothing:
       db (DB_ACTIONS, "Nothing\n");
       break;

     case cleanup:
       db (DB_ACTIONS, "Cleanup\n");
       break;

     case handler:
       db (DB_ACTIONS, "Handler, filter = %d\n", (int) action->ttype_filter);
       break;

     default:
       db (DB_ACTIONS, "Err? Unexpected action kind !\n");
       break;
    }

  return;
}
Пример #2
0
static void
get_call_site_action_for (_Unwind_Context *uw_context,
                          region_descriptor *region,
                          action_descriptor *action)
{
  const unsigned char *p = region->call_site_table;
  _Unwind_Ptr ip = get_ip_from_context (uw_context);

  /* Unless we are able to determine otherwise...  */
  action->kind = nothing;

  db (DB_CSITE, "\n");

  while (p < region->action_table)
    {
      _Unwind_Ptr cs_start, cs_len, cs_lp;
      _uleb128_t cs_action;

      /* Note that all call-site encodings are "absolute" displacements.  */
      p = read_encoded_value (0, region->call_site_encoding, p, &cs_start);
      p = read_encoded_value (0, region->call_site_encoding, p, &cs_len);
      p = read_encoded_value (0, region->call_site_encoding, p, &cs_lp);
      p = read_uleb128 (p, &cs_action);

      db (DB_CSITE,
	  "c_site @ %p (+%p), len = %p, lpad @ %p (+%p)\n",
	  (void *)region->base + cs_start, (void *)cs_start, (void *)cs_len,
	  (void *)region->lp_base + cs_lp, (void *)cs_lp);

      /* The table is sorted, so if we've passed the IP, stop.  */
      if (ip < region->base + cs_start)
 	break;

      /* If we have a match, fill the ACTION fields accordingly.  */
      else if (ip < region->base + cs_start + cs_len)
	{
	  /* Let the caller know there may be an action to take, but let it
	     determine the kind.  */
	  action->kind = unknown;

	  if (cs_lp)
	    action->landing_pad = region->lp_base + cs_lp;
	  else
	    action->landing_pad = 0;

	  if (cs_action)
	    action->table_entry = region->action_table + cs_action - 1;
	  else
	    action->table_entry = 0;

	  db (DB_CSITE, "+++\n");
	  return;
	}
    }

  db (DB_CSITE, "---\n");
}
Пример #3
0
static void
get_call_site_action_for (_Unwind_Context *uw_context,
                          region_descriptor *region,
                          action_descriptor *action)
{
  _Unwind_Ptr call_site = get_ip_from_context (uw_context);

  /* call_site is a direct index into the call-site table, with two special
     values : -1 for no-action and 0 for "terminate".  The latter should never
     show up for Ada.  To test for the former, beware that _Unwind_Ptr might
     be unsigned.  */

  if ((int)call_site < 0)
    {
      action->kind = nothing;
      return;
    }
  else if (call_site == 0)
    {
      db (DB_ERR, "========> Err, null call_site for Ada/sjlj\n");
      action->kind = nothing;
      return;
    }
  else
    {
      _uleb128_t cs_lp, cs_action;

      /* Let the caller know there may be an action to take, but let it
	 determine the kind.  */
      action->kind = unknown;

      /* We have a direct index into the call-site table, but this table is
	 made of leb128 values, the encoding length of which is variable.  We
	 can't merely compute an offset from the index, then, but have to read
	 all the entries before the one of interest.  */

      const unsigned char *p = region->call_site_table;

      do {
	p = read_uleb128 (p, &cs_lp);
	p = read_uleb128 (p, &cs_action);
      } while (--call_site);

      action->landing_pad = cs_lp + 1;

      if (cs_action)
	action->table_entry = region->action_table + cs_action - 1;
      else
	action->table_entry = 0;

      return;
    }
}
Пример #4
0
static void
db_region_for (region_descriptor *region, _Unwind_Context *uw_context)
{
  _Unwind_Ptr ip;

  if (! (db_accepted_codes () & DB_REGIONS))
    return;

  ip = get_ip_from_context (uw_context);

  db (DB_REGIONS, "For ip @ %p => ", (void *)ip);

  if (region->lsda)
    db (DB_REGIONS, "lsda @ %p", (void *)region->lsda);
  else
    db (DB_REGIONS, "no lsda");

  db (DB_REGIONS, "\n");
}
Пример #5
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;
}