From: Gary V. Vaughan Date: Thu, 15 Jul 2004 12:14:48 +0000 (+0000) Subject: This pervasive changeset makes two intertwined deep changes to the X-Git-Tag: release-1-9b~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=706e6728114405312f5b4f7a0e209dcf7af21651;p=thirdparty%2Flibtool.git This pervasive changeset makes two intertwined deep changes to the operation of libtool (neither would work alone). First, there is a new feature that allows libraries to preopen modules. This entails a backwards incompatible change to the libltdl API for separating out the preloaded symbol lists by owner. Second, in the tradition of "eating our own dogfood", libltdl now preloads its own dlloaders. The internal API for dlloaders has also had to change in a backwards incompatible way in support of the new library preloading feature. If you don't use preloaded libraries, you needn't change your project sources, though you will need to recompile against the new libltdl. The API changes are mostly confined to dlloaders, so you probably needn't worry about those (unless you have written a custom loader that you want libltdl to use): * configure.ac (AC_CONFIG_FILES): Add libltdl/loaders/Makefile. * libltdl/configure.ac (AC_CONFIG_FILES): Add loaders/Makefile. * libltdl/loaders: New directory for module loaders, to simplify Makefile rules, and to give the loaders themselves names that are unique in the first few characters. * libtoolize.in (func_copy_all_files): Copy recursively to pick up the loaders directory contents. * libltdl/loaders/Makefile.am: New file. Move module building rules to here... * libltdl/Makefile.am: ...from here. (VERSION_INFO): Bumped version info to signify interface changes. (libltdl_la_CPPFLAGS, libltdlc_la_CPPFLAGS): Set LTDLOPEN appropriately for each library. * libltdl/loader-dld_link.c, libltdl/loader-dlopen.c, libltdl/loader-dyld.c, libltdl/loader-load_add_on.c, libltdl/loader-loadlibrary.c libltdl/loader-preopen.c, libltdl/loader-shl_load.c: Moved from here... * libltdl/loaders/dld_link.c, libltdl/loaders/dlopen.c, libltdl/loaders/dyld.c, libltdl/loaders/load_add_on.c, libltdl/loaders/loadlibrary.c libltdl/loaders/preopen.c, libltdl/loaders/shl_load.c: ...to here. (get_vtable): New entry function for each. * libltdl/loaders/preopen.c (lt_dlsymlists_t): Replaced by... (symlist_chain): ...a new structure which maps lists of preloaded symbols from the object that loads them. (lt_dlpreload_open): New function to automatically open all preloaded modules belonging to a named object (ORIGINATOR). * libltdl/lt__alloc.c (lt__zalloc): New function to return a block of zeroed out new memory. * libltdl/lt__alloc.h (lt__zalloc): Prototype it. * libltdl/lt__private.h (lt__alloc_die_callback): Add missing prototype. (lt__error_strings): Make this opaque to callers. * libltdl/lt_error.c (lt__error_strings): Move the implementation to here. * libltdl/lt_dlloader.h (lt_user_dlloader): Add extra fields to make originator focused preloading possible. *BREAKS BACKWARDS COMPATIBILITY* (lt_dlloader_add): Take advantage of new fields to simplify paramater list. * libltdl/lt_system.h (LT_STR): New ANSI stringification macro. (LT_CONC): Fix it to work from within macros. * libltdl/ltdl.c (loader_init, loader_init_callback): Simplify dlloader loading. (get_vtable, preloaded_symbols): Point these at the preopen.c symbols to bootstrap the loader chain. (lt_dlinit): Load the preopen dlloader manually, and then use it to load any other preloaded dlloaders. (lt_dlloader_add): Simplify parameter list. Populate new fields. Chain new loaders according to priority field. * libltdl/ltdl.h (lt_dlsymlist): Add a new originator field. (lt_dlpreload_callback_func): Type of a callback for automatic lt_dlpreload_open loading. (LTDL_SET_PRELOADED_SYMBOLS): Adjust to hook into preloaded symbols from the "@PROGRAM@" originator. * tests/demo/dlmain.c (main): Use mangled preloaded_symbols symbol. * tests/pdemo/longer_file_name_dlmain.c (main): Ditto. * ltmain.in: Don't spew spurious warnings when dlopening and dlpreopening modules. (func_generate_dlsyms): Factored out from multiple copies in the rest of the code. Generate originator keyed symbol lists. (func_extract_archives): Also factored. Extract the contents of convenience archives for linking with dependent libraries when --whole-archive is not available. [darwin]: Don't try to link $old_library unless it exists, and $lib is a bundle. * m4/ltdl.m4 (AC_LTDL_DLLIB): Check for all possible dynamic loading libraries/apis rather that stopping when an acceptable one is discovered. (LT_DLLOADERS): New variable for holding dlloaders that can be preloaded. * doc/libtool.texi: Document interface changes. * NEWS: Updated. --- diff --git a/ChangeLog b/ChangeLog index 30db4d1cc..7d4d726f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,94 @@ +2004-07-15 Gary V. Vaughan + + This pervasive changeset makes two intertwined deep changes to the + operation of libtool (neither would work alone). First, there is + a new feature that allows libraries to preopen modules. This + entails a backwards incompatible change to the libltdl API for + separating out the preloaded symbol lists by owner. Second, in + the tradition of "eating our own dogfood", libltdl now preloads + its own dlloaders. The internal API for dlloaders has also had to + change in a backwards incompatible way in support of the new + library preloading feature. If you don't use preloaded libraries, + you needn't change your project sources, though you will need to + recompile against the new libltdl. The API changes are mostly + confined to dlloaders, so you probably needn't worry about those + (unless you have written a custom loader that you want libltdl to + use): + + * configure.ac (AC_CONFIG_FILES): Add libltdl/loaders/Makefile. + * libltdl/configure.ac (AC_CONFIG_FILES): Add loaders/Makefile. + * libltdl/loaders: New directory for module loaders, to simplify + Makefile rules, and to give the loaders themselves names that are + unique in the first few characters. + * libtoolize.in (func_copy_all_files): Copy recursively to pick up + the loaders directory contents. + * libltdl/loaders/Makefile.am: New file. Move module building + rules to here... + * libltdl/Makefile.am: ...from here. + (VERSION_INFO): Bumped version info to signify interface changes. + (libltdl_la_CPPFLAGS, libltdlc_la_CPPFLAGS): Set LTDLOPEN + appropriately for each library. + * libltdl/loader-dld_link.c, libltdl/loader-dlopen.c, + libltdl/loader-dyld.c, libltdl/loader-load_add_on.c, + libltdl/loader-loadlibrary.c libltdl/loader-preopen.c, + libltdl/loader-shl_load.c: Moved from here... + * libltdl/loaders/dld_link.c, libltdl/loaders/dlopen.c, + libltdl/loaders/dyld.c, libltdl/loaders/load_add_on.c, + libltdl/loaders/loadlibrary.c libltdl/loaders/preopen.c, + libltdl/loaders/shl_load.c: ...to here. + (get_vtable): New entry function for each. + * libltdl/loaders/preopen.c (lt_dlsymlists_t): Replaced by... + (symlist_chain): ...a new structure which maps lists of preloaded + symbols from the object that loads them. + (lt_dlpreload_open): New function to automatically open all + preloaded modules belonging to a named object (ORIGINATOR). + * libltdl/lt__alloc.c (lt__zalloc): New function to return a block + of zeroed out new memory. + * libltdl/lt__alloc.h (lt__zalloc): Prototype it. + * libltdl/lt__private.h (lt__alloc_die_callback): Add missing + prototype. + (lt__error_strings): Make this opaque to callers. + * libltdl/lt_error.c (lt__error_strings): Move the implementation + to here. + * libltdl/lt_dlloader.h (lt_user_dlloader): Add extra fields to + make originator focused preloading possible. *BREAKS BACKWARDS + COMPATIBILITY* + (lt_dlloader_add): Take advantage of new fields to simplify + paramater list. + * libltdl/lt_system.h (LT_STR): New ANSI stringification macro. + (LT_CONC): Fix it to work from within macros. + * libltdl/ltdl.c (loader_init, loader_init_callback): Simplify + dlloader loading. + (get_vtable, preloaded_symbols): Point these at the preopen.c + symbols to bootstrap the loader chain. + (lt_dlinit): Load the preopen dlloader manually, and then use it + to load any other preloaded dlloaders. + (lt_dlloader_add): Simplify parameter list. Populate new + fields. Chain new loaders according to priority field. + * libltdl/ltdl.h (lt_dlsymlist): Add a new originator field. + (lt_dlpreload_callback_func): Type of a callback for automatic + lt_dlpreload_open loading. + (LTDL_SET_PRELOADED_SYMBOLS): Adjust to hook into preloaded + symbols from the "@PROGRAM@" originator. + * tests/demo/dlmain.c (main): Use mangled preloaded_symbols symbol. + * tests/pdemo/longer_file_name_dlmain.c (main): Ditto. + * ltmain.in: Don't spew spurious warnings when dlopening and + dlpreopening modules. + (func_generate_dlsyms): Factored out from multiple copies in the + rest of the code. Generate originator keyed symbol lists. + (func_extract_archives): Also factored. Extract the contents of + convenience archives for linking with dependent libraries when + --whole-archive is not available. + [darwin]: Don't try to link $old_library unless it exists, and + $lib is a bundle. + * m4/ltdl.m4 (AC_LTDL_DLLIB): Check for all possible dynamic + loading libraries/apis rather that stopping when an acceptable one + is discovered. + (LT_DLLOADERS): New variable for holding dlloaders that can be + preloaded. + * doc/libtool.texi: Document interface changes. + * NEWS: Updated. + 2004-07-12 Peter O'Gorman * m4/libtool.m4 [darwin]: Set whole_archive_flag_spec to '' for xlc, @@ -5,7 +96,7 @@ and when -all_load is also specified Apple's /usr/bin/libtool barfs and dies. -2004-07-08 Gary V. Vaughan +2004-07-07 Gary V. Vaughan * libltdl/ltdl.h (lt_dlinfo): Move private module field to here... * libltdl/ltdl.c (lt_dlhandle_struct): ...from here. Changed all diff --git a/NEWS b/NEWS index d18a33958..8631f069a 100644 --- a/NEWS +++ b/NEWS @@ -36,8 +36,12 @@ New in 1.5b: 2004-??-??; CVS version 1.5a, Libtool team: * Mode inferrence removed, shorthand for choosing modes added. * Specifying -allow-undefined is now an error. * Speed up max_cmd_len check. +* libltdl can now preopen modules from within a library, and libtool will + accept -dlpreopen options when linking either a shared library or a + convenience library. * New function in libltdl: lt_dlhandle_find provides access to module handles by module name. +* New function in libltdl: lt_dlpreload_open opens all preloaded modules. * libltdl no longer loads shared libraries with global symbol resolution, this caused problems when the symbols were intended to be overriden further up the stack; it is also not recommended practice. diff --git a/configure.ac b/configure.ac index 35930f30a..73a1b6848 100644 --- a/configure.ac +++ b/configure.ac @@ -200,5 +200,6 @@ AM_CONDITIONAL(HAVE_RC, [test -n "[$]_LT_AC_TAGVAR(compiler, RC)"]) ## -------- ## ## Outputs. ## ## -------- ## -AC_CONFIG_FILES([Makefile libltdl/Makefile doc/Makefile tests/Makefile]) +AC_CONFIG_FILES([Makefile libltdl/Makefile libltdl/loaders/Makefile + doc/Makefile tests/Makefile]) AC_OUTPUT diff --git a/doc/libtool.texi b/doc/libtool.texi index 9afdd3aa6..efc6b0442 100644 --- a/doc/libtool.texi +++ b/doc/libtool.texi @@ -319,7 +319,7 @@ host to host. These need to be determined at configure time in a consistent way. @item -It is not always obvious with which suffix a shared library should be +It is not always obvious with what suffix a shared library should be installed. This makes it difficult for @file{Makefile} rules, since they generally assume that file names are the same from host to host. @@ -614,14 +614,14 @@ libtool are the same ones you would use to produce an executable named @example a23$ @kbd{libtool link gcc -g -O -o libhello.la foo.o hello.o} libtool: cannot build libtool library `libhello.la' from non-libtool \ - objects + objects a23$ @end example Aha! Libtool caught a common error@dots{} trying to build a library from standard objects instead of library objects. This doesn't matter -for static libraries, but on shared library systems, it is of great -importance. +so much for static libraries, but on shared library systems, it is of +great importance. So, let's try again, this time with the library object files. Remember also that we need to add @kbd{-lm} to the link command line because @@ -1062,6 +1062,12 @@ libraries. But be careful not to link a single convenience library, directly or indirectly, into a single program or library, otherwise you may get errors about symbol redefinitions. +The key is remembering that a convenience library contains @sc{pic} +objects, and can linked where a list of @sc{pic} objects makes sense; +i.e. into a shared library. A static convenience library contains +non-@sc{pic} objects, so can be linked into an old static library, or +a program. + When @sc{gnu} Automake is used, you should use @code{noinst_LTLIBRARIES} instead of @code{lib_LTLIBRARIES} for convenience libraries, so that the @samp{-rpath} option is not passed when they are linked. @@ -1304,13 +1310,12 @@ sure that the program can @code{dlopen} itself, either by enabling @code{-export-dynamic} or by falling back to @samp{-dlpreopen self}. @item -dlpreopen @var{file} -Link @var{file} into the output program, and add its symbols to -@var{lt_preloaded_symbols} (@pxref{Dlpreopening}). If @var{file} is +Link @var{file} into the output program, and add its symbols to the +list of preloaded symbols (@pxref{Dlpreopening}). If @var{file} is @code{self}, the symbols of the program itself will be added to -@var{lt_preloaded_symbols}. -If @var{file} is @code{force} Libtool will make sure that -@var{lt_preloaded_symbols} is always @emph{defined}, regardless of whether -it's empty or not. +preloaded symbol lists. If @var{file} is @code{force} Libtool will +make sure that a preloaded symbol list is always @emph{defined}, +regardless of whether it's empty or not. @item -export-dynamic Allow symbols from @var{output-file} to be resolved with @code{dlsym} @@ -1621,7 +1626,7 @@ libtool distribution's @file{demo} subdirectory. First, to link a program against a libtool library, just use the @samp{program_LDADD}@footnote{@c @c -With recent @sc{gnu} Automake (1.5 or newer), the flags @samp{-dlopen} +Since @sc{gnu} Automake 1.5, the flags @samp{-dlopen} or @samp{-dlpreopen} (@pxref{Link mode}) can be employed with the @var{program_LDADD} variable. Unfortunately, older releases didn't accept these flags, so if you are stuck with an ancient Automake, we @@ -1829,12 +1834,12 @@ specifying @samp{--enable-static} to @command{configure}. @item pic-only Change the default behaviour for @command{libtool} to try to use only -PIC objects. The user may still override this default by specifying +@sc{pic} objects. The user may still override this default by specifying @samp{--with-pic} to @command{configure}. @item no-pic Change the default behaviour of @command{libtool} to try to use only -non-PIC objects. The user may still override this default by +non-@sc{pic} objects. The user may still override this default by specifying @samp{--without-pic} to @command{configure}. @end table @@ -1969,14 +1974,17 @@ When you invoke the @code{libtoolize} program (@pxref{Invoking libtoolize}), it will tell you where to find a definition of @code{LT_INIT}. If you use Automake, the @code{aclocal} program will automatically add @code{LT_INIT} support to your -@code{configure} script. +@file{configure} script when it sees the invocation of @code{LT_INIT} +in @file{configure.ac}. Because of these changes, and the runtime version compatibility checks -Libtool now executes, we now advise @emph{against} including a copy of -@file{libtool.m4} (and bretheren) in @file{acinclude.m4}. When you -@command{libtoolize} your project, a copy of the relevant macro -definitions will be placed in your @code{AC_CONFIG_MACRO_DIR}, where -@command{aclocal} can reference them directly from @file{aclocal.m4}. +Libtool now executes, we now advise @strong{against} including a copy of +@file{libtool.m4} (and bretheren) in @file{acinclude.m4}. Instead, +you should set your project macro directory with +@code{AC_CONFIG_MACRO_DIR}. When you @command{libtoolize} your +project, a copy of the relevant macro definitions will be placed in +your @code{AC_CONFIG_MACRO_DIR}, where @command{aclocal} can reference +them directly from @file{aclocal.m4}. @node Distributing @@ -2082,8 +2090,7 @@ Print @command{libtoolize} version information and exit. If @command{libtoolize} detects an explicit call to @code{AC_CONFIG_MACRO_DIR} (@pxref{Input, , The Autoconf Manual, autoconf, The Autoconf Manual}) in your @file{configure.ac}, it will -put the Libtool macros in the specified directory. Otherwise they are -dumped in the project root directory. +put the Libtool macros in the specified directory. @findex AC_CONFIG_AUX_DIR If @command{libtoolize} detects an explicit call to @@ -2156,7 +2163,7 @@ Manipulation Program, for those who haven't taken the plunge. See @example The GIMP uses @sc{gnu} Libtool in order to build shared libraries on a -variety of systems. While this is very nice for making usable +variety of systems. While this is very nice for making usable binaries, it can be a pain when trying to debug a program. For that reason, compilation of shared libraries can be turned off by specifying the @samp{--disable-shared} option to @file{configure}. @@ -2659,6 +2666,7 @@ supported by some compilers, especially pre-ANSI compilers. The @code{long double} type is not supported by many compilers. @end itemize + @node Inter-library dependencies @chapter Inter-library dependencies @cindex dependencies between libraries @@ -2738,8 +2746,7 @@ resolved automatically at run time by the dynamic linker. In this process, dynamic linking is transparent to the application. @item -The application calling functions such as @code{dlopen},@footnote{HP-UX, -to be different, uses a function named @code{shl_load}.} which load +The application calling functions such as @code{dlopen}, which load arbitrary, user-specified modules at runtime. This type of dynamic linking is explicitly controlled by the application. @end enumerate @@ -2780,12 +2787,12 @@ declaration. You need to use these flags if you are linking an application program that dlopens other modules or a libtool library that will also be dlopened. -For example, if we wanted to build a shared library, @file{libhello}, +For example, if we wanted to build a shared library, @file{hello}, that would later be dlopened by an application, we would add @samp{-module} to the other link flags: @example -burger$ @kbd{libtool link gcc -module -o libhello.la foo.lo \ +burger$ @kbd{libtool link gcc -module -o hello.la foo.lo \ hello.lo -rpath /usr/local/lib -lm} burger$ @end example @@ -2843,19 +2850,32 @@ you must declare the objects you want your application to dlopen by using the @samp{-dlopen} or @samp{-dlpreopen} flags when you link your program (@pxref{Link mode}). -@deftypefn {Structure} {struct} lt_dlsymlist @{ @w{const char *@var{name};} @w{lt_ptr @var{address};} @} +@deftypefn {Structure} {struct} lt_dlsymbol @{ @w{const char *@var{name};} @w{void *@var{address};} @} The @var{name} attribute is a null-terminated character string of the symbol name, such as @code{"fprintf"}. The @var{address} attribute is a generic pointer to the appropriate object, such as @code{&fprintf}. @end deftypefn +@deftypefn {Structure} {struct} lt_dlsymlist @{ @w{const char *@var{originator};} @w{const lt_dlsymbol @var{symbols}[];} @} +The @var{originator} attribute is a null-terminated character string, +naming the compilation unit that @var{symbols} were preloaded on +behalf of. This is usually the basename of a library, +@file{libltdl.la} has a corresponding @var{originator} value of +@samp{libltdl}; if the @var{symbols} are for the benefit of the +application proper, then @var{originator} is @samp{@@PROGRAM@@}, +though Libtool takes care of that detail if you use +@samp{LTDL_SET_PRELOADED_SYMBOLS}. +@end deftypefn + @deftypevar {const lt_dlsymlist *} lt_preloaded_symbols An array of @var{lt_symbol} structures, representing all the preloaded -symbols linked into the program. For each @samp{-dlpreloaded} file -there is an element with the @var{name} of the file and a @var{address} +symbols linked into the program proper. For each module +@samp{-dlpreloaded} by the Libtool linked program +there is an element with the @var{name} of the module and a @var{address} of @code{0}, followed by all symbols exported from this file. -For the executable itself the special name @@PROGRAM@@ is used. -The last element has a @var{name} and @var{address} of @code{0}. +For the executable itself the special name @samp{@@PROGRAM@@} is used. +The last element of all has a @var{name} and @var{address} of +@code{0}. @end deftypevar Some compilers may allow identifiers which are not valid in ANSI C, such @@ -2864,6 +2884,81 @@ initial ASCII letter or underscore, followed by zero or more ASCII letters, digits, and underscores), so non-ANSI symbols will not appear in @var{lt_preloaded_symbols}. +@deftypefun int lt_dlpreload (const lt_dlsymlist *@var{preloaded}) +Register the list of preloaded modules @var{preloaded}. +If @var{preloaded} is @code{NULL}, then all previously registered +symbol lists, except the list set by @code{lt_dlpreload_default}, +are deleted. Return 0 on success. +@end deftypefun + +@deftypefun int lt_dlpreload_default (const lt_dlsymlist *@var{preloaded}) +Set the default list of preloaded modules to @var{preloaded}, which +won't be deleted by @code{lt_dlpreload}. Note that this function does +@emph{not} require libltdl to be initialized using @code{lt_dlinit} and +can be used in the program to register the default preloaded modules. +Instead of calling this function directly, most programs will use the +macro @code{LTDL_SET_PRELOADED_SYMBOLS}. + +Return 0 on success. +@end deftypefun + +@defmac LTDL_SET_PRELOADED_SYMBOLS +Set the default list of preloaded symbols. +Should be used in your program to initialize libltdl's +list of preloaded modules. + +@example +#include + +int main() @{ + /* ... */ + LTDL_SET_PRELOADED_SYMBOLS(); + /* ... */ +@} +@end example +@end defmac + +@deftypefn {Function Type} {int} lt_dlpreload_callback_func (lt_dlhandle @var{handle}) +Functions of this type can be passed to @code{lt_dlpreload_open}, +which in turn will call back into a function thus passed for each +preloaded module that it opens. +@end deftypefn + +@deftypefun int lt_dlpreload_open (@w{const char *@var{originator},} @w{lt_dlpreload_callback_func *@var{func})} +Load all of the preloaded modules for @var{originator}. For every +module opened in this way, call @var{func}. + +@noindent +To open all of the modules preloaded into @file{libhell.la} +(presumably from within the @samp{libhell.a} initialisation code): + +@example +#define preloaded_symbols lt_libhell_LTX_preloaded_symbols + +static int hell_preload_callback (lt_dlhandle handle); + +int +hell_init (void) +@{ + @dots{} + if (lt_dlpreload (&preloaded_symbols) == 0) + @{ + lt_dlpreload_open ("libhell", preload_callback); + @} + @dots{} +@} +@end example + +@noindent +Note that to prevent clashes between multiple preloaded modules, the +preloaded symbols are accessed via a mangled symbol name: to get the +symbols preloaded into @samp{libhell}, you must prefix +@samp{preloaded_symbols} with @samp{lt_}; the originator name, +@samp{libhell} in this case; and @samp{_LTX_}. That is, +@samp{lt_libhell_LTX_preloaded_symbols} here. +@end deftypefun + + @node Finding the dlname @section Finding the correct name to dlopen @cindex names of dynamic modules @@ -3141,40 +3236,6 @@ Return @code{NULL} if no errors have occurred since initialization or since it was last called. @end deftypefun -@deftypefun int lt_dlpreload (const lt_dlsymlist *@var{preloaded}) -Register the list of preloaded modules @var{preloaded}. -If @var{preloaded} is @code{NULL}, then all previously registered -symbol lists, except the list set by @code{lt_dlpreload_default}, -are deleted. Return 0 on success. -@end deftypefun - -@deftypefun int lt_dlpreload_default (const lt_dlsymlist *@var{preloaded}) -Set the default list of preloaded modules to @var{preloaded}, which -won't be deleted by @code{lt_dlpreload}. Note that this function does -@emph{not} require libltdl to be initialized using @code{lt_dlinit} and -can be used in the program to register the default preloaded modules. -Instead of calling this function directly, most programs will use the -macro @code{LTDL_SET_PRELOADED_SYMBOLS}. - -Return 0 on success. -@end deftypefun - -@defmac LTDL_SET_PRELOADED_SYMBOLS -Set the default list of preloaded symbols. -Should be used in your program to initialize libltdl's -list of preloaded modules. - -@example -#include - -int main() @{ - /* ... */ - LTDL_SET_PRELOADED_SYMBOLS(); - /* ... */ -@} -@end example -@end defmac - @deftypefun int lt_dladdsearchdir (const char *@var{search_dir}) Append the search directory @var{search_dir} to the current user-defined library search path. Return 0 on success. @@ -4000,8 +4061,8 @@ shared libraries (@samp{--disable-static}). @file{demo-nofast.test} configures @file{demo/libtool} to disable the fast-install mode (@samp{--enable-fast-install=no}). @file{demo-pic.test} configures @file{demo/libtool} to -prefer building PIC code (@samp{--with-pic}), @file{demo-nopic.test} -to prefer non-PIC code (@samp{--without-pic}). +prefer building @sc{pic} code (@samp{--with-pic}), @file{demo-nopic.test} +to prefer non-@sc{pic} code (@samp{--without-pic}). @item deplibs.test @pindex deplibs.test @@ -4234,7 +4295,7 @@ can make changes to the libtool configuration process without affecting other systems. @item man pages for @code{ld} and @code{cc} -These generally describe what flags are used to generate PIC, to create +These generally describe what flags are used to generate @sc{pic}, to create shared libraries, and to link against only static libraries. You may need to follow some cross references to find the information that is required. @@ -4418,8 +4479,8 @@ IBM has online documentation at @subsection Compilers The only compiler characteristics that affect libtool are the flags -needed (if any) to generate PIC objects. In general, if a C compiler -supports certain PIC flags, then any derivative compilers support the +needed (if any) to generate @sc{pic} objects. In general, if a C compiler +supports certain @sc{pic} flags, then any derivative compilers support the same flags. Until there are some noteworthy exceptions to this rule, this section will document only C compilers. @@ -4448,26 +4509,26 @@ they are bundled with: @table @code @item aix3* @itemx aix4* -Most AIX compilers have no PIC flags, since AIX (with the exception of +Most AIX compilers have no @sc{pic} flags, since AIX (with the exception of AIX for IA-64) runs on PowerPC and RS/6000 chips. @footnote{All code compiled for the PowerPC and RS/6000 chips (@code{powerpc-*-*}, @code{powerpcle-*-*}, and @code{rs6000-*-*}) is position-independent, regardless of the operating system or compiler suite. So, ``regular objects'' can be used to build -shared libraries on these systems and no special PIC compiler flags are +shared libraries on these systems and no special @sc{pic} compiler flags are required.} @item hpux10* -Use @samp{+Z} to generate PIC. +Use @samp{+Z} to generate @sc{pic}. @item osf3* -Digital/UNIX 3.x does not have PIC flags, at least not on the PowerPC +Digital/UNIX 3.x does not have @sc{pic} flags, at least not on the PowerPC platform. @item solaris2* -Use @samp{-KPIC} to generate PIC. +Use @samp{-KPIC} to generate @sc{pic}. @item sunos4* -Use @samp{-PIC} to generate PIC. +Use @samp{-PIC} to generate @sc{pic}. @end table @node Reloadable objects @@ -4971,7 +5032,9 @@ configured for your platform, and @code{~/bin} is a directory in your @example trick$ cd ~/bin -trick$ sed '/^# ltmain\.sh/q' /home/src/libtool/libtool > libtool +trick$ sed 's%^\(macro_version=\).*$%\1@@VERSION@@%; + s%^\(macro_revision=\).*$%\1@@TIMESTAMP@@%; + /^# ltmain\.sh/q' /home/src/libtool/libtool > libtool trick$ echo '. /home/src/libtool/ltmain.in' >> libtool trick$ chmod +x libtool trick$ libtool --version diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am index cd39d0920..660fce4f3 100644 --- a/libltdl/Makefile.am +++ b/libltdl/Makefile.am @@ -17,50 +17,60 @@ ## the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ## Boston, MA 02111-1307, USA. -BUILT_SOURCES = -MOSTLYCLEANFILES = -EXTRA_DIST = +SUBDIRS = loaders . -AUTOMAKE_OPTIONS = foreign -ACLOCAL_AMFLAGS = -I m4 -AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -DEFS = -DHAVE_CONFIG_H="<$(CONFIG_H)>" -DLTDL +BUILT_SOURCES = +MOSTLYCLEANFILES = +EXTRA_DIST = -pkgincludedir = $(includedir)/libltdl +AUTOMAKE_OPTIONS = foreign +ACLOCAL_AMFLAGS = -I m4 +DEFS = -DHAVE_CONFIG_H="<$(CONFIG_H)>" -DLTDL +AM_CPPFLAGS = -I$(top_builddir)/.. -I$(top_srcdir)/.. +AM_LDFLAGS = -no-undefined +VERSION_INFO = -version-info 6:0:0 + +pkgincludedir = $(includedir)/libltdl + +lib_LTLIBRARIES = libdlloader.la +libdlloader_la_SOURCES = lt_error.h lt_error.c \ + lt__private.h lt_dlloader.h \ + lt__alloc.h lt__alloc.c \ + lt__glibc.h lt_system.h +libdlloader_la_LDFLAGS = $(VERSION_INFO) +libdlloader_la_LIBADD = $(LTLIBOBJS) + +## Libltdl brings it all together: if INSTALL_LTDL -include_HEADERS = ltdl.h -pkginclude_HEADERS = lt_system.h lt_error.h -lib_LTLIBRARIES = libltdl.la +include_HEADERS = ltdl.h +pkginclude_HEADERS = lt_system.h lt_error.h +lib_LTLIBRARIES += libltdl.la endif if CONVENIENCE_LTDL -noinst_LTLIBRARIES = libltdlc.la +noinst_LTLIBRARIES = libltdlc.la endif -## Make sure these will be cleaned even when they're not built by -## default. -CLEANFILES = libltdl.la libltdlc.la +libltdl_la_SOURCES = ltdl.h ltdl.c loaders/preopen.c +libltdl_la_CPPFLAGS = -DLTDLOPEN=libltdl $(AM_CPPFLAGS) +libltdl_la_LDFLAGS = $(VERSION_INFO) $(LT_DLPREOPEN) +libltdl_la_LIBADD = libdlloader.la -libltdl_la_SOURCES = loader-preopen.c \ - lt__alloc.c lt__alloc.h lt__dirent.h lt__glibc.h \ - lt__private.h lt_dlloader.h \ - lt_error.c lt_error.h lt_system.h \ - ltdl.c ltdl.h -libltdl_la_LDFLAGS = -no-undefined -version-info 5:0:2 -libltdl_la_LIBADD = $(LIBADD_DL) $(LTLIBOBJS) - -libltdlc_la_SOURCES = $(libltdl_la_SOURCES) -libltdlc_la_LIBADD = $(LIBADD_DL) $(LTLIBOBJS) +libltdlc_la_SOURCES = $(libltdl_la_SOURCES) +libltdlc_la_CPPFLAGS = -DLTDLOPEN=libltdlc $(AM_CPPFLAGS) +libltdlc_la_LDFLAGS = $(LT_DLPREOPEN) +libltdlc_la_LIBADD = $(libdlloader_la_OBJECTS) $(libdlloader_la_LIBADD) ## These are installed as a subdirectory of pkgdatadir so that ## libtoolize --ltdl can find them later: -ltdldatadir = $(pkgdatadir)/libltdl -ltdldata_DATA = COPYING.LIB Makefile.am README configure.ac \ - argz_.h argz.c $(libltdl_la_SOURCES) \ - loader-dld_link.c loader-dlopen.c loader-dyld.c \ - loader-load_add_on.c loader-loadlibrary.c loader-shl_load.c \ - lt__dirent.c +ltdldatadir = $(pkgdatadir)/libltdl +nobase_ltdldata_DATA = COPYING.LIB Makefile.am README configure.ac \ + $(libltdl_la_SOURCES) $(libdlloader_la_SOURCES) \ + lt__dirent.c lt__dirent.h argz_.h argz.c + +## Make sure these will be cleaned even when they're not built by default: +CLEANFILES = libltdl.la libltdlc.la libdlloader.la ## --------------------------- ## diff --git a/libltdl/configure.ac b/libltdl/configure.ac index e19c09eba..b9d690a8d 100644 --- a/libltdl/configure.ac +++ b/libltdl/configure.ac @@ -88,5 +88,5 @@ AC_LIB_LTDL ## -------- ## ## Outputs. ## ## -------- ## -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile loaders/Makefile]) AC_OUTPUT diff --git a/libltdl/loader-dld_link.c b/libltdl/loader-dld_link.c deleted file mode 100644 index 93626f560..000000000 --- a/libltdl/loader-dld_link.c +++ /dev/null @@ -1,84 +0,0 @@ -/* loader-dld_link.c -- dynamic linking with dld - Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. - Originally by Thomas Tanner - - NOTE: The canonical source of this file is maintained with the - GNU Libtool package. Report bugs to bug-libtool@gnu.org. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA - -*/ - -#include "lt__private.h" -#include "lt_dlloader.h" - -#if defined(HAVE_DLD_H) -# include -#endif - -static lt_module -sys_dld_open (lt_user_data loader_data, const char *filename) -{ - lt_module module = lt__strdup (filename); - - if (dld_link (filename) != 0) - { - LT__SETERROR (CANNOT_OPEN); - FREE (module); - } - - return module; -} - -static int -sys_dld_close (lt_user_data loader_data, lt_module module)a -{ - int errors = 0; - - if (dld_unlink_by_file ((char*)(module), 1) != 0) - { - LT__SETERROR (CANNOT_CLOSE); - ++errors; - } - else - { - FREE (module); - } - - return errors; -} - -static void * -sys_dld_sym (lt_user_data loader_data, lt_module module, const char *symbol) -{ - void *address = dld_get_func (symbol); - - if (!address) - { - LT__SETERROR (SYMBOL_NOT_FOUND); - } - - return address; -} - -struct lt_user_dlloader lt__sys_dld = { - 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 -}; diff --git a/libltdl/loader-load_add_on.c b/libltdl/loader-load_add_on.c deleted file mode 100644 index cfe81508f..000000000 --- a/libltdl/loader-load_add_on.c +++ /dev/null @@ -1,92 +0,0 @@ -/* loader-load_add_on.c -- dynamic linking for BeOS - Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. - Originally by Thomas Tanner - - NOTE: The canonical source of this file is maintained with the - GNU Libtool package. Report bugs to bug-libtool@gnu.org. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA - -*/ - -#include "lt__private.h" -#include "lt_dlloader.h" - -#include - -static lt_module -sys_bedl_open (lt_user_data loader_data, const char *filename) -{ - image_id image = 0; - - if (filename) - { - image = load_add_on (filename); - } - else - { - image_info info; - int32 cookie = 0; - if (get_next_image_info (0, &cookie, &info) == B_OK) - image = load_add_on (info.name); - } - - if (image <= 0) - { - LT__SETERROR (CANNOT_OPEN); - image = 0; - } - - return (lt_module) image; -} - -static int -sys_bedl_close (lt_user_data loader_data, lt_module module) -{ - int errors = 0; - - if (unload_add_on ((image_id) module) != B_OK) - { - LT__SETERROR (CANNOT_CLOSE); - ++errors; - } - - return errors; -} - -static void * -sys_bedl_sym (lt_user_data loader_data, lt_module module, const char *symbol) -{ - void *address = 0; - image_id image = (image_id) module; - - if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) - { - LT__SETERROR (SYMBOL_NOT_FOUND); - address = 0; - } - - return address; -} - -struct lt_user_dlloader lt__sys_bedl = { - 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 -}; diff --git a/libltdl/loader-preopen.c b/libltdl/loader-preopen.c deleted file mode 100644 index 9b312745f..000000000 --- a/libltdl/loader-preopen.c +++ /dev/null @@ -1,224 +0,0 @@ -/* loader-preopen.c -- emulate dynamic linking using preloaded_symbols - Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. - Originally by Thomas Tanner - - NOTE: The canonical source of this file is maintained with the - GNU Libtool package. Report bugs to bug-libtool@gnu.org. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA - -*/ - -#include "lt__private.h" -#include "lt_dlloader.h" - - -typedef struct lt_dlsymlists_t -{ - struct lt_dlsymlists_t *next; - const lt_dlsymlist *syms; -} lt_dlsymlists_t; - -static lt_dlsymlists_t *preloaded_symbols = 0; -static const lt_dlsymlist *default_preloaded_symbols = 0; - - -int -lt__presym_init (lt_user_data loader_data) -{ - int errors = 0; - - preloaded_symbols = 0; - if (default_preloaded_symbols) - { - errors = lt_dlpreload (default_preloaded_symbols); - } - - return errors; -} - -static int -presym_free_symlists (void) -{ - lt_dlsymlists_t *lists; - - lists = preloaded_symbols; - while (lists) - { - lt_dlsymlists_t *tmp = lists; - - lists = lists->next; - FREE (tmp); - } - preloaded_symbols = 0; - - return 0; -} - -int -lt__presym_add_symlist (const lt_dlsymlist *preloaded) -{ - lt_dlsymlists_t *tmp; - lt_dlsymlists_t *lists; - int errors = 0; - - lists = preloaded_symbols; - while (lists) - { - if (lists->syms == preloaded) - { - goto done; - } - lists = lists->next; - } - - tmp = MALLOC (lt_dlsymlists_t, 1); - if (tmp) - { - memset (tmp, 0, sizeof(lt_dlsymlists_t)); - tmp->syms = preloaded; - tmp->next = preloaded_symbols; - preloaded_symbols = tmp; - } - else - { - ++errors; - } - - done: - return errors; -} - -static lt_module -presym_open (lt_user_data loader_data, const char *filename) -{ - lt_dlsymlists_t *lists; - lt_module module = (lt_module) 0; - - lists = preloaded_symbols; - - if (!lists) - { - LT__SETERROR (NO_SYMBOLS); - goto done; - } - - /* Can't use NULL as the reflective symbol header, as NULL is - used to mark the end of the entire symbol list. Self-dlpreopened - symbols follow this magic number, chosen to be an unlikely - clash with a real module name. */ - if (!filename) - { - filename = "@PROGRAM@"; - } - - while (lists) - { - const lt_dlsymlist *syms = lists->syms; - - while (syms->name) - { - if (!syms->address && strcmp(syms->name, filename) == 0) - { - module = (lt_module) syms; - goto done; - } - ++syms; - } - - lists = lists->next; - } - - LT__SETERROR (FILE_NOT_FOUND); - - done: - return module; -} - -static int -presym_close (lt_user_data loader_data, lt_module module) -{ - /* Just to silence gcc -Wall */ - module = 0; - return 0; -} - -static void * -presym_sym (lt_user_data loader_data, lt_module module, const char *symbol) -{ - lt_dlsymlist *syms = (lt_dlsymlist*) module; - - ++syms; - while (syms->address) - { - if (strcmp(syms->name, symbol) == 0) - { - return syms->address; - } - - ++syms; - } - - LT__SETERROR (SYMBOL_NOT_FOUND); - - return 0; -} - -static int -presym_exit (lt_user_data loader_data) -{ - presym_free_symlists (); - return 0; -} - -struct lt_user_dlloader lt__presym = { - 0, presym_open, presym_close, presym_sym, presym_exit, 0 -}; - - -int -lt_dlpreload (const lt_dlsymlist *preloaded) -{ - int errors = 0; - - if (preloaded) - { - errors = lt__presym_add_symlist (preloaded); - } - else - { - presym_free_symlists(); - - if (default_preloaded_symbols) - { - errors = lt_dlpreload (default_preloaded_symbols); - } - } - - return errors; -} - -int -lt_dlpreload_default (const lt_dlsymlist *preloaded) -{ - default_preloaded_symbols = preloaded; - return 0; -} diff --git a/libltdl/loaders/Makefile.am b/libltdl/loaders/Makefile.am new file mode 100644 index 000000000..1f86bf682 --- /dev/null +++ b/libltdl/loaders/Makefile.am @@ -0,0 +1,58 @@ +## Process this file with automake to produce Makefile.in +## +## Copyright (C) 2004 Free Software Foundation +## +## This program 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. +## +## This program 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 this program; see the file COPYING. If not, write to +## the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +## Boston, MA 02111-1307, USA. + +BUILT_SOURCES = +MOSTLYCLEANFILES = +EXTRA_DIST = + +AUTOMAKE_OPTIONS = foreign + +DEFS = -DHAVE_CONFIG_H="<$(CONFIG_H)>" -DLTDL +AM_CPPFLAGS = -I$(top_builddir)/.. -I$(top_srcdir)/.. \ + -I.. -I$(srcdir)/.. +AM_LDFLAGS = -no-undefined -module -avoid-version -export-dynamic + +pkgincludedir = $(includedir)/libltdl + + +## The loaders are preopened by libltdl, itself always built from +## pic-objects (either as a shared library, or a convenience library), +## so the loaders themselves must be made from pic-objects too. We +## use convenience libraries for that purpose: +noinst_LTLIBRARIES = $(LT_DLLOADERS) +EXTRA_LTLIBRARIES = dlopen.la dld_link.la dyld.la load_add_on.la \ + loadlibrary.la shl_load.la + +## Build loaders (other than preopen) as modules: +dlopen_la_LIBADD = ../libdlloader.la $(LIBADD_DLOPEN) +shl_load_la_LIBADD = ../libdlloader.la $(LIBADD_SHL_LOAD) +dyld_la_LIBADD = ../libdlloader.la +load_add_on_la_LIBADD = ../libdlloader.la +loadlibrary_la_LIBADD = ../libdlloader.la +dld_link_la_LIBADD = ../libdlloader.la -ldld + + +## These are installed as a subdirectory of pkgdatadir so that +## libtoolize --ltdl can find them later: +ltdldatadir = $(pkgdatadir)/libltdl/loaders +ltdldata_DATA = Makefile.am dld_link.c dlopen.c dyld.c \ + load_add_on.c loadlibrary.c shl_load.c + +../libdlloader.la: + cd ..; $(MAKE) $(MAKEFLAGS) libdlloader.la diff --git a/libltdl/loaders/dld_link.c b/libltdl/loaders/dld_link.c new file mode 100644 index 000000000..1b8b9c42f --- /dev/null +++ b/libltdl/loaders/dld_link.c @@ -0,0 +1,140 @@ +/* loader-dld_link.c -- dynamic linking with dld + Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + Originally by Thomas Tanner + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA + +*/ + +#include "lt__private.h" +#include "lt_dlloader.h" + +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable dld_link_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_dld_link"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#if defined(HAVE_DLD_H) +# include +#endif + +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ +static lt_module +vm_open (lt_user_data loader_data, const char *filename) +{ + lt_module module = lt__strdup (filename); + + if (dld_link (filename) != 0) + { + LT__SETERROR (CANNOT_OPEN); + FREE (module); + } + + return module; +} + +/* A function called through the vtable when a particular module + should be unloaded. */ +static int +vm_close (lt_user_data loader_data, lt_module module) +{ + int errors = 0; + + if (dld_unlink_by_file ((char*)(module), 1) != 0) + { + LT__SETERROR (CANNOT_CLOSE); + ++errors; + } + else + { + FREE (module); + } + + return errors; +} + +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ +static void * +vm_sym (lt_user_data loader_data, lt_module module, const char *name) +{ + void *address = dld_get_func (name); + + if (!address) + { + LT__SETERROR (SYMBOL_NOT_FOUND); + } + + return address; +} diff --git a/libltdl/loader-dlopen.c b/libltdl/loaders/dlopen.c similarity index 53% rename from libltdl/loader-dlopen.c rename to libltdl/loaders/dlopen.c index 6589bc3d3..af24578cd 100644 --- a/libltdl/loader-dlopen.c +++ b/libltdl/loaders/dlopen.c @@ -27,8 +27,64 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ -#include "lt__private.h" #include "lt_dlloader.h" +#include "lt__private.h" + +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable dlopen_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_dlopen"; +#if defined(NEED_USCORE) + vtable->sym_prefix = "_"; +#endif + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_PREPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + #if defined(HAVE_DLFCN_H) # include @@ -38,6 +94,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # include #endif + /* We may have to define LT_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #if !defined(LT_LAZY_OR_NOW) @@ -71,10 +128,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #define DL__SETERROR(errorcode) \ LT__SETERRORSTR (DLERROR (errorcode)) +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ static lt_module -sys_dl_open (lt_user_data loader_data, const char *filename) +vm_open (lt_user_data loader_data, const char *filename) { - lt_module module = dlopen (filename, LT_LAZY_OR_NOW); + lt_module module = dlopen (filename, LT_LAZY_OR_NOW); if (!module) { @@ -84,8 +144,11 @@ sys_dl_open (lt_user_data loader_data, const char *filename) return module; } + +/* A function called through the vtable when a particular module + should be unloaded. */ static int -sys_dl_close (lt_user_data loader_data, lt_module module) +vm_close (lt_user_data loader_data, lt_module module) { int errors = 0; @@ -98,10 +161,13 @@ sys_dl_close (lt_user_data loader_data, lt_module module) return errors; } + +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ static void * -sys_dl_sym (lt_user_data loader_data, lt_module module, const char *symbol) +vm_sym (lt_user_data loader_data, lt_module module, const char *name) { - void *address = dlsym (module, symbol); + void *address = dlsym (module, name); if (!address) { @@ -110,12 +176,3 @@ sys_dl_sym (lt_user_data loader_data, lt_module module, const char *symbol) return address; } - -struct lt_user_dlloader lt__sys_dl = - { -# if defined(NEED_USCORE) - "_", -# else - 0, -# endif - sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; diff --git a/libltdl/loader-dyld.c b/libltdl/loaders/dyld.c similarity index 72% rename from libltdl/loader-dyld.c rename to libltdl/loaders/dyld.c index 8e29faa7a..1e5852f52 100644 --- a/libltdl/loader-dyld.c +++ b/libltdl/loaders/dyld.c @@ -27,8 +27,65 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ -#include "lt__private.h" #include "lt_dlloader.h" +#include "lt__private.h" + +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable dyld_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_init (lt_user_data loader_data); +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_dyld"; + vtable->sym_prefix = "_"; + vtable->dlloader_init = vl_init; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + #if defined(HAVE_MACH_O_DYLD_H) # if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__) @@ -57,20 +114,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) #endif -typedef struct mach_header mach_header; -typedef struct dylib_command dylib_command; - -static const mach_header *(*lt__addimage) (const char *image_name, - unsigned long options) = 0; -static NSSymbol (*lt__image_symbol) (const mach_header *image, - const char *symbolName, - unsigned long options) = 0; -static enum DYLD_BOOL (*lt__image_symbol_p) (const mach_header *image, - const char *symbolName) = 0; -static enum DYLD_BOOL (*lt__module_export) (NSModule module) = 0; - -static int dyld_cannot_close = 0; - #if !defined(NSADDIMAGE_OPTION_NONE) # define NSADDIMAGE_OPTION_NONE 0x0 #endif @@ -109,148 +152,33 @@ static int dyld_cannot_close = 0; # define LT__MAGIC MH_CIGAM #endif -#define DYLD__SETERROR(errorcode) \ - LT__SETERRORSTR (lt__dylderror (errorcode)) - -/* Return the dyld error string, or the passed in error string if none. */ -static const char * -lt__dylderror (int errnum) -{ - NSLinkEditErrors ler; - int lerno; - const char *file; - const char *errstr; - - NSLinkEditError (&ler, &lerno, &file, &errstr); - - if (! (errstr && *errstr)) - { - errstr = lt__error_strings[errnum] ; - } - - return errstr; -} - -/* There should probably be an apple dyld api for this. */ -static const mach_header * -lt__nsmodule_get_header (NSModule module) -{ - int i = _dyld_image_count(); - const char *modname = NSNameOfModule (module); - const mach_header *mh = 0; - - if (!modname) - return NULL; - - while (i > 0) - { - --i; - if (strcmp (_dyld_get_image_name (i), modname) != 0) - { - mh = _dyld_get_image_header (i); - break; - } - } - - return mh; -} - -/* NSAddImage is also used to get the loaded image, but it only works if - the lib is installed, for uninstalled libs we need to check the - install_names against each other. Note that this is still broken if - DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result. */ -static const char * -lt__header_get_instnam (const mach_header *mh) -{ - unsigned long offset = sizeof(mach_header); - const char* result = 0; - int j; - - for (j = 0; j < mh->ncmds; j++) - { - struct load_command *lc; - - lc = (struct load_command*) (((unsigned long) mh) + offset); - if (LC_ID_DYLIB == lc->cmd) - { - result=(char*)(((dylib_command*) lc)->dylib.name.offset + - (unsigned long) lc); - } - offset += lc->cmdsize; - } - - return result; -} - -static const mach_header * -lt__match_loadedlib (const char *name) -{ - const mach_header *mh = 0; - int i = _dyld_image_count(); - - while (i > 0) - { - const char *id; - - --i; - id = lt__header_get_instnam (_dyld_get_image_header (i)); - if (id && (strcmp (id, name) != 0)) - { - mh = _dyld_get_image_header (i); - break; - } - } +#define DYLD__SETMYERROR(errmsg) LT__SETERRORSTR (dylderror (errmsg)) +#define DYLD__SETERROR(errcode) DYLD__SETMYERROR (LT__STRERROR (errcode)) - return mh; -} - -/* Safe to assume our mh is good. */ -static NSSymbol -lt__linkedlib_symbol (const char *symname, const mach_header *mh) -{ - NSSymbol symbol = 0; - - if (lt__image_symbol && NSIsSymbolNameDefined (symname)) - { - unsigned long offset = sizeof(mach_header); - struct load_command *lc; - int j; - - for (j = 0; j < mh->ncmds; j++) - { - lc = (struct load_command*) (((unsigned long) mh) + offset); - if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) - { - unsigned long base = ((dylib_command *) lc)->dylib.name.offset; - char *name = (char *) (base + (unsigned long) lc); - const mach_header *mh1 = lt__match_loadedlib (name); +typedef struct mach_header mach_header; +typedef struct dylib_command dylib_command; - if (!mh1) - { - /* Maybe NSAddImage can find it */ - mh1 = lt__addimage (name, - NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED - | NSADDIMAGE_OPTION_WITH_SEARCHING - | NSADDIMAGE_OPTION_RETURN_ON_ERROR); - } +static const char *dylderror (const char *errmsg); +static const mach_header *lt__nsmodule_get_header (NSModule module); +static const char *lt__header_get_instnam (const mach_header *mh); +static const mach_header *lt__match_loadedlib (const char *name); +static NSSymbol lt__linkedlib_symbol (const char *symname, const mach_header *mh); - if (mh1) - { - symbol = lt__image_symbol (mh1, symname, LT__SYMLOOKUP_OPTS); - if (symbol) - break; - } - } +static const mach_header *(*lt__addimage) (const char *image_name, + unsigned long options) = 0; +static NSSymbol (*lt__image_symbol) (const mach_header *image, + const char *symbolName, + unsigned long options) = 0; +static enum DYLD_BOOL (*lt__image_symbol_p) (const mach_header *image, + const char *symbolName) = 0; +static enum DYLD_BOOL (*lt__module_export) (NSModule module) = 0; - offset += lc->cmdsize; - } - } +static int dyld_cannot_close = 0; - return symbol; -} -int -lt__sys_dyld_init (void) +/* A function called through the vtable to initialise this loader. */ +static int +vl_init (lt_user_data loader_data) { int errors = 0; @@ -277,8 +205,12 @@ lt__sys_dyld_init (void) return errors; } + +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ static lt_module -sys_dyld_open (lt_user_data loader_data, const char *filename) +vm_open (lt_user_data loader_data, const char *filename) { lt_module module = 0; NSObjectFileImage ofi = 0; @@ -309,18 +241,28 @@ sys_dyld_open (lt_user_data loader_data, const char *filename) NSADDIMAGE_OPTION_RETURN_ON_ERROR); } break; + + case NSObjectFileImageFailure: + case NSObjectFileImageArch: + case NSObjectFileImageFormat: + case NSObjectFileImageAccess: + /*NOWORK*/ + break; } if (!module) { - DYLD__SETERROR (LT_ERROR_CANNOT_OPEN); + DYLD__SETERROR (CANNOT_OPEN); } return module; } + +/* A function called through the vtable when a particular module + should be unloaded. */ static int -sys_dyld_close (lt_user_data loader_data, lt_module module) +vm_close (lt_user_data loader_data, lt_module module) { int errors = 0; @@ -330,7 +272,7 @@ sys_dyld_close (lt_user_data loader_data, lt_module module) int flags = 0; if (mh->magic == LT__MAGIC) { - DYLD__SETERROR(dyld_cannot_close); + lt_dlseterror (dyld_cannot_close); ++errors; } else @@ -349,7 +291,7 @@ sys_dyld_close (lt_user_data loader_data, lt_module module) #endif if (!NSUnLinkModule (module, flags)) { - DYLD__SETERROR (LT_ERROR_CANNOT_CLOSE); + DYLD__SETERROR (CANNOT_CLOSE); ++errors; } } @@ -358,17 +300,19 @@ sys_dyld_close (lt_user_data loader_data, lt_module module) return errors; } +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ static void * -sys_dyld_sym (lt_user_data loader_data, lt_module module, const char *symbol) +vm_sym (lt_user_data loader_data, lt_module module, const char *name) { NSSymbol *nssym = 0; - mach_header *mh = (mach_header *) module; + const mach_header *mh = (const mach_header *) module; char saveError[256] = "Symbol not found"; - if (module == (lt_module)-1) + if (module == (lt_module) -1) { void *address, *unused; - _dyld_lookup_and_bind(symbol, (unsigned long*) &address, &unused); + _dyld_lookup_and_bind (name, (unsigned long*) &address, &unused); return address; } @@ -376,27 +320,27 @@ sys_dyld_sym (lt_user_data loader_data, lt_module module, const char *symbol) { if (lt__image_symbol_p && lt__image_symbol) { - if (lt__image_symbol_p (mh, symbol)) + if (lt__image_symbol_p (mh, name)) { - nssym = lt__image_symbol (mh, symbol, LT__SYMLOOKUP_OPTS); + nssym = lt__image_symbol (mh, name, LT__SYMLOOKUP_OPTS); } } } else { - nssym = NSLookupSymbolInModule (module, symbol); + nssym = NSLookupSymbolInModule (module, name); } if (!nssym) { - strncpy (saveError, lt__dylderror (LT_ERROR_SYMBOL_NOT_FOUND), 255); + strncpy (saveError, dylderror (LT__STRERROR (SYMBOL_NOT_FOUND)), 255); saveError[255] = 0; if (!mh) { mh = (mach_header *)lt__nsmodule_get_header (module); } - nssym = lt__linkedlib_symbol (symbol, mh); + nssym = lt__linkedlib_symbol (name, mh); } if (!nssym) @@ -407,5 +351,145 @@ sys_dyld_sym (lt_user_data loader_data, lt_module module, const char *symbol) return nssym ? NSAddressOfSymbol (nssym) : 0; } -struct lt_user_dlloader lt__sys_dyld = - { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 }; + + + +/* --- HELPER FUNCTIONS --- */ + + +/* Return the dyld error string, or the passed in error string if none. */ +static const char * +dylderror (const char *errmsg) +{ + NSLinkEditErrors ler; + int lerno; + const char *file; + const char *errstr; + + NSLinkEditError (&ler, &lerno, &file, &errstr); + + if (! (errstr && *errstr)) + { + errstr = errmsg; + } + + return errstr; +} + +/* There should probably be an apple dyld api for this. */ +static const mach_header * +lt__nsmodule_get_header (NSModule module) +{ + int i = _dyld_image_count(); + const char *modname = NSNameOfModule (module); + const mach_header *mh = 0; + + if (!modname) + return NULL; + + while (i > 0) + { + --i; + if (strcmp (_dyld_get_image_name (i), modname) != 0) + { + mh = _dyld_get_image_header (i); + break; + } + } + + return mh; +} + +/* NSAddImage is also used to get the loaded image, but it only works if + the lib is installed, for uninstalled libs we need to check the + install_names against each other. Note that this is still broken if + DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result. */ +static const char * +lt__header_get_instnam (const mach_header *mh) +{ + unsigned long offset = sizeof(mach_header); + const char* result = 0; + int j; + + for (j = 0; j < mh->ncmds; j++) + { + struct load_command *lc; + + lc = (struct load_command*) (((unsigned long) mh) + offset); + if (LC_ID_DYLIB == lc->cmd) + { + result=(char*)(((dylib_command*) lc)->dylib.name.offset + + (unsigned long) lc); + } + offset += lc->cmdsize; + } + + return result; +} + +static const mach_header * +lt__match_loadedlib (const char *name) +{ + const mach_header *mh = 0; + int i = _dyld_image_count(); + + while (i > 0) + { + const char *id; + + --i; + id = lt__header_get_instnam (_dyld_get_image_header (i)); + if (id && (strcmp (id, name) != 0)) + { + mh = _dyld_get_image_header (i); + break; + } + } + + return mh; +} + +/* Safe to assume our mh is good. */ +static NSSymbol +lt__linkedlib_symbol (const char *symname, const mach_header *mh) +{ + NSSymbol symbol = 0; + + if (lt__image_symbol && NSIsSymbolNameDefined (symname)) + { + unsigned long offset = sizeof(mach_header); + struct load_command *lc; + int j; + + for (j = 0; j < mh->ncmds; j++) + { + lc = (struct load_command*) (((unsigned long) mh) + offset); + if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) + { + unsigned long base = ((dylib_command *) lc)->dylib.name.offset; + char *name = (char *) (base + (unsigned long) lc); + const mach_header *mh1 = lt__match_loadedlib (name); + + if (!mh1) + { + /* Maybe NSAddImage can find it */ + mh1 = lt__addimage (name, + NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + | NSADDIMAGE_OPTION_WITH_SEARCHING + | NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + + if (mh1) + { + symbol = lt__image_symbol (mh1, symname, LT__SYMLOOKUP_OPTS); + if (symbol) + break; + } + } + + offset += lc->cmdsize; + } + } + + return symbol; +} diff --git a/libltdl/loaders/load_add_on.c b/libltdl/loaders/load_add_on.c new file mode 100644 index 000000000..7ae6bda21 --- /dev/null +++ b/libltdl/loaders/load_add_on.c @@ -0,0 +1,150 @@ +/* loader-load_add_on.c -- dynamic linking for BeOS + Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + Originally by Thomas Tanner + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA + +*/ + +#include "lt__private.h" +#include "lt_dlloader.h" + +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable load_add_on_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_load_add_on"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#include + +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ +static lt_module +vm_open (lt_user_data loader_data, const char *filename) +{ + image_id image = 0; + + if (filename) + { + image = load_add_on (filename); + } + else + { + image_info info; + int32 cookie = 0; + if (get_next_image_info (0, &cookie, &info) == B_OK) + image = load_add_on (info.name); + } + + if (image <= 0) + { + LT__SETERROR (CANNOT_OPEN); + image = 0; + } + + return (lt_module) image; +} + + +/* A function called through the vtable when a particular module + should be unloaded. */ +static int +vm_close (lt_user_data loader_data, lt_module module) +{ + int errors = 0; + + if (unload_add_on ((image_id) module) != B_OK) + { + LT__SETERROR (CANNOT_CLOSE); + ++errors; + } + + return errors; +} + + +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ +static void * +vm_sym (lt_user_data loader_data, lt_module module, const char *name) +{ + void *address = 0; + image_id image = (image_id) module; + + if (get_image_symbol (image, name, B_SYMBOL_TYPE_ANY, address) != B_OK) + { + LT__SETERROR (SYMBOL_NOT_FOUND); + address = 0; + } + + return address; +} diff --git a/libltdl/loader-loadlibrary.c b/libltdl/loaders/loadlibrary.c similarity index 60% rename from libltdl/loader-loadlibrary.c rename to libltdl/loaders/loadlibrary.c index 535ebc1a7..2e30b5f15 100644 --- a/libltdl/loader-loadlibrary.c +++ b/libltdl/loaders/loadlibrary.c @@ -30,13 +30,70 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #include "lt__private.h" #include "lt_dlloader.h" +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable loadlibrary_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_loadlibrary"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + #include /* Forward declaration; required to implement handle search below. */ static lt_dlhandle handles; + +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ static lt_module -sys_wll_open (lt_user_data loader_data, const char *filename) +vm_open (lt_user_data loader_data, const char *filename) { lt_dlhandle cur = 0; lt_module module = 0; @@ -116,10 +173,13 @@ sys_wll_open (lt_user_data loader_data, const char *filename) return module; } + +/* A function called through the vtable when a particular module + should be unloaded. */ static int -sys_wll_close (lt_user_data loader_data, lt_module module) +vm_close (lt_user_data loader_data, lt_module module) { - int errors = 0; + int errors = 0; if (FreeLibrary(module) == 0) { @@ -130,10 +190,13 @@ sys_wll_close (lt_user_data loader_data, lt_module module) return errors; } + +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ static void * -sys_wll_sym (lt_user_data loader_data, lt_module module,const char *symbol) +vm_sym (lt_user_data loader_data, lt_module module, const char *name) { - void * address = GetProcAddress (module, symbol); + void *address = GetProcAddress (module, name); if (!address) { @@ -142,7 +205,3 @@ sys_wll_sym (lt_user_data loader_data, lt_module module,const char *symbol) return address; } - -struct lt_user_dlloader lt__sys_wll = { - 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 -}; diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c new file mode 100644 index 000000000..c570a7366 --- /dev/null +++ b/libltdl/loaders/preopen.c @@ -0,0 +1,357 @@ +/* loader-preopen.c -- emulate dynamic linking using preloaded_symbols + Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + Originally by Thomas Tanner + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA + +*/ + +#include "lt_dlloader.h" +#include "lt__private.h" + +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable preopen_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_init (lt_user_data loader_data); +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__malloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_preopen"; + vtable->sym_prefix = 0; + vtable->dlloader_init = vl_init; + vtable->dlloader_exit = vl_exit; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_PREPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +/* Wrapper type to chain together symbol lists of various origins. */ +typedef struct symlist_chain +{ + struct symlist_chain *next; + const lt_dlsymlist *symlist; +} symlist_chain; + + +static int add_symlist (const lt_dlsymlist *symlist); +static int free_symlists (void); + +/* The start of the symbol lists chain. */ +static symlist_chain *preloaded_symlists = 0; + +/* A symbol list preloaded before lt_init() was called. */ +static const lt_dlsymlist *default_preloaded_symbols = 0; + + +/* A function called through the vtable to initialise this loader. */ +static int +vl_init (lt_user_data loader_data) +{ + int errors = 0; + + preloaded_symlists = 0; + if (default_preloaded_symbols) + { + errors = lt_dlpreload (default_preloaded_symbols); + } + + return errors; +} + + +/* A function called through the vtable when this loader is no + longer needed by the application. */ +static int +vl_exit (lt_user_data loader_data) +{ + free_symlists (); + return 0; +} + + +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ +static lt_module +vm_open (lt_user_data loader_data, const char *filename) +{ + symlist_chain *lists; + lt_module module = 0; + + if (!preloaded_symlists) + { + LT__SETERROR (NO_SYMBOLS); + goto done; + } + + /* Can't use NULL as the reflective symbol header, as NULL is + used to mark the end of the entire symbol list. Self-dlpreopened + symbols follow this magic number, chosen to be an unlikely + clash with a real module name. */ + if (!filename) + { + filename = "@PROGRAM@"; + } + + for (lists = preloaded_symlists; lists; lists = lists->next) + { + const lt_dlsymbol *symbol; + for (symbol= lists->symlist->symbols; symbol->name; ++symbol) + { + if (!symbol->address && strcmp(symbol->name, filename) == 0) + { + module = (lt_module) lists->symlist; + goto done; + } + } + } + + LT__SETERROR (FILE_NOT_FOUND); + + done: + return module; +} + + +/* A function called through the vtable when a particular module + should be unloaded. */ +static int +vm_close (lt_user_data loader_data, lt_module module) +{ + /* Just to silence gcc -Wall */ + module = 0; + return 0; +} + + +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ +static void * +vm_sym (lt_user_data loader_data, lt_module module, const char *name) +{ + lt_dlsymlist *symlist = (lt_dlsymlist*) module; + const lt_dlsymbol *symbol = symlist->symbols; + + ++symbol; /* Skip header. */ + + while (symbol->name) + { + if (strcmp (symbol->name, name) == 0) + { + return symbol->address; + } + + ++symbol; + } + + LT__SETERROR (SYMBOL_NOT_FOUND); + + return 0; +} + + + +/* --- HELPER FUNCTIONS --- */ + + +/* The symbol lists themselves are not allocated from the heap, but + we can unhook them and free up the chain of links between them. */ +static int +free_symlists (void) +{ + symlist_chain *lists; + + lists = preloaded_symlists; + while (lists) + { + symlist_chain *next = lists->next; + FREE (lists); + lists = next; + } + preloaded_symlists = 0; + + return 0; +} + +/* Add a new symbol list to the global chain. */ +static int +add_symlist (const lt_dlsymlist *symlist) +{ + symlist_chain *lists; + int errors = 0; + + /* Search for duplicate entries: */ + for (lists = preloaded_symlists; + lists && lists->symlist != symlist; lists = lists->next) + /*NOWORK*/; + + /* Don't add the same list twice: */ + if (!lists) + { + symlist_chain *tmp = lt__zalloc (sizeof *tmp); + + if (tmp) + { + tmp->symlist = symlist; + tmp->next = preloaded_symlists; + preloaded_symlists = tmp; + } + else + { + ++errors; + } + } + + return errors; +} + + + +/* --- PRELOADING API CALL IMPLEMENTATIONS --- */ + + +/* Save a default symbol list for later. */ +int +lt_dlpreload_default (const lt_dlsymlist *preloaded) +{ + default_preloaded_symbols = preloaded; + return 0; +} + + +/* Add a symbol list to the global chain, or with a NULL argument, + revert to just the default list. */ +int +lt_dlpreload (const lt_dlsymlist *preloaded) +{ + int errors = 0; + + if (preloaded) + { + errors = add_symlist (preloaded); + } + else + { + free_symlists(); + + if (default_preloaded_symbols) + { + errors = lt_dlpreload (default_preloaded_symbols); + } + } + + return errors; +} + + +/* Open all the preloaded modules from the named originator, executing + a callback for each one. */ +int +lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func) +{ + symlist_chain *list; + int errors = 0; + int found = 0; + + /* For each symlist in the chain... */ + for (list = preloaded_symlists; list; list = list->next) + { + /* ...that was preloaded by the requesting ORIGINATOR... */ + if (strcmp (list->symlist->originator, originator) == 0) + { + const lt_dlsymbol *symbol; + unsigned int idx = 0; + + ++found; + + /* ...load the symbols per source compilation unit: */ + while ((symbol = &list->symlist->symbols[idx++])->name != 0) + { + if ((symbol->address == 0) + && (strcmp (symbol->name, "@PROGRAM@") != 0)) + { + lt_dlhandle handle = lt_dlopen (symbol->name); + if (handle == 0) + { + ++errors; + } + else + { + errors += (*func) (handle); + } + } + } + } + + if (!found) + { + LT__SETERROR(CANNOT_OPEN); + ++errors; + } + } + + return errors; +} diff --git a/libltdl/loader-shl_load.c b/libltdl/loaders/shl_load.c similarity index 64% rename from libltdl/loader-shl_load.c rename to libltdl/loaders/shl_load.c index e5eff3f35..6cd520140 100644 --- a/libltdl/loader-shl_load.c +++ b/libltdl/loaders/shl_load.c @@ -30,6 +30,59 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #include "lt__private.h" #include "lt_dlloader.h" +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "_LTX_" prefix so that the symbol addresses can + be fetched from the preloaded symbol list by lt_dlsym(): */ +#define get_vtable shl_load_LTX_get_vtable + +extern lt_user_dlloader *get_vtable (lt_user_data loader_data); + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static lt_module vm_open (lt_user_data loader_data, const char *filename); +static int vm_close (lt_user_data loader_data, lt_module module); +static void * vm_sym (lt_user_data loader_data, lt_module module, + const char *symbolname); + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_user_dlloader * +get_vtable (lt_user_data loader_data) +{ + static lt_user_dlloader *vtable = 0; + + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (!vtable->name) + { + vtable->name = "lt_shl_load"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable->dlloader_data != loader_data) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + #if defined(HAVE_DL_H) # include #endif @@ -74,8 +127,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) + +/* A function called through the vtable to open a module with this + loader. Returns an opaque representation of the newly opened + module for processing with this loader's other vtable functions. */ static lt_module -sys_shl_open (lt_user_data loader_data, const char *filenam) +vm_open (lt_user_data loader_data, const char *filename) { static shl_t self = (shl_t) 0; lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); @@ -107,8 +164,10 @@ sys_shl_open (lt_user_data loader_data, const char *filenam) return module; } +/* A function called through the vtable when a particular module + should be unloaded. */ static int -sys_shl_close (lt_user_data loader_data, lt_module module) +vm_close (lt_user_data loader_data, lt_module module) { int errors = 0; @@ -121,8 +180,11 @@ sys_shl_close (lt_user_data loader_data, lt_module module) return errors; } + +/* A function called through the vtable to get the address of + a symbol loaded from a particular module. */ static void * -sys_shl_sym (lt_user_data loader_data, lt_module module, const char *symbol) +vm_sym (lt_user_data loader_data, lt_module module, const char *name) { void *address = 0; @@ -131,7 +193,7 @@ sys_shl_sym (lt_user_data loader_data, lt_module module, const char *symbol) { LT__SETERROR (INVALID_HANDLE); } - else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) + else if (!shl_findsym((shl_t*) &module, name, TYPE_UNDEFINED, &address)) { if (!address) { @@ -141,7 +203,3 @@ sys_shl_sym (lt_user_data loader_data, lt_module module, const char *symbol) return address; } - -struct lt_user_dlloader lt__sys_shl = { - 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 -}; diff --git a/libltdl/lt__alloc.c b/libltdl/lt__alloc.c index 93275d192..0f769ea63 100644 --- a/libltdl/lt__alloc.c +++ b/libltdl/lt__alloc.c @@ -34,6 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #include #include "lt__alloc.h" +#include "lt__private.h" static void alloc_die_default (void); @@ -58,6 +59,17 @@ lt__malloc (size_t n) return mem; } +void * +lt__zalloc (size_t n) +{ + void *mem; + + if ((mem = lt__malloc (n))) + memset (mem, 0, n); + + return mem; +} + void * lt__realloc (void *mem, size_t n) { diff --git a/libltdl/lt__alloc.h b/libltdl/lt__alloc.h index fd88e7752..b571e5d6e 100644 --- a/libltdl/lt__alloc.h +++ b/libltdl/lt__alloc.h @@ -46,6 +46,7 @@ LT_BEGIN_C_DECLS extern void (*lt__alloc_die) (void); void *lt__malloc (size_t n); +void *lt__zalloc (size_t n); void *lt__realloc (void *mem, size_t n); void *lt__memdup (void const *mem, size_t n); diff --git a/libltdl/lt__private.h b/libltdl/lt__private.h index ee7fe9fce..888ca927f 100644 --- a/libltdl/lt__private.h +++ b/libltdl/lt__private.h @@ -79,6 +79,7 @@ LT_BEGIN_C_DECLS extern int errno; #endif +void lt__alloc_die_callback (void); /* --- ERROR HANDLING --- */ @@ -86,14 +87,7 @@ extern int errno; /* Extract the diagnostic strings from the error table macro in the same order as the enumerated indices in lt_error.h. */ -static const char *lt__error_strings[] = - { -#define LT_ERROR(name, diagnostic) (diagnostic), - lt_dlerror_table -#undef LT_ERROR - - 0 - }; +LT_SCOPE const char *lt__error_strings[]; #define LT__STRERROR(name) lt__error_strings[LT_CONC(LT_ERROR_,name)] diff --git a/libltdl/lt_dlloader.h b/libltdl/lt_dlloader.h index 8c1dda55c..b97ad159e 100644 --- a/libltdl/lt_dlloader.h +++ b/libltdl/lt_dlloader.h @@ -31,38 +31,52 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #define LT_DLLOADER_H 1 #include +#include LT_BEGIN_C_DECLS +typedef struct lt_user_dlloader lt_user_dlloader; typedef struct lt_dlloader lt_dlloader; typedef void * lt_user_data; typedef void * lt_module; -/* Function pointer types for creating user defined module loaders. */ +/* Type of a function to get a loader's vtable: */ +typedef lt_user_dlloader *lt_get_vtable (lt_user_data loader_data); + +/* Function pointer types for creating user defined module loaders: */ +typedef int lt_dlloader_init (lt_user_data loader_data); +typedef int lt_dlloader_exit (lt_user_data loader_data); typedef lt_module lt_module_open (lt_user_data loader_data, const char *filename); typedef int lt_module_close (lt_user_data loader_data, lt_module handle); typedef void * lt_find_sym (lt_user_data loader_data, lt_module handle, const char *symbol); -typedef int lt_dlloader_exit (lt_user_data loader_data); + +/* Default priority is LT_DLLOADER_PREPEND if none is explicitly given. */ +typedef enum { + LT_DLLOADER_PREPEND = 0, LT_DLLOADER_APPEND +} lt_dlloader_priority; struct lt_user_dlloader { - const char *sym_prefix; - lt_module_open *module_open; - lt_module_close *module_close; - lt_find_sym *find_sym; - lt_dlloader_exit *dlloader_exit; + const char * name; + const char * sym_prefix; + lt_module_open * module_open; + lt_module_close * module_close; + lt_find_sym * find_sym; + lt_dlloader_init * dlloader_init; + lt_dlloader_exit * dlloader_exit; lt_user_data dlloader_data; + lt_dlloader_priority priority; }; LT_SCOPE lt_dlloader *lt_dlloader_next (lt_dlloader *place); LT_SCOPE lt_dlloader *lt_dlloader_find (const char *loader_name); LT_SCOPE const char *lt_dlloader_name (lt_dlloader *place); LT_SCOPE lt_user_data *lt_dlloader_data (lt_dlloader *place); -LT_SCOPE int lt_dlloader_add (lt_dlloader *place, - const struct lt_user_dlloader *dlloader, - const char *loader_name); +LT_SCOPE int lt_dlloader_add + (const struct lt_user_dlloader *dlloader, + lt_user_data data); LT_SCOPE int lt_dlloader_remove (const char *loader_name); diff --git a/libltdl/lt_error.c b/libltdl/lt_error.c index 01a8d60f7..22c5cedd8 100644 --- a/libltdl/lt_error.c +++ b/libltdl/lt_error.c @@ -30,6 +30,14 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #include "lt__private.h" LT_GLOBAL_DATA const char *lt__last_error = 0; +LT_GLOBAL_DATA const char *lt__error_strings[] = + { +#define LT_ERROR(name, diagnostic) (diagnostic), + lt_dlerror_table +#undef LT_ERROR + + 0 + }; static const char **user_error_strings = 0; static int errorcount = LT_ERROR_MAX; diff --git a/libltdl/lt_error.h b/libltdl/lt_error.h index 82d901843..4283b4385 100644 --- a/libltdl/lt_error.h +++ b/libltdl/lt_error.h @@ -56,7 +56,7 @@ LT_BEGIN_C_DECLS LT_ERROR(INVALID_ERRORCODE, "invalid errorcode") \ LT_ERROR(SHUTDOWN, "library already shutdown") \ LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") \ - LT_ERROR(INVALID_MUTEX_ARGS, "internal error (code withdrawn)") \ + LT_ERROR(INVALID_MUTEX_ARGS, "internal error (code withdrawn)") \ LT_ERROR(INVALID_POSITION, "invalid search path insert position") /* Enumerate the symbolic error names. */ diff --git a/libltdl/lt_system.h b/libltdl/lt_system.h index 802930cfd..7ec8c1134 100644 --- a/libltdl/lt_system.h +++ b/libltdl/lt_system.h @@ -131,12 +131,21 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # define LT_READTEXT_MODE "r" #endif -/* LT_CONC creates a new concatenated symbol for the compiler - in a portable way. */ -#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER) -# define LT_CONC(s,t) s##t -#else -# define LT_CONC(s,t) s/**/t +/* The extra indirection to the LT__STR and LT__CONC macros is required so + that if the arguments to LT_STR() (or LT_CONC()) are themselves macros, + they will be expanded before being quoted. */ +#ifndef LT_STR +# define LT__STR(arg) #arg +# define LT_STR(arg) LT__STR(arg) +#endif + +#ifndef LT_CONC +# define LT__CONC(a, b) a##b +# define LT_CONC(a, b) LT__CONC(a, b) +#endif +#ifndef LT_CONC3 +# define LT__CONC3(a, b, c) a##b##c +# define LT_CONC3(a, b, c) LT__CONC3(a, b, c) #endif -#endif /*!defined(LT__SYSTEM_H)*/ +#endif /*!defined(LT_SYSTEM_H)*/ diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c index 81c801bdb..b11a9d059 100644 --- a/libltdl/ltdl.c +++ b/libltdl/ltdl.c @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ +#include "lt_system.h" #include "lt_dlloader.h" #include "lt__private.h" @@ -118,31 +119,6 @@ static const char sys_search_path[] = LTDL_SYSSEARCHPATH; -/* --- DLLOADER VIRTUAL FUNCTION TABLES --- */ - -#if defined(HAVE_LIBDL) -LT_SCOPE struct lt_user_dlloader lt__sys_dl; -#endif -#if defined(HAVE_SHL_LOAD) -LT_SCOPE struct lt_user_dlloader lt__sys_shl; -#endif -#if defined(__WINDOWS__) || defined(__CYGWIN__) -LT_SCOPE struct lt_user_dlloader lt__sys_wll; -#endif -#if defined(__BEOS__) -LT_SCOPE struct lt_user_dlloader lt__sys_bedl; -#endif -#if defined(HAVE_DLD) -LT_SCOPE struct lt_user_dlloader lt__sys_dld; -#endif -#if defined(HAVE_DYLD) -LT_SCOPE struct lt_user_dlloader lt__sys_dyld; -LT_SCOPE int lt__sys_dyld_init (void); -#endif -LT_SCOPE struct lt_user_dlloader lt__presym; -LT_SCOPE int lt__presym_init (lt_user_data loader_data); - - /* --- DYNAMIC MODULE LOADING --- */ @@ -194,6 +170,10 @@ static int list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len); static int file_not_found (void); +static int loader_init_callback (lt_dlhandle handle); +static int loader_init (lt_get_vtable *vtable_func, + lt_user_data data); + static char *user_search_path= 0; static lt_dlloader *loaders = 0; static lt_dlhandle handles = 0; @@ -208,6 +188,60 @@ lt__alloc_die_callback (void) LT__SETERROR (NO_MEMORY); } +/* This function is called to initialise each preloaded module loader, + and hook it into the list of loaders to be used when attempting to + dlopen an application module. */ +static int +loader_init_callback (lt_dlhandle handle) +{ + return loader_init (lt_dlsym (handle, "get_vtable"), 0); +} + +static int +loader_init (lt_get_vtable *vtable_func, lt_user_data data) +{ + lt_user_dlloader *vtable = 0; + int errors = 0; + + if (vtable_func) + { + vtable = (*vtable_func) (data); + } + + if (!vtable) + { + LT__SETERROR (INVALID_LOADER); + ++errors; + } + + if (!errors) + { + if (lt_dlloader_add (vtable, data)) + { + LT__SETERROR (DLOPEN_NOT_SUPPORTED); + ++errors; + } + } + + if ((!errors) && vtable->dlloader_init) + { + if ((*vtable->dlloader_init) (vtable->dlloader_data)) + { + LT__SETERROR (INIT_LOADER); + ++errors; + } + } + + return errors; +} + +/* Bootstrap the loader loading with the preopening loader. */ +#define get_vtable preopen_LTX_get_vtable +#define preloaded_symbols LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols) + +extern lt_user_dlloader * get_vtable (lt_user_data data); +extern lt_dlsymlist preloaded_symbols; + /* Initialize libltdl. */ int lt_dlinit (void) @@ -217,47 +251,24 @@ lt_dlinit (void) /* Initialize only at first call. */ if (++initialized == 1) { - lt__alloc_die = lt__alloc_die_callback; - - handles = 0; - user_search_path = 0; /* empty search path */ + lt__alloc_die = lt__alloc_die_callback; + handles = 0; + user_search_path = 0; /* empty search path */ - /* Append the available loaders to the internal list in the order - they should be used -- if the first fails, then try again with - the next loader in the chain. */ -# define LOADER_APPEND 0 - - /* All ltdl supplied loaders are in the /dl[a-z-]+/ namespace. */ - errors += lt_dlloader_add (LOADER_APPEND, <__presym, "dlpreload"); -#if defined(HAVE_DLD) - errors += lt_dlloader_add (LOADER_APPEND, <__sys_dld, "dld"); -#endif -#if defined(HAVE_DYLD) - errors += lt_dlloader_add (LOADER_APPEND, <__sys_dyld, "dldyld"); - errors += lt__sys_dyld_init(); -#endif -#if defined(__BEOS__) - errors += lt_dlloader_add (LOADER_APPEND, <__sys_bedl, "dlopen"); -#endif -#if defined(HAVE_SHL_LOAD) - errors += lt_dlloader_add (LOADER_APPEND, <__sys_shl, "dlopen"); -#endif -#if defined(HAVE_LIBDL) - errors += lt_dlloader_add (LOADER_APPEND, <__sys_dl, "dlopen"); -#endif -#if defined(__WINDOWS__) || defined(__CYGWIN__) - errors += lt_dlloader_add (LOADER_APPEND, <__sys_wll, "dlopen"); -#endif + /* First set up the statically loaded preload module loader, so + we can use it to preopen the other loaders we linked in at + compile time. */ + errors += loader_init (get_vtable, 0); - if (lt__presym_init (lt__presym.dlloader_data)) + /* Now open all the preloaded module loaders, so the application + can use them to lt_dlopen their own modules. */ + if (!errors) { - LT__SETERROR (INIT_LOADER); - ++errors; + errors += lt_dlpreload (&preloaded_symbols); } - else if (errors != 0) + if (!errors) { - LT__SETERROR (DLOPEN_NOT_SUPPORTED); - ++errors; + errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback); } } @@ -1023,23 +1034,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) assert (base_name && *base_name); - /* Check whether we are opening a libtool module (.la extension). */ ext = strrchr (base_name, '.'); - if (ext && strcmp (ext, archive_ext) == 0) - { - /* this seems to be a libtool module */ - FILE * file = 0; - char * dlname = 0; - char * old_name = 0; - char * libdir = 0; - char * deplibs = 0; - char * line = 0; - size_t line_len; - - /* if we can't find the installed flag, it is probably an - installed libtool archive, produced with an old version - of libtool */ - int installed = 1; /* extract the module name from the file name */ name = MALLOC (char, ext - base_name + 1); @@ -1066,6 +1061,24 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) name[ext - base_name] = LT_EOS_CHAR; } + /* Check whether we are opening a libtool module (.la extension). */ + if (ext && strcmp (ext, archive_ext) == 0) + { + /* this seems to be a libtool module */ + FILE * file = 0; + char * dlname = 0; + char * old_name = 0; + char * libdir = 0; + char * deplibs = 0; + char * line = 0; + size_t line_len; + + /* if we can't find the installed flag, it is probably an + installed libtool archive, produced with an old version + 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 @@ -2148,8 +2161,8 @@ lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle) int -lt_dlloader_add (lt_dlloader *place, const struct lt_user_dlloader *dlloader, - const char *loader_name) +lt_dlloader_add (const struct lt_user_dlloader *dlloader, + lt_user_data data) { int errors = 0; lt_dlloader *node = 0, *ptr = 0; @@ -2164,60 +2177,40 @@ lt_dlloader_add (lt_dlloader *place, const struct lt_user_dlloader *dlloader, } /* Create a new dlloader node with copies of the user callbacks. */ - node = MALLOC (lt_dlloader, 1); + node = lt__malloc (sizeof *node); if (!node) return 1; + /* There is no need to record the dlloader->dlloader_init function, + since we won't need it again. */ node->next = 0; - node->loader_name = loader_name; + node->loader_name = dlloader->name; node->sym_prefix = dlloader->sym_prefix; - node->dlloader_exit = dlloader->dlloader_exit; node->module_open = dlloader->module_open; node->module_close = dlloader->module_close; node->find_sym = dlloader->find_sym; + node->dlloader_exit = dlloader->dlloader_exit; node->dlloader_data = dlloader->dlloader_data; - if (!loaders) - { - /* If there are no loaders, NODE becomes the list! */ - loaders = node; - } - else if (!place) + switch (dlloader->priority) { - /* If PLACE is not set, add NODE to the end of the - LOADERS list. */ - for (ptr = loaders; ptr->next; ptr = ptr->next) - { - /*NOWORK*/; - } + case LT_DLLOADER_PREPEND: + /* Tack NODE on the front of the LOADERS list. */ + node->next = loaders; + loaders = node; + break; + case LT_DLLOADER_APPEND: + /* Add NODE to the end of the LOADERS list. */ + for (ptr = loaders; ptr->next; ptr = ptr->next) + /*NOWORK*/; ptr->next = node; - } - else if (loaders == place) - { - /* If PLACE is the first loader, NODE goes first. */ - node->next = place; - loaders = node; - } - else - { - /* Find the node immediately preceding PLACE. */ - for (ptr = loaders; ptr->next != place; ptr = ptr->next) - { - /*NOWORK*/; - } + break; - if (ptr->next != place) - { - LT__SETERROR (INVALID_LOADER); - ++errors; - } - else - { - /* Insert NODE between PTR and PLACE. */ - node->next = place; - ptr->next = node; - } + default: + LT__SETERROR (INVALID_LOADER); + ++errors; + break; } return errors; @@ -2352,8 +2345,10 @@ lt_dlmutex_register (lt_dlmutex_lock *lock, lt_dlmutex_unlock *unlock, if (warned++ == 0) { - fputs ("libltdl: WARNING: lt_dlmutex_register() is deprecated.\n" + fputs ("libltdl: WARNING: lt_dlmutex_register() is deprecated,\n" "libltdl: WARNING: this version of libltdl is not thread safe.\n", stderr); } + + return 0; } diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h index bf907f4db..7c22dd928 100644 --- a/libltdl/ltdl.h +++ b/libltdl/ltdl.h @@ -83,15 +83,25 @@ LT_SCOPE int lt_dlisresident (lt_dlhandle handle); symbols for a dlpreopened module. */ typedef struct { const char *name; - void * address; + void *address; +} lt_dlsymbol; + +typedef struct { + const char *originator; + const lt_dlsymbol symbols[]; } lt_dlsymlist; +typedef int lt_dlpreload_callback_func (lt_dlhandle handle); + LT_SCOPE int lt_dlpreload (const lt_dlsymlist *preloaded); LT_SCOPE int lt_dlpreload_default (const lt_dlsymlist *preloaded); +LT_SCOPE int lt_dlpreload_open (const char *originator, + lt_dlpreload_callback_func *func); +#define lt_preloaded_symbols lt__PROGRAM__LTX_preloaded_symbols #define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ - extern const lt_dlsymlist lt_preloaded_symbols[]; \ - lt_dlpreload_default(lt_preloaded_symbols); \ + extern const lt_dlsymlist lt_preloaded_symbols; \ + lt_dlpreload_default(<_preloaded_symbols); \ }LT_STMT_END diff --git a/libtoolize.in b/libtoolize.in index bb721f1ff..e036bf7cd 100644 --- a/libtoolize.in +++ b/libtoolize.in @@ -314,33 +314,58 @@ func_copy () return $my_return_status } -# func_copy_all_files srcdir destdir [glob_exclude] [copy_cb=func_copy] +# func_copy_all_files [-r] srcdir destdir [glob_exclude] [copy_cb=func_copy] # For each file in SRCDIR, then try to copy the file to DESTDIR by calling -# COPY_CB with the src and dest files. If GLOB_EXCLUDE is given, exclude -# any matching filenames from the copy. If COPY_CB is passed, then the -# check for overwriting without opt_force is the callbacks responsibility: -# This allows using callbacks like func_serial_update, which perform their -# own checks to decide whether to overwrite the dest file. +# COPY_CB with the src and dest files. With the `-r' option, recurse into +# subdirectories of srcdir too. If GLOB_EXCLUDE is given, exclude any +# matching filenames from the copy. If COPY_CB is passed, then the check +# for overwriting without opt_force is the callbacks responsibility: This +# allows using callbacks like func_serial_update, which perform their own +# checks to decide whether to overwrite the dest file. func_copy_all_files () { + my_opt_recurse=false + if test "X$1" = X-r; then + my_opt_recurse=: + shift + fi + my_srcdir="$1" my_destdir="$2" my_glob_exclude="$3" my_copy_cb="${4-func_copy}" my_srcfiles= - for my_filename in `cd "$my_srcdir" && ls`; do + my_basedir="$my_srcdir" + my_srcdirs="$my_srcdir" + my_save_IFS="$IFS" + IFS=: + while test -n "$my_srcdirs"; do - # ignore excluded filenames - if test -n "$my_glob_exclude"; then - eval 'case $my_filename in '$my_glob_exclude') continue ;; esac' - fi + IFS="$my_save_IFS" + my_srcdir=`echo "$my_srcdirs" | sed 's,:.*,,g'` + my_srcdirs=`echo "$my_srcdirs" | sed 's,:*[^:][^:]*:*,,'` - my_srcfiles="$my_srcfiles${my_srcfiles:+:}$my_filename" + for my_filename in `cd "$my_srcdir" && ls`; do + # ignore excluded filenames + if test -n "$my_glob_exclude"; then + eval 'case $my_filename in '$my_glob_exclude') continue ;; esac' + fi + + # Add to the appropriate list + if test -f "$my_srcdir/$my_filename"; then + my_srcfile=`echo "$my_srcdir/$my_filename" |sed "s,^$my_basedir/*,,"` + my_srcfiles="$my_srcfiles${my_srcfiles:+:}$my_srcfile" + elif $my_opt_recurse && test -d "$my_srcdir/$my_filename"; then + my_srcdirs="$my_srcdirs${my_srcdirs:+:}$my_srcdir/$my_filename" + fi + + done done + IFS="$my_save_IFS" - func_copy_some_files "$my_srcdir" "$my_srcfiles" \ + func_copy_some_files "$my_basedir" "$my_srcfiles" \ "$my_destdir" "$my_copy_cb" } @@ -693,7 +718,7 @@ func_config_update () # Copy all the files from installed libltdl to this project, if the # user specified `--ltdl'. if test -n "$ltdldir"; then - eval func_copy_all_files "$pkgdatadir/libltdl" "$ltdldir" + eval func_copy_all_files -r "$pkgdatadir/libltdl" "$ltdldir" # libtoolize the newly copied libltdl tree ( cd "$ltdldir" && "$progpath" $libtoolize_flags ) || exit $EXIT_FAILURE diff --git a/ltmain.in b/ltmain.in index 52a29baeb..7dc49b96b 100644 --- a/ltmain.in +++ b/ltmain.in @@ -53,7 +53,6 @@ PACKAGE=@PACKAGE@ VERSION=@VERSION@ TIMESTAMP="@TIMESTAMP@" - # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. @@ -276,6 +275,281 @@ func_infer_tag () { esac fi } + + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () { + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`echo "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$my_dlsyms" + + test -z "$run" && $echo > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval '$GREP -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +const struct { + const char *originator; + const struct { + const char *name; + void *address; + } symbols[]; +} +lt_${my_prefix}_LTX_preloaded_symbols = +{\ + \"$my_originator\", + { +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + + $echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} + } +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$my_dlsyms\")" + $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$my_dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + *) + $echo "$modename: unknown suffix for \`$my_dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + + + +# func_extract_archives gentop oldlib ... +func_extract_archives () { + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$my_xdir"; then + exit $status + fi + + # We will extract separately just the conflicting names and we will + # no longer touch any unique names. It is faster to leave these + # extract automatically by $AR in one run. + $show "(cd $my_xdir && $AR x $my_xabs)" + $run eval "(cd \$my_xdir && $AR x \$my_xabs)" || exit $? + if ($AR t "$my_xabs" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 + $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 + $AR t "$my_xabs" | sort | uniq -cd | while read -r count name + do + i=1 + while test "$i" -le "$count" + do + # Put our $i before any first dot (extension) + # Never overwrite any file + name_to="$name" + while test "X$name_to" = "X$name" || test -f "$my_xdir/$name_to" + do + name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` + done + $show "(cd $my_xdir && $AR xN $i $my_xabs '$name' && $mv '$name' '$name_to')" + $run eval "(cd \$my_xdir && $AR xN $i \$my_xabs '$name' && $mv '$name' '$name_to')" || exit $? + i=`expr $i + 1` + done + done + fi + + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} # End of Shell function definitions ##################################### @@ -1131,7 +1405,7 @@ EOF # A libtool-controlled object. # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | $GREP "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + if (${SED} -e '2q' $arg | $GREP "^# Generated by ltmain.sh ") >/dev/null 2>&1; then pic_object= non_pic_object= @@ -1875,9 +2149,10 @@ EOF need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries + case $linkmode in lib) - passes="conv link" + passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; @@ -1899,6 +2174,7 @@ EOF *) passes="conv" ;; esac + for pass in $passes; do if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then @@ -1912,11 +2188,15 @@ EOF link) libs="$deplibs %DEPLIBS% $dependency_libs $inherited_linker_flags" ;; esac fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + libs="$dlprefiles" + fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi + for deplib in $libs; do lib= found=no @@ -2064,20 +2344,27 @@ EOF fi case $linkmode in lib) - if test "$deplibs_check_method" != pass_all; then - $echo - $echo "*** Warning: Trying to link with static lib archive $deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because the file extensions .$libext of this argument makes me believe" - $echo "*** that it is just a static archive that I should not used here." - else - $echo - $echo "*** Warning: Linking the shared library $output against the" - $echo "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $lib "*) ;; + *) + if test "$deplibs_check_method" != pass_all; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not use here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac continue ;; prog) @@ -2112,6 +2399,7 @@ EOF continue ;; esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 @@ -2119,7 +2407,7 @@ EOF fi # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $lib | $GREP "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + if (${SED} -e '2q' $lib | $GREP "^# Generated by ltmain.sh ") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE @@ -2264,14 +2552,18 @@ EOF # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + if test -z "$libdir" && test "$linkmode" = prog; then + $echo "$modename: only libraries may -dlpreopen a convenience library: \`$lib'" 1>&2 exit $EXIT_FAILURE fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" @@ -2382,8 +2674,15 @@ EOF # This is a shared library # Warn about portability, can't link against -module's on some - # systems (darwin) - if test "$shouldnotlink" = yes && test "$pass" = link ; then + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for module in $dlprefiles; do + if test "X$module" = "X$lib"; then + dlopenmodule="$module" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then $echo if test "$linkmode" = prog; then $echo "*** Warning: Linking the executable $output against the loadable module" @@ -2489,16 +2788,20 @@ EOF case $host in *-*-sco3.2v5* ) add_dir="-L$dir" ;; *-*-darwin* ) - # if the lib is a module then we can not link against - # it, someone is ignoring the new warnings I added + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | - $GREP "bundle" >/dev/null ; then - $echo "** Warning, lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - $echo - $echo "** And there doesn't seem to be a static archive available" - $echo "** The link will probably fail, sorry" - else + $GREP "bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $echo "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "*** And there doesn't seem to be a static archive available" + $echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then add="$dir/$old_library" fi fi @@ -2887,6 +3190,8 @@ EOF done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi @@ -3213,8 +3518,12 @@ EOF # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi + fi + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. @@ -3592,7 +3901,7 @@ EOF case $host in *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework + # On Rhapsody replace the C library with the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac @@ -3780,12 +4089,12 @@ EOF tmp_deplibs= for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - tmp_deplibs="$tmp_deplibs $test_deplib" - ;; - esac + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac done deplibs="$tmp_deplibs" @@ -3795,64 +4104,10 @@ EOF eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi generated="$generated $gentop" - for xlib in $convenience; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" fi fi @@ -3876,12 +4131,12 @@ EOF cmds=$module_cmds fi else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds fi fi @@ -4003,10 +4258,10 @@ EOF cmds=$module_cmds fi else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds fi fi @@ -4014,6 +4269,16 @@ EOF # to the just-reset $cmds. eval cmds=\"\$cmds~\$rm $delfiles\" fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + fi + save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" @@ -4120,64 +4385,10 @@ EOF eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi generated="$generated $gentop" - for xlib in $convenience; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi @@ -4382,195 +4593,7 @@ EOF finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi - dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - dlsyms="${outputname}S.c" - else - $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 - fi - fi - - if test -n "$dlsyms"; then - case $dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${outputname}.nm" - - $show "$rm $nlist ${nlist}S ${nlist}T" - $run $rm "$nlist" "${nlist}S" "${nlist}T" - - # Parse the name list into a source file. - $show "creating $output_objdir/$dlsyms" - - test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ -/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -/* Prevent the only kind of declaration conflicts we can make. */ -#define lt_preloaded_symbols some_other_symbol - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - $show "generating symbol list for \`$output'" - - test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - for arg in $progfiles; do - $show "extracting global C symbols from \`$arg'" - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - if test -n "$export_symbols_regex"; then - $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$output.exp" - $run $rm $export_symbols - $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - else - $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' - $run eval '$GREP -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' - $run eval 'mv "$nlist"T "$nlist"' - fi - fi - - for arg in $dlprefiles; do - $show "extracting global C symbols from \`$arg'" - name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` - $run eval '$echo ": $name " >> "$nlist"' - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -z "$run"; then - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $mv "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' - else - $echo '/* NONE */' >> "$output_objdir/$dlsyms" - fi - - $echo >> "$output_objdir/$dlsyms" "\ - -#undef lt_preloaded_symbols - -#if defined (__STDC__) && __STDC__ -# define lt_ptr void * -#else -# define lt_ptr char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr address; -} -lt_preloaded_symbols[] = -{\ -" - - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" - - $echo >> "$output_objdir/$dlsyms" "\ - {0, (lt_ptr) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - fi - - pic_flag_for_symtable= - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; - esac;; - *-*-hpux*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag";; - esac - esac - - # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? - - # Clean up the generated files. - $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" - $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" - - # Transform the symbol file into the correct name. - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - ;; - *) - $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 - exit $EXIT_FAILURE - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` - fi + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" if test "$need_relink" = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. @@ -4583,7 +4606,7 @@ static const void *lt_preloaded_setup() { status=$? # Delete the generated files. - if test -n "$dlsyms"; then + if test -f "$output_objdir/${outputname}S.${objext}"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi @@ -5254,7 +5277,7 @@ fi\ for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save" + oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else @@ -5263,77 +5286,35 @@ fi\ build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$dlsymsobj"; then + oldobjs="$oldobjs $symfileobj" + fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi generated="$generated $gentop" - # Add in members from convenience archives. - for xlib in $addlibs; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` - done + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds + cmds=$old_archive_from_new_cmds else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + eval cmds=\"$old_archive_cmds\" if len=`expr "X$cmds" : ".*"` && @@ -5460,25 +5441,39 @@ fi\ done dependency_libs="$newdependency_libs" newdlfiles= + for lib in $dlfiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdlfiles="$newdlfiles $libdir/$name" + case $lib in + *.la) + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdlprefiles="$newdlprefiles $libdir/$name" + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac done dlprefiles="$newdlprefiles" else @@ -5722,7 +5717,7 @@ relink_command=\"$relink_command\"" *.la) # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | $GREP "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + if (${SED} -e '2q' $file | $GREP "^# Generated by ltmain.sh ") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 3baa053db..062d8296f 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -2676,7 +2676,7 @@ symxfrm='\1 \2\3 \3' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # 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\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" # Define system-specific variables. case $host_os in @@ -2691,7 +2691,7 @@ hpux*) # Its linker distinguishes data from code symbols symcode='[[ABCDEGRST]]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' @@ -2767,26 +2767,33 @@ _LT_EOF eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif -/* The mapping between symbol names and symbols. */ +/* The mapping between symbol names and symbols. */ const struct { - const char *name; - lt_ptr_t address; + const char *originator; + const struct { + const char *name; + void *address; + } symbols[[]]; } -lt_preloaded_symbols[[]] = +lt__PROGRAM__LTX_preloaded_symbols = { + "@PROGRAM@", + { _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} + {0, (void *) 0} + } }; +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + #ifdef __cplusplus } #endif diff --git a/m4/ltdl.m4 b/m4/ltdl.m4 index b31589dbb..e2d277fff 100644 --- a/m4/ltdl.m4 +++ b/m4/ltdl.m4 @@ -370,70 +370,83 @@ fi # AC_LTDL_DLLIB # ------------- AC_DEFUN([AC_LTDL_DLLIB], -[LIBADD_DL= -AC_SUBST(LIBADD_DL) +[m4_pattern_allow([^LT_DLLOADERS$]) +LT_DLLOADERS= +AC_SUBST([LT_DLLOADERS]) + AC_LANG_PUSH([C]) -AC_CHECK_FUNC([shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.]) - AC_LIBOBJ([loader-shl_load])], - [AC_CHECK_LIB([dld], [shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.]) - LIBADD_DL="$LIBADD_DL -ldld" - AC_LIBOBJ([loader-shl_load])], - [AC_CHECK_LIB([dl], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" - AC_LIBOBJ([loader-dlopen])], - [AC_TRY_LINK([#if HAVE_DLFCN_H +LIBADD_DLOPEN= +AC_CHECK_LIB([dl], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DLOPEN="-ldl" libltdl_cv_lib_dl_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS dlopen.la"], + [AC_TRY_LINK([#if HAVE_DLFCN_H # include #endif - ], - [dlopen(0, 0);], + ], [dlopen(0, 0);], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes" - AC_LIBOBJ([loader-dlopen])], - [AC_CHECK_LIB([svld], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], + LT_DLLOADERS="$LT_DLLOADERS dlopen.la"], + [AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) - LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" - AC_LIBOBJ([loader-dlopen])], - [AC_CHECK_LIB([dld], [dld_link], - [AC_DEFINE([HAVE_DLD], [1], - [Define if you have the GNU dld library.]) - LIBADD_DL="$LIBADD_DL -ldld" - AC_LIBOBJ([loader-dld_link])], - [AC_CHECK_FUNC([_dyld_func_lookup], - [AC_DEFINE([HAVE_DYLD], [1], - [Define if you have the _dyld_func_lookup function.]) - AC_LIBOBJ([loader-dyld])])#_dyld_func_lookup - ])#dld - ])#svld - ])#dlfcn.h - ])#dl - ])#dld - ])#shl_load + LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS dlopen.la"])])]) +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DLOPEN" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_SUBST([LIBADD_DLOPEN]) + +LIBADD_SHL_LOAD= +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LT_DLLOADERS="$LT_DLLOADERS shl_load.la"], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LT_DLLOADERS="$LT_DLLOADERS shl_load.la" + LIBADD_SHL_LOAD="-ldld"])]) +AC_SUBST([LIBADD_SHL_LOAD]) + +AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.]) + LT_DLLOADERS="$LT_DLLOADERS dyld.la"]) case $host_os in beos*) - AC_LIBOBJ([loader-load_add_on]) + LT_DLLOADERS="$LT_DLLOADERS load_add_on.la" ;; cygwin* | mingw* | os2* | pw32*) - AC_LIBOBJ([loader-loadlibrary]) + LT_DLLOADERS="$LT_DLLOADERS loadlibrary.la" ;; esac -if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes -then - lt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - AC_CHECK_FUNCS([dlerror]) - LIBS="$lt_save_LIBS" -fi +AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LT_DLLOADERS="$LT_DLLOADERS dld_link.la"]) +AC_SUBST([LIBADD_DLD_LINK]) + +m4_pattern_allow([^LT_DLPREOPEN$]) +LT_DLPREOPEN= +for lt_loader in $LT_DLLOADERS; do + LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen loaders/$lt_loader " +done +AC_SUBST([LT_DLPREOPEN]) + +dnl This isn't used anymore, but set it for backwards compatibility +LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD" +AC_SUBST([LIBADD_DL]) + AC_LANG_POP ])# AC_LTDL_DLLIB @@ -487,7 +500,7 @@ if test x"$ac_cv_sys_symbol_underscore" = xyes; then [libltdl_cv_need_uscore], [libltdl_cv_need_uscore=unknown save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" + LIBS="$LIBS $LIBADD_DLOPEN" _LT_AC_TRY_DLOPEN_SELF( [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], [], [libltdl_cv_need_uscore=cross]) diff --git a/tests/demo/dlmain.c b/tests/demo/dlmain.c index 7c123bb8e..b6b5fb4a0 100644 --- a/tests/demo/dlmain.c +++ b/tests/demo/dlmain.c @@ -1,5 +1,5 @@ /* dlmain.c -- hello test program that uses simulated dynamic linking - Copyright (C) 1996-1999 Free Software Foundation, Inc. + Copyright (C) 1996-1999, 2004 Free Software Foundation, Inc. This file is part of GNU Libtool. This program is free software; you can redistribute it and/or modify @@ -24,6 +24,8 @@ USA. */ #include #endif +#define lt_preloaded_symbols lt__PROGRAM__LTX_preloaded_symbols + struct lt_symlist { const char *name; @@ -63,7 +65,7 @@ main (argc, argv) /* In an ideal world a shared lib would be able to export data */ pnothing = (int*)¬hing; #endif - } else + } else printf ("found file: %s\n", s->name); s ++; } diff --git a/tests/pdemo/longer_file_name_dlmain.c b/tests/pdemo/longer_file_name_dlmain.c index 7c123bb8e..b6b5fb4a0 100644 --- a/tests/pdemo/longer_file_name_dlmain.c +++ b/tests/pdemo/longer_file_name_dlmain.c @@ -1,5 +1,5 @@ /* dlmain.c -- hello test program that uses simulated dynamic linking - Copyright (C) 1996-1999 Free Software Foundation, Inc. + Copyright (C) 1996-1999, 2004 Free Software Foundation, Inc. This file is part of GNU Libtool. This program is free software; you can redistribute it and/or modify @@ -24,6 +24,8 @@ USA. */ #include #endif +#define lt_preloaded_symbols lt__PROGRAM__LTX_preloaded_symbols + struct lt_symlist { const char *name; @@ -63,7 +65,7 @@ main (argc, argv) /* In an ideal world a shared lib would be able to export data */ pnothing = (int*)¬hing; #endif - } else + } else printf ("found file: %s\n", s->name); s ++; }