+2008-08-01 Gary V. Vaughan <gary@gnu.org>
+
+ 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-08-01 Vincent Torri <doursse@users.sf.net>
Add cegcc (Windows CE/PocketPC) support.
NEWS - list of user-visible changes between releases of GNU Libtool
-New in 2.2.??: 2008-06-??: git version 2.2.5a, Libtool team:
+New in 2.2.??: 2008-08-??: 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.
* Changes in supported systems or compilers:
message that can be retrieved with @code{lt_dlerror}.
@end deftypefun
+@deftypefun int lt_dladvise_preload (lt_dladvise *@var{advise})
+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 preloaded module is
+not found, @code{lt_dlopenadvise} will return @code{NULL}.
+@end 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,
subsequently loaded modules. */
unsigned int is_symlocal:1; /* module symbols are only available
locally. */
+ unsigned int try_preload_only:1;/* only preloaded modules will be tried. */
};
/* --- ERROR HANDLING --- */
lt_dladvise advise)
{
const char * saved_error = 0;
+ char * archive_name = 0;
char * canonical = 0;
char * base_name = 0;
char * dir = 0;
if (vtable)
{
+ 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 are allowing only preloaded modules, and we didn't find
+ anything yet, give up on the search here. */
+ if (advise && advise->try_preload_only)
+ {
+ goto cleanup;
+ }
+
/* Check whether we are opening a libtool module (.la extension). */
if (ext && streq (ext, archive_ext))
{
if (!canonical) /* was MEMREASSIGNed */
FREE (base_name);
FREE (canonical);
+ FREE (archive_name);
return errors;
}
return 0;
}
+int
+lt_dladvise_preload (lt_dladvise *padvise)
+{
+ assert (padvise && *padvise);
+ (*padvise)->try_preload_only = 1;
+ return 0;
+}
+
/* Libtool-1.5.x interface for loading a new module named FILENAME. */
lt_dlhandle
lt_dlopen (const char *filename)
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);
# 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],
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)
{
hint_resident ();
hint_local ();
hint_global ();
+ hint_preload ();
if (lt_dlexit () != 0)
complain ("error during exit");
#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"}
CPPFLAGS="$LTDLINCL $CPPFLAGS"
dlopenable='resident local global'
+dlpreloadable='preload'
# ------------------------------------------------------------------------- #
# The depend test makes no sense unless compiled without -no-undefined. By #
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])
+
+# Remove loadable libpreload module, so we know it is the preloaded module
+# that is being executed by a successful test invocation:
+$LIBTOOL --mode=clean rm libpreload.la
+
+LT_AT_NOINST_EXEC_CHECK([./main], [$modules], [], [expout], [])
+
AT_CLEANUP