[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
330-gary-ltdl-vs-need-lib-prefix-unknown
From: |
Gary V. Vaughan |
Subject: |
330-gary-ltdl-vs-need-lib-prefix-unknown |
Date: |
Wed, 9 May 2007 19:14:18 +0100 |
Here is a patch to fix the last release blocking issue in the NEWS
file. Crafting the test uncovered many fine bugs in the dusty
corners of libltdl, so that the fix itself was not too hard once
the test was working.
A side effect of this patch may be that preloading modules will work
without requiring the .la files to be in the filesystem, though I
haven't tested that theory (and won't patch to make it work if I'm
wrong until after the release).
Okay to commit?
Index: libtool--devo--0/ChangeLog
===================================================================
--- libtool--devo--0.orig/ChangeLog
+++ libtool--devo--0/ChangeLog
@@ -1,5 +1,44 @@
2007-05-09 Gary V. Vaughan <address@hidden>
+ Add a test to simulate a failure visible on systems which
+ need a library prefix like 'lib', such as BeOS. Fix a number
+ of bugs exposed by this test in order for it to pass.
+ Currently the prefix is hardcoded as 'lib', as I am not aware
+ of systems that require a different prefix:
+
+ * libltdl/loaders/preopen.c (lt_dlpreload_open): Move error
+ condition out of test loop to be sure that each originator is
+ tried, instead of erroring out if the first doesn't match.
+ Support passing NULL as the originator to load all preloaded
+ modules originating in the program itself.
+ * libltdl/lt_dlloader.c (lt_dlloader_dump): New debug function.
+ * libltdl/libltdl/lt_dlloader.h (lt_dlloader_dump): Declare it
+ when LT_DEBUG_LOADERS is defined at compile time.
+ * libltdl/ltdl.c (lt_dlinit): Dump loader list after successful
+ initialisation.
+ (tryall_dlopen): Add a new VTABLE parameter to force use of a
+ specific loader in preference to trying every loader in turn.
+ Adjust all callers.
+ (try_dlopen): Always see whether a module was preloaded for
+ module names with no directory component before searching the
+ filesystem for a match.
+ * libltdl/m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS): Declare
+ a new global_symbol_to_c_name_address_lib_prefix variable.
+ (global_symbol_to_c_name_address_lib_prefix): The sed
+ expressions to use when a lib prefix is enforced need to be
+ slightly different to work with preloaded modules.
+ * libltdl/config/ltmain.m4sh (func_generate_dlsyms): In order
+ to name preloaded symbols correctly for the lookup algorithm
+ to work when the loaded module file must be prefixed with lib.
+ Use global_symbol_to_c_name_address_lib_prefix when
+ need_lib_prefix is other than no.
+ * tests/need_lib_prefix.at: New test to check for breakage on
+ hosts where need_lib_prefix is unknown.
+ * Makefile.am (TESTSUITE_AT): Add new test.
+ * NEWS: Updated.
+
+2007-05-09 Gary V. Vaughan <address@hidden>
+
* tests/lt_dladvise.at: Commit missing file from below.
2007-05-08 Gary V. Vaughan <address@hidden>
Index: libtool--devo--0/Makefile.am
===================================================================
--- libtool--devo--0.orig/Makefile.am
+++ libtool--devo--0/Makefile.am
@@ -446,6 +446,7 @@ TESTSUITE_AT = tests/testsuite.at \
tests/am-subdir.at \
tests/lt_dlexit.at \
tests/lt_dladvise.at \
+ tests/need_lib_prefix.at \
tests/standalone.at \
tests/subproject.at \
tests/nonrecursive.at \
Index: libtool--devo--0/NEWS
===================================================================
--- libtool--devo--0.orig/NEWS
+++ libtool--devo--0/NEWS
@@ -2,12 +2,6 @@ NEWS - list of user-visible changes betw
New in 2.1a: 2007-??-??; CVS version 2.1a, Libtool team:
-* Regressions over 1.5.x that may be fixed later:
-
- - On systems which need a library prefix like `lib', such as BeOS,
- libltdl currently does not build. The new structure of
libltdl with
- preopened modules exposes some long-lived bugs here.
-
* Important incompatible changes and obsoleted features:
- Removed deprecated APIs from libltdl: lt_dlcaller_register,
Index: libtool--devo--0/tests/need_lib_prefix.at
===================================================================
--- /dev/null
+++ libtool--devo--0/tests/need_lib_prefix.at
@@ -0,0 +1,165 @@
+# need-lib-prefix.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.
+####
+
+AT_SETUP([enforced lib prefix])
+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_dlhandle handle;
+
+ handle = lt_dlopen (filename);
+ if (!handle)
+ {
+ fprintf (stderr, "can't open the module %s!\n", filename);
+ complain ("error was");
+ }
+
+ return handle;
+}
+
+static int
+moduletest (lt_dlhandle handle)
+{
+ const lt_dlinfo *info = lt_dlgetinfo (handle);
+ funcp *f = (funcp *) lt_dlsym (handle, "f");
+ int *v = (int *) lt_dlsym (handle, "i");
+
+ if (!f)
+ {
+ complain ("function `f' not found");
+ return 1;
+ }
+ if (!v)
+ {
+ complain ("variable `i' not found");
+ return 1;
+ }
+ printf ("%s: %d\n", info->name, f (*v));
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ lt_dlhandle handle;
+
+ LTDL_SET_PRELOADED_SYMBOLS();
+
+ if (lt_dlinit() != 0)
+ {
+ fprintf (stderr, "error during initialization: %s\n",
lt_dlerror());
+ return 1;
+ }
+
+ if (lt_dlpreload_open (0, moduletest) != 0)
+ complain ("error during preloading");
+
+ if (lt_dlexit () != 0)
+ complain ("error during exit");
+
+ return (errors != 0);
+}
+]])
+
+AT_DATA([foo1.c],
+[[#define f foo1_LTX_f
+#define i foo1_LTX_i
+#ifdef __cplusplus
+extern "C" {
+#endif
+int f (int x) { return x / 3; }
+int i = 7;
+#ifdef __cplusplus
+}
+#endif
+]])
+
+AT_DATA([foo2.c],
+[[#define f libfoo2_LTX_f
+#define i libfoo2_LTX_i
+#ifdef __cplusplus
+extern "C" {
+#endif
+int f (int x) { return (x * x) / 10; }
+int i = 6;
+#ifdef __cplusplus
+}
+#endif
+]])
+
+AT_DATA([expout],
+[[libfoo1: 2
+libfoo2: 3
+]])
+
+: ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
+: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"}
+
+CPPFLAGS="$CPPFLAGS $LTDLINCL"
+LDFLAGS="$LDFLAGS"
+
+# Create our own libtool, forcing need_lib_prefix setting
+sed 's,^\(need_lib_prefix\)=.*$,\1=unknown,' $LIBTOOL > ./libtool
+LIBTOOL="$SHELL ./libtool"
+
+$CC $CPPFLAGS $CFLAGS -c main.c
+for file in foo1 foo2; do
+ $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c $file.c
+done
+
+AT_CHECK([$LIBTOOL --mode=link $CC -module -avoid-version $CFLAGS
$LDFLAGS \
+ -o foo1.la foo1.lo -rpath /foo], [], [ignore], [ignore])
+AT_CHECK([$LIBTOOL --mode=link $CC -module -avoid-version $CFLAGS
$LDFLAGS \
+ -o libfoo2.la foo2.lo -rpath /foo], [], [ignore],
[ignore])
+AT_CHECK([$LIBTOOL --mode=link $CC -static $CFLAGS $LDFLAGS -o
main \
+ main.$OBJEXT -dlpreopen foo1.la -dlpreopen libfoo2.la
$LIBLTDL],
+ [], [ignore], [ignore])
+
+LT_AT_NOINST_EXEC_CHECK([./main], [-dlopen foo1.la -dlopen
libfoo2.la],
+ [], [expout], [])
+
+AT_CLEANUP
Index: libtool--devo--0/libltdl/loaders/preopen.c
===================================================================
--- libtool--devo--0.orig/libltdl/loaders/preopen.c
+++ libtool--devo--0/libltdl/loaders/preopen.c
@@ -322,7 +322,8 @@ lt_dlpreload (const lt_dlsymlist *preloa
/* Open all the preloaded modules from the named originator,
executing
- a callback for each one. */
+ a callback for each one. If ORIGINATOR is NULL, then call
FUNC for
+ each preloaded module from the program itself. */
int
lt_dlpreload_open (const char *originator,
lt_dlpreload_callback_func *func)
{
@@ -334,7 +335,8 @@ lt_dlpreload_open (const char *originato
for (list = preloaded_symlists; list; list = list->next)
{
/* ...that was preloaded by the requesting ORIGINATOR... */
- if (streq (list->symlist->name, originator))
+ if ((originator && streq (list->symlist->name, originator))
+ || (!originator && streq (list->symlist->name,
"@PROGRAM@")))
{
const lt_dlsymlist *symbol;
unsigned int idx = 0;
@@ -360,12 +362,12 @@ lt_dlpreload_open (const char *originato
}
}
}
+ }
- if (!found)
- {
- LT__SETERROR(CANNOT_OPEN);
- ++errors;
- }
+ if (!found)
+ {
+ LT__SETERROR(CANNOT_OPEN);
+ ++errors;
}
return errors;
Index: libtool--devo--0/libltdl/libltdl/lt_dlloader.h
===================================================================
--- libtool--devo--0.orig/libltdl/libltdl/lt_dlloader.h
+++ libtool--devo--0/libltdl/libltdl/lt_dlloader.h
@@ -81,6 +81,10 @@ LT_SCOPE const lt_dlvtable *lt_dlloader_
/* Type of a function to get a loader's vtable: */
typedef const lt_dlvtable *lt_get_vtable (lt_user_data data);
+#ifdef LT_DEBUG_LOADERS
+LT_SCOPE void lt_dlloader_dump (void);
+#endif
+
LT_END_C_DECLS
#endif /*!defined(LT_DLLOADER_H)*/
Index: libtool--devo--0/libltdl/lt_dlloader.c
===================================================================
--- libtool--devo--0.orig/libltdl/lt_dlloader.c
+++ libtool--devo--0/libltdl/lt_dlloader.c
@@ -97,6 +97,33 @@ lt_dlloader_add (const lt_dlvtable *vtab
return RETURN_SUCCESS;
}
+#ifdef LT_DEBUG_LOADERS
+static void *
+loader_dump_callback (SList *item, void *userdata)
+{
+ const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
+ fprintf (stderr, ", %s", vtable->name);
+ return 0;
+}
+
+void
+lt_dlloader_dump (void)
+{
+ fprintf (stderr, "loaders: ");
+ if (!loaders)
+ {
+ fprintf (stderr, "(empty)");
+ }
+ else
+ {
+ const lt_dlvtable *head = (const lt_dlvtable *) loaders-
>userdata;
+ fprintf (stderr, "%s", head->name);
+ if (slist_tail (loaders))
+ slist_foreach (slist_tail (loaders),
loader_dump_callback, NULL);
+ }
+ fprintf (stderr, "\n");
+}
+#endif
/* An iterator for the global loader list: if LOADER is NULL, then
return the first element, otherwise the following element. */
Index: libtool--devo--0/libltdl/ltdl.c
===================================================================
--- libtool--devo--0.orig/libltdl/ltdl.c
+++ libtool--devo--0/libltdl/ltdl.c
@@ -120,7 +120,8 @@ static int try_dlopen
(lt_dlhandle
lt_dladvise advise);
static int tryall_dlopen (lt_dlhandle *handle,
const char *filename,
- lt_dladvise advise);
+ lt_dladvise advise,
+ const lt_dlvtable *vtable);
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,
@@ -239,6 +240,10 @@ lt_dlinit (void)
#endif /* HAVE_LIBDLLOADER */
}
+#ifdef LT_DEBUG_LOADERS
+ lt_dlloader_dump();
+#endif
+
return errors;
}
@@ -332,17 +337,22 @@ lt_dlexit (void)
}
-/* Try all dlloaders for FILENAME. If the library is not
successfully
- loaded, return non-zero. Otherwise, the dlhandle is stored at
the
- address given in PHANDLE. */
+/* Try VTABLE or, if VTABLE is NULL, all available loaders for
FILENAME.
+ If the library is not successfully loaded, return non-zero.
Otherwise,
+ the dlhandle is stored at the address given in PHANDLE. */
static int
tryall_dlopen (lt_dlhandle *phandle, const char *filename,
- lt_dladvise advise)
+ lt_dladvise advise, const lt_dlvtable *vtable)
{
lt__handle * handle = (lt__handle *) handles;
const char * saved_error = 0;
int errors = 0;
+#ifdef LT_DEBUG_LOADERS
+ fprintf (stderr, "tryall_dlopen (%s, %s)\n", filename,
+ vtable ? vtable->name : "(ALL)");
+#endif
+
LT__GETERROR (saved_error);
/* check whether the module was already opened */
@@ -391,19 +401,31 @@ tryall_dlopen (lt_dlhandle *phandle, con
}
{
- const lt_dlvtable *vtable = 0;
- lt_dlloader *loader = 0;
+ lt_dlloader loader = lt_dlloader_next (0);
+ const lt_dlvtable *loader_vtable;
- while ((loader = (lt_dlloader *) lt_dlloader_next (loader)))
+ do
{
lt__advise *advise_taken = 0;
if (advise)
advise_taken = advise_dup (advise);
- vtable = lt_dlloader_get (loader);
- handle->module = (*vtable->module_open) (vtable->dlloader_data,
- filename,
advise_taken);
+ if (vtable)
+ loader_vtable = vtable;
+ else
+ loader_vtable = lt_dlloader_get (loader);
+
+#ifdef LT_DEBUG_LOADERS
+ fprintf (stderr, "Calling %s->module_open (%s)\n",
+ loader_vtable->name, filename);
+#endif
+ handle->module = (*loader_vtable->module_open)
(loader_vtable->dlloader_data,
+ filename,
advise_taken);
+#ifdef LT_DEBUG_LOADERS
+ fprintf (stderr, " Result: %s\n",
+ handle->module ? "Success" : "Failed");
+#endif
if (handle->module != 0)
{
@@ -418,15 +440,20 @@ tryall_dlopen (lt_dlhandle *phandle, con
FREE (advise_taken);
}
+ while (!vtable && (loader = lt_dlloader_next (loader)));
- if (!loader)
+ /* If VTABLE was given but couldn't open the module, or
VTABLE wasn't
+ given but we exhausted all loaders without opening the
module, bail
+ out! */
+ if ((vtable && !handle->module)
+ || (!vtable && !loader))
{
FREE (handle->info.filename);
++errors;
goto done;
}
- handle->vtable = vtable;
+ handle->vtable = loader_vtable;
}
LT__SETERRORSTR (saved_error);
@@ -476,7 +503,7 @@ tryall_dlopen_module (lt_dlhandle *handl
error += tryall_dlopen_module (handle, (const char *) 0,
prefix, filename, advise);
}
- else if (tryall_dlopen (handle, filename, advise) != 0)
+ else if (tryall_dlopen (handle, filename, advise, 0) != 0)
{
++error;
}
@@ -493,7 +520,7 @@ find_module (lt_dlhandle *handle, const
/* Try to open the old library first; if it was dlpreopened,
we want the preopened version of it, even if a dlopenable
module is available. */
- if (old_name && tryall_dlopen (handle, old_name, advise) == 0)
+ if (old_name && tryall_dlopen (handle, old_name, advise, 0) == 0)
{
return 0;
}
@@ -737,7 +764,7 @@ find_handle_callback (char *filename, vo
/* Try to dlopen the file, but do not continue searching in any
case. */
- if (tryall_dlopen (handle, filename, advise) != 0)
+ if (tryall_dlopen (handle, filename, advise, 0) != 0)
*handle = 0;
return 1;
@@ -1107,6 +1134,10 @@ try_dlopen (lt_dlhandle *phandle, const
assert (phandle);
assert (*phandle == 0);
+#ifdef LT_DEBUG_LOADERS
+ fprintf (stderr, "try_dlopen (%s, %s)\n", filename, ext);
+#endif
+
LT__GETERROR (saved_error);
/* dlopen self? */
@@ -1121,7 +1152,7 @@ try_dlopen (lt_dlhandle *phandle, const
/* lt_dlclose()ing yourself is very bad! Disallow it. */
((lt__handle *) newhandle)->info.is_resident = 1;
- if (tryall_dlopen (&newhandle, 0, advise) != 0)
+ if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
{
FREE (*phandle);
return 1;
@@ -1210,6 +1241,35 @@ try_dlopen (lt_dlhandle *phandle, const
name[ext - base_name] = LT_EOS_CHAR;
}
+ /* Before trawling through the filesystem in search of a module,
+ check whether we are opening a preloaded module. */
+ if (!dir)
+ {
+ const lt_dlvtable *vtable = lt_dlloader_find
("lt_preopen");
+
+ if (vtable)
+ {
+ *phandle = (lt_dlhandle) lt__zalloc (sizeof
(lt__handle));
+
+ if (*phandle == NULL)
+ {
+ ++errors;
+ goto cleanup;
+ }
+ newhandle = *phandle;
+
+ if (tryall_dlopen (&newhandle, filename, 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 (*phandle);
+ newhandle = NULL;
+ }
+ }
+
/* Check whether we are opening a libtool module (.la
extension). */
if (ext && streq (ext, archive_ext))
{
@@ -1225,16 +1285,14 @@ try_dlopen (lt_dlhandle *phandle, const
of libtool */
int installed = 1;
-
/* Now try to open the .la file. If there is no directory
name
component, try to find it first in user_search_path and
then other
prescribed paths. Otherwise (or in any case if the
module was not
yet found) try opening just the module name as passed. */
if (!dir)
{
- const char *search_path;
+ const char *search_path = user_search_path;
- search_path = user_search_path;
if (search_path)
file = find_file (user_search_path, base_name, &dir);
@@ -1277,7 +1335,7 @@ try_dlopen (lt_dlhandle *phandle, const
/* read the .la file */
if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
&old_name, &installed) != 0)
- errors++;
+ ++errors;
fclose (file);
@@ -1347,7 +1405,7 @@ try_dlopen (lt_dlhandle *phandle, const
Otherwise (or in any case if the module was not yet found) try
opening just the module name as passed. */
if ((dir || (!find_handle (user_search_path, base_name,
- &newhandle, advise)
+ &newhandle, advise)
&& !find_handle (getenv (LTDL_SEARCHPATH_VAR),
base_name,
&newhandle, advise)
#if defined(LT_MODULE_PATH_VAR)
@@ -1356,14 +1414,14 @@ try_dlopen (lt_dlhandle *phandle, const
#endif
#if defined(LT_DLSEARCH_PATH)
&& !find_handle (sys_dlsearch_path, base_name,
- &newhandle, advise)
+ &newhandle, advise)
#endif
)))
{
- if (tryall_dlopen (&newhandle, filename, advise) != 0)
+ if (tryall_dlopen (&newhandle, filename, advise, 0) != 0)
{
newhandle = NULL;
- }
+ }
}
if (!newhandle)
Index: libtool--devo--0/libltdl/config/ltmain.m4sh
===================================================================
--- libtool--devo--0.orig/libltdl/config/ltmain.m4sh
+++ libtool--devo--0/libltdl/config/ltmain.m4sh
@@ -978,8 +978,14 @@ lt_${my_prefix}_LTX_preloaded_symbols[]
{\
{ \"$my_originator\", (void *) 0 },"
- eval "$global_symbol_to_c_name_address" < "$nlist" >>
"$output_objdir/$my_dlsyms"
-
+ case $need_lib_prefix in
+ no)
+ eval "$global_symbol_to_c_name_address" < "$nlist" >>
"$output_objdir/$my_dlsyms"
+ ;;
+ *)
+ eval "$global_symbol_to_c_name_address_lib_prefix" <
"$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ esac
$ECHO >> "$output_objdir/$my_dlsyms" "\
{0, (void *) 0}
};
Index: libtool--devo--0/libltdl/m4/libtool.m4
===================================================================
--- libtool--devo--0.orig/libltdl/m4/libtool.m4
+++ libtool--devo--0/libltdl/m4/libtool.m4
@@ -3216,6 +3216,7 @@ lt_cv_sys_global_symbol_to_cdecl="sed -n
# Transform an extracted symbol line into symbol name and symbol
address
lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \
([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*
\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e
's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \
([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^
$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
# Handle CRLF in mingw tool chain
opt_cr=
@@ -3369,6 +3370,9 @@ _LT_DECL([global_symbol_to_cdecl], [lt_c
_LT_DECL([global_symbol_to_c_name_address],
[lt_cv_sys_global_symbol_to_c_name_address], [1],
[Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib
prefix is needed])
]) # _LT_CMD_GLOBAL_SYMBOLS
Cheers,
Gary
--
())_. Email me: address@hidden
( '/ Read my blog: http://blog.azazil.net
/ )= ...and my book: http://sources.redhat.com/autobook
`(_~)_ Join my AGLOCO Network: http://www.agloco.com/r/BBBS7912
PGP.sig
Description: This is a digitally signed message part
- 330-gary-ltdl-vs-need-lib-prefix-unknown,
Gary V. Vaughan <=