* 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.
This commit is contained in:
Gary V. Vaughan 2005-09-27 10:03:51 +00:00
parent 121d473ead
commit 9d4089fbbb
6 changed files with 86 additions and 67 deletions

View File

@ -1,3 +1,12 @@
2005-09-27 Gary V. Vaughan <gary@gnu.org>
* 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-27 Tim Rice <tim@multitalents.net>
* tests/defs.m4sh, tests/testsuite.at (PREPARE_TESTS)

View File

@ -233,7 +233,7 @@ DEFS = -DLTDL -DHAVE_CONFIG_H -DLT_CONFIG_H='<$(LT_CONFIG_H)>'
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)

View File

@ -3774,12 +3774,12 @@ However, you might still need to maintain your own list of loaded
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.
@deftp {Type} lt_dlcaller_id
@deftp {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 iterating over the global
handle list.
@end deftp
@deftypefun lt_dlcaller_id lt_dlcaller_register (@w{const char *@var{id_string},} @w{lt_dlhandle_interface *@var{iface}})
@deftypefun lt_dlinterface_id lt_dlinterface_register (@w{const char *@var{id_string},} @w{lt_dlhandle_interface *@var{iface}})
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
@code{lt_dlcaller_id} can be used to filter the module handles
@code{lt_dlinterface_id} can be used to filter the module handles
returned by @samp{lt_dlhandle_next}.
@end deftypefun
@deftypefun lt_ptr lt_dlcaller_set_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}, @w{lt_ptr @var{data}})
@deftypefun 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
@deftypefun lt_ptr lt_dlcaller_get_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}})
@deftypefun 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 have been loaded and unloaded:
@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
@deftypefun lt_dlhandle lt_dlhandle_first (@w{lt_dlcaller_id @var{key}})
@deftypefun 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 handle, const char *id_string)
@end example
@noindent
When you register for a caller identification with
@samp{lt_dlcaller_register}, you log the interface validator. But
When you register for an interface identification key with
@samp{lt_dlinterface_register}, 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 the registered interface
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 ("example", iface_validator_callback);
@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

View File

@ -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 <gary@gnu.org>
NOTE: The canonical source of this file is maintained with the
@ -95,11 +95,11 @@ LT_SCOPE void lt__alloc_die_callback (void);
/* --- 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 */
};

View File

@ -1447,7 +1447,7 @@ lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
/* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
pargz_len, NULL, entry) failed with EINVAL. */
if (before)
if (before)
error = argz_insert (pargz, pargz_len, before, entry);
else
error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
@ -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, lt_dlhandle handle, void *data)
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 key, lt_dlhandle handle)
/* 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;
}

View File

@ -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 <tanner@ffii.org>
NOTE: The canonical source of this file is maintained with the
@ -106,15 +106,16 @@ LT_SCOPE int lt_dlpreload_open (const char *originator,
/* 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_dlhandle_interface *iface);
LT_SCOPE void * lt_dlcaller_set_data (lt_dlcaller_id key,
lt_dlhandle handle, void *data);
LT_SCOPE void * lt_dlcaller_get_data (lt_dlcaller_id key,
lt_dlhandle handle);
LT_SCOPE lt_dlinterface_id lt_dlinterface_register (const char *id_string,
lt_dlhandle_interface *iface);
LT_SCOPE void * lt_dlcaller_set_data (lt_dlinterface_id key,
lt_dlhandle handle, void *data);
LT_SCOPE void * lt_dlcaller_get_data (lt_dlinterface_id key,
lt_dlhandle handle);
/* Read only information pertaining to a loaded module. */
typedef struct {
@ -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 (
@ -136,9 +137,9 @@ LT_SCOPE int lt_dlforeach (
/* --- BINARY COMPATIBILITY WITH OLD LIBLTDL --- */
typedef void lt_dlmutex_lock (void);
typedef void lt_dlmutex_unlock (void);
typedef void lt_dlmutex_seterror (const char *errmsg);
typedef void lt_dlmutex_lock (void);
typedef void lt_dlmutex_unlock (void);
typedef void lt_dlmutex_seterror (const char *errmsg);
typedef const char *lt_dlmutex_geterror (void);
LT_SCOPE void * (*lt_dlmalloc) (size_t size);