Beispiel #1
0
/*
 * Call all handlers registered with __cxa_atexit for the shared
 * object owning 'dso'.  Note: if 'dso' is NULL, then all remaining
 * handlers are called.
 */
void
__cxa_finalize(void *dso)
{
	struct dl_phdr_info phdr_info;
	struct atexit *p;
	struct atexit_fn fn;
	int n, has_phdr;

	if (dso != NULL) {
		has_phdr = _rtld_addr_phdr(dso, &phdr_info);
	} else {
		has_phdr = 0;
		global_exit = 1;
	}

	_MUTEX_LOCK(&atexit_mutex);
	for (p = __atexit; p; p = p->next) {
		for (n = p->ind; --n >= 0;) {
			if (p->fns[n].fn_type == ATEXIT_FN_EMPTY)
				continue; /* already been called */
			fn = p->fns[n];
			if (dso != NULL && dso != fn.fn_dso) {
				/* wrong DSO ? */
				if (!has_phdr || global_exit ||
				    !__elf_phdr_match_addr(&phdr_info,
				    fn.fn_ptr.cxa_func))
					continue;
			}
			/*
			  Mark entry to indicate that this particular handler
			  has already been called.
			*/
			p->fns[n].fn_type = ATEXIT_FN_EMPTY;
		        _MUTEX_UNLOCK(&atexit_mutex);
		
			/* Call the function of correct type. */
			if (fn.fn_type == ATEXIT_FN_CXA)
				fn.fn_ptr.cxa_func(fn.fn_arg);
			else if (fn.fn_type == ATEXIT_FN_STD)
				fn.fn_ptr.std_func();
			_MUTEX_LOCK(&atexit_mutex);
		}
	}
	_MUTEX_UNLOCK(&atexit_mutex);
	if (dso == NULL)
		_MUTEX_DESTROY(&atexit_mutex);

	if (has_phdr && !global_exit && &__pthread_cxa_finalize != NULL)
		__pthread_cxa_finalize(&phdr_info);
}
/*
 * Unwind helper for dynamically linked code.
 *
 * This finds the shared object that contains the given address, and returns the
 * address of the exidx section in that shared object along with the number of
 * entries in that section, or NULL if it wasn't found.
 */
void *
dl_unwind_find_exidx(const void *pc, int *pcount)
{
	const Elf_Phdr *hdr;
	struct dl_phdr_info info;
	int i;

	if (_rtld_addr_phdr(pc, &info)) {
		hdr = info.dlpi_phdr;
		for (i = 0; i < info.dlpi_phnum; i++, hdr++) {
			if (hdr->p_type == PT_ARM_EXIDX) {
				*pcount = hdr->p_memsz / sizeof(exidx_entry);
				return ((void *)(info.dlpi_addr + hdr->p_vaddr));
			}
		}
	}
	return (NULL);
}