Repost with changes in light of comments in this thread. ChangeLog | 11 +++++++ Makefile.am | 2 - doc/libtool.texi | 47 ++++++++++++++++++++-------------- libltdl/libltdl/lt__private.h | 10 +++---- libltdl/ltdl.c | 58 +++++++++++++++++++++--------------------- libltdl/ltdl.h | 13 +++++---- 6 files changed, 81 insertions(+), 60 deletions(-)
Index: libtool--devo--1.0/ChangeLog =================================================================== --- libtool--devo--1.0.orig/ChangeLog +++ libtool--devo--1.0/ChangeLog @@ -1,3 +1,12 @@ +2005-09-17 Gary V. Vaughan <[EMAIL PROTECTED]> + + * libltdl/ltdl.c (lt_dlcaller_register): Renamed to avoid + problems with module visibilty when linked with programs + written for the old API. + (lt_dlinterface_register): New name. + * Makefile.am (VERSION_INFO): Bumped. + * doc/libtool.texi (User defined module data): Updated. + 2005-09-17 Ralf Wildenhues <[EMAIL PROTECTED]> * libltdl/config/ltmain.m4sh (func_mode_link): Allow some Index: libtool--devo--1.0/Makefile.am =================================================================== --- libtool--devo--1.0.orig/Makefile.am +++ libtool--devo--1.0/Makefile.am @@ -233,7 +233,7 @@ DEFS = -DLTDL -DHAVE_CONFIG_H -DLT_CON AM_CPPFLAGS = -I. -I$(srcdir) -Ilibltdl -I$(srcdir)/libltdl \ -I$(srcdir)/libltdl/libltdl AM_LDFLAGS = -no-undefined -VERSION_INFO = -version-info 6:1:0 +VERSION_INFO = -version-info 7:0:0 noinst_LTLIBRARIES = $(LT_DLLOADERS) Index: libtool--devo--1.0/doc/libtool.texi =================================================================== --- libtool--devo--1.0.orig/doc/libtool.texi +++ libtool--devo--1.0/doc/libtool.texi @@ -3774,12 +3774,12 @@ However, you might still need to maintai module handles (in parallel with the list maintained inside libltdl) if there were any other data that your application wanted to associate with each open module. Instead, you can use the following @sc{api} -calls to do that for you. You must first obtain a unique caller id +calls to do that for you. You must first obtain a unique interface id from libltdl, and subsequently always use it to retrieve the data you stored earlier. This allows different libraries to each store their own data against loaded modules, without interfering with one another. [EMAIL PROTECTED] {Type} lt_dlcaller_id [EMAIL PROTECTED] {Type} lt_dlinterface_id The opaque type used to hold individual data set keys. @end deftp @@ -3789,14 +3789,14 @@ library's expected module interface when handle list. @end deftp [EMAIL PROTECTED] lt_dlcaller_id lt_dlcaller_register (@w{const char [EMAIL PROTECTED],} @w{lt_dlhandle_interface [EMAIL PROTECTED]) [EMAIL PROTECTED] lt_dlinterface_id lt_dlinterface_register (@w{const char [EMAIL PROTECTED],} @w{lt_dlhandle_interface [EMAIL PROTECTED]) Use this to obtain a unique key to store and retrieve per module data, if you supply an @var{id_string} and @var{iface}, then the resulting [EMAIL PROTECTED] can be used to filter the module handles [EMAIL PROTECTED] can be used to filter the module handles returned by @samp{lt_dlhandle_next}. @end deftypefun [EMAIL PROTECTED] lt_ptr lt_dlcaller_set_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}, @w{lt_ptr @var{data}}) [EMAIL PROTECTED] lt_ptr lt_dlcaller_set_data (@w{lt_dlinterface_id @var{key}}, @w{lt_dlhandle @var{handle}}, @w{lt_ptr @var{data}}) Set @var{data} as the set of data uniquely associated with @var{key} and @var{handle} for later retrieval. This function returns the @var{data} previously associated with @var{key} and @var{handle} if any. A result of @@ -3824,7 +3824,7 @@ else @end example @end deftypefun [EMAIL PROTECTED] lt_ptr lt_dlcaller_get_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}) [EMAIL PROTECTED] lt_ptr lt_dlcaller_get_data (@w{lt_dlinterface_id @var{key}}, @w{lt_dlhandle @var{handle}}) Return the address of the data associated with @var{key} and @var{handle}, or else @code{NULL} if there is none. @end deftypefun @@ -3835,23 +3835,23 @@ application to track the modules that ha @example int -my_dlcaller_callback (lt_dlhandle handle, lt_ptr key_ptr) +my_dlinterface_callback (lt_dlhandle handle, void *key) @{ struct my_module_data *my_data; - my_data = lt_dlcaller_get_data (handle, (lt_dlcaller_id) *key_ptr); + my_data = lt_dlcaller_get_data (handle, (lt_dlinterface_id) key); return process (my_data); @} int -my_dlcaller_foreach (lt_dlcaller_id key) +my_dlinterface_foreach (lt_dlinterface_id key) @{ - lt_dlforeach (my_dlcaller_callback, (lt_ptr) &key); + lt_dlforeach (my_dlinterface_callback, (void *) key); @} @end example [EMAIL PROTECTED] lt_dlhandle lt_dlhandle_first (@w{lt_dlcaller_id @var{key}}) [EMAIL PROTECTED] lt_dlhandle lt_dlhandle_first (@w{lt_dlinterface_id @var{key}}) Normally, you can fetch each of the loaded module handles in turn with successive calls to @samp{lt_dlhandle_next} as shown in the example above. In that example, the loop iterates over every libltdl loaded @@ -3873,8 +3873,8 @@ iface_validator_callback (lt_dlhandle ha @end example @noindent -When you register for a caller identification with [EMAIL PROTECTED], you log the interface validator. But +When you register for an interface identification key with [EMAIL PROTECTED], you log the interface validator. But this time, when you start the iterator loop over the loaded module handles, if you fetch the first handle with @samp{lt_dlhandle_first}, then that and all subsequent calls to @samp{lt_dlhandle_next} will @@ -3882,15 +3882,16 @@ skip any loaded module handles that fail validator callback function: @example -/* @r{Register for a} caller_id @r{to identify ourselves to} libltdl. */ -caller_id = lt_dlcaller_register ("example", iface_validator_callback); +/* @r{Register for an} interface_id @r{to identify ourselves to} libltdl. */ +interface_id = lt_dlinterface_register ("example", iface_validator_callback); @dots{} -/* @r{Iterate over the modules related to my} caller_id. */ +/* @r{Iterate over the modules related to my} interface_id. */ @{ - lt_dlhandle handle = lt_dlhandle_first (caller_id); - - while ((handle = lt_dlhandle_next (handle))) + lt_dlhandle handle; + for (handle = lt_dlhandle_first (interface_id); + handle; + handle = lt_dlhandle_next (handle)) @{ @dots{} @} @@ -3898,6 +3899,14 @@ caller_id = lt_dlcaller_register ("examp @end example @end deftypefun +Old versions of libltdl also provided a simpler, but similar, @sc{api} +based around @code{lt_dlcaller_id}. Unfortunately, it had no +provision for detecting whether a module belonged to a particular +interface as libltdl didn't support multiple loaders in the same +address space at that time. Those @sc{api}s are no longer supported +as there would be no way to stop clients of the old @sc{api}s from +seeing (and accidentally altering) modules loaded by other libraries. + @node Module loaders for libltdl @section How to create and register new module loaders Index: libtool--devo--1.0/libltdl/libltdl/lt__private.h =================================================================== --- libtool--devo--1.0.orig/libltdl/libltdl/lt__private.h +++ libtool--devo--1.0/libltdl/libltdl/lt__private.h @@ -1,5 +1,5 @@ /* lt__private.h -- internal apis for libltdl - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. Originally by Gary V. Vaughan <[EMAIL PROTECTED]> NOTE: The canonical source of this file is maintained with the @@ -95,11 +95,11 @@ LT_SCOPE void lt__alloc_die_callback (vo /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ -/* This type is used for the array of caller data sets in each handler. */ +/* This type is used for the array of interface data sets in each handler. */ typedef struct { - lt_dlcaller_id key; + lt_dlinterface_id key; void * data; -} lt_caller_data; +} lt_interface_data; typedef struct lt__handle lt__handle; @@ -111,7 +111,7 @@ struct lt__handle { 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_interface_data * interface_data; /* per caller associated data */ int flags; /* various boolean stats */ }; Index: libtool--devo--1.0/libltdl/ltdl.c =================================================================== --- libtool--devo--1.0.orig/libltdl/ltdl.c +++ libtool--devo--1.0/libltdl/ltdl.c @@ -1712,7 +1712,7 @@ lt_dlclose (lt_dlhandle handle) errors += unload_deplibs (handle); /* It is up to the callers to free the data itself. */ - FREE (cur->caller_data); + FREE (cur->interface_data); FREE (cur->info.filename); FREE (cur->info.name); @@ -2013,51 +2013,51 @@ lt_dlisresident (lt_dlhandle handle) typedef struct { const char *id_string; lt_dlhandle_interface *iface; -} lt__caller_id; +} lt__interface_id; -lt_dlcaller_id -lt_dlcaller_register (const char *id_string, lt_dlhandle_interface *iface) +lt_dlinterface_id +lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface) { - lt__caller_id *caller_id = lt__malloc (sizeof *caller_id); + lt__interface_id *interface_id = lt__malloc (sizeof *interface_id); /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which can then be detected with lt_dlerror() if we return 0. */ - if (caller_id) + if (interface_id) { - caller_id->id_string = lt__strdup (id_string); - caller_id->iface = iface; + interface_id->id_string = lt__strdup (id_string); + interface_id->iface = iface; } - return (lt_dlcaller_id) caller_id; + return (lt_dlinterface_id) interface_id; } void * -lt_dlcaller_set_data (lt_dlcaller_id key, lt_dlhandle handle, void *data) +lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data) { int n_elements = 0; void *stale = (void *) 0; lt__handle *cur = (lt__handle *) handle; int i; - if (cur->caller_data) - while (cur->caller_data[n_elements].key) + if (cur->interface_data) + while (cur->interface_data[n_elements].key) ++n_elements; for (i = 0; i < n_elements; ++i) { - if (cur->caller_data[i].key == key) + if (cur->interface_data[i].key == key) { - stale = cur->caller_data[i].data; + stale = cur->interface_data[i].data; break; } } - /* Ensure that there is enough room in this handle's caller_data + /* Ensure that there is enough room in this handle's interface_data array to accept a new element (and an empty end marker). */ if (i == n_elements) { - lt_caller_data *temp - = REALLOC (lt_caller_data, cur->caller_data, 2+ n_elements); + lt_interface_data *temp + = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements); if (!temp) { @@ -2065,21 +2065,21 @@ lt_dlcaller_set_data (lt_dlcaller_id key goto done; } - cur->caller_data = temp; + cur->interface_data = temp; - /* We only need this if we needed to allocate a new caller_data. */ - cur->caller_data[i].key = key; - cur->caller_data[1+ i].key = 0; + /* We only need this if we needed to allocate a new interface_data. */ + cur->interface_data[i].key = key; + cur->interface_data[1+ i].key = 0; } - cur->caller_data[i].data = data; + cur->interface_data[i].data = data; done: return stale; } void * -lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle) +lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle) { void *result = (void *) 0; lt__handle *cur = (lt__handle *) handle; @@ -2087,11 +2087,11 @@ lt_dlcaller_get_data (lt_dlcaller_id ke /* Locate the index of the element with a matching KEY. */ { int i; - for (i = 0; cur->caller_data[i].key; ++i) + for (i = 0; cur->interface_data[i].key; ++i) { - if (cur->caller_data[i].key == key) + if (cur->interface_data[i].key == key) { - result = cur->caller_data[i].data; + result = cur->interface_data[i].data; break; } } @@ -2118,12 +2118,12 @@ lt_dlgetinfo (lt_dlhandle handle) or else iterate over just the handles of modules that satisfy a given interface by getting the first element using lt_dlhandle_first(iface). */ -static lt__caller_id *iterator = 0; +static lt__interface_id *iterator = 0; lt_dlhandle -lt_dlhandle_first (lt_dlcaller_id caller) +lt_dlhandle_first (lt_dlinterface_id iface) { - iterator = caller; + iterator = iface; return handles; } Index: libtool--devo--1.0/libltdl/ltdl.h =================================================================== --- libtool--devo--1.0.orig/libltdl/ltdl.h +++ libtool--devo--1.0/libltdl/ltdl.h @@ -1,5 +1,5 @@ /* ltdl.h -- generic dlopen functions - Copyright (C) 1998-2000, 2004 Free Software Foundation, Inc. + Copyright (C) 1998-2000, 2004, 2005 Free Software Foundation, Inc. Originally by Thomas Tanner <[EMAIL PROTECTED]> NOTE: The canonical source of this file is maintained with the @@ -106,16 +106,17 @@ LT_SCOPE int lt_dlpreload_open (const /* Associating user data with loaded modules. */ -typedef void * lt_dlcaller_id; +typedef void * lt_dlinterface_id; typedef int lt_dlhandle_interface (lt_dlhandle handle, const char *id_string); -LT_SCOPE lt_dlcaller_id lt_dlcaller_register (const char *id_string, +LT_SCOPE lt_dlinterface_id lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface); -LT_SCOPE void * lt_dlcaller_set_data (lt_dlcaller_id key, +LT_SCOPE void * lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data); -LT_SCOPE void * lt_dlcaller_get_data (lt_dlcaller_id key, +LT_SCOPE void * lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle); + /* Read only information pertaining to a loaded module. */ typedef struct { char * filename; /* file name */ @@ -125,7 +126,7 @@ typedef struct { } lt_dlinfo; LT_SCOPE const lt_dlinfo *lt_dlgetinfo (lt_dlhandle handle); -LT_SCOPE lt_dlhandle lt_dlhandle_first (lt_dlcaller_id key); +LT_SCOPE lt_dlhandle lt_dlhandle_first (lt_dlinterface_id key); LT_SCOPE lt_dlhandle lt_dlhandle_next (lt_dlhandle place); LT_SCOPE lt_dlhandle lt_dlhandle_find (const char *module_name); LT_SCOPE int lt_dlforeach ( -- Gary V. Vaughan ())_. [EMAIL PROTECTED],gnu.org} Research Scientist ( '/ http://tkd.kicks-ass.net GNU Hacker / )= http://www.gnu.org/software/libtool Technical Author `(_~)_ http://sources.redhat.com/autobook