/*	$OpenBSD: atexit.c,v 1.14 2007/09/05 20:47:47 chl Exp $ */
/*
 * Copyright (c) 2002 Daniel Hartmeier
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *      disclaimer in the documentation and/or other materials provided
 *      with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "atexit.h"
#include "private/thread_private.h"

struct atexit *__atexit;

/*
 * TODO: Read this before upstreaming:
 *
 * As of Apr 2014 there is a bug regaring function type detection logic in
 * Free/Open/NetBSD implementations of __cxa_finalize().
 *
 * What it is about:
 * First of all there are two kind of atexit handlers:
 *  1) void handler(void) - this is the regular type
 *     available for to user via atexit(.) function call.
 *
 *  2) void internal_handler(void*) - this is the type
 *     __cxa_atexit() function expects. This handler is used
 *     by C++ compiler to register static destructor calls.
 *     Note that calling this function as the handler of type (1)
 *     results in incorrect this pointer in static d-tors.
 *
 * What is wrong with BSD implementations:
 *
 *  They use dso argument to identify the handler type. The problem
 *  with it is dso is also used to identify the handlers associated
 *  with particular dynamic library and allow __cxa_finalize to call correct
 *  set of functions on dlclose(). And it cannot identify both.
 *
 * What is correct way to identify function type?
 *
 *  Consider this:
 *  1. __cxa_finalize and __cxa_atexit are part of libc and do not have access to hidden
 *     &__dso_handle.
 *  2. __cxa_atexit has only 3 arguments: function pointer, function argument, dso.
 *     none of them can be reliably used to pass information about handler type.
 *  3. following http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (3.3.5.3 - B)
 *     translation of user atexit -> __cxa_atexit(f, NULL, NULL) results in crashes
 *     on exit() after dlclose() of a library with an atexit() call.
 *
 *  One way to resolve this is to always call second form of handler, which will
 *  result in storing unused argument in register/stack depending on architecture
 *  and should not present any problems.
 *
 *  Another way is to make them dso-local in one way or the other.
 */

/*
 * Function pointers are stored in a linked list of pages. The list
 * is initially empty, and pages are allocated on demand. The first
 * function pointer in the first allocated page (the last one in
 * the linked list) was reserved for the cleanup function.
 *
 * Outside the following functions, all pages are mprotect()'ed
 * to prevent unintentional/malicious corruption.
 */

/*
 * Register a function to be performed at exit or when a shared object
 * with the given dso handle is unloaded dynamically.  Also used as
 * the backend for atexit().  For more info on this API, see:
 *
 *	http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
 */
int
__cxa_atexit(void (*func)(void *), void *arg, void *dso)
{
	struct atexit *p = __atexit;
	struct atexit_fn *fnp;
	size_t pgsize = sysconf(_SC_PAGESIZE);
	int ret = -1;

	if (pgsize < sizeof(*p))
		return (-1);
	_ATEXIT_LOCK();
	p = __atexit;
	if (p != NULL) {
		if (p->ind + 1 >= p->max)
			p = NULL;
		else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
			goto unlock;
	}
	if (p == NULL) {
		p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
		    MAP_ANON | MAP_PRIVATE, -1, 0);
		if (p == MAP_FAILED)
			goto unlock;
		if (__atexit == NULL) {
			memset(&p->fns[0], 0, sizeof(p->fns[0]));
			p->ind = 1;
		} else
			p->ind = 0;
		p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
		    sizeof(p->fns[0]);
		p->next = __atexit;
		__atexit = p;
	}
	fnp = &p->fns[p->ind++];
	fnp->cxa_func = func;
	fnp->fn_arg = arg;
	fnp->fn_dso = dso;
	if (mprotect(p, pgsize, PROT_READ))
		goto unlock;
	ret = 0;
unlock:
	_ATEXIT_UNLOCK();
	return (ret);
}

/*
 * 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 atexit *p, *q, *original_atexit;
	struct atexit_fn fn;
	int n, pgsize = getpagesize(), original_ind;
	static int call_depth;

	_ATEXIT_LOCK();
	call_depth++;

	p = original_atexit = __atexit;
	n = original_ind = p != NULL ? p->ind : 0;
	while (p != NULL) {
		if (p->fns[n].cxa_func != NULL /* not called */
				&& (dso == NULL || dso == p->fns[n].fn_dso)) { /* correct DSO */
			/*
			 * Mark handler as having been already called to avoid
			 * dupes and loops, then call the appropriate function.
			 */
			fn = p->fns[n];
			if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
				p->fns[n].cxa_func = NULL;
				mprotect(p, pgsize, PROT_READ);
			}

			_ATEXIT_UNLOCK();
			(*fn.cxa_func)(fn.fn_arg);
			_ATEXIT_LOCK();
			// check for new atexit handlers
			if ((__atexit->ind != original_ind) || (__atexit != original_atexit)) {
				// need to restart now to preserve correct
				// call order - LIFO
				p = original_atexit = __atexit;
				n = original_ind = p->ind;
				continue;
			}
		}
		if (n == 0) {
			p = p->next;
			n = p != NULL ? p->ind : 0;
		} else {
			--n;
		}
	}

	--call_depth;

	/*
	 * If called via exit(), unmap the pages since we have now run
	 * all the handlers.  We defer this until calldepth == 0 so that
	 * we don't unmap things prematurely if called recursively.
	 */
	if (dso == NULL && call_depth == 0) {
		for (p = __atexit; p != NULL; ) {
			q = p;
			p = p->next;
			munmap(q, pgsize);
		}
		__atexit = NULL;
	}
	_ATEXIT_UNLOCK();
}

/*
 * Register the cleanup function
 */
void
__atexit_register_cleanup(void (*func)(void))
{
        struct atexit *p;
        size_t pgsize = sysconf(_SC_PAGESIZE);

        if (pgsize < sizeof(*p))
                return;
        _ATEXIT_LOCK();
        p = __atexit;
        while (p != NULL && p->next != NULL)
                p = p->next;
        if (p == NULL) {
                p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
                    MAP_ANON | MAP_PRIVATE, -1, 0);
                if (p == MAP_FAILED)
                        goto unlock;
                p->ind = 1;
                p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
                    sizeof(p->fns[0]);
                p->next = NULL;
                __atexit = p;
        } else {
                if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
                        goto unlock;
        }
        p->fns[0].cxa_func = (void (*)(void*))func;
        p->fns[0].fn_arg = NULL;
        p->fns[0].fn_dso = NULL;
        mprotect(p, pgsize, PROT_READ);
unlock:
        _ATEXIT_UNLOCK();
}

