libtool-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 370] Implement lt_dlopening of only preloaded modules.


From: Gary V. Vaughan
Subject: [PATCH 370] Implement lt_dlopening of only preloaded modules.
Date: Tue, 6 May 2008 13:24:46 -0400 (EDT)
User-agent: mailnotify/0.9

* libltdl/m4/ltdl.m4 (LTDL_INIT): Check for a libltdl that
provides lt_dladvise_preopen when deciding if installed libltdl
is 'new enough'.
* libltdl/libltdl/lt__private.h (lt__advise): Add a new
is_preload flag.
* libltdl/ltdl.c (lt_dladvise_preload): New api call to set it.
(try_dlopen): If it is set, and the search of preloaded modules
didn't return a match, don't bother searching the filesystem.
* libltdl/ltdl.h (lt_dladvise_preload): Declare it.
* doc/libtool.texi (Libltdl Interface): Document it.
* tests/lt_dladvise.at: Test it (and incidentally add some test
coverage for `libtool -dlpreopen').
* NEWS: Announce it.
---

This makes it possible to build a libltdl client with some preloaded
modules, and limit lt_dlopenadvise to open only the preloaded modules.

For example: nearly all of GNU M4 is implemented as modules, with the
core functionality preloaded by default.  All module loading is
handled by lt_dlopenadvise irrespective of whether modules were
preloaded or need to be found in M4PATH.  However, it is also
possible to turn off gnu extensions, such as path searching and
module loading with -G, but we still need to be able to lt_dlopen
the preloaded core modules when module loading proper has been
disabled.  With this patch I can use the lt_dlodvise_preopen hint
when the driver loads the preloaded core modules, even though user
module loading from the filesystem is turned off without the need
to maintain two codepaths (load preloaded core modules even if
they can't be found in the filesystem vs load arbitrary modules
from the filesystem in gnu extended mode).

Okay to push?

 ChangeLog                     |   17 ++++++++++++
 NEWS                          |    5 ++-
 doc/libtool.texi              |    7 +++++
 libltdl/libltdl/lt__private.h |    1 +
 libltdl/ltdl.c                |   25 +++++++++++++++++-
 libltdl/ltdl.h                |    1 +
 libltdl/m4/ltdl.m4            |    2 +-
 tests/lt_dladvise.at          |   56 +++++++++++++++++++++++++++++++++--------
 8 files changed, 98 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 15ffae1..2a1c843 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2008-05-06  Gary V. Vaughan  <address@hidden>
+
+       Implement lt_dlopening of only preloaded modules.
+       * libltdl/m4/ltdl.m4 (LTDL_INIT): Check for a libltdl that
+       provides lt_dladvise_preopen when deciding if installed libltdl
+       is 'new enough'.
+       * libltdl/libltdl/lt__private.h (lt__advise): Add a new
+       is_preload flag.
+       * libltdl/ltdl.c (lt_dladvise_preload): New api call to set it.
+       (try_dlopen): If it is set, and the search of preloaded modules
+       didn't return a match, don't bother searching the filesystem.
+       * libltdl/ltdl.h (lt_dladvise_preload): Declare it.
+       * doc/libtool.texi (Libltdl Interface): Document it.
+       * tests/lt_dladvise.at: Test it (and incidentally add some test
+       coverage for `libtool -dlpreopen').
+       * NEWS: Announce it.
+
 2008-05-05  Gary V. Vaughan  <address@hidden>
 
        Fix libtoolize test failure with aclocal < 1.10.1
diff --git a/NEWS b/NEWS
index 2b113fb..3354e6c 100644
--- a/NEWS
+++ b/NEWS
@@ -2,9 +2,10 @@ NEWS - list of user-visible changes between releases of GNU 
Libtool
 
 New in 2.2.??: 2008-06-??: git version 2.2.5a, Libtool team:
 
-* Bug fixes:
+* New features:
 
-  - None yet
+  - New lt_dloadvise_preload() call to set a hint that only preloadeded
+    modules can be opened.
 
 New in 2.2.4: 2008-05-04: git version 2.2.3a, Libtool team:
 
diff --git a/doc/libtool.texi b/doc/libtool.texi
index 31ba0c7..e694655 100644
--- a/doc/libtool.texi
+++ b/doc/libtool.texi
@@ -3816,6 +3816,13 @@ On failure, @code{lt_dladvise_resident} returns non-zero 
and sets an error
 message that can be retrieved with @code{lt_dlerror}.
 @end deftypefun
 
address@hidden int lt_dladvise_preload (lt_dladvise address@hidden)
+Set the @code{preload} hint on @var{advise}.  Passing an @var{advise}
+parameter to @code{lt_dlopenadvise} with this hint set causes it to
+load only preloaded modules, so that if a suitable preleaded module is
+not found, @code{lt_dlopenadvise} will return @code{NULL}.
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,
diff --git a/libltdl/libltdl/lt__private.h b/libltdl/libltdl/lt__private.h
index 4ce936d..fd6e662 100644
--- a/libltdl/libltdl/lt__private.h
+++ b/libltdl/libltdl/lt__private.h
@@ -126,6 +126,7 @@ struct lt__advise {
                                   subsequently loaded modules.  */
   unsigned int is_symlocal:1;  /* module symbols are only available
                                   locally. */
+  unsigned int is_preload:1;   /* only preloaded modules will be tried.  */
 };
 
 /* --- ERROR HANDLING --- */
diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
index a89c6bb..920e186 100644
--- a/libltdl/ltdl.c
+++ b/libltdl/ltdl.c
@@ -1257,27 +1257,40 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, 
const char *ext,
 
       if (vtable)
        {
+         char *archive_name = MALLOC (char, LT_STRLEN (name) + 3);
          *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
 
-         if (*phandle == NULL)
+         if ((*phandle == NULL) || (archive_name == NULL))
            {
              ++errors;
              goto cleanup;
            }
          newhandle = *phandle;
 
-         if (tryall_dlopen (&newhandle, attempt, advise, vtable) == 0)
+         /* Preloaded modules are always named according to their old
+            archive name.  */
+         sprintf (archive_name, "%s.a", name);
+
+         if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
            {
              goto register_handle;
            }
 
          /* If we're still here, there was no matching preloaded module,
             so put things back as we found them, and continue searching.  */
+         FREE (archive_name);
          FREE (*phandle);
          newhandle = NULL;
        }
     }
 
