/* Handle loading/unloading of shared object for transformation.
- Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
#include <assert.h>
#include <dlfcn.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
-#include <bits/libc-lock.h>
+#include <libc-lock.h>
#include <sys/param.h>
#include <gconv_int.h>
+#include <sysdep.h>
#ifdef DEBUG
/* Open the gconv database if necessary. A non-negative return value
means success. */
struct __gconv_loaded_object *
-internal_function
__gconv_find_shlib (const char *name)
{
struct __gconv_loaded_object *found;
found->init_fct = __libc_dlsym (found->handle, "gconv_init");
found->end_fct = __libc_dlsym (found->handle, "gconv_end");
+#ifdef PTR_MANGLE
+ PTR_MANGLE (found->fct);
+ PTR_MANGLE (found->init_fct);
+ PTR_MANGLE (found->end_fct);
+#endif
+
/* We have succeeded in loading the shared object. */
found->counter = 1;
}
return found;
}
-
-/* This is very ugly but the tsearch functions provide no way to pass
- information to the walker function. So we use a global variable.
- It is MT safe since we use a lock. */
-static struct __gconv_loaded_object *release_handle;
-
static void
-do_release_shlib (void *nodep, VISIT value, int level)
+do_release_shlib (const void *nodep, VISIT value, void *closure)
{
+ struct __gconv_loaded_object *release_handle = closure;
struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
if (value != preorder && value != leaf)
/* Notify system that a shared object is not longer needed. */
void
-internal_function
__gconv_release_shlib (struct __gconv_loaded_object *handle)
{
- /* Urgh, this is ugly but we have no other possibility. */
- release_handle = handle;
-
/* Process all entries. Please note that we also visit entries
with release counts <= 0. This way we can finally unload them
if necessary. */
- __twalk (loaded, (__action_fn_t) do_release_shlib);
+ __twalk_r (loaded, do_release_shlib, handle);
}
/* We run this if we debug the memory allocation. */
-static void
+static void __libc_freeres_fn_section
do_release_all (void *nodep)
{
struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;
free (obj);
}
-static void __attribute__ ((unused))
-free_mem (void)
+libc_freeres_fn (free_mem)
{
__tdestroy (loaded, do_release_all);
+ loaded = NULL;
}
-text_set_element (__libc_subfreeres, free_mem);
#ifdef DEBUG
+
+#include <stdio.h>
+
static void
do_print (const void *nodep, VISIT value, int level)
{
struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
printf ("%10s: \"%s\", %d\n",
- value == leaf ? "leaf" :
- value == preorder ? "preorder" :
- value == postorder ? "postorder" : "endorder",
+ value == leaf ? "leaf"
+ : value == preorder ? "preorder"
+ : value == postorder ? "postorder" : "endorder",
obj->name, obj->counter);
}
-static void
+static void __attribute__ ((used))
print_all (void)
{
__twalk (loaded, do_print);