[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 329-gary-allow-RTLD_GLOBAL
From: |
Ralf Wildenhues |
Subject: |
Re: 329-gary-allow-RTLD_GLOBAL |
Date: |
Sun, 6 May 2007 22:57:46 +0200 (CEST) |
User-agent: |
SquirrelMail/1.4.9a |
Hi Gary,
* Gary V. Vaughan wrote on Tue, May 01, 2007 at 04:33:37PM CEST:
> Sorry for the delay.
Don't worry, and likewise. Thanks for the patch. Please ensure next time
that your mailer does not wrap long lines; I should apologize in advance
that my mailer may do the same now.
> I've added a test, which tries to be sympathetic to architectures that
have
> no loaders that listen to advise, but will probably take a few
iterations
> to shake out spurious failures on some hosts.
Sure. Let's get the remaining stuff out once this is in.
Which hosts have you done testing on already?
> Okay to commit?
Yes. Below is a bunch of nits. Please address as many as you can and
indicate which ones you left out, and apply. Thanks.
Cheers,
Ralf
> * libltdl/ltdl.c (LT_DLRESIDENT_FLAG): Removed.
> (LT_DLIS_RESIDENT): Use public is_resident info field.
> (LT_DLIS_SYMLOCAL, LT_DLIS_SYMGLOBAL): New macros to test for module
symbol visibility status.
> (tryall_dlopen): If vtable->module_open() was able to act on
> either is_symlocal or is_symglobal hints, store that in
> the handle flags.
> (lt_dlopenadvise): New function that works like lt_dlopen(),
> but accepts an advise type to determine whether to ask
> dlloaders to change default symbol visibility.
> (lt_dlopen, lt_dlopenext): Just call lt_dlopenadvise() with
> the correct parameters.
> (lt_dladvise_init, lt_dladvise_destroy): New functions to
> initialize and destroy an advise type hint.
> (lt_dladvise_ext, lt_dladvise_resident, lt_dladvise_local)
> (lt_dladvise_global): Set hints on an advise type.
Upon reading, I wondered whether s/advise type/advice/ would benefit or
hurt the text and the code. No idea really.
> (openadvise): Factored out of lt_dlopenadvise.
> (has_library_ext): Factored out of lt_dlopenadvise.
> * libltdl/ltdl.h: Declare all of the above.
> (lt_dlinfo): New fields for advise hints.
> * libltdl/libltdl/lt_dlloader.h (lt_module_open): Add a new
> advise parameter. Adjust all callers.
> (lt_dladvise): New opaque type for advise hints.
> * libltdl/libltdl/lt__private.h (lt__advise): Declare
> contents of opaque lt_dladvise type.
> * libltdl/libltdl/lt_error.h (CONFLICTING_FLAGS): New error
> for attempts to have local and global symbol visibility at the same
time.
> * libltdl/loaders/dld_link.c, libltdl/loaders/dyld.c,
> libltdl/loaders/load_add_on.c, libltdl/loaders/loadlibrary.c,
libltdl/loaders/preopen.c, libltdl/loaders/shl_load.c: Adjust. *
libltdl/loaders/dlopen.c (RTLD_LOCAL, RTLD_GLOBAL): Try to
> define these symbols if the system has equivalents.
> (vmopen): If unable to act on a caller request to set symbol
> visibility, then unset the relevant hints in the advise type. *
tests/lt_dladvise.at: New tests for the above.
> * doc/libtool.texi (Libltdl Interface): Updated.
> * NEWS: Updated.
> Index: Makefile.am
> ===================================================================
RCS file: /sources/libtool/libtool/Makefile.am,v
> retrieving revision 1.218
> diff -u -p -u -r1.218 Makefile.am
> --- Makefile.am 26 Apr 2007 22:34:05 -0000 1.218
> +++ Makefile.am 1 May 2007 14:03:54 -0000
> @@ -443,6 +443,7 @@ TESTSUITE_AT = tests/testsuite.at \
> tests/old-m4-iface.at \
> tests/am-subdir.at \
> tests/lt_dlexit.at \
> + tests/lt_dladvise.at \
> tests/standalone.at \
> tests/subproject.at \
> tests/nonrecursive.at \
> Index: NEWS
> ===================================================================
RCS file: /sources/libtool/libtool/NEWS,v
> retrieving revision 1.203
> diff -u -p -u -r1.203 NEWS
> --- NEWS 23 Apr 2007 17:10:16 -0000 1.203
> +++ NEWS 1 May 2007 14:04:01 -0000
> @@ -8,10 +8,6 @@ New in 2.1a: 2007-??-??; CVS version 2.1
> libltdl currently does not build. The new structure of libltdl
with
> preopened modules exposes some long-lived bugs here.
> - - Since libltdl does not use the RTLD_GLOBAL global flag with
dlopen
> - any more, some setups may fail. A mechanism to allow the user to
- choose the mode has not been implemented yet.
> -
> * Important incompatible changes and obsoleted features:
> - Removed deprecated APIs from libltdl: lt_dlcaller_register,
> @@ -54,6 +50,14 @@ New in 2.1a: 2007-??-??; CVS version 2.1
> lt_dlhandle_iterate, lt_dlhandle_fetch, lt_dlhandle_map.
> - New lt_dlinterface_register to maintain separation of concerns
> between modules loaded by different libraries.
> + - New lt_dlopenadvise takes a new lt_dladvise type argument, which
+ lets the caller request local or global symbol visibility from
the
> + module loader with lt_dladvise_local and lt_dladvise_global +
respectively. If neither is given, or if lt_dlopen (or
> lt_dlopenext)
> + are called, then the system default module symbol visibility is
> used.
> + - The new lt_dladvise_init based APIs also allow caller requests
for
> + a filename extension search with lt_dladvise_ext, and for marking
a
> + module unloadable with lt_dladvise_resident.
Should all new interfaces (all functions) be listed in NEWS? I'd prefer
that, even if you don't give any explanation for their semantics.
Autoconf does this, too.
> - Allow shell special characters like `$' in source file names, but
> not in object names, to enhance GCJ support.
> - An entire new Autotest-based testsuite in addition to the old
one.
> Index: doc/libtool.texi
> ===================================================================
RCS file: /sources/libtool/libtool/doc/libtool.texi,v
> retrieving revision 1.226
> diff -u -p -u -r1.226 libtool.texi
> --- doc/libtool.texi 3 Apr 2007 19:09:39 -0000 1.226
> +++ doc/libtool.texi 1 May 2007 14:04:19 -0000
> @@ -222,8 +222,8 @@ Platform quirks
> In the past, if a source code package developer wanted to take
advantage
> of the power of shared libraries, he needed to write custom support
code
> for each platform on which his package ran. He also had to design a
> -configuration interface so that the package installer could choose
what
> sort of
> -libraries were built.
> +configuration interface so that the package installer could choose
what
> +sort of libraries were built.
> @sc{gnu} Libtool simplifies the developer's job by encapsulating both
> the
> platform-specific dependencies, and the user interface, in a single
> @@ -3590,6 +3590,12 @@ The following types are defined in @file
> Every lt_dlopened module has a handle associated with it.
> @end deftp
> address@hidden {Type} lt_dladvise
> address@hidden is used to control optional module loading modes.
+If it is not used, the default mode of the underlying system module
+loader is used.
> address@hidden deftp
> +
> @deftp {Type} lt_dlsymlist
> @code{lt_dlsymlist} is a symbol list for dlpreopened modules. This
structure is described in @pxref{Dlpreopening}.
> @@ -3679,6 +3685,91 @@ to be able to @code{dlopen} such librari
> transparently.
> @end deftypefun
> address@hidden int lt_dladvise_init (lt_dladvise address@hidden)
> +The @var{advise} parameter can be used to pass hints to the module
+loader when using @code{lt_dlopenadvise} to perform the loading. +The
@var{advise} paramater needs to be initialised by this function
s/paramater/parameter/
> +before it can be used. Any memory used by @var{advise} is
automatically
> +recycled when it is passed to @code{lt_dlopenadvise}.
Is that a good idea? What if I want to advise hundreds of libraries?
Also, I think this bit of documentation does not match the
implementation, nor the my_dlopenext example below: lt_dlopenadvice does
not free the storage that `advise' uses. So I guess rather point to
lt_dladvise_destroy here, or, as it's described as very next, just do
without a pointer.
> +On failure, @code{lt_dladvise_init} returns non-zero and sets an
error
> +message that can be retrieved with @code{lt_dlerror}.
> address@hidden deftypefun
> +
> address@hidden int lt_dladvise_destroy (lt_dladvise address@hidden)
+Recycle the memory used by @var{advise}. For an example, see the
+documentation for @code{lt_dladvise_ext}.
> +
> +On failure, @code{lt_dladvise_destroy} returns non-zero and sets an
> error
> +message that can be retrieved with @code{lt_dlerror}.
> address@hidden deftypefun
> +
> address@hidden int lt_dladvise_ext (lt_dladvise address@hidden)
> +Set the @code{ext} hint on @var{advise}. Passing an @var{advise}
+parameter to @code{lt_dlopenadvise} with this hint set causes it to
+try to append different file name extensions like
@code{lt_dlopenext}.
> +
> +The following example is equivalent to calling
> address@hidden (filename)}:
> +
> address@hidden
> +lt_dlhandle
> +my_dlopenext (const char *filename)
> address@hidden
> + lt_dlhandle handle = 0;
> + lt_dladvise advise;
> +
> + if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise)) +
handle = lt_dlopenadvise (filename, &advise);
> +
> + lt_dladvise_destroy (&advise);
> +
> + return handle;
> address@hidden
> address@hidden example
It would be cool if this example matched exactly a bit of testsuite code.
As of now, there are small differences to hint_ext in the test you added.
> +On failure, @code{lt_dladvise_ext} returns non-zero and sets an error
+message that can be retrieved with @code{lt_dlerror}.
Also, it would be cool if this functionality (failure to open) were
exposed in the testsuite; likewise for the other new functions.
> address@hidden deftypefun
> +
> address@hidden int lt_dladvise_global (lt_dladvise address@hidden) +Set
the @code{symglobal} hint on @var{advise}. Passing an
@var{advise}
> +parameter to @code{lt_dlopenadvise} with this hint set causes it to
try
> +to make the loaded module's symbols globally available for resolving
+unresolved symbols in subsequently loaded modules.
> +
> +If neither the @code{symglobal} nor the @code{symlocal} hints are
set,
> +or if a module is loaded without using the @code{lt_dlopenadvise}
call
> +in any case, then the visibility of the module's symbols will be as
per
> +the default for the underlying module loader and @sc{os}. Even if a
+suitable hint is passed, not all loaders are able to act upon it in
+which case @code{lt_dlgetinfo} will reveal whether the hint was
actually
> +followed.
> +
> +On failure, @code{lt_dladvise_global} returns non-zero and sets an
error
> +message that can be retrieved with @code{lt_dlerror}.
> address@hidden deftypefun
> +
> address@hidden int lt_dladvise_local (lt_dladvise address@hidden) +Set
the @code{symlocal} hint on @var{advise}. Passing an
@var{advise}
> +parameter to @code{lt_dlopenadvise} with this hint set causes it to
try
> +to keep the loaded module's symbols hidden so that they are not
+visible to subsequently loaded modules.
> +
> +On failure, @code{lt_dladvise_local} returns non-zero and sets an
error
> +message that can be retrieved with @code{lt_dlerror}.
Should the hint about lt_dlgetinfo be repeated here? Otherwise, the user
may think that a non-failure of lt_dladvise_local may indicate that the
host /can/ localize/hide symbols. WDYT?
> address@hidden deftypefun
> +
> address@hidden int lt_dladvise_resident (lt_dladvise address@hidden) +Set
the @code{resident} hint on @var{advise}. Passing an
@var{advise}
> +parameter to @code{lt_dlopenadvise} with this hint set causes it to
try
> +to make the loaded module resident in memory, so that it cannot be
+unloaded with a later call to @code{lt_dlclose}.
> +
> +On failure, @code{lt_dladvise_resident} returns non-zero and sets an
> error
> +message that can be retrieved with @code{lt_dlerror}.
> address@hidden deftypefun
> +
> @deftypefun int lt_dlclose (lt_dlhandle @var{handle})
> Decrement the reference count on the module @var{handle}.
> If it drops to zero and no other module depends on this module,
> @@ -3853,17 +3944,16 @@ Some of the internal information about e
> maintained by libltdl is available to the user, in the form of this
structure:
> address@hidden {Type} {struct} lt_dlinfo @{ @w{char address@hidden;}
> @w{char address@hidden;} @w{int @var{ref_count};} @w{lt_module
> @var{module};address@hidden
> address@hidden {Type} {struct} lt_dlinfo @{ @w{char address@hidden;}
> @w{char address@hidden;} @w{int @var{ref_count};} @w{int
@var{is_resident};}
> @w{int @var{is_symglobal};} @w{int @var{is_symlocal};address@hidden
Hmm. If lt_dlinfo is part of the public interface, and looking at 1.5.22
it seems is it, then this is an incompatible change that requires a major
version bump.
We could discourage use of lt_dlinfo without going through pointer access
and malloc, in order to avoid this next time.
> @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. @var{module} is the
-dlloader's internal handle for the native module, and can be used,
for
> -example, by a loader to check whether @var{module} has already been
-loaded to save loading it again.
> +often the same module is currently loaded. The remaining fields can
+be compared to any hints that were passed to @code{lt_dlopenadvise}
+to determine whether the underlying loader was able to follow them.
> @end deftypefn
> The following function will return a pointer to libltdl's internal
copy
> Index: libltdl/lt_dlloader.c
> ===================================================================
RCS file: /sources/libtool/libtool/libltdl/lt_dlloader.c,v
> retrieving revision 1.9
> diff -u -p -u -r1.9 lt_dlloader.c
> --- libltdl/lt_dlloader.c 25 Mar 2007 12:12:42 -0000 1.9
> +++ libltdl/lt_dlloader.c 1 May 2007 14:04:19 -0000
> @@ -1,6 +1,6 @@
> /* lt_dlloader.c -- dynamic library loader interface
> - Copyright (C) 2004 Free Software Foundation, Inc.
> + Copyright (C) 2004, 2007 Free Software Foundation, Inc.
Any reason for this change?
> Written by Gary V. Vaughan, 2004
> NOTE: The canonical source of this file is maintained with the
> Index: libltdl/ltdl.c
> ===================================================================
RCS file: /sources/libtool/libtool/libltdl/ltdl.c,v
> retrieving revision 1.248
> diff -u -p -u -r1.248 ltdl.c
> --- libltdl/ltdl.c 25 Mar 2007 12:12:42 -0000 1.248
> +++ libltdl/ltdl.c 1 May 2007 14:04:22 -0000
> @@ -1,7 +1,7 @@
> /* ltdl.c -- system independent dlopen wrapper
> - Copyright (C) 1998, 1999, 2000, 2004, 2005,
> - 2006 Free Software Foundation, Inc.
> + Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
> + 2007 Free Software Foundation, Inc.
> Written by Thomas Tanner, 1998
> NOTE: The canonical source of this file is maintained with the
> @@ -58,16 +58,11 @@ or obtained by writing to the Free Softw
> #undef LT_SYMBOL_OVERHEAD
> #define LT_SYMBOL_OVERHEAD 5
> -
> /* Various boolean flags can be stored in the flags field of an
> lt_dlhandle... */
> -#define LT_DLGET_FLAG(handle, flag) ((((lt__handle *) handle)->flags
&
> (flag)) == (flag))
> -#define LT_DLSET_FLAG(handle, flag) (((lt__handle *)handle)->flags |=
> (flag))
> -
> -#define LT_DLRESIDENT_FLAG (0x01 << 0)
> -/* ...add more flags here... */
> -
> -#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle,
> LT_DLRESIDENT_FLAG)
> +#define LT_DLIS_RESIDENT(handle)
> (((lt__handle*)handle)->info.is_resident)
> +#define LT_DLIS_SYMGLOBAL(handle)
> (((lt__handle*)handle)->info.is_symglobal)
> +#define LT_DLIS_SYMLOCAL(handle)
> (((lt__handle*)handle)->info.is_symlocal)
> static const char objdir[] = LT_OBJDIR;
> @@ -91,11 +86,11 @@ typedef int foreach_callback_func (char
> /* foreachfile_callback itself calls a function of this type: */
typedef int file_worker_func (const char *filename, void *data);
> +
> static int foreach_dirinpath (const char *search_path,
> const char *base_name,
> foreach_callback_func *func,
> void *data1, void *data2);
> -
> static int find_file_callback (char *filename, void *data1,
> void *data2);
> static int find_handle_callback (char *filename, void *data,
> @@ -111,17 +106,23 @@ static FILE *find_file (const ch
> const char *base_name, char **pdir);
> static lt_dlhandle *find_handle (const char *search_path,
> const char *base_name,
> - lt_dlhandle *handle);
> + lt_dlhandle *handle,
> + lt_dladvise advise);
> static int find_module (lt_dlhandle *handle, const char
> *dir,
> const char *libdir, const char *dlname,
> - const char *old_name, int installed);
> + const char *old_name, int installed,
> + lt_dladvise advise);
> +static int has_library_ext (const char *filename);
> static int load_deplibs (lt_dlhandle handle, char
> *deplibs);
static int trim (char **dest, const char *str);
> static int try_dlopen (lt_dlhandle *handle,
> - const char *filename);
> + const char *filename, const char *ext,
> + lt_dladvise advise);
> static int tryall_dlopen (lt_dlhandle *handle,
> - const char *filename);
> + const char *filename,
> + lt_dladvise advise);
> static int unload_deplibs (lt_dlhandle handle);
> +static lt__advise *advise_dup (lt__advise *advise);
> static int lt_argz_insert (char **pargz, size_t *pargz_len,
> char *before, const char *entry);
> static int lt_argz_insertinorder (char **pargz, size_t *pargz_len,
> @@ -330,8 +331,13 @@ lt_dlexit (void)
> return errors;
> }
> +
> +/* Try all dlloaders for FILENAME. If the library is not
successfully
> + loaded, return non-zero. Otherwise, the dlhondle is stored at the
s/dlhondle/dlhandle/
> + address given in PHANDLE. */
> static int
> -tryall_dlopen (lt_dlhandle *phandle, const char *filename)
> +tryall_dlopen (lt_dlhandle *phandle, const char *filename,
> + lt_dladvise advise)
> {
> lt__handle * handle = (lt__handle *) handles;
> const char * saved_error = 0;
[...]
> @@ -1382,92 +1414,172 @@ file_not_found (void)
> return 0;
> }
> -/* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to -
open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, -
and if a file is still not found try again with MODULE_EXT
appended
> - instead. */
> -lt_dlhandle
> -lt_dlopenext (const char *filename)
> -{
> - lt_dlhandle handle = 0;
> - char * tmp = 0;
> - char * ext = 0;
> - size_t len;
> - int errors = 0;
> - if (!filename)
> - {
> - return lt_dlopen (filename);
> - }
> +/* Unless FILENAME already bears a suitable library extension, then +
return 0. */
> +static int
> +has_library_ext (const char *filename)
> +{
> + char * ext = 0;
> + size_t len;
> assert (filename);
> len = LT_STRLEN (filename);
> ext = strrchr (filename, '.');
> - /* If FILENAME already bears a suitable extension, there is no need
- to try appending additional extensions. */
> if (ext && ((streq (ext, archive_ext))
> #if defined(LT_MODULE_EXT)
> - || (streq (ext, shlib_ext))
> + || (streq (ext, shlib_ext))
> #endif
> - ))
> + ))
> {
> - return lt_dlopen (filename);
> + return 1;
> }
> - /* First try appending ARCHIVE_EXT. */
> - tmp = MALLOC (char, len + LT_STRLEN (archive_ext) + 1);
> - if (!tmp)
> - return 0;
> + return 0;
> +}
> +
> +
> +/* Initialise and configure a user lt_dladvise opaque object. */ +
> +int
> +lt_dladvise_init (lt_dladvise *padvise)
> +{
> + lt__advise *advise = (lt__advise *) lt__zalloc (sizeof
(lt__advise));
> + *padvise = advise;
> + return (advise ? 0 : 1);
> +}
> +
> +int
> +lt_dladvise_destroy (lt_dladvise *padvise)
> +{
> + if (padvise)
> + FREE(*padvise);
> + return 0;
> +}
> +
> +int
> +lt_dladvise_ext (lt_dladvise *padvise)
> +{
> + assert (padvise && *padvise);
> + ((lt__advise *) *padvise)->try_ext = 1;
> + return 0;
> +}
> +
> +int
> +lt_dladvise_resident (lt_dladvise *padvise)
> +{
> + assert (padvise && *padvise);
> + ((lt__advise *) *padvise)->is_resident = 1;
> + return 0;
> +}
> +
> +int
> +lt_dladvise_local (lt_dladvise *padvise)
> +{
> + assert (padvise && *padvise);
> + ((lt__advise *) *padvise)->is_symlocal = 1;
> + return 0;
> +}
> +
> +int
> +lt_dladvise_global (lt_dladvise *padvise)
> +{
> + assert (padvise && *padvise);
> + ((lt__advise *) *padvise)->is_symglobal = 1;
> + return 0;
> +}
> - strcpy (tmp, filename);
> - strcat (tmp, archive_ext);
> - errors = try_dlopen (&handle, tmp);
> -
> - /* If we found FILENAME, stop searching -- whether we were able to
- load the file as a module or not. If the file exists but
loading
> - failed, it is better to return an error message here than to -
report FILE_NOT_FOUND when the alternatives (foo.so etc) are not -
in the module search path. */
> - if (handle || ((errors > 0) && !file_not_found ()))
> +static lt__advise *
> +advise_dup (lt__advise *advise)
> +{
> + lt__advise *dup = (lt__advise *) lt__zalloc (sizeof (lt__advise));
+ return memcpy (dup, advise, sizeof (lt__advise));
> +}
> +
> +/* Libtool-1.5x interface for loading a new module named FILENAME.
*/
s/1\.5x/1.5.x/
> +lt_dlhandle
> +lt_dlopen (const char *filename)
> +{
> + return lt_dlopenadvise (filename, NULL);
> +}
> +
> +
> +/* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to +
open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, +
and if a file is still not found try again with MODULE_EXT
appended
> + instead. */
> +lt_dlhandle
> +lt_dlopenext (const char *filename)
> +{
> + lt_dlhandle handle = 0;
> + lt_dladvise advise;
> +
> + if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise)) +
handle = lt_dlopenadvise (filename, advise);
> +
> + lt_dladvise_destroy (&advise);
> + return handle;
> +}
> +
> +
> +lt_dlhandle
> +lt_dlopenadvise (const char *filename, lt_dladvise advise)
> +{
> + lt_dlhandle handle = 0;
> + int errors = 0;
> +
> + /* Can't have symbols hidden and visible at the same time! */ +
if (advise
> + && ((lt__advise *) advise)->is_symlocal
> + && ((lt__advise *) advise)->is_symglobal)
> {
> - FREE (tmp);
> - return handle;
> + LT__SETERROR (CONFLICTING_FLAGS);
> + return 0;
> }
> -#if defined(LT_MODULE_EXT)
> - /* Try appending MODULE_EXT. */
> - if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
> - {
> - FREE (tmp);
> - tmp = MALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
> - if (!tmp)
> - return 0;
> + if (!filename
> + || !advise
> + || !((lt__advise *) advise)->try_ext
> + || has_library_ext (filename))
> + {
> + /* Just incase we missed a code path in try_dlopen() that
reports
> + an error, but forgot to reset handle... */
> + if (try_dlopen (&handle, filename, NULL, advise) != 0)
> + return 0;
> - strcpy (tmp, filename);
> + return handle;
> }
> else
> {
> - tmp[len] = LT_EOS_CHAR;
> - }
> + assert (filename);
> - strcat(tmp, shlib_ext);
> - errors = try_dlopen (&handle, tmp);
> + /* First try appending ARCHIVE_EXT. */
> + errors += try_dlopen (&handle, filename, archive_ext, advise);
- /* As before, if the file was found but loading failed, return now
- with the current error message. */
> - if (handle || ((errors > 0) && !file_not_found ()))
> - {
> - FREE (tmp);
> - return handle;
> - }
> + /* If we found FILENAME, stop searching -- whether we were able
to
> + load the file as a module or not. If the file exists but
> loading
> + failed, it is better to return an error message here than to
+ report FILE_NOT_FOUND when the alternatives (foo.so etc) are
> not
> + in the module search path. */
> + if (handle || ((errors > 0) && !file_not_found ()))
> + return handle;
> +
> +#if defined(LT_MODULE_EXT)
> + /* Try appending SHLIB_EXT. */
> + errors = try_dlopen (&handle, filename, shlib_ext, advise); +
> + /* As before, if the file was found but loading failed, return
now
> + with the current error message. */
> + if (handle || ((errors > 0) && !file_not_found ()))
> + return handle;
> #endif
> + }
> /* Still here? Then we really did fail to locate any of the file
> names we tried. */
> LT__SETERROR (FILE_NOT_FOUND);
> - FREE (tmp);
> return 0;
> }
> @@ -2020,7 +2132,7 @@ lt_dlmakeresident (lt_dlhandle handle)
> }
> else
> {
> - LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
> + ((lt__handle *) handle)->info.is_resident = 1;
> }
> return errors;
> @@ -2040,7 +2152,6 @@ lt_dlisresident (lt_dlhandle handle)
> -
> /* --- MODULE INFORMATION --- */
> typedef struct {
> Index: libltdl/ltdl.h
> ===================================================================
RCS file: /sources/libtool/libtool/libltdl/ltdl.h,v
> retrieving revision 1.84
> diff -u -p -u -r1.84 ltdl.h
> --- libltdl/ltdl.h 25 Mar 2007 12:12:42 -0000 1.84
> +++ libltdl/ltdl.h 1 May 2007 14:04:22 -0000
> @@ -1,6 +1,7 @@
> /* ltdl.h -- generic dlopen functions
> - Copyright (C) 1998-2000, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998-2000, 2004, 2005,
> + 2007 Free Software Foundation, Inc.
> Written by Thomas Tanner, 1998
> NOTE: The canonical source of this file is maintained with the
> @@ -42,7 +43,6 @@ LT_BEGIN_C_DECLS
> /* LT_STRLEN can be used safely on NULL pointers. */
> #define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0)
> -
>
> /* --- DYNAMIC MODULE LOADING API --- */
> @@ -64,20 +64,25 @@ LT_SCOPE int lt_dlforeachfile (
> int (*func) (const char *filename, void *data),
> void *data);
> +/* User module loading advisors. */
> +LT_SCOPE int lt_dladvise_init (lt_dladvise *advise);
> +LT_SCOPE int lt_dladvise_destroy (lt_dladvise *advise);
> +LT_SCOPE int lt_dladvise_ext (lt_dladvise *advise);
> +LT_SCOPE int lt_dladvise_resident (lt_dladvise *advise);
> +LT_SCOPE int lt_dladvise_local (lt_dladvise *advise);
> +LT_SCOPE int lt_dladvise_global (lt_dladvise *advise);
> +
> /* Portable libltdl versions of the system dlopen() API. */
> LT_SCOPE lt_dlhandle lt_dlopen (const char *filename);
> LT_SCOPE lt_dlhandle lt_dlopenext (const char *filename);
> +LT_SCOPE lt_dlhandle lt_dlopenadvise (const char *filename,
> + lt_dladvise advise);
> LT_SCOPE void * lt_dlsym (lt_dlhandle handle, const char
> *name);
LT_SCOPE const char *lt_dlerror (void);
> LT_SCOPE int lt_dlclose (lt_dlhandle handle);
> -/* Module residency management. */
> -LT_SCOPE int lt_dlmakeresident (lt_dlhandle handle);
> -LT_SCOPE int lt_dlisresident (lt_dlhandle handle);
> -
> -
> /* --- PRELOADED MODULE SUPPORT --- */
> @@ -126,6 +131,11 @@ typedef struct {
> char * name; /* module name */
> int ref_count; /* number of times lt_dlopened minus
> number of times lt_dlclosed. */
> + int is_resident:1; /* module can't be unloaded. */
> + int is_symglobal:1; /* module symbols can satisfy
> + subsequently loaded modules. */
> + int is_symlocal:1; /* module symbols are only available
> + locally. */
Are we certain that bitfields are portable enough? I suppose with C89 as
prerequisite that should be no issue.
> } lt_dlinfo;
> LT_SCOPE const lt_dlinfo *lt_dlgetinfo (lt_dlhandle handle);
> @@ -138,6 +148,12 @@ LT_SCOPE int lt_dlhandle_map (lt_dl
> int (*func) (lt_dlhandle handle, void *data),
> void *data);
> +
> +
> +/* Deprecated module residency management API. */
> +LT_SCOPE int lt_dlmakeresident (lt_dlhandle handle);
> +LT_SCOPE int lt_dlisresident (lt_dlhandle handle);
> +
> #define lt_ptr void *
> LT_END_C_DECLS
> Index: libltdl/libltdl/lt__private.h
> ===================================================================
RCS file: /sources/libtool/libtool/libltdl/libltdl/lt__private.h,v
retrieving revision 1.13
> diff -u -p -u -r1.13 lt__private.h
> --- libltdl/libltdl/lt__private.h 25 Mar 2007 12:12:43 -0000 1.13 +++
libltdl/libltdl/lt__private.h 1 May 2007 14:04:41 -0000
> @@ -121,7 +121,16 @@ struct lt__handle {
> int flags; /* various boolean stats */
> };
> +typedef struct lt__advise lt__advise;
> +struct lt__advise {
> + unsigned int try_ext:1; /* try system library extensions. */ +
unsigned int is_resident:1; /* module can't be unloaded. */ +
unsigned int is_symglobal:1; /* module symbols can satisfy
> + subsequently loaded modules. */
> + unsigned int is_symlocal:1; /* module symbols are only available
+ locally. */
> +};
> /* --- ERROR HANDLING --- */
> Index: libltdl/libltdl/lt_dlloader.h
> ===================================================================
RCS file: /sources/libtool/libtool/libltdl/libltdl/lt_dlloader.h,v
retrieving revision 1.3
> diff -u -p -u -r1.3 lt_dlloader.h
> --- libltdl/libltdl/lt_dlloader.h 25 Mar 2007 12:12:43 -0000 1.3 +++
libltdl/libltdl/lt_dlloader.h 1 May 2007 14:04:41 -0000
> @@ -38,10 +38,12 @@ LT_BEGIN_C_DECLS
> typedef void * lt_dlloader;
> typedef void * lt_module;
> typedef void * lt_user_data;
> +typedef void * lt_dladvise;
> /* Function pointer types for module loader vtable entries: */
typedef lt_module lt_module_open (lt_user_data data,
> - const char *filename);
> + const char *filename,
> + lt_dladvise advise);
> typedef int lt_module_close (lt_user_data data,
> lt_module module);
> typedef void * lt_find_sym (lt_user_data data, lt_module
> module,
> Index: libltdl/libltdl/lt_error.h
> ===================================================================
RCS file: /sources/libtool/libtool/libltdl/libltdl/lt_error.h,v
retrieving revision 1.5
> diff -u -p -u -r1.5 lt_error.h
> --- libltdl/libltdl/lt_error.h 25 Mar 2007 12:12:43 -0000 1.5
> +++ libltdl/libltdl/lt_error.h 1 May 2007 14:04:41 -0000
Missing copyright year adjustment.
> @@ -60,7 +60,8 @@ LT_BEGIN_C_DECLS
> LT_ERROR(SHUTDOWN, "library already shutdown\0")
> \
> LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident
module\0") \
> LT_ERROR(INVALID_MUTEX_ARGS, "internal error (code
> withdrawn)\0")\
> - LT_ERROR(INVALID_POSITION, "invalid search path insert
> position\0")
> + LT_ERROR(INVALID_POSITION, "invalid search path insert
> position\0")\
> + LT_ERROR(CONFLICTING_FLAGS, "symbol visibility can be global
or
> local\0")
> /* Enumerate the symbolic error names. */
> enum {
[...]
> Index: tests/lt_dladvise.at
> ===================================================================
RCS file: tests/lt_dladvise.at
> diff -N tests/lt_dladvise.at
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ tests/lt_dladvise.at 1 May 2007 14:04:45 -0000
> @@ -0,0 +1,292 @@
> +# lt_dlexit.at -- test libltdl functionality -*-
> Autotest -*-
> +#
> +# Copyright (C) 2007 Free Software Foundation, Inc.
> +# Written by Gary V. Vaughan, 2007
> +#
> +# This file is part of GNU Libtool.
> +#
> +# GNU Libtool is free software; you can redistribute it and/or +#
modify it under the terms of the GNU General Public License as +#
published by the Free Software Foundation; either version 2 of +# the
License, or (at your option) any later version.
> +#
> +# GNU Libtool 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
General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy +#
can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or
obtained by writing to the Free Software Foundation, Inc., +# 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +####
> +
> +# Try to keep the new interfaces of HEAD separate from those of +#
branch-1-5 to facilitate testing of older releases.
> +
> +AT_SETUP([lt_dlopenadvise library loading])
> +AT_KEYWORDS([libltdl])
> +
> +AT_DATA([main.c],
> +[[#include <ltdl.h>
> +#include <stdio.h>
> +
> +typedef int funcp (int);
> +
> +static int errors = 0;
> +
> +static void
> +complain (const char *msg)
> +{
> + const char *errmsg = lt_dlerror ();
> + fprintf (stderr, "%s", msg);
> + if (errmsg)
> + fprintf (stderr, ": %s\n", errmsg);
> + else
> + fprintf (stderr, ".\n");
> + ++errors;
> +}
> +
> +static lt_dlhandle
> +moduleopen (const char *filename, lt_dladvise advise)
> +{
> + lt_dlhandle handle;
> +
> + handle = lt_dlopenadvise (filename, advise);
> + if (!handle)
> + {
> + fprintf (stderr, "can't open the module %s!\n", filename); +
complain ("error was");
> + }
> +
> + return handle;
> +}
> +
> +static int
> +moduletest (lt_dlhandle handle, const char *fname, const char *vname) +{
> + funcp *f = (funcp *) lt_dlsym (handle, fname);
> + int *v = (int *) lt_dlsym (handle, vname);
> +
> + if (!f)
> + {
> + fprintf (stderr, "function `%s' not found\n", fname);
> + ++errors;
> + return -1;
> + }
> + if (!v)
> + {
> + fprintf (stderr, "variable `%s' not found\n", vname);
> + ++errors;
> + return -1;
> + }
> + return f (*v);
> +}
> +
> +void
> +hint_ext (void)
> +{
> + lt_dlhandle handle;
> + lt_dladvise advise;
> +
> + if (lt_dladvise_init (&advise) || lt_dladvise_ext (&advise)) +
complain ("error setting advise ext");
> +
> + handle = moduleopen ("moddepend", advise);
> +
> + if (handle)
> + printf ("depend: %d\n", moduletest (handle, "g", "j"));
> +
> + lt_dladvise_destroy (&advise);
> +}
handle is never closed here. This is important: some failures are only
caught at module closing time.
> +void
> +hint_resident (void)
> +{
> + const lt_dlinfo *info;
> + lt_dlhandle handle;
> + lt_dladvise advise;
> +
> + if (lt_dladvise_init (&advise) || lt_dladvise_resident (&advise)) +
complain ("error setting advise resident");
> +
> + handle = moduleopen ("modresident.la", advise);
> +
> + if (handle)
> + {
> + info = lt_dlgetinfo (handle);
> + if (!info->is_resident)
> + complain ("error taking advise resident");
> +
> + /* cannot close resident modules */
> + if (lt_dlclose (handle) == 0)
> + complain ("successfully unloaded resident module");
> +
> + printf ("resident: %d\n", moduletest (handle, "func", "numb"));
+ }
> +
> + lt_dladvise_destroy (&advise);
> +}
> +
> +void
> +hint_local (void)
> +{
> + const lt_dlinfo *info;
> + lt_dlhandle handle;
> + lt_dladvise advise;
> +
> + if (lt_dladvise_init (&advise) || lt_dladvise_local (&advise)) +
complain ("error setting advise local");
> +
> + handle = moduleopen ("modlocal.la", advise);
> +
> + if (handle)
> + {
> + info = lt_dlgetinfo (handle);
> + printf ("local: %d\n", moduletest (handle, "f", "i"));
> +
> + /* If the symlocal hint was taken, don't unload this module +
and test that our local symbolnames won't clash with
modglobal.
> */
> + if (!info->is_symlocal && lt_dlclose (handle))
> + complain ("error unloading modlocal");
> + }
> +
> + lt_dladvise_destroy (&advise);
> +}
> +
> +void
> +hint_global (void)
> +{
> + const lt_dlinfo *info;
> + lt_dlhandle handle;
> + lt_dladvise advise;
> +
> + if (lt_dladvise_init (&advise) || lt_dladvise_global (&advise)) +
complain ("error setting advise global");
> +
> + handle = moduleopen ("modglobal.la", advise);
> +
> + if (handle)
> + {
> + info = lt_dlgetinfo (handle);
> + printf ("global: %d\n", moduletest (handle, "f", "i")); +
> + /* Don't attempt to load moddepend unless modglobal was
> successfully
> + loaded and the symglobal hint was taken. */
> + if (info && info->is_symglobal)
> + {
> + hint_ext ();
> + }
> + else
> + {
> + /* Fake the output so the test won't fail when using a
> dlloader
> + unable to take symglobal hints. */
> + printf ("depend: 5\n");
> + }
> + }
> +
> + lt_dladvise_destroy (&advise);
> +}
> +
> +int
> +main (int argc, char **argv)
> +{
> +
> + LTDL_SET_PRELOADED_SYMBOLS();
> +
> + if (lt_dlinit() != 0)
> + {
> + fprintf (stderr, "error during initialization: %s\n",
> lt_dlerror());
> + return 1;
> + }
> +
> + hint_resident ();
> + hint_local ();
> + hint_global ();
> +
> + if (lt_dlexit () != 0)
> + complain ("error during exit");
> +
> + return (errors != 0);
> +}
> +]])
> +
> +AT_DATA([modresident.c],
> +[[#ifdef __cplusplus
> +extern "C" {
> +#endif
> +int func (int x) { return x / 3; }
> +int numb = 7;
> +#ifdef __cplusplus
> +}
> +#endif
> +]])
> +
> +AT_DATA([modlocal.c],
> +[[#ifdef __cplusplus
> +extern "C" {
> +#endif
> +int f (int x) { return (x * x) / 10; }
> +int i = 6;
> +#ifdef __cplusplus
> +}
> +#endif
> +]])
> +
> +AT_DATA([modglobal.c],
> +[[#ifdef __cplusplus
> +extern "C" {
> +#endif
> +int f (int x) { return x - 1; }
> +int i = 5;
> +#ifdef __cplusplus
> +}
> +#endif
> +]])
> +
> +AT_DATA([moddepend.c],
> +[[#ifdef __cplusplus
> +extern "C" {
> +#endif
> +extern int f (int), i;
> +int g (int x) { return f (i) + x - 3; }
> +int j = 4;
> +#ifdef __cplusplus
> +}
> +#endif
> +]])
> +
> +AT_DATA([expout],
> +[[resident: 2
> +local: 3
> +global: 4
> +depend: 5
> +]])
> +
> +: ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
> +: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"}
> +
> +CPPFLAGS="$CPPFLAGS $LTDLINCL"
> +LDFLAGS="$LDFLAGS"
> +
> +$CC $CPPFLAGS $CFLAGS -c main.c
> +for file in modresident modlocal modglobal moddepend; do
> + $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c $file.c
> + AT_CHECK([$LIBTOOL --mode=link $CC -module $CFLAGS $LDFLAGS -o
> $file.la \
> + $file.lo -rpath /foo -avoid-version], [], [ignore],
What about -no-undefined, for w32?
> [ignore])
> +done
> +
> +# TODO: test -dlpreopen
> +for dlopen in -dlopen; do
> + AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main
> main.$OBJEXT \
> + $dlopen modresident.la $dlopen modlocal.la $dlopen
> modglobal.la \
> + $dlopen moddepend.la $LIBLTDL],
> + [], [ignore], [ignore])
> + LT_AT_NOINST_EXEC_CHECK([./main],
> + [$dlopen modresident.la $dlopen modlocal.la $dlopen modglobal.la
\
> + $dlopen moddepend.la],
> + [], [expout], [])
> +done
> +
> +AT_CLEANUP
- Re: 329-gary-allow-RTLD_GLOBAL, Gary V. Vaughan, 2007/05/01
- Re: 329-gary-allow-RTLD_GLOBAL,
Ralf Wildenhues <=
- Re: 329-gary-allow-RTLD_GLOBAL, Ralf Wildenhues, 2007/05/21
- Re: 329-gary-allow-RTLD_GLOBAL, Gary V. Vaughan, 2007/05/21
- Re: 329-gary-allow-RTLD_GLOBAL, Gary V. Vaughan, 2007/05/22
- Re: 329-gary-allow-RTLD_GLOBAL, Ralf Wildenhues, 2007/05/22
- Re: 329-gary-allow-RTLD_GLOBAL, Gary V. Vaughan, 2007/05/22
- Re: 329-gary-allow-RTLD_GLOBAL, Ralf Wildenhues, 2007/05/22