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 |
{ |