From: Gary V. Vaughan Date: Thu, 15 Jul 2004 12:33:20 +0000 (+0000) Subject: Split lt_dlloader management into a separate file, and factor X-Git-Tag: release-1-9b~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5451db06bd5391fa674846acba23b1a1ab778bc9;p=thirdparty%2Flibtool.git Split lt_dlloader management into a separate file, and factor `loaders' list management into a new SList ADT. In the process, the API for writing loaders is a little cleaner, so all the existing loaders were tweaked to take advantage of that: * libltdl/slist.h, libltdl/slist.c: New files implementing a generic singly linked list container ADT. The ADT is purely internal, and none of its API's are visible from an installed libltdl. * libltdl/lt_dlloader.h (lt_dlloader): Removed next field again :-) Renamed to lt_dlvtable for API. Changed all callers. (lt_dlloader_get): New function to turn an lt_dlloader into its associated lt_dlvtable. (lt_dlloader_add): Removed unused data parameter. The caller data belongs to (and is set by) the loader itself, not the loader's client. Changed all callers. (lt_dlloader_name, lt_dlloader_data): Removed. Use lt_dlloader_get instead! * libltdl/lt__private.h: Include slist.h. (lt__alloc_die_callback): Add missing LT_SCOPE to declaration. (lt_dlhandle_struct): Use lt_dlvtable instead of opaque lt_dlloader. * libltdl/ltdl.c (lt_dlexit): Rewritten for the new loader API. (loaders, lt_dlloader_add, lt_dlloader_remove, lt_dlloader_next, lt_dlloader_find): Moved from here... * libltdl/lt_dlloader.c ((loaders, lt_dlloader_add, lt_dlloader_remove, lt_dlloader_next, lt_dlloader_find): ...to here. And rewritten in terms of new SList interface. * libltdl/ltdl.c (lt_dlexit, tryall_dlopen): Rewritten in terms of new lt_dlloader interface. * libltdl/Makefile.am (libdlloader_la_SOURCES): Add slist.h and slist.c. Move lt_dlloader.h from here... (pkginclude_HEADERS): ...to here. (libltdl_la_SOURCES): Add lt_dlloader.c and lt_dlloader.h. --- diff --git a/ChangeLog b/ChangeLog index a286dad7c..7c3a094b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2004-07-15 Gary V. Vaughan + + Split lt_dlloader management into a separate file, and factor + `loaders' list management into a new SList ADT. In the process, + the API for writing loaders is a little cleaner, so all the + existing loaders were tweaked to take advantage of that: + + * libltdl/slist.h, libltdl/slist.c: New files implementing a + generic singly linked list container ADT. The ADT is purely + internal, and none of its API's are visible from an installed + libltdl. + * libltdl/lt_dlloader.h (lt_dlloader): Removed next field again + :-) Renamed to lt_dlvtable for API. Changed all callers. + (lt_dlloader_get): New function to turn an lt_dlloader into its + associated lt_dlvtable. + (lt_dlloader_add): Removed unused data parameter. The caller + data belongs to (and is set by) the loader itself, not the + loader's client. Changed all callers. + (lt_dlloader_name, lt_dlloader_data): Removed. Use + lt_dlloader_get instead! + * libltdl/lt__private.h: Include slist.h. + (lt__alloc_die_callback): Add missing LT_SCOPE to declaration. + (lt_dlhandle_struct): Use lt_dlvtable instead of opaque + lt_dlloader. + * libltdl/ltdl.c (lt_dlexit): Rewritten for the new loader API. + (loaders, lt_dlloader_add, lt_dlloader_remove, lt_dlloader_next, + lt_dlloader_find): Moved from here... + * libltdl/lt_dlloader.c ((loaders, lt_dlloader_add, + lt_dlloader_remove, lt_dlloader_next, lt_dlloader_find): ...to + here. And rewritten in terms of new SList interface. + * libltdl/ltdl.c (lt_dlexit, tryall_dlopen): Rewritten in terms of + new lt_dlloader interface. + * libltdl/Makefile.am (libdlloader_la_SOURCES): Add slist.h and + slist.c. Move lt_dlloader.h from here... + (pkginclude_HEADERS): ...to here. + (libltdl_la_SOURCES): Add lt_dlloader.c and lt_dlloader.h. + 2004-07-15 Gary V. Vaughan Collapse two almost identical structures into one: diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am index 660fce4f3..dfc16052d 100644 --- a/libltdl/Makefile.am +++ b/libltdl/Makefile.am @@ -35,16 +35,17 @@ pkgincludedir = $(includedir)/libltdl lib_LTLIBRARIES = libdlloader.la libdlloader_la_SOURCES = lt_error.h lt_error.c \ - lt__private.h lt_dlloader.h \ + lt__private.h lt_system.h \ lt__alloc.h lt__alloc.c \ - lt__glibc.h lt_system.h + lt__glibc.h \ + slist.h slist.c libdlloader_la_LDFLAGS = $(VERSION_INFO) libdlloader_la_LIBADD = $(LTLIBOBJS) ## Libltdl brings it all together: if INSTALL_LTDL include_HEADERS = ltdl.h -pkginclude_HEADERS = lt_system.h lt_error.h +pkginclude_HEADERS = lt_system.h lt_error.h lt_dlloader.h lib_LTLIBRARIES += libltdl.la endif @@ -52,7 +53,8 @@ if CONVENIENCE_LTDL noinst_LTLIBRARIES = libltdlc.la endif -libltdl_la_SOURCES = ltdl.h ltdl.c loaders/preopen.c +libltdl_la_SOURCES = ltdl.h ltdl.c \ + lt_dlloader.h lt_dlloader.c loaders/preopen.c libltdl_la_CPPFLAGS = -DLTDLOPEN=libltdl $(AM_CPPFLAGS) libltdl_la_LDFLAGS = $(VERSION_INFO) $(LT_DLPREOPEN) libltdl_la_LIBADD = libdlloader.la diff --git a/libltdl/loaders/dld_link.c b/libltdl/loaders/dld_link.c index 51a4d59a8..ba8fed9cc 100644 --- a/libltdl/loaders/dld_link.c +++ b/libltdl/loaders/dld_link.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable dld_link_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlloader *vtable = 0; + static lt_dlvtable *vtable = 0; if (!vtable) { vtable = lt__zalloc (sizeof *vtable); } - if (!vtable->name) + if (vtable && !vtable->name) { vtable->name = "lt_dld_link"; vtable->module_open = vm_open; @@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data) vtable->priority = LT_DLLOADER_APPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/loaders/dlopen.c b/libltdl/loaders/dlopen.c index cfb9a9277..f477b498a 100644 --- a/libltdl/loaders/dlopen.c +++ b/libltdl/loaders/dlopen.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable dlopen_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlloader *vtable = 0; + static lt_dlvtable *vtable = 0; if (!vtable) { vtable = lt__zalloc (sizeof *vtable); } - if (!vtable->name) + if (vtable && !vtable->name) { vtable->name = "lt_dlopen"; #if defined(NEED_USCORE) @@ -72,7 +72,7 @@ get_vtable (lt_user_data loader_data) vtable->priority = LT_DLLOADER_PREPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/loaders/dyld.c b/libltdl/loaders/dyld.c index 0d994b07f..5c5e9ab3e 100644 --- a/libltdl/loaders/dyld.c +++ b/libltdl/loaders/dyld.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable dyld_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -51,17 +51,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlloader *vtable = 0; + static lt_dlvtable *vtable = 0; if (!vtable) { vtable = lt__zalloc (sizeof *vtable); } - if (!vtable->name) + if (vtable && !vtable->name) { vtable->name = "lt_dyld"; vtable->sym_prefix = "_"; @@ -73,7 +73,7 @@ get_vtable (lt_user_data loader_data) vtable->priority = LT_DLLOADER_APPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/loaders/load_add_on.c b/libltdl/loaders/load_add_on.c index d29bd8261..6d3e904e4 100644 --- a/libltdl/loaders/load_add_on.c +++ b/libltdl/loaders/load_add_on.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable load_add_on_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlloader *vtable = 0; + static lt_dlvtable *vtable = 0; if (!vtable) { vtable = lt__zalloc (sizeof *vtable); } - if (!vtable->name) + if (vtable && !vtable->name) { vtable->name = "lt_load_add_on"; vtable->module_open = vm_open; @@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data) vtable->priority = LT_DLLOADER_APPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/loaders/loadlibrary.c b/libltdl/loaders/loadlibrary.c index df123d6cb..98fc1ec97 100644 --- a/libltdl/loaders/loadlibrary.c +++ b/libltdl/loaders/loadlibrary.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable loadlibrary_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -49,7 +49,7 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { static lt_dlloader *vtable = 0; @@ -59,7 +59,7 @@ get_vtable (lt_user_data loader_data) vtable = lt__zalloc (sizeof *vtable); } - if (!vtable->name) + if (vtable && !vtable->name) { vtable->name = "lt_loadlibrary"; vtable->module_open = vm_open; @@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data) vtable->priority = LT_DLLOADER_APPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c index 171bcc273..958c5a4e3 100644 --- a/libltdl/loaders/preopen.c +++ b/libltdl/loaders/preopen.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable preopen_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -51,30 +51,30 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlloader *vtable = 0; + static lt_dlvtable *vtable = 0; if (!vtable) { vtable = lt__malloc (sizeof *vtable); } - if (!vtable->name) + if (vtable && !vtable->name) { vtable->name = "lt_preopen"; vtable->sym_prefix = 0; - vtable->dlloader_init = vl_init; - vtable->dlloader_exit = vl_exit; vtable->module_open = vm_open; vtable->module_close = vm_close; vtable->find_sym = vm_sym; + vtable->dlloader_init = vl_init; + vtable->dlloader_exit = vl_exit; vtable->dlloader_data = loader_data; vtable->priority = LT_DLLOADER_PREPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/loaders/shl_load.c b/libltdl/loaders/shl_load.c index 20635aa1b..cfd9f7494 100644 --- a/libltdl/loaders/shl_load.c +++ b/libltdl/loaders/shl_load.c @@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA be fetched from the preloaded symbol list by lt_dlsym(): */ #define get_vtable shl_load_LTX_get_vtable -extern lt_dlloader *get_vtable (lt_user_data loader_data); +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); /* Boilerplate code to set up the vtable for hooking this loader into @@ -49,17 +49,17 @@ static void * vm_sym (lt_user_data loader_data, lt_module module, /* Return the vtable for this loader, only the name and sym_prefix attributes (plus the virtual function implementations, obviously) change between loaders. */ -lt_dlloader * +lt_dlvtable * get_vtable (lt_user_data loader_data) { - static lt_dlloader *vtable = 0; + static lt_dlvtable *vtable = 0; if (!vtable) { vtable = lt__zalloc (sizeof *vtable); } - if (!vtable->name) + if (table && !vtable->name) { vtable->name = "lt_shl_load"; vtable->module_open = vm_open; @@ -69,7 +69,7 @@ get_vtable (lt_user_data loader_data) vtable->priority = LT_DLLOADER_APPEND; } - if (vtable->dlloader_data != loader_data) + if (vtable && (vtable->dlloader_data != loader_data)) { LT__SETERROR (INIT_LOADER); return 0; diff --git a/libltdl/lt__private.h b/libltdl/lt__private.h index e5e7b602f..90734dccb 100644 --- a/libltdl/lt__private.h +++ b/libltdl/lt__private.h @@ -58,6 +58,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #include "lt__alloc.h" #include "lt__dirent.h" #include "lt__glibc.h" +#include "slist.h" /* ...and all exported interfaces. */ #include "ltdl.h" @@ -79,7 +80,7 @@ LT_BEGIN_C_DECLS extern int errno; #endif -void lt__alloc_die_callback (void); +LT_SCOPE void lt__alloc_die_callback (void); /* For readability: */ @@ -98,13 +99,13 @@ typedef struct { struct lt_dlhandle_struct { struct lt_dlhandle_struct *next; - lt_dlloader *loader; /* dlopening interface */ + const lt_dlvtable * vtable; /* dlopening interface */ lt_dlinfo info; /* user visible fields */ int depcount; /* number of dependencies */ - lt_dlhandle *deplibs; /* dependencies */ + lt_dlhandle * deplibs; /* dependencies */ lt_module module; /* system module handle */ void * system; /* system specific data */ - lt_caller_data *caller_data; /* per caller associated data */ + lt_caller_data * caller_data; /* per caller associated data */ int flags; /* various boolean stats */ }; diff --git a/libltdl/lt_dlloader.c b/libltdl/lt_dlloader.c new file mode 100644 index 000000000..e4d9195b3 --- /dev/null +++ b/libltdl/lt_dlloader.c @@ -0,0 +1,156 @@ +/* lt_dlloader.c -- dynamic library loader interface + Copyright (C) 2004 Free Software Foundation, Inc. + Originally by Gary V. Vaughan + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA + +*/ + +#include "lt_dlloader.h" +#include "lt__private.h" + +#define RETURN_SUCCESS 0 +#define RETURN_FAILURE 1 + +static void * loader_cmp (const SList *node, const void *userdata); + +/* A list of all the dlloaders we know about, each stored in the + USERDATA field of an SList node: */ +static SList *loaders = 0; + +/* Return NULL, unless the loader in this NODE has a matching name, + in which case we return the vtable from matching node so that its + address is passed back out (for possible freeing) by slist_remove. */ +static void * +loader_cmp (const SList *node, const void *userdata) +{ + const lt_dlvtable *vtable = node->userdata; + const char * name = userdata; + + assert (vtable); + + return streq (vtable->name, name) ? (void *) vtable : 0; +} + + +/* Hook VTABLE into our global LOADERS list according to its own + PRIORITY field value. */ +int +lt_dlloader_add (const lt_dlvtable *vtable) +{ + if ((vtable == 0) /* diagnose null parameters */ + || (vtable->module_open == 0) + || (vtable->module_close == 0) + || (vtable->find_sym == 0)) + { + LT__SETERROR (INVALID_LOADER); + return RETURN_FAILURE; + } + + switch (vtable->priority) + { + case LT_DLLOADER_PREPEND: + loaders = slist_cons (slist_new (vtable), loaders); + break; + + case LT_DLLOADER_APPEND: + loaders = slist_concat (loaders, slist_new (vtable)); + break; + + default: + LT__SETERROR (INVALID_LOADER); + return RETURN_FAILURE; + /*NOTREACHED*/ + } + + return RETURN_SUCCESS; +} + + +/* An iterator for the global loader list: if LOADER is NULL, then + return the first element, otherwise the following element. */ +lt_dlloader +lt_dlloader_next (lt_dlloader loader) +{ + SList *node = (SList *) loader; + return (lt_dlloader) (node ? node->next : loaders); +} + + +const lt_dlvtable * +lt_dlloader_get (lt_dlloader loader) +{ + return ((SList *) loader)->userdata; +} + +/* Return the contents of the first item in the global loader list + with a matching NAME after removing it from that list. If there + was no match, return NULL; if there is an error, return NULL and + set an error for lt_dlerror; in either case the loader list is + not changed. */ +const lt_dlvtable * +lt_dlloader_remove (const char *name) +{ + const lt_dlvtable * vtable = lt_dlloader_find (name); + lt_dlhandle handle = 0; + int errors = 0; + + if (!vtable) + { + LT__SETERROR (INVALID_LOADER); + return 0; + } + + /* Fail if there are any open modules which use this loader. */ + while (handle = lt_dlhandle_next (handle)) + { + if (handle->vtable == vtable) + { + LT__SETERROR (REMOVE_LOADER); + return 0; + } + } + + /* Call the loader finalisation function. */ + if (vtable && vtable->dlloader_exit) + { + if (vtable->dlloader_exit (vtable->dlloader_data) != 0) + { + /* If there is an exit function, and it returns non-zero + then it must set an error, and we will not remove it + from the list. */ + return 0; + } + } + + /* If we got this far, remove the loader from our global list. */ + return slist_remove (&loaders, name, loader_cmp); +} + + +const lt_dlvtable * +lt_dlloader_find (const char *name) +{ + return slist_find (loaders, name, loader_cmp); +} diff --git a/libltdl/lt_dlloader.h b/libltdl/lt_dlloader.h index 7fd1f904f..c65df3876 100644 --- a/libltdl/lt_dlloader.h +++ b/libltdl/lt_dlloader.h @@ -31,26 +31,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #define LT_DLLOADER_H 1 #include -#include LT_BEGIN_C_DECLS -typedef struct lt_dlloader lt_dlloader; -typedef void * lt_user_data; -typedef void * lt_module; - -/* Type of a function to get a loader's vtable: */ -typedef lt_dlloader *lt_get_vtable (lt_user_data loader_data); +typedef void * lt_dlloader; +typedef void * lt_module; +typedef void * lt_user_data; /* Function pointer types for module loader vtable entries: */ -typedef int lt_dlloader_init (lt_user_data loader_data); -typedef int lt_dlloader_exit (lt_user_data loader_data); -typedef lt_module lt_module_open (lt_user_data loader_data, +typedef lt_module lt_module_open (lt_user_data data, const char *filename); -typedef int lt_module_close (lt_user_data loader_data, - lt_module handle); -typedef void * lt_find_sym (lt_user_data loader_data, - lt_module handle, const char *symbol); +typedef int lt_module_close (lt_user_data data, + lt_module module); +typedef void * lt_find_sym (lt_user_data data, lt_module module, + const char *symbolname); +typedef int lt_dlloader_init (lt_user_data data); +typedef int lt_dlloader_exit (lt_user_data data); /* Default priority is LT_DLLOADER_PREPEND if none is explicitly given. */ typedef enum { @@ -59,8 +55,7 @@ typedef enum { /* This structure defines a module loader, as populated by the get_vtable entry point of each loader. */ -struct lt_dlloader { - lt_dlloader * next; +typedef struct { const char * name; const char * sym_prefix; lt_module_open * module_open; @@ -70,22 +65,18 @@ struct lt_dlloader { lt_dlloader_exit * dlloader_exit; lt_user_data dlloader_data; lt_dlloader_priority priority; -}; - -LT_SCOPE lt_dlloader * lt_dlloader_next (lt_dlloader *place); -LT_SCOPE lt_dlloader * lt_dlloader_find (const char *name); -LT_SCOPE const char * lt_dlloader_name (lt_dlloader *place); -LT_SCOPE lt_user_data * lt_dlloader_data (lt_dlloader *place); -LT_SCOPE int lt_dlloader_add (lt_dlloader *dlloader, - lt_user_data data); -LT_SCOPE int lt_dlloader_remove (const char *name); +} lt_dlvtable; +LT_SCOPE int lt_dlloader_add (const lt_dlvtable *vtable); +LT_SCOPE lt_dlloader lt_dlloader_next (const lt_dlloader loader); +LT_SCOPE const lt_dlvtable *lt_dlloader_remove (const char *name); +LT_SCOPE const lt_dlvtable *lt_dlloader_find (const char *name); +LT_SCOPE const lt_dlvtable *lt_dlloader_get (lt_dlloader loader); -/* --- Backwards source compatibility --- */ - -#define lt_user_dlloader lt_dlloader +/* Type of a function to get a loader's vtable: */ +typedef const lt_dlvtable *lt_get_vtable (lt_user_data data); LT_END_C_DECLS diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c index c519227f3..dd2f6f1e7 100644 --- a/libltdl/ltdl.c +++ b/libltdl/ltdl.c @@ -58,7 +58,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA /* Various boolean flags can be stored in the flags field of an - lt_dlhandle_struct... */ + lt_dlhandle... */ #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) @@ -135,7 +135,6 @@ static int loader_init (lt_get_vtable *vtable_func, lt_user_data data); static char *user_search_path= 0; -static lt_dlloader *loaders = 0; static lt_dlhandle handles = 0; static int initialized = 0; @@ -160,7 +159,7 @@ loader_init_callback (lt_dlhandle handle) static int loader_init (lt_get_vtable *vtable_func, lt_user_data data) { - lt_dlloader *vtable = 0; + const lt_dlvtable *vtable = 0; int errors = 0; if (vtable_func) @@ -176,7 +175,7 @@ loader_init (lt_get_vtable *vtable_func, lt_user_data data) if (!errors) { - if (lt_dlloader_add (vtable, data)) + if (lt_dlloader_add (vtable)) { LT__SETERROR (DLOPEN_NOT_SUPPORTED); ++errors; @@ -199,14 +198,14 @@ loader_init (lt_get_vtable *vtable_func, lt_user_data data) #define get_vtable preopen_LTX_get_vtable #define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols) -extern lt_dlloader * get_vtable (lt_user_data data); -extern lt_dlsymlist preloaded_symbols; +LT_SCOPE const lt_dlvtable * get_vtable (lt_user_data data); +LT_SCOPE lt_dlsymlist preloaded_symbols; /* Initialize libltdl. */ int lt_dlinit (void) { - int errors = 0; + int errors = 0; /* Initialize only at first call. */ if (++initialized == 1) @@ -221,11 +220,12 @@ lt_dlinit (void) errors += loader_init (get_vtable, 0); /* Now open all the preloaded module loaders, so the application - can use them to lt_dlopen their own modules. */ + can use _them_ to lt_dlopen its own modules. */ if (!errors) { errors += lt_dlpreload (&preloaded_symbols); } + if (!errors) { errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback); @@ -239,11 +239,9 @@ int lt_dlexit (void) { /* shut down libltdl */ - lt_dlloader *loader; + lt_dlloader *loader = 0; int errors = 0; - loader = loaders; - if (!initialized) { LT__SETERROR (SHUTDOWN); @@ -287,18 +285,19 @@ lt_dlexit (void) } /* close all loaders */ - while (loader) + while (loader = lt_dlloader_next (loader)) { - lt_dlloader *next = loader->next; - lt_user_data data = loader->dlloader_data; - if (loader->dlloader_exit && loader->dlloader_exit (data)) + const lt_dlvtable *vtable = lt_dlloader_get (loader); + + if ((vtable = lt_dlloader_remove (vtable->name))) + { + FREE ((void *) vtable); + } + else { ++errors; } - - MEMREASSIGN (loader, next); } - loaders = 0; } done: @@ -306,44 +305,33 @@ lt_dlexit (void) } static int -tryall_dlopen (lt_dlhandle *handle, const char *filename) +tryall_dlopen (lt_dlhandle *phandle, const char *filename) { - lt_dlhandle cur; - lt_dlloader *loader; - const char *saved_error; - int errors = 0; + lt_dlhandle handle = 0; + const char * saved_error = 0; + int errors = 0; LT__GETERROR (saved_error); - cur = handles; - loader = loaders; - /* check whether the module was already opened */ - while (cur) + while (handle = lt_dlhandle_next (handle)) { - /* try to dlopen the program itself? */ - if (!cur->info.filename && !filename) - { - break; - } - - if (cur->info.filename && filename - && streq (cur->info.filename, filename)) + if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */ + || (handle->info.filename && filename + && streq (handle->info.filename, filename))) { break; } - - cur = cur->next; } - if (cur) + if (handle) { - ++cur->info.ref_count; - *handle = cur; + ++handle->info.ref_count; + *phandle = handle; goto done; } - cur = *handle; + handle = *phandle; if (filename) { /* Comment out the check of file permissions using access. @@ -358,8 +346,8 @@ tryall_dlopen (lt_dlhandle *handle, const char *filename) goto done; } */ - cur->info.filename = lt__strdup (filename); - if (!cur->info.filename) + handle->info.filename = lt__strdup (filename); + if (!handle->info.filename) { ++errors; goto done; @@ -367,36 +355,41 @@ tryall_dlopen (lt_dlhandle *handle, const char *filename) } else { - cur->info.filename = 0; + handle->info.filename = 0; } - while (loader) - { - lt_user_data data = loader->dlloader_data; + { + const lt_dlvtable *vtable = 0; + lt_dlloader *loader = 0; - cur->module = loader->module_open (data, filename); + while (loader = lt_dlloader_next (loader)) + { + vtable = lt_dlloader_get (loader); + handle->module = vtable->module_open (vtable->dlloader_data, filename); - if (cur->module != 0) - { - break; - } - loader = loader->next; - } + if (handle->module != 0) + { + break; + } + } - if (!loader) - { - FREE (cur->info.filename); - ++errors; - goto done; - } + if (!loader) + { + FREE (handle->info.filename); + ++errors; + goto done; + } + + handle->vtable = vtable; + } - cur->loader = loader; LT__SETERRORSTR (saved_error); done: return errors; } + static int tryall_dlopen_module (lt_dlhandle *handle, const char *prefix, const char *dirname, const char *dlname) @@ -1673,7 +1666,7 @@ lt_dlclose (lt_dlhandle handle) moment). */ if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) { - lt_user_data data = handle->loader->dlloader_data; + lt_user_data data = handle->vtable->dlloader_data; if (handle != handles) { @@ -1684,7 +1677,7 @@ lt_dlclose (lt_dlhandle handle) handles = handle->next; } - errors += handle->loader->module_close (data, handle->module); + errors += handle->vtable->module_close (data, handle->module); errors += unload_deplibs(handle); /* It is up to the callers to free the data itself. */ @@ -1728,7 +1721,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol) return 0; } - lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) + lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix) + LT_STRLEN (handle->info.name); if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) @@ -1745,7 +1738,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol) } } - data = handle->loader->dlloader_data; + data = handle->vtable->dlloader_data; if (handle->info.name) { const char *saved_error; @@ -1753,9 +1746,9 @@ lt_dlsym (lt_dlhandle handle, const char *symbol) LT__GETERROR (saved_error); /* this is a libtool module */ - if (handle->loader->sym_prefix) + if (handle->vtable->sym_prefix) { - strcpy(sym, handle->loader->sym_prefix); + strcpy(sym, handle->vtable->sym_prefix); strcat(sym, handle->info.name); } else @@ -1767,7 +1760,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol) strcat(sym, symbol); /* try "modulename_LTX_symbol" */ - address = handle->loader->find_sym (data, handle->module, sym); + address = handle->vtable->find_sym (data, handle->module, sym); if (address) { if (sym != lsym) @@ -1780,9 +1773,9 @@ lt_dlsym (lt_dlhandle handle, const char *symbol) } /* otherwise try "symbol" */ - if (handle->loader->sym_prefix) + if (handle->vtable->sym_prefix) { - strcpy(sym, handle->loader->sym_prefix); + strcpy(sym, handle->vtable->sym_prefix); strcat(sym, symbol); } else @@ -1790,7 +1783,7 @@ lt_dlsym (lt_dlhandle handle, const char *symbol) strcpy(sym, symbol); } - address = handle->loader->find_sym (data, handle->module, sym); + address = handle->vtable->find_sym (data, handle->module, sym); if (sym != lsym) { FREE (sym); @@ -1995,12 +1988,14 @@ lt_dlgetinfo (lt_dlhandle handle) return &(handle->info); } + lt_dlhandle lt_dlhandle_next (lt_dlhandle place) { return place ? place->next : handles; } + lt_dlhandle lt_dlhandle_find (const char *module_name) { @@ -2116,161 +2111,6 @@ lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle) } - -/* --- USER MODULE LOADER API --- */ - - -int -lt_dlloader_add (lt_dlloader *dlloader, lt_user_data data) -{ - int errors = 0; - lt_dlloader *ptr = 0; - - if ((dlloader == 0) /* diagnose null parameters */ - || (dlloader->module_open == 0) - || (dlloader->module_close == 0) - || (dlloader->find_sym == 0)) - { - LT__SETERROR (INVALID_LOADER); - return 1; - } - - switch (dlloader->priority) - { - case LT_DLLOADER_PREPEND: - /* Tack NODE on the front of the LOADERS list. */ - dlloader->next = loaders; - loaders = dlloader; - break; - - case LT_DLLOADER_APPEND: - /* Add NODE to the end of the LOADERS list. */ - for (ptr = loaders; ptr->next; ptr = ptr->next) - /*NOWORK*/; - ptr->next = dlloader; - break; - - default: - LT__SETERROR (INVALID_LOADER); - ++errors; - break; - } - - return errors; -} - -int -lt_dlloader_remove (const char *name) -{ - lt_dlloader *place = lt_dlloader_find (name); - lt_dlhandle handle; - int errors = 0; - - if (!place) - { - LT__SETERROR (INVALID_LOADER); - return 1; - } - - /* Fail if there are any open modules which use this loader. */ - for (handle = handles; handle; handle = handle->next) - { - if (handle->loader == place) - { - LT__SETERROR (REMOVE_LOADER); - return ++errors; - } - } - - if (place == loaders) - { - /* PLACE is the first loader in the list. */ - loaders = loaders->next; - } - else - { - /* Find the loader before the one being removed. */ - lt_dlloader *prev; - for (prev = loaders; prev->next; prev = prev->next) - { - if (streq (prev->next->name, name)) - { - break; - } - } - - place = prev->next; - prev->next = prev->next->next; - } - - if (place->dlloader_exit) - { - errors = place->dlloader_exit (place->dlloader_data); - } - - FREE (place); - - return errors; -} - -lt_dlloader * -lt_dlloader_next (lt_dlloader *place) -{ - return place ? place->next : loaders; -} - -const char * -lt_dlloader_name (lt_dlloader *place) -{ - const char *name = 0; - - if (place) - { - name = place ? place->name : 0; - } - else - { - LT__SETERROR (INVALID_LOADER); - } - - return name; -} - -lt_user_data * -lt_dlloader_data (lt_dlloader *place) -{ - lt_user_data *data = 0; - - if (place) - { - data = place ? &(place->dlloader_data) : 0; - } - else - { - LT__SETERROR (INVALID_LOADER); - } - - return data; -} - -lt_dlloader * -lt_dlloader_find (const char *name) -{ - lt_dlloader *place = 0; - - for (place = loaders; place; place = place->next) - { - if (streq (place->name, name)) - { - break; - } - } - - return place; -} - - - /* These symbols are part of the published interface to libltdl, although they are no longer used. */ diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h index b2fb7db6e..34ac39cef 100644 --- a/libltdl/ltdl.h +++ b/libltdl/ltdl.h @@ -153,7 +153,7 @@ LT_SCOPE int lt_dlmutex_register (lt_dlmutex_lock *lock, lt_dlmutex_seterror *seterror, lt_dlmutex_geterror *geterror); -# define lt_ptr void * +# define lt_ptr void * diff --git a/libltdl/slist.c b/libltdl/slist.c new file mode 100644 index 000000000..fca530a6f --- /dev/null +++ b/libltdl/slist.c @@ -0,0 +1,206 @@ +/* slist.h -- generalised singly linked lists + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Originally by Gary V. Vaughan + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA + +*/ + +#include + +#include "slist.h" + + +SList * +slist_new (const void *userdata) +{ + SList *node = malloc (sizeof *node); + + node->next = 0; + node->userdata = userdata; + + return node; +} + +SList * +slist_delete (SList *head, void (*delete) (void *data)) +{ + assert (delete); + + while (head) + { + SList *next = head->next; + (*delete) (head); + head = next; + } + + return 0; +} + +/* Call Find repeatedly with MATCH and each element of *PHEAD, until + FIND returns non-NULL, or the list is exhausted. If a match is found + the matching element is removed from *PHEAD, and the value returned + by the matching call to FIND is returned. + + To avoid memory leaks, unless you already have the address of the + stale element, you should probably return that from FIND if it makes + a successful match. */ +void * +slist_remove (SList **phead, const void *match, SListCompare *find) +{ + SList *stale = 0; + void *result = 0; + + assert (find); + + if (!phead || !*phead) + return 0; + + /* Does the head of the passed list match? */ + result = (*find) (*phead, match); + if (result) + { + stale = *phead; + *phead = stale->next; + } + /* what about the rest of the elements? */ + else + { + SList *head; + for (head = *phead; head->next; head = head->next) + { + result = (*find) (head->next, match); + if (result) + { + stale = head->next; + head->next = stale->next; + } + } + } + + return result; +} + +SList * +slist_concat (SList *head, SList *tail) +{ + if (!head) + { + return tail; + } + + while (head->next) + head = head->next; + + head->next = tail; + + return head; +} + +SList * +slist_cons (SList *head, SList *tail) +{ + if (!head) + { + return tail; + } + + head->next = tail; + return head; +} + +SList * +slist_tail (SList *head) +{ + return head ? head->next : 0; +} + +SList * +slist_nth (SList *head, size_t n) +{ + for (;n > 1 && head; n--) + head = head->next; + + return head; +} + +/* Call FIND repeatedly with SEARCH and each element of HEAD, until + FIND returns non-NULL, or the list is exhausted. If a match is found + the value returned by the matching call to FIND is returned. */ +void * +slist_find (SList *head, const void *match, SListCompare *find) +{ + void *result = 0; + + assert (find); + + for (; head; head = head->next) + { + result = (*find) (head, match); + if (result) + break; + } + + return result; +} + +size_t +slist_length (SList *head) +{ + size_t n; + + for (n = 0; head; ++n) + head = head->next; + + return n; +} + +SList * +slist_reverse (SList *head) +{ + SList *result = 0; + SList *next; + + while (head) + { + next = head->next; + head->next = result; + result = head; + head = next; + } + + return result; +} + +int +slist_foreach (SList *head, SListCallback *foreach, const void *userdata) +{ + assert (foreach); + + for (; head; head = head->next) + if ((*foreach) (head, userdata) < 0) + return -1; + + return 0; +} diff --git a/libltdl/slist.h b/libltdl/slist.h new file mode 100644 index 000000000..1a3aa16de --- /dev/null +++ b/libltdl/slist.h @@ -0,0 +1,73 @@ +/* slist.h -- generalised singly linked lists + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Originally by Gary V. Vaughan + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA + +*/ + +/* A generalised list. This is deliberately transparent so that you + can make the NEXT field of all your chained data structures first, + and then cast them to `(SList *)' so that they can be manipulated + by this API. + + Alternatively, you can generate raw SList elements using slist_new(), + and put the element data in the USERDATA field. Either way you + get to manage the memory involved by yourself. +*/ + +#if !defined(SLIST_H) +#define SLIST_H 1 + +#include + + +LT_BEGIN_C_DECLS + +typedef struct slist { + struct slist *next; /* chain forward pointer*/ + const void * userdata; /* incase you want to use raw `SList's */ +} SList; + +typedef void * SListCompare (const SList *node, const void *userdata); +typedef int SListCallback (const SList *node, const *userdata); + +LT_SCOPE SList *slist_new (const void *userdata); +LT_SCOPE SList *slist_delete (SList *head, void (*delete) (void *data)); +LT_SCOPE void * slist_remove (SList **phead, const void *match, + SListCompare *find); +LT_SCOPE SList *slist_concat (SList *head, SList *tail); +LT_SCOPE SList *slist_cons (SList *head, SList *tail); +LT_SCOPE SList *slist_tail (SList *head); +LT_SCOPE SList *slist_nth (SList *head, size_t n); +LT_SCOPE void * slist_find (SList *head, const void *match, + SListCompare *find); +LT_SCOPE size_t slist_length (SList *head); +LT_SCOPE SList *slist_reverse (SList *head); +LT_SCOPE int slist_foreach (SList *head, SListCallback *foreach, + const void *userdata); + +LT_END_C_DECLS + +#endif /*!defined(SLIST_H)*/