Beispiel #1
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);
    }
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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 = ⊤ *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);
    }
}
_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;
}
Beispiel #7
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);
}
Beispiel #8
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);
}
Beispiel #9
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;
}
Beispiel #10
0
static inline const fde *
examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
{
  const fde *result = NULL;
  struct live_images *image;

  image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);

  for (; image != NULL; image = image->next)
    if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
      {
        char *fde = NULL;
        unsigned long sz;

        /* For ppc only check whether or not we have __DATA eh frames.  */
#ifdef __ppc__
        fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
#endif

        if (fde == NULL)
          {
#if __LP64__
            fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
                                            "__TEXT", "__eh_frame", &sz);
#else
            fde = getsectdatafromheader (image->mh, "__TEXT",
                                         "__eh_frame", &sz);
#endif
            if (fde != NULL)
              image->examined_p |= IMAGE_IS_TEXT_MASK;
          }

        /* If .eh_frame is empty, don't register at all.  */
        if (fde != NULL && sz > 0)
          {
            char *real_fde = (fde + image->vm_slide);
            struct object *ob = NULL;
            struct object panicob;

            if (! dont_alloc)
              ob = calloc (1, sizeof (struct object));
            dont_alloc |= ob == NULL;
            if (dont_alloc)
              ob = &panicob;

            ob->pc_begin = (void *)-1;
            ob->tbase = 0;
            ob->dbase = 0;
            ob->u.single = (struct dwarf_fde *)real_fde;
            ob->s.i = 0;
            ob->s.b.encoding = DW_EH_PE_omit;
            ob->fde_end = real_fde + sz;

            image->fde = real_fde;

            result = search_object (ob, pc);

            if (! dont_alloc)
              {
                struct object **p;

                image->destructor = live_image_destructor;
                image->object_info = ob;

                image->examined_p |= (EXAMINED_IMAGE_MASK
                                      | DESTRUCTOR_MAY_BE_CALLED_LIVE);

                /* Insert the object into the classified list.  */
                for (p = &seen_objects; *p ; p = &(*p)->next)
                  if ((*p)->pc_begin < ob->pc_begin)
                    break;
                ob->next = *p;
                *p = ob;
              }

            if (result)
              {
                int encoding;
                _Unwind_Ptr func;

                bases->tbase = ob->tbase;
                bases->dbase = ob->dbase;

                encoding = ob->s.b.encoding;
                if (ob->s.b.mixed_encoding)
                  encoding = get_fde_encoding (result);
                read_encoded_value_with_base (encoding,
                                              base_from_object (encoding, ob),
                                              result->pc_begin, &func);
                bases->func = (void *) func;
                break;
              }
          }
        else
          image->examined_p |= EXAMINED_IMAGE_MASK;
      }

  _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);

  return result;
}