* 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 <[EMAIL PROTECTED]> + + 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 <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED] int lt_dladvise_preload (lt_dladvise [EMAIL PROTECTED]) +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}. [EMAIL PROTECTED] 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
pgpiJwYXVaSfR.pgp
Description: PGP signature