Пример #1
0
_LIBUNWIND_HIDDEN
bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) {
#if __MAC_OS_X_VERSION_MIN_REQUIRED
  // lastly check for old style keymgr registration of dynamically generated
  // FDEs acquire exclusive access to libgcc_object_info
  libgcc_object_info *head = (libgcc_object_info *)
                _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
  if (head != NULL) {
    // look at each FDE in keymgr
    for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) {
      CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
      CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
      const char *msg = CFI_Parser<LocalAddressSpace>::decodeFDE(
                                      LocalAddressSpace::sThisAddressSpace,
                                      (uintptr_t)ob->fde, &fdeInfo, &cieInfo);
      if (msg == NULL) {
        // Check if this FDE is for a function that includes the pc
        if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
          fde = (void*)fdeInfo.pcStart;
          _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
                                                 head);
          return true;
        }
      }
    }
  }
  // release libgcc_object_info
  _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
#else
  (void)pc;
  (void)fde;
#endif
  return false;
}
Пример #2
0
static void
cxa_atexit_wrapper (void* routine_param)
{
  struct one_atexit_routine * routine = routine_param;
  struct keymgr_atexit_list *g;
  struct atexit_routine_list * base = NULL;
  char prev_running = 0;
  
  g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
  if (g)
    {
      prev_running = g->running_routines;
      g->running_routines = 1;
      base = g->l;
      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
    }

  if (routine->has_arg)
    routine->callback.cac (routine->arg);
  else
    routine->callback.ac ();

  if (g)
    g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
  if (g)
    g = run_routines (g, base);
  if (g)
    {
      g->running_routines = prev_running;
      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
    }
}
Пример #3
0
static int
atexit_common (const struct one_atexit_routine *r, const void *dso)
{
  struct keymgr_atexit_list *g = get_globals ();

  if (! g)
    return -1;
  
  if (g->running_routines || g->atexit_status == atexit_status_missing)
    return add_routine (g, r);

  if (g->atexit_status >= atexit_status_working)
    {
      int result;
      if (r->has_arg)
	{
	  cxa_atexit_p cxa_atexit = g->cxa_atexit_f;
	  result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST,
							   g);
	  if (CHECK_KEYMGR_ERROR (result))
	    return -1;
	  return cxa_atexit (r->callback.cac, r->arg, dso);
	}
      else
	{
	  atexit_p atexit_f = g->atexit_f;
	  result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST,
							   g);
	  if (CHECK_KEYMGR_ERROR (result))
	    return -1;
	  return atexit_f (r->callback.ac);
	}
    }
  else
    {
      cxa_atexit_p cxa_atexit = g->cxa_atexit_f;
      struct one_atexit_routine *alloced;
      int result;

      result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
      if (CHECK_KEYMGR_ERROR (result))
	return -1;

      alloced = malloc (sizeof (struct one_atexit_routine));
      if (! alloced)
	return -1;
      *alloced = *r;
      return cxa_atexit (cxa_atexit_wrapper, alloced, dso);
    }
}
Пример #4
0
/* This runs the routines in G->L up to STOP.  */
static struct keymgr_atexit_list *
run_routines (struct keymgr_atexit_list *g,
	      struct atexit_routine_list *stop)
{
  for (;;)
    {
      struct atexit_routine_list * cur = g->l;
      if (! cur || cur == stop)
	break;
      g->l = cur->next;
      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);

      switch (cur->r.has_arg) {
      case 0: case 2: case 4:
	cur->r.callback.ac ();
	break;
      case 1: case 3: case 5:
	cur->r.callback.cac (cur->r.arg);
	break;
      default:
	/* Don't understand, so don't call it.  */
	break;
      }
      free (cur);

