View | Details | Raw Unified | Return to bug 115631
Collapse All | Expand All

(-)lib/libc/stdlib/atexit.h (+20 lines)
Lines 34-36 Link Here
34
#define	ATEXIT_SIZE	32
34
#define	ATEXIT_SIZE	32
35
35
36
void __cxa_finalize(void *dso);
36
void __cxa_finalize(void *dso);
37
38
#define	ATEXIT_FN_EMPTY	0
39
#define	ATEXIT_FN_STD	1
40
#define	ATEXIT_FN_CXA	2
41
42
struct atexit {
43
	struct atexit *next;			/* next in list */
44
	int ind;				/* next index in this table */
45
	struct atexit_fn {
46
		int fn_type;			/* ATEXIT_? from above */
47
		union {
48
			void (*std_func)(void);
49
			void (*cxa_func)(void *);
50
		} fn_ptr;			/* function pointer */
51
		void *fn_arg;			/* argument for CXA callback */
52
		void *fn_dso;			/* shared module handle */
53
	} fns[ATEXIT_SIZE];			/* the table itself */
54
};
55
56
extern struct atexit *__atexit;		/* points to head of LIFO stack */
(-)libexec/rtld-elf/Makefile (+1 lines)
Lines 8-13 Link Here
8
MK_SSP=		no
8
MK_SSP=		no
9
9
10
PROG?=		ld-elf.so.1
10
PROG?=		ld-elf.so.1
11
CFLAGS+=	-I${.CURDIR:H:H}/lib/libc/stdlib	# atexit.h
11
SRCS=		rtld_start.S \
12
SRCS=		rtld_start.S \
12
		reloc.c rtld.c rtld_lock.c rtld_printf.c map_object.c \
13
		reloc.c rtld.c rtld_lock.c rtld_printf.c map_object.c \
13
		malloc.c xmalloc.c debug.c libmap.c
14
		malloc.c xmalloc.c debug.c libmap.c
(-)libexec/rtld-elf/rtld.c (-1 / +79 lines)
Lines 57-62 Link Here
57
#include <string.h>
57
#include <string.h>
58
#include <unistd.h>
58
#include <unistd.h>
59
59
60
#include "atexit.h"	/* Not a centrally installed header. Yet? */
60
#include "debug.h"
61
#include "debug.h"
61
#include "rtld.h"
62
#include "rtld.h"
62
#include "libmap.h"
63
#include "libmap.h"
Lines 123-128 Link Here
123
    Obj_Entry *rtldobj, int flags, RtldLockState *lockstate);
124
    Obj_Entry *rtldobj, int flags, RtldLockState *lockstate);
124
static int relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj,
125
static int relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj,
125
    int flags, RtldLockState *lockstate);
126
    int flags, RtldLockState *lockstate);
127
static const char *addr_to_name(const Obj_Entry *, const void *);
126
static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int,
128
static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int,
127
    RtldLockState *);
129
    RtldLockState *);
128
static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now,
130
static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now,
Lines 2706-2711 Link Here
2706
    return (p);
2708
    return (p);
2707
}
2709
}
2708
2710
2711
/*
2712
 * Check if the object being dlclose-d holds a function registered
2713
 * via atexit() or __cxa_atexit(). If it does, formulate a descriptive
2714
 * error message and return 1. Otherwise return 0 to allow the object
2715
 * to be closed/unloaded.
2716
 */
2717
static int
2718
check_atexit(const Obj_Entry *root)
2719
{
2720
	static const struct atexit	*__atexit;
2721
	const struct atexit	*p;
2722
	int	n;
2723
2724
	if (__atexit == NULL)
2725
		__atexit = (struct atexit *)get_program_var_addr("__atexit");
2726
2727
	for (p = __atexit; p; p = p->next) {
2728
		for (n = p->ind; --n >= 0;) {
2729
			void	*addr;
2730
			switch (p->fns[n].fn_type) {
2731
			case ATEXIT_FN_CXA:
2732
				if (p->fns[n].fn_dso == root)
2733
					continue;
2734
				addr = p->fns[n].fn_ptr.cxa_func;
2735
				break;
2736
			case ATEXIT_FN_STD:
2737
				addr = p->fns[n].fn_ptr.std_func;
2738
				break;
2739
			default:
2740
				continue;
2741
			}
2742
			if (addr > (void *)root->mapbase &&
2743
			    addr < (void *)root->mapbase + root->mapsize) {
2744
				const char *name = addr_to_name(root, addr);
2745
2746
				_rtld_error("shared object %s provides "
2747
				    "%satexit-registered function %p (%s)",
2748
				    root->path,
2749
				    p->fns[n].fn_type == ATEXIT_FN_STD ?
2750
					"an " : "a __cxa_",
2751
				    addr, name ? name : "static?");
2752
				return 1;
2753
			}
2754
		}
2755
	}
2756
	return 0;
2757
}
2758
2709
int
2759
int
2710
dlclose(void *handle)
2760
dlclose(void *handle)
2711
{
2761
{
Lines 2714-2720 Link Here
2714
2764
2715
    wlock_acquire(rtld_bind_lock, &lockstate);
2765
    wlock_acquire(rtld_bind_lock, &lockstate);
2716
    root = dlcheck(handle);
2766
    root = dlcheck(handle);
2717
    if (root == NULL) {
2767
    if (root == NULL || check_atexit(root)) {
2718
	lock_release(rtld_bind_lock, &lockstate);
2768
	lock_release(rtld_bind_lock, &lockstate);
2719
	return -1;
2769
	return -1;
2720
    }
2770
    }
Lines 3986-3991 Link Here
3986
	return (ESRCH);
4036
	return (ESRCH);
3987
}
4037
}
3988
4038
4039
/*
4040
 * If the addr-specified symbol exists in obj's symbol-table,
4041
 * return its name. Otherwise, return NULL. Searches through
4042
 * the entire symbol table, but we don't care, because it is
4043
 * not called often.
4044
 */
4045
static const char *
4046
addr_to_name(const Obj_Entry *obj, const void *addr)
4047
{
4048
	unsigned long symnum, bucket;
4049
	if (obj->buckets == NULL)
4050
		return NULL;
4051
4052
	for (bucket = 0; bucket < obj->nbuckets; bucket++) {
4053
		for (symnum = obj->buckets[bucket];
4054
		    symnum != STN_UNDEF && symnum < obj->nchains;
4055
		    symnum = obj->chains[symnum]) {
4056
			const Elf_Sym *symp;
4057
4058
			symp  = obj->symtab + symnum;
4059
			if (symp->st_value + obj->relocbase == addr)
4060
				return obj->strtab + symp->st_name;
4061
		}
4062
	}
4063
4064
	return NULL;
4065
}
4066
3989
static void
4067
static void
3990
trace_loaded_objects(Obj_Entry *obj)
4068
trace_loaded_objects(Obj_Entry *obj)
3991
{
4069
{

Return to bug 115631