+  /* If we are allowing only preloaded modules, and we didn't find
+     anything yet, give up on the search here.  */
+  if (advise && advise->is_preload)
+    {
+      goto cleanup;
+    }
+
   /* Check whether we are opening a libtool module (.la extension).  */
   if (ext && streq (ext, archive_ext))
     {
@@ -1555,6 +1568,14 @@ lt_dladvise_global (lt_dladvise *padvise)
   return 0;
 }
 
+int
+lt_dladvise_preload (lt_dladvise *padvise)
+{
+  assert (padvise && *padvise);
+  (*padvise)->is_preload = 1;
+  return 0;
+}
+
 /* Libtool-1.5.x interface for loading a new module named FILENAME.  */
 lt_dlhandle
 lt_dlopen (const char *filename)
diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h
index bc60b88..8b516ad 100644
--- a/libltdl/ltdl.h
+++ b/libltdl/ltdl.h
@@ -71,6 +71,7 @@ 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);
+LT_SCOPE int       lt_dladvise_preload  (lt_dladvise *advise);
 
 /* Portable libltdl versions of the system dlopen() API. */
 LT_SCOPE lt_dlhandle lt_dlopen         (const char *filename);
diff --git a/libltdl/m4/ltdl.m4 b/libltdl/m4/ltdl.m4
index 6c277b4..8e5b8ed 100644
--- a/libltdl/m4/ltdl.m4
+++ b/libltdl/m4/ltdl.m4
@@ -264,7 +264,7 @@ if test "x$with_included_ltdl" != xyes; then
   # decide whether there is a useful installed version we can use.
   AC_CHECK_HEADER([ltdl.h],
       [AC_CHECK_DECL([lt_dlinterface_register],
-          [AC_CHECK_LIB([ltdl], [lt_dlinterface_register],
+          [AC_CHECK_LIB([ltdl], [lt_dladvise_preload],
               [with_included_ltdl=no],
               [with_included_ltdl=yes])],
           [with_included_ltdl=yes],
diff --git a/tests/lt_dladvise.at b/tests/lt_dladvise.at
index 617539f..f28f74f 100644
--- a/tests/lt_dladvise.at
+++ b/tests/lt_dladvise.at
@@ -190,6 +190,25 @@ hint_global (void)
   lt_dladvise_destroy (&advise);
 }
 
+void
+hint_preload (void)
+{
+  lt_dlhandle handle;
+  lt_dladvise advise;
+
+  if (lt_dladvise_init (&advise) || lt_dladvise_preload (&advise))
+    complain ("error setting advise preload");
+
+  handle = moduleopen ("libpreload.la", advise);
+
+  if (handle)
+    {
+      printf("preload: %d\n", moduletest (handle, "h", "k"));
+    }
+
+  lt_dladvise_destroy (&advise);
+}
+
 int
 main (void)
 {
@@ -205,6 +224,7 @@ main (void)
   hint_resident ();
   hint_local ();
   hint_global ();
+  hint_preload ();
 
   if (lt_dlexit () != 0)
     complain ("error during exit");
@@ -258,11 +278,23 @@ int j = 4;
 #endif
 ]])
 
+AT_DATA([modpreload.c],
+[[#ifdef __cplusplus
+extern "C" {
+#endif
+int h (int x) { return 2 * x; }
+int k = 3;
+#ifdef __cplusplus
+}
+#endif
+]])
+
 AT_DATA([expout],
 [[resident: 2
 local: 3
 global: 4
 depend: 5
+preload: 6
 ]])
 
 : ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
@@ -277,6 +309,7 @@ esac], [], [ignore])
 CPPFLAGS="$LTDLINCL $CPPFLAGS"
 
 dlopenable='resident local global'