      g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
      if (! g)
	break;
    }
  return g;
}
Пример #5
0
const fde *
_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
{
  struct km_object_info *the_obj_info;
  const fde *ret = NULL;

  the_obj_info =
    _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
  if (! the_obj_info)
    the_obj_info = calloc (1, sizeof (*the_obj_info));

  if (the_obj_info != NULL)
    {
      seen_objects = the_obj_info->seen_objects;
      unseen_objects = the_obj_info->unseen_objects;

      ret = _Unwind_Find_registered_FDE (pc, bases);
    }

  /* OK, didn't find it in the list of FDEs we've seen before,
     so go through and look at the new ones.  */
  if (ret == NULL)
    ret = examine_objects (pc, bases, the_obj_info == NULL);

  if (the_obj_info != NULL)
    {
      the_obj_info->seen_objects = seen_objects;
      the_obj_info->unseen_objects = unseen_objects;
    }
  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
                                          the_obj_info);
  return ret;
}
Пример #6
0
static void
live_image_destructor (struct live_images *image)
{
  if (image->object_info)
    {
      struct km_object_info *the_obj_info;

      the_obj_info =
        _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
      if (the_obj_info)
        {
          seen_objects = the_obj_info->seen_objects;
          unseen_objects = the_obj_info->unseen_objects;

          /* Free any sorted arrays.  */
          __deregister_frame_info_bases (image->fde);

          the_obj_info->seen_objects = seen_objects;
          the_obj_info->unseen_objects = unseen_objects;
        }
      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
                                              the_obj_info);

      free (image->object_info);
      image->object_info = NULL;
      if (image->examined_p & ALLOCED_IMAGE_MASK)
        free (image->fde);
      image->fde = NULL;
    }
  image->examined_p = 0;
  image->destructor = NULL;
}
Пример #7
0
static void
darwin_unwind_dyld_remove_image_hook (struct mach_header *m, unsigned long s)
{
  struct live_images *top, **lip, *destroy = NULL;

  /* Look for it in the list of live images and delete it.  */

  top = (struct live_images *)
           _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
  for (lip = &top; *lip != NULL; lip = &(*lip)->next)
    {
      if ((*lip)->mh == m && (*lip)->vm_slide == s)
        {
          destroy = *lip;
          *lip = destroy->next;                        /* unlink DESTROY  */

          if (destroy->this_size != sizeof (*destroy))        /* sanity check  */
            abort ();

          break;
        }
    }
  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, top);

  /* Now that we have unlinked this from the image list, toss it.  */
  if (destroy != NULL)
    {
      if (destroy->destructor != NULL)
        (*destroy->destructor) (destroy);
      free (destroy);
    }
}
Пример #8
0
static int
add_routine (struct keymgr_atexit_list * g,
	     const struct one_atexit_routine * to_add)
{
  struct atexit_routine_list * s
    = malloc (sizeof (struct atexit_routine_list));
  int result;
  
  if (!s)
    {
      _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
      return -1;
    }
  s->r = *to_add;
  s->next = g->l;
  g->l = s;
  result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
  return CHECK_KEYMGR_ERROR (result) == 0 ? 0 : -1;
}
Пример #9
0
static void
darwin_unwind_dyld_add_image_hook (struct mach_header *mh, unsigned long slide)
{
  struct live_images *l = (struct live_images *)calloc (1, sizeof (*l));
  l->mh = mh;
  l->vm_slide = slide;
  l->this_size = sizeof (*l);
  l->next = (struct live_images *)
        _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, l);
}
Пример #10
0
static void
our_atexit (void)
{
  struct keymgr_atexit_list *g;
  char prev_running;

  g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
  if (! g || g->version != 0 || g->atexit_status != atexit_status_missing)
    return;
  
  prev_running = g->running_routines;
  g->running_routines = 1;
  g = run_routines (g, NULL);
  if (! g)
    return;
  g->running_routines = prev_running;
  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
}
Пример #11
0
/* Create (if necessary), find, lock, fill in, and return our globals.  
   Return NULL on error, in which case the globals will not be locked.  
   The caller should call keymgr_set_and_unlock.  */
static struct keymgr_atexit_list *
get_globals (void)
{
  struct keymgr_atexit_list * r;
  
#ifdef __ppc__
  /* 10.3.9 doesn't have _keymgr_get_and_lock_processwide_ptr_2 so the
     PPC side can't use it.  On 10.4 this just means the error gets
     reported a little later when
     _keymgr_set_and_unlock_processwide_ptr finds that the key was
     never locked.  */
  r = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
#else
  void * rr;
  if (_keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_ATEXIT_LIST, &rr))
    return NULL;
  r = rr;
#endif
  
  if (r == NULL)
    {
      r = calloc (sizeof (struct keymgr_atexit_list), 1);
      if (! r)
	return NULL;
    }

  if (r->atexit_status == atexit_status_unknown)
    {
      void *handle;

      handle = dlopen ("/usr/lib/libSystem.B.dylib", RTLD_NOLOAD);
      if (!handle)
	{
#ifdef __ppc__
	  r->atexit_status = atexit_status_missing;
	  r->atexit_f = find_atexit_10_3 ();
	  if (! r->atexit_f)
	    goto error;
	  if (r->atexit_f (our_atexit))
	    goto error;
#else
	  goto error;
#endif
	}
      else
	{
	  int chk_result;

	  r->cxa_atexit_f = (cxa_atexit_p)dlsym (handle, "__cxa_atexit");
	  r->cxa_finalize_f = (cxa_finalize_p)dlsym (handle, "__cxa_finalize");
	  if (! r->cxa_atexit_f || ! r->cxa_finalize_f)
	    goto error;

	  chk_result = check_cxa_atexit (r->cxa_atexit_f, r->cxa_finalize_f);
	  if (chk_result == -1)
	    goto error;
	  else if (chk_result == 0)
	    r->atexit_status = atexit_status_broken;
	  else
	    {
	      r->atexit_f = (atexit_p)dlsym (handle, "atexit");
	      if (! r->atexit_f)
		goto error;
	      r->atexit_status = atexit_status_working;
	    }
	}
    }

  return r;
  
 error:
  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, r);
  return NULL;
}