* NEWS: Updated.

* doc/libtool.texi (User defined module data):  Document it all.
* ltdl.m4:  Check for memcpy, or else bcopy.
* ltdl.c (lt_caller_data): New type.
(lt_dl_handle_struct): Add an lt_caller_data field.
(lt_dlcaller_register, lt_dlcaller_set_data,
lt_dlcaller_get_data): New functions.
(rpl_memcpy): A minimal fallback implementation.
(rpl_realloc): A realloc implemented with lt_dlmalloc and
lt_dlfree.
(LT_DLMALLOC, LT_DLFREE, LT_DLREALLOC, LT_DLMEM_REASSIGN):
New memory handling convenience macros.  Use them
appropriately throughout the rest of this file.
* ltdl.h (lt_dlcaller_register, lt_dlcaller_set_data,
lt_dlcaller_get_data): Prototyped.
This commit is contained in:
Gary V. Vaughan 2001-01-05 09:33:39 +00:00
parent c821715109
commit bd96d1928a
6 changed files with 606 additions and 332 deletions

View File

@ -1,3 +1,21 @@
2001-01-05 Gary V. Vaughan <gvv@techie.com>
* NEWS: Updated.
* doc/libtool.texi (User defined module data): Document it all.
* ltdl.m4: Check for memcpy, or else bcopy.
* ltdl.c (lt_caller_data): New type.
(lt_dl_handle_struct): Add an lt_caller_data field.
(lt_dlcaller_register, lt_dlcaller_set_data,
lt_dlcaller_get_data): New functions.
(rpl_memcpy): A minimal fallback implementation.
(rpl_realloc): A realloc implemented with lt_dlmalloc and
lt_dlfree.
(LT_DLMALLOC, LT_DLFREE, LT_DLREALLOC, LT_DLMEM_REASSIGN):
New memory handling convenience macros. Use them
appropriately throughout the rest of this file.
* ltdl.h (lt_dlcaller_register, lt_dlcaller_set_data,
lt_dlcaller_get_data): Prototyped.
2001-01-04 Gary V. Vaughan <gvv@techie.com>
* libltdl/ltdl.h: formatting change.

2
NEWS
View File

@ -13,6 +13,8 @@ New in 1.3d: 2000-??-??; CVS version 1.3c, Libtool team:
* Libtool now allows you to link shared libraries against static code.
* New functions in libltdl:
lt_dlgetinfo, lt_dlforeach provide access to module specific data in handles.
lt_dlcaller_register, lt_dlcaller_set_data and lt_dlcaller_get_data provide
management for user storage of per module data.
lt_dlloader_next, lt_dlloader_name, lt_dlloader_find, lt_dlloader_add and
lt_dlloader_remove can be used for adding new types of module loaders.
lt_dladderror, lt_dlseterror integrate user module loaders with lt_dlerror.

View File