+dlpreloadable='preload'
 
 # ------------------------------------------------------------------------- #
 # The depend test makes no sense unless compiled without -no-undefined. By  #
@@ -306,23 +339,24 @@ esac
 LDFLAGS="$LDFLAGS -no-undefined"
 
 $CC $CPPFLAGS $CFLAGS -c main.c
-for name in resident local global; do
+for name in resident local global preload; do
   $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c mod$name.c
   AT_CHECK([$LIBTOOL --mode=link $CC -module $CFLAGS $LDFLAGS -o lib$name.la \
             mod$name.lo -rpath /foo -avoid-version], [], [ignore], [ignore])
 done
 
-# TODO: test -dlpreopen
-for dlopen in -dlopen; do
-
-  modules=
-  for module in $dlopenable; do
-    modules="${modules+$modules }$dlopen lib$module.la"
-  done
+preloaded=
+for module in $dlpreloadable; do
+  preloaded="${preloaded+$preloaded }-dlpreopen lib$module.la"
+done
 
-  AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main main.$OBJEXT 
$modules $LIBLTDL],
-          [], [ignore], [ignore])
-  LT_AT_NOINST_EXEC_CHECK([./main], [$modules], [], [expout], [])
+modules=
+for module in $dlopenable; do
+  modules="${modules+$modules }-dlopen lib$module.la"
 done
 
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main main.$OBJEXT 
$preloaded $modules $LIBLTDL],
+        [], [ignore], [ignore])
+LT_AT_NOINST_EXEC_CHECK([./main], [$modules], [], [expout], [])
+
 AT_CLEANUP
-- 
1.5.4.3

Attachment: pgp50DK60MGLV.pgp
Description: PGP signature


reply via email to

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