libtool-patches
[Top][All Lists]
Advanced

[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








reply via email to

[Prev in Thread] Current Thread [Next in Thread]