@ -165,8 +165,9 @@ Using libltdl
* Libltdl interface:: How to use libltdl in your programs.
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed.
* Distributing libltdl:: How to distribute libltdl with your package.
* User defined module data:: Associating data with loaded modules.
* Module loaders for libltdl:: Creating user defined module loaders.
* Distributing libltdl:: How to distribute libltdl with your package.
Using libtool with other languages
@ -2634,8 +2635,9 @@ distribution terms that you use for the rest of that program.
@menu
* Libltdl interface:: How to use libltdl in your programs.
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed.
* Distributing libltdl:: How to distribute libltdl with your package.
* User defined module data:: Associating data with loaded modules.
* Module loaders for libltdl:: Creating user defined module loaders.
* Distributing libltdl:: How to distribute libltdl with your package.
@end menu
@node Libltdl interface
@ -2684,16 +2686,6 @@ The following types are defined in @file{ltdl.h}:
Every lt_dlopened module has a handle associated with it.
@end deftp
@deftypefn {Type} {struct} lt_dlinfo @{ @w{char *@var{filename};} @w{char *@var{name};} @w{int @var{ref_count};} @}
@code{lt_dlinfo} is used to store information about a module.
The @var{filename} attribute is a null-terminated character string of the
real module file name. If the module is a libtool module then @var{name}
is its module name (e.g. @code{"libfoo"} for @code{"dir/libfoo.la"}),
otherwise it is set to @code{NULL}.
The @var{ref_count} attribute is a reference counter that describes how often
the same module is currently loaded.
@end deftypefn
@deftp {Type} lt_dlsymlist
@code{lt_dlsymlist} is a symbol list for dlpreopened modules.
This structure is described in @pxref{Dlpreopening}.
@ -2863,21 +2855,6 @@ function, return -1 and set an error message for retrieval with
@code{lt_dlerror}.
@end deftypefun
@deftypefun {const lt_dlinfo *}lt_dlgetinfo (lt_dlhandle @var{handle})
Return a pointer to a struct that contains some information about
the module @var{handle}. The contents of the struct must not be modified.
Return @code{NULL} on failure.
@end deftypefun
@deftypefun int lt_dlforeach (int (*@var{func})(lt_dlhandle @var{handle}, lt_ptr @var{data}), lt_ptr @var{data})
For each loaded module call the function @var{func}. The argument
@var{handle} is the handle of one of the loaded modules, @var{data} is
the @var{data} argument passed to @code{lt_dlforeach}.
As soon as @var{func} returns a non-zero value for one of the handles,
@code{lt_dlforeach} will stop calling @var{func} and immediately return 1.
Otherwise 0 is returned.
@end deftypefun
@deftypevar {lt_ptr (*) (size_t @var{size})} lt_dlmalloc
@deftypevarx {void (*) (lt_ptr @var{ptr})} lt_dlfree
These variables are set to @code{malloc} and @code{free}, by default,
@ -2953,143 +2930,121 @@ foo1_la_LDFLAGS = -module
...
@end example
@node Distributing libltdl
@section How to distribute libltdl with your package
Even though libltdl is installed together with libtool, you may wish to
include libltdl in the distribution of your package, for the convenience
of users of your package that don't have libtool or libltdl installed.
In this case, you must decide whether to manually add the @code{ltdl}
objects to your package, or else which flavor of libltdl you want to use:
a convenience library or an installable libtool library.
@node User defined module data
@section Data associated with loaded modules
The most simplistic way to add @code{libltdl} to your package is to copy
the source files, @file{ltdl.c} and @file{ltdl.h}, to a source directory
withing your package and to build and link them along with the rest of
your sources. To help you do this, the m4 macros for autoconf are
available in @file{ltdl.m4}. You must ensure that they are available in
@file{aclocal.m4} before you run autoconf -- by appending the contents
of @file{ltdl.m4} to @file{acinclude.m4}, if you are using automake, or
to @file{aclocal.m4} if you are not. Having made the macros available,
you must add a call to the @samp{AC_LIB_LTDL} macro to your package's
@file{configure.in} to perform the configure time checks required to
build @file{ltdl.o} correctly. This method has problems if you then try
to link the package binaries with an installed libltdl, or a library
which depends on libltdl: you may have problems with duplicate symbol
definitions.
Some of the internal information about each loaded module that is
maintained by libltdl is available to the user, in the form of this
structure:
One advantage of the convenience library is that it is not installed, so
the fact that you use libltdl will not be apparent to the user, and it
will not overwrite a pre-installed version of libltdl a user might have.
On the other hand, if you want to upgrade libltdl for any reason
(e.g. a bugfix) you'll have to recompile your package instead of just
replacing an installed version of libltdl.
However, if your programs or libraries are linked with other libraries
that use such a pre-installed version of libltdl, you may get linker
errors or run-time crashes. Another problem is that you cannot link the
convenience library into more than one libtool library, then link a
single program with these libraries, because you may get duplicate
symbols. In general you can safely use the convenience library in programs
which don't depend on other libraries that might use libltdl too.
In order to enable this flavor of libltdl, you should add the
line @samp{AC_LIBLTDL_CONVENIENCE} to your @file{configure.in},
@emph{before} @samp{AC_PROG_LIBTOOL}.
@deftypefn {Type} {struct} lt_dlinfo @{ @w{char *@var{filename};} @w{char *@var{name};} @w{int @var{ref_count};} @}
@code{lt_dlinfo} is used to store information about a module.
The @var{filename} attribute is a null-terminated character string of
the real module file name. If the module is a libtool module then
@var{name} is its module name (e.g. @code{"libfoo"} for
@code{"dir/libfoo.la"}), otherwise it is set to @code{NULL}. The
@var{ref_count} attribute is a reference counter that describes how
often the same module is currently loaded.
@end deftypefn
In order to select the installable version of libltdl, you should add a
call of the macro @samp{AC_LIBLTDL_INSTALLABLE} to your
@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}. This macro
will check whether libltdl is already installed and, if not, request the
libltdl embedded in your package to be built and installed. Note,
however, that no version checking is performed. The user may override
the test and determine that the libltdl embedded must be installed,
regardless of the existence of another version, using the configure
switch @samp{--enable-ltdl-install}.
The following function will return a pointer to libltdl's internal copy
of this structure for the given @var{handle}:
In order to embed libltdl into your package, just add @samp{--ltdl} to
the @code{libtoolize} command line. It will copy the libltdl sources
to a subdirectory @samp{libltdl} in your package.
Both macros accept an optional argument to specify the location
of the @samp{libltdl} directory. By the default both macros assume that it
is @samp{$@{top_srcdir@}/libltdl}.
@deftypefun {const lt_dlinfo *} lt_dlgetinfo (@w{lt_dlhandle @var{handle}})
Return a pointer to a struct that contains some information about
the module @var{handle}. The contents of the struct must not be modified.
Return @code{NULL} on failure.
@end deftypefun
Whatever macro you use, it is up to you to ensure that your
@file{configure.in} will configure libltdl, using
@samp{AC_CONFIG_SUBDIRS}, and that your @file{Makefile}s will start
sub-makes within libltdl's directory, using automake's @var{SUBDIRS},
for example. Both macros define the shell variables @var{LIBLTDL}, to
the link flag that you should use to link with libltdl, and
@var{INCLTDL}, to the preprocessor flag that you should use to compile
with programs that include @file{ltdl.h}. It is up to you to use
@samp{AC_SUBST} to ensure that this variable will be available in
@file{Makefile}s, or add them to variables that are @samp{AC_SUBST}ed by
default, such as @var{LIBS} and @var{CPPFLAGS}.
Furthermore, in order to save you from having to keep a list of the
handles of all the modules you have loaded, this function will supply
the @var{handle} for each loaded module to a given callback:
If you're using the convenience libltdl, @var{LIBLTDL} will be the
pathname for the convenience version of libltdl and @var{INCLTDL} will be
@samp{-I} followed by the directory that contains libltdl, both starting
with @samp{$@{top_builddir@}/} or @samp{$@{top_srcdir@}/}, respectively.
@deftypefun int lt_dlforeach (@w{int (*@var{func}) (lt_dlhandle @var{handle}, lt_ptr @var{data})}, @w{lt_ptr @var{data}})
For each loaded module call the function @var{func}. The argument
@var{handle} is the handle of one of the loaded modules, @var{data} is
the @var{data} argument passed to @code{lt_dlforeach}.
As soon as @var{func} returns a non-zero value for one of the handles,
@code{lt_dlforeach} will stop calling @var{func} and immediately return 1.
Otherwise 0 is returned.
@end deftypefun
If you request an installed version of libltdl and one is
found@footnote{Even if libltdl is installed,
@samp{AC_LIBLTDL_INSTALLABLE} may fail to detect it, if libltdl depends
on symbols provided by libraries other than the C library. In this
case, it will needlessly build and install libltdl.}, @var{LIBLTDL} will
be set to @samp{-lltdl} and @var{INCLTDL} will be empty (which is just a
blind assumption that @file{ltdl.h} is somewhere in the include path if
libltdl is in the library path). If an installable version of libltdl
must be built, its pathname, starting with @samp{$@{top_builddir@}/},
will be stored in @var{LIBLTDL}, and @var{INCLTDL} will be set just like
in the case of convenience library.
Of course, you would still need to maintain your own list of loaded
module handles to parallel the list maintained by libltdl if there are
any other data that you need to associate with each handle for the
purposes of your application. However, if you use the following
@sc{api} calls to associate your application data with individual module
handles as they are loaded there is actually no need to do that. You
must first obtain a unique caller id from libltdl which you subsequently
use to retrieve the data you stored earlier. This allows for different
libraries that each wish to store their own data against loaded modules
to do so without interfering with one another's data.
So, when you want to link a program with libltdl, be it a convenience,
installed or installable library, just compile with @samp{$(INCLTDL)}
and link it with @samp{$(LIBLTDL)}, using libtool.
@deftp {Type} lt_dlcaller_id
The opaque type used to hold individual data set keys.
@end deftp
You should probably also add @samp{AC_LIBTOOL_DLOPEN} to your
@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}, otherwise
libtool will assume no dlopening mechanism is supported, and revert to
dlpreopening, which is probably not what you want.
@deftypefun lt_dlcaller_id lt_dlcaller_register (void)
Use this to obtain a unique key to store and retrieve individual sets of
per module data.
@end deftypefun
Avoid using the @code{-static} or @code{-all-static} switches when
linking programs with libltdl. This will not work on all platforms,
because the dlopening functions may not be available for static linking.
@deftypefun lt_ptr lt_dlcaller_set_data (@w{lt_dlcaller_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
0, may indicate that a diagnostic for the last error (if any) is available
from @code{lt_dlerror()}.
The following example shows you how to embed the convenience libltdl in
your package. In order to use the installable variant just replace
@samp{AC_LIBLTDL_CONVENIENCE} with @samp{AC_LIBLTDL_INSTALLABLE}. We
assume that libltdl was embedded using @samp{libtoolize --ltdl}.
For example, to correctly remove some associated data:
configure.in:
@example
...
dnl Enable building of the convenience library
dnl and set LIBLTDL accordingly
AC_LIBLTDL_CONVENIENCE
dnl Substitute INCLTDL and LIBLTDL in the Makefiles
AC_SUBST(INCLTDL)
AC_SUBST(LIBLTDL)
dnl Check for dlopen support
AC_LIBTOOL_DLOPEN
dnl Configure libtool
AC_PROG_LIBTOOL
dnl Configure libltdl
AC_CONFIG_SUBDIRS(libltdl)
...
lt_ptr stale = lt_dlcaller_set_data (key, handle, 0);
if (stale == NULL)
@{
char *error_msg = lt_dlerror ();
if (error_msg != NULL)
@{
my_error_handler (error_msg);
return STATUS_FAILED;
@}
@}
else
@{
free (stale);
@}
@end example
@end deftypefun
@deftypefun lt_ptr lt_dlcaller_get_data (@w{lt_dlcaller_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
The preceding functions can be combined with @code{lt_dlforeach} to
implement search and apply operations without the need for your
application to track the modules that have been loaded and unloaded:
@example
int
my_dlcaller_callback (lt_dlhandle handle, lt_ptr key_ptr)
@{
struct my_module_data *my_data;
my_data = lt_dlcaller_get_data (handle, (lt_dlcaller_id) *key_ptr);
return process (my_data);
@}
int
my_dlcaller_foreach (lt_dlcaller_id key)
@{
lt_dlforeach (my_dlcaller_callback, (lt_ptr) &key);
@}
@end example
Makefile.am:
@example
...
SUBDIRS = libltdl
INCLUDES = $(INCLTDL)
myprog_LDFLAGS = -export-dynamic
# The quotes around -dlopen below fool automake <= 1.4 into accepting it
myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la
myprog_DEPENDENCIES = $(LIBLTDL) foo1.la
...
@end example
@node Module loaders for libltdl
@section How to create and register new module loaders
@ -3337,6 +3292,144 @@ if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
@end example
@end deftypefun
@node Distributing libltdl
@section How to distribute libltdl with your package
Even though libltdl is installed together with libtool, you may wish to
include libltdl in the distribution of your package, for the convenience
of users of your package that don't have libtool or libltdl installed.
In this case, you must decide whether to manually add the @code{ltdl}
objects to your package, or else which flavor of libltdl you want to use:
a convenience library or an installable libtool library.
The most simplistic way to add @code{libltdl} to your package is to copy
the source files, @file{ltdl.c} and @file{ltdl.h}, to a source directory
withing your package and to build and link them along with the rest of
your sources. To help you do this, the m4 macros for autoconf are
available in @file{ltdl.m4}. You must ensure that they are available in
@file{aclocal.m4} before you run autoconf -- by appending the contents
of @file{ltdl.m4} to @file{acinclude.m4}, if you are using automake, or
to @file{aclocal.m4} if you are not. Having made the macros available,
you must add a call to the @samp{AC_LIB_LTDL} macro to your package's
@file{configure.in} to perform the configure time checks required to
build @file{ltdl.o} correctly. This method has problems if you then try
to link the package binaries with an installed libltdl, or a library
which depends on libltdl: you may have problems with duplicate symbol
definitions.
One advantage of the convenience library is that it is not installed, so
the fact that you use libltdl will not be apparent to the user, and it
will not overwrite a pre-installed version of libltdl a user might have.
On the other hand, if you want to upgrade libltdl for any reason
(e.g. a bugfix) you'll have to recompile your package instead of just
replacing an installed version of libltdl.
However, if your programs or libraries are linked with other libraries
that use such a pre-installed version of libltdl, you may get linker
errors or run-time crashes. Another problem is that you cannot link the
convenience library into more than one libtool library, then link a
single program with these libraries, because you may get duplicate
symbols. In general you can safely use the convenience library in programs
which don't depend on other libraries that might use libltdl too.
In order to enable this flavor of libltdl, you should add the
line @samp{AC_LIBLTDL_CONVENIENCE} to your @file{configure.in},
@emph{before} @samp{AC_PROG_LIBTOOL}.
In order to select the installable version of libltdl, you should add a
call of the macro @samp{AC_LIBLTDL_INSTALLABLE} to your
@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}. This macro
will check whether libltdl is already installed and, if not, request the
libltdl embedded in your package to be built and installed. Note,
however, that no version checking is performed. The user may override
the test and determine that the libltdl embedded must be installed,
regardless of the existence of another version, using the configure
switch @samp{--enable-ltdl-install}.
In order to embed libltdl into your package, just add @samp{--ltdl} to
the @code{libtoolize} command line. It will copy the libltdl sources
to a subdirectory @samp{libltdl} in your package.
Both macros accept an optional argument to specify the location
of the @samp{libltdl} directory. By the default both macros assume that it
is @samp{$@{top_srcdir@}/libltdl}.
Whatever macro you use, it is up to you to ensure that your
@file{configure.in} will configure libltdl, using
@samp{AC_CONFIG_SUBDIRS}, and that your @file{Makefile}s will start
sub-makes within libltdl's directory, using automake's @var{SUBDIRS},
for example. Both macros define the shell variables @var{LIBLTDL}, to
the link flag that you should use to link with libltdl, and
@var{INCLTDL}, to the preprocessor flag that you should use to compile
with programs that include @file{ltdl.h}. It is up to you to use
@samp{AC_SUBST} to ensure that this variable will be available in
@file{Makefile}s, or add them to variables that are @samp{AC_SUBST}ed by
default, such as @var{LIBS} and @var{CPPFLAGS}.
If you're using the convenience libltdl, @var{LIBLTDL} will be the
pathname for the convenience version of libltdl and @var{INCLTDL} will be
@samp{-I} followed by the directory that contains libltdl, both starting
with @samp{$@{top_builddir@}/} or @samp{$@{top_srcdir@}/}, respectively.
If you request an installed version of libltdl and one is
found@footnote{Even if libltdl is installed,
@samp{AC_LIBLTDL_INSTALLABLE} may fail to detect it, if libltdl depends
on symbols provided by libraries other than the C library. In this
case, it will needlessly build and install libltdl.}, @var{LIBLTDL} will
be set to @samp{-lltdl} and @var{INCLTDL} will be empty (which is just a
blind assumption that @file{ltdl.h} is somewhere in the include path if
libltdl is in the library path). If an installable version of libltdl
must be built, its pathname, starting with @samp{$@{top_builddir@}/},
will be stored in @var{LIBLTDL}, and @var{INCLTDL} will be set just like
in the case of convenience library.
So, when you want to link a program with libltdl, be it a convenience,
installed or installable library, just compile with @samp{$(INCLTDL)}
and link it with @samp{$(LIBLTDL)}, using libtool.
You should probably also add @samp{AC_LIBTOOL_DLOPEN} to your
@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}, otherwise
libtool will assume no dlopening mechanism is supported, and revert to
dlpreopening, which is probably not what you want.
Avoid using the @code{-static} or @code{-all-static} switches when
linking programs with libltdl. This will not work on all platforms,
because the dlopening functions may not be available for static linking.
The following example shows you how to embed the convenience libltdl in
your package. In order to use the installable variant just replace
@samp{AC_LIBLTDL_CONVENIENCE} with @samp{AC_LIBLTDL_INSTALLABLE}. We
assume that libltdl was embedded using @samp{libtoolize --ltdl}.
configure.in:
@example
...
dnl Enable building of the convenience library
dnl and set LIBLTDL accordingly
AC_LIBLTDL_CONVENIENCE
dnl Substitute INCLTDL and LIBLTDL in the Makefiles
AC_SUBST(INCLTDL)
AC_SUBST(LIBLTDL)
dnl Check for dlopen support
AC_LIBTOOL_DLOPEN
dnl Configure libtool
AC_PROG_LIBTOOL
dnl Configure libltdl
AC_CONFIG_SUBDIRS(libltdl)
...
@end example
Makefile.am:
@example
...
SUBDIRS = libltdl
INCLUDES = $(INCLTDL)
myprog_LDFLAGS = -export-dynamic
# The quotes around -dlopen below fool automake <= 1.4 into accepting it
myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la
myprog_DEPENDENCIES = $(LIBLTDL) foo1.la
...
@end example
@node Other languages
@chapter Using libtool with other languages
@cindex C, not using

View File

@ -98,6 +98,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
#undef LT_SYMBOL_OVERHEAD
#define LT_SYMBOL_OVERHEAD 5
/* --- TYPE DEFINITIONS -- */
/* This type is used for the array of caller data sets in each handler. */
typedef struct {
lt_dlcaller_id key;
lt_ptr data;
} lt_caller_data;
/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
@ -122,6 +136,7 @@ struct lt_dlhandle_struct {
lt_dlhandle *deplibs; /* dependencies */
lt_module module; /* system module handle */
lt_ptr system; /* system specific data */
lt_caller_data *caller_data; /* per caller associated data */
int flags; /* various boolean stats */
};
@ -144,11 +159,29 @@ static const char shlib_ext[] = LTDL_SHLIB_EXT;
static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
#endif
/* --- MEMORY HANDLING --- */
LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
= (lt_ptr (*) LT_PARAMS((size_t))) malloc;
LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
= (void (*) LT_PARAMS((lt_ptr))) free;
static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr,
size_t size));
#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
#define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
#define LT_DLFREE(p) \
LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
if ((p) != (q)) { lt_dlfree (p); (p) = (q); } \
} LT_STMT_END
/* --- ERROR MESSAGES --- */
@ -177,26 +210,20 @@ lt_dladderror (diagnostic)
const char *diagnostic;
{
int index = errorcode - LT_ERROR_MAX;
const char **temp = 0;
const char **temp = 0;
/* realloc is not entirely portable, so simulate it using
lt_dlmalloc and lt_dlfree. */
temp = (const char **) lt_dlmalloc ((1+index) * sizeof (const char*));
temp = LT_DLREALLOC (const char *, user_error_strings, 1 + index);
if (temp == 0)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
return -1;
}
/* Build the new vector in the memory addressed by temp. */
temp[index] = diagnostic;
while (--index >= 0)
else
{
temp[index] = user_error_strings[index];
user_error_strings = temp;
}
lt_dlfree (user_error_strings);
user_error_strings = temp;
user_error_strings[index] = diagnostic;
return errorcode++;
}
@ -240,7 +267,7 @@ strdup(str)
if (str)
{
tmp = (char*) lt_dlmalloc (1+ strlen (str));
tmp = LT_DLMALLOC (char, 1+ strlen (str));
if (tmp)
{
strcpy(tmp, str);
@ -330,6 +357,78 @@ strrchr(str, ch)
# endif
#endif
/* NOTE: Neither bcopy nor the memcpy implementation below can
reliably handle copying in overlapping areas of memory, so
do not rely on this behaviour when invoking memcpy later. */
#if ! HAVE_MEMCPY
# if HAVE_BCOPY
# define memcpy(dest, src, size) bcopy (src, dest, size)
# else
# define memcpy rpl_memcpy
static inline char *
memcpy (dest, src, size)
char *dest;
const char *src;
size_t size;
{
size_t i = 0;
for (i = 0; i < size; ++i)
{
dest[i] = src[i];
}
return dest;
}
# endif
#endif
/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
``realloc is not entirely portable''
In any case we want to use the allocator supplied by the user without
burdening them with an lt_dlrealloc function pointer to maintain.
Instead implement our own version (with known boundary conditions)
using lt_dlmalloc and lt_dlfree. */
static lt_ptr
rpl_realloc (ptr, size)
lt_ptr ptr;
size_t size;
{
if (size < 1)
{
/* For zero or less bytes, free the original memory */
if (ptr != 0)
{
lt_dlfree (ptr);
}
return (lt_ptr) 0;
}
else if (ptr == 0)
{
/* Allow reallocation of a NULL pointer. */
return lt_dlmalloc (size);
}
else
{
/* Allocate a new block, copy and free the old block. */
lt_ptr mem = lt_dlmalloc (size);
if (mem)
{
memcpy (mem, ptr, size);
lt_dlfree (ptr);
}
/* Note that the contents of PTR are not damaged if there is
insufficient memory to realloc. */
return mem;
}
}
@ -600,7 +699,7 @@ sys_wll_open (loader_data, filename)
{
/* Append a `.' to stop Windows from adding an
implicit `.dll' extension. */
searchname = (char*) lt_dlmalloc (2+ strlen (filename));
searchname = LT_DLMALLOC (char, 2+ strlen (filename));
if (!searchname)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -611,7 +710,7 @@ sys_wll_open (loader_data, filename)
}
module = LoadLibrary (searchname);
lt_dlfree (searchname);
LT_DLFREE (searchname);
/* libltdl expects this function to fail if it is unable
to physically load the library. Sadly, LoadLibrary
@ -791,7 +890,7 @@ sys_dld_open (loader_data, filename)
if (dld_link (filename) != 0)
{
last_error = LT_DLSTRERROR (CANNOT_OPEN);
lt_dlfree(module);
LT_DLFREE (module);
return 0;
}
@ -808,7 +907,7 @@ sys_dld_close (loader_data, module)
last_error = LT_DLSTRERROR (CANNOT_CLOSE);
return 1;
}
lt_dlfree (module);
LT_DLFREE (module);
return 0;
}
@ -876,7 +975,7 @@ presym_free_symlists ()
lt_dlsymlists_t *tmp = lists;
lists = lists->next;
lt_dlfree (tmp);
LT_DLFREE (tmp);
}
preloaded_symbols = 0;
@ -907,7 +1006,7 @@ presym_add_symlist (preloaded)
lists = lists->next;
}
tmp = (lt_dlsymlists_t*) lt_dlmalloc (sizeof (lt_dlsymlists_t));
tmp = LT_DLMALLOC (lt_dlsymlists_t, 1);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1135,8 +1234,7 @@ lt_dlexit ()
++errors;
}
lt_dlfree (loader);
loader = next;
LT_DLMEM_REASSIGN (loader, next);
}
loaders = 0;
}
@ -1208,10 +1306,7 @@ tryall_dlopen (handle, filename)
if (!loader)
{
if (cur->info.filename)
{
lt_dlfree(cur->info.filename);
}
LT_DLFREE (cur->info.filename);
return 1;
}
@ -1250,7 +1345,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
if (installed && libdir)
{
len = strlen (libdir) + 1 + strlen (dlname);
filename = (char*) lt_dlmalloc (1+ len);
filename = LT_DLMALLOC (char, 1+ len);
if (!filename)
{
@ -1260,7 +1355,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
sprintf (filename, "%s/%s", libdir, dlname);
error = (tryall_dlopen (handle, filename) != 0);
lt_dlfree (filename);
LT_DLFREE (filename);
if (!error)
{
@ -1272,7 +1367,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
if (!installed)
{
len = (dir ? strlen (dir) : 0) + strlen (objdir) + strlen (dlname);
filename = (char*) lt_dlmalloc(1+ len);
filename = LT_DLMALLOC (char, 1+ len);
if (!filename)
{
@ -1292,7 +1387,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
strcat(filename, dlname);
error = tryall_dlopen (handle, filename) != 0;
lt_dlfree (filename);
LT_DLFREE (filename);
if (!error)
{
return 0;
@ -1302,7 +1397,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
/* maybe it was moved to another directory */
{
len = (dir ? strlen (dir) : 0) + strlen (dlname);
filename = (char*) lt_dlmalloc (1+ len);
filename = LT_DLMALLOC (char, 1+ len);
if (dir)
{
@ -1315,7 +1410,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
strcat(filename, dlname);
error = (tryall_dlopen (handle, filename) != 0);
lt_dlfree (filename);
LT_DLFREE (filename);
if (!error)
{
return 0;
@ -1408,13 +1503,9 @@ find_file (basename, search_path, pdir, handle)
if (lendir + 1 + lenbase >= filenamesize)
{
if (filename)
{
lt_dlfree (filename);
}
LT_DLFREE (filename);
filenamesize = lendir + 1 + lenbase + 1;
filename = (char*) lt_dlmalloc(filenamesize);
filename = LT_DLMALLOC (char, filenamesize);
if (!filename)
{
@ -1442,10 +1533,7 @@ find_file (basename, search_path, pdir, handle)
FILE *file = fopen (filename, LT_READTEXT_MODE);
if (file)
{
if (*pdir)
{
lt_dlfree (*pdir);
}
LT_DLFREE (*pdir);
filename[lendir] = '\0';
*pdir = strdup(filename);
@ -1466,8 +1554,8 @@ find_file (basename, search_path, pdir, handle)
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
cleanup:
if (filename) lt_dlfree (filename);
if (canonical) lt_dlfree (canonical);
LT_DLFREE (filename);
LT_DLFREE (canonical);
return result;
}
@ -1537,13 +1625,13 @@ load_deplibs(handle, deplibs)
goto cleanup;
}
names = (char**) lt_dlmalloc (depcount * sizeof (char*));
names = LT_DLMALLOC (char *, depcount * sizeof (char*));
if (!names)
{
goto cleanup;
}
handles = (lt_dlhandle*) lt_dlmalloc (depcount * sizeof (lt_dlhandle*));
handles = (lt_dlhandle*) LT_DLMALLOC (lt_dlhandle *, depcount);
if (!handles)
{
goto cleanup;
@ -1572,8 +1660,7 @@ load_deplibs(handle, deplibs)
*end = 0; /* set a temporary string terminator */
if (strncmp(p, "-l", 2) == 0)
{
name = lt_dlmalloc(3+ /* "lib" */
strlen(p+2)+1);
name = LT_DLMALLOC (char, 3+ /* "lib" */ strlen (p+2) + 1);
if (name)
{
sprintf (name, "lib%s", p+2);
@ -1625,15 +1712,15 @@ load_deplibs(handle, deplibs)
cleanup_names:
for (i = 0; i < depcount; ++i)
{
lt_dlfree(names[i]);
LT_DLFREE (names[i]);
}
cleanup:
if (names) lt_dlfree(names);
if (handles) lt_dlfree(handles);
LT_DLFREE (names);
LT_DLFREE (handles);
/* restore the old search path */
if (user_search_path) lt_dlfree (user_search_path);
LT_DLFREE (user_search_path);
user_search_path = save_search_path;
return ret;
@ -1671,14 +1758,11 @@ trim (dest, str)
int len = strlen (str);
char *tmp;
if (*dest)
{
lt_dlfree(*dest);
}
LT_DLFREE (*dest);
if (len > 3 && str[0] == '\'')
{
tmp = (char*) lt_dlmalloc(end - str);
tmp = LT_DLMALLOC (char, end - str);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1704,10 +1788,10 @@ free_vars( dlname, oldname, libdir, deplibs)
char *libdir;
char *deplibs;
{
if (dlname) lt_dlfree(dlname);
if (oldname) lt_dlfree(oldname);
if (libdir) lt_dlfree(libdir);
if (deplibs) lt_dlfree(deplibs);
LT_DLFREE (dlname);
LT_DLFREE (oldname);
LT_DLFREE (libdir);
LT_DLFREE (deplibs);
return 0;
}
@ -1724,7 +1808,7 @@ lt_dlopen (filename)
/* dlopen self? */
if (!filename)
{
handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct));
handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1734,6 +1818,7 @@ lt_dlopen (filename)
handle->info.ref_count = 0;
handle->depcount = 0;
handle->deplibs = 0;
handle->caller_data = 0;
newhandle = handle;
/* lt_dlclose()ing yourself is very bad! Disallow it. */
@ -1741,7 +1826,7 @@ lt_dlopen (filename)
if (tryall_dlopen (&newhandle, 0) != 0)
{
lt_dlfree(handle);
LT_DLFREE (handle);
return 0;
}
goto register_handle;
@ -1751,10 +1836,7 @@ lt_dlopen (filename)
if (!canonical)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
if (handle)
{
lt_dlfree(handle);
}
LT_DLFREE (handle);
return 0;
}
@ -1764,7 +1846,7 @@ lt_dlopen (filename)
if (basename)
{
++basename;
dir = (char*) lt_dlmalloc (basename - canonical + 1);
dir = LT_DLMALLOC (char, basename - canonical + 1);
if (!dir)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1798,7 +1880,7 @@ lt_dlopen (filename)
int installed = 1;
/* extract the module name from the file name */
name = (char*) lt_dlmalloc(ext - basename + 1);
name = LT_DLMALLOC (char, ext - basename + 1);
if (!name)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1863,7 +1945,7 @@ lt_dlopen (filename)
goto cleanup;
}
line = (char*) lt_dlmalloc (LT_FILENAME_MAX);
line = LT_DLMALLOC (char, LT_FILENAME_MAX);
if (!line)
{
fclose (file);
@ -1933,8 +2015,7 @@ lt_dlopen (filename)
(last_libname = strrchr (dlname, ' ')) != NULL)
{
last_libname = strdup (last_libname + 1);
lt_dlfree (dlname);
dlname = last_libname;
LT_DLMEM_REASSIGN (dlname, last_libname);
}
}
@ -1945,16 +2026,13 @@ lt_dlopen (filename)
}
fclose (file);
lt_dlfree (line);
LT_DLFREE (line);
/* allocate the handle */
handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct));
handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle || error)
{
if (handle)
{
lt_dlfree(handle);
}
LT_DLFREE (handle);
if (!error)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1984,8 +2062,7 @@ lt_dlopen (filename)
free_vars (dlname, old_name, libdir, deplibs);
if (error)
{
lt_dlfree (handle);
handle = 0;
LT_DLFREE (handle);
goto cleanup;
}
@ -1997,7 +2074,7 @@ lt_dlopen (filename)
else
{
/* not a libtool module */
handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct));
handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2026,18 +2103,13 @@ lt_dlopen (filename)
#endif
)) && tryall_dlopen (&newhandle, filename))
{
lt_dlfree (handle);
handle = 0;
LT_DLFREE (handle);
goto cleanup;
}
}
register_handle:
if (newhandle != handle)
{
lt_dlfree(handle);
handle = newhandle;
}
LT_DLMEM_REASSIGN (handle, newhandle);
if (handle->info.ref_count == 0)
{
@ -2051,9 +2123,9 @@ lt_dlopen (filename)
last_error = saved_error;
cleanup:
if (dir) lt_dlfree(dir);
if (name) lt_dlfree(name);
if (canonical) lt_dlfree(canonical);
LT_DLFREE (dir);
LT_DLFREE (name);
LT_DLFREE (canonical);
return handle;
}
@ -2080,7 +2152,7 @@ lt_dlopenext (filename)
}
/* try "filename.la" */
tmp = (char*) lt_dlmalloc (len+4);
tmp = LT_DLMALLOC (char, len+4);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2092,7 +2164,7 @@ lt_dlopenext (filename)
if (handle)
{
last_error = saved_error;
lt_dlfree (tmp);
LT_DLFREE (tmp);
return handle;
}
@ -2100,8 +2172,8 @@ lt_dlopenext (filename)
/* try "filename.EXT" */
if (strlen(shlib_ext) > 3)
{
lt_dlfree (tmp);
tmp = (char*) lt_dlmalloc (len + strlen (shlib_ext) + 1);
LT_DLFREE (tmp);
tmp = LT_DLMALLOC (char, len + strlen (shlib_ext) + 1);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2119,7 +2191,7 @@ lt_dlopenext (filename)
if (handle)
{
last_error = saved_error;
lt_dlfree (tmp);
LT_DLFREE (tmp);
return handle;
}
#endif
@ -2132,7 +2204,7 @@ lt_dlopenext (filename)
}
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
lt_dlfree (tmp);
LT_DLFREE (tmp);
return 0;
}
@ -2179,17 +2251,10 @@ lt_dlclose (handle)
error = handle->loader->module_close (data, handle->module);
error += unload_deplibs(handle);
if (handle->info.filename)
{
lt_dlfree (handle->info.filename);
}
LT_DLFREE (handle->info.filename);
LT_DLFREE (handle->info.name);
if (handle->info.name)
{
lt_dlfree (handle->info.name);
}
lt_dlfree (handle);
LT_DLFREE (handle);
return error;
}
@ -2243,7 +2308,7 @@ lt_dlsym (handle, symbol)
}
else
{
sym = (char*) lt_dlmalloc(lensym + LT_SYMBOL_OVERHEAD + 1);
sym = LT_DLMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
}
if (!sym)
@ -2277,7 +2342,7 @@ lt_dlsym (handle, symbol)
{
if (sym != lsym)
{
lt_dlfree(sym);
LT_DLFREE (sym);
}
return address;
}
@ -2298,7 +2363,7 @@ lt_dlsym (handle, symbol)
address = handle->loader->find_sym (data, handle->module, sym);
if (sym != lsym)
{
lt_dlfree(sym);
LT_DLFREE (sym);
}
return address;
@ -2334,7 +2399,7 @@ lt_dladdsearchdir (search_dir)
else
{
size_t len = strlen (user_search_path) + 1 + strlen (search_dir);
char *new_search_path = (char*) lt_dlmalloc (1+ len);
char *new_search_path = LT_DLMALLOC (char, 1+ len);
if (!new_search_path)
{
@ -2345,8 +2410,7 @@ lt_dladdsearchdir (search_dir)
sprintf (new_search_path, "%s%c%s", user_search_path,
LT_PATHSEP_CHAR, search_dir);
lt_dlfree (user_search_path);
user_search_path = new_search_path;
LT_DLMEM_REASSIGN (user_search_path, new_search_path);
}
return 0;
@ -2356,11 +2420,7 @@ int
lt_dlsetsearchpath (search_path)
const char *search_path;
{
if (user_search_path)
{
lt_dlfree (user_search_path);
user_search_path = 0;
}
LT_DLFREE (user_search_path);
if (!search_path || !strlen (search_path))
{
@ -2410,6 +2470,11 @@ lt_dlisresident (handle)
return LT_DLIS_RESIDENT (handle);
}
/* --- MODULE INFORMATION --- */
const lt_dlinfo *
lt_dlgetinfo (handle)
lt_dlhandle handle;
@ -2444,6 +2509,96 @@ lt_dlforeach (func, data)
return 0;
}
lt_dlcaller_id
lt_dlcaller_register ()
{
static unsigned last_caller_id = -1;
return ++last_caller_id;
}
#define N_ELEMENTS(a) (sizeof(a) / sizeof(*(a)))
lt_ptr
lt_dlcaller_set_data (key, handle, data)
lt_dlcaller_id key;
lt_dlhandle handle;
lt_ptr data;
{
int n_elements = 0;
lt_ptr stale = (lt_ptr) 0;
int i;
if (handle->caller_data)
n_elements = N_ELEMENTS (handle->caller_data);
for (i = 0; i < n_elements; ++i)
{
if (handle->caller_data[i].key == key)
{
stale = handle->caller_data[i].data;
break;
}
}
/* Ensure that there is enough room in this handle's caller_data
array to accept a new element. */
if (i == n_elements)
{
lt_caller_data *temp
= LT_DLREALLOC (lt_caller_data, handle->caller_data, 1+ n_elements);
if (temp == 0)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
return (lt_ptr) 0;
}
else
{
handle->caller_data = temp;
}
/* We only need this if we needed to allocate a new caller_data. */
handle->caller_data[i].key = key;
}
handle->caller_data[i].data = data;
return stale;
}
lt_ptr
lt_dlcaller_get_data (key, handle)
lt_dlcaller_id key;
lt_dlhandle handle;
{
lt_ptr result = (lt_ptr) 0;
int n_elements = 0;
if (handle->caller_data)
n_elements = N_ELEMENTS (handle->caller_data);
/* Locate the index of the element with a matching KEY. */
{
int i;
for (i = 0; i < n_elements; ++i)
{
if (handle->caller_data[i].key == key)
{
result = handle->caller_data[i].data;
break;
}
}
}
return result;
}
/* --- USER MODULE LOADER API --- */
int
lt_dlloader_add (place, dlloader, loader_name)
lt_dlloader *place;
@ -2462,7 +2617,7 @@ lt_dlloader_add (place, dlloader, loader_name)
}
/* Create a new dlloader node with copies of the user callbacks. */
node = (lt_dlloader *) lt_dlmalloc (sizeof (lt_dlloader));
node = LT_DLMALLOC (lt_dlloader, 1);
if (node == 0)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2571,10 +2726,7 @@ lt_dlloader_remove (loader_name)
result = place->dlloader_exit (place->dlloader_data);
}
if (place)
{
lt_dlfree (place);
}
LT_DLFREE (place);
return result;
}
@ -2626,4 +2778,3 @@ lt_dlloader_find (loader_name)
return place;
}

View File

@ -208,6 +208,15 @@ extern int lt_dlforeach LT_PARAMS((
int (*func) (lt_dlhandle handle, lt_ptr data),
lt_ptr data));
/* Associating user data with loaded modules. */
typedef unsigned lt_dlcaller_id;
extern lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void));
extern lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key,
lt_dlhandle handle,
lt_ptr data));
extern lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key,
lt_dlhandle handle));

View File

@ -39,6 +39,7 @@ AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dl.h dld.h)
AC_CHECK_HEADERS(string.h strings.h, break)
AC_CHECK_FUNCS(strchr index, break)
AC_CHECK_FUNCS(strrchr rindex, break)
AC_CHECK_FUNCS(memcpy bcopy, break)
AC_CHECK_FUNCS(strcmp)
AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl