From: Gary V. Vaughan Date: Wed, 2 Feb 2000 22:43:14 +0000 (+0000) Subject: * NEWS: updated. X-Git-Tag: release-1-3d~202 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f802484346e502b00287194af184a8f74c2157a4;p=thirdparty%2Flibtool.git * NEWS: updated. * doc/libtool.texi (Libltdl interface): Moved user defined module loader documentation from here... (Module loaders for libltdl) ...to here, and updated the text and added examples. * ltdl.m4 (AC_CHECK_FUNCS): check strcmp for lt_find_dlloader. * libltdl/ltdl.h: Reformatted and commented for readability. (struct lt_user_dlloader): New data type for passing initialisation pointers to lt_add_dlloader. (LTDL_ERROR_INVALID_LOADER): New error message when non loader handles are passed to the user loader API. (LTDL_ERROR_INIT_LOADER): New error when loader initialisation fails. (LTDL_ERROR_REMOVE_LOADER): New error when loader removal fails. (lt_module_open_t): renamed from lt_lib_open_t. (lt_module_close_t): renamed from lt_lib_close_t. (lt_dlloader_exit_t): renamed from lt_dlloader_exit_t. * libltdl/ltdl.c: Reordered builtin loaders so that the "dld" loader no longer occurs before "dlopen" on some platforms and after it on others. (lt_dlloader_t): Moved here from ltdl.h, added a field, "loader_name", for identifying the loader, and renamed from lt_dltype_t. Renamed type variables to loader IFF of type lt_dlloader_t. (lt_module_t): Renamed from lt_syshandle. Renamed handle variables to module IFF of type lt_module_t. (LTDL_TYPE_TOP): Deleted. No longer required. (sys_dl): Initialised as a struct lt_user_dlloader. (sys_dl_init): Deleted. No longer required. (sys_dl_exit): Ditto. (sys_shl): Initialised as a struct lt_user_dlloader. (sys_shl_init): Deleted. No longer required. (sys_shl_exit): Ditto. (sys_wll): Initialised as a struct lt_user_dlloader. (sys_wll_init): Deleted. No longer required. (sys_wll_exit): Ditto. (sys_bedl): Initialised as a struct lt_user_dlloader. (sys_bedl_init): Deleted. No longer required. (sys_bedl_exit): Ditto. (sys_dld): Initialised as a struct lt_user_dlloader. (sys_dld_init): Deleted. No longer required. (sys_dld_exit): Ditto. (sys_presym): Initialised as a struct lt_user_dlloader. (lt_mod_init_t): Moved to here from ltdl.h. (lt_dlinit): Add builtin loaders using the user loader API. (lt_dlexit): Unregister and free all loaders. (lt_add_dlloader): New function to add a new module loader after the loader specified in the argument. (lt_remove_dlloader): New function to remove a module loader. (lt_next_dlloader): New function for iterating over module loaders. (lt_dlloader_name): Accessor function for name of dlloader. (lt_find_dlloader): New function to get a reference to a registered module loader. (strcmp): static implementation incase the host has none. (lt_dlgettypes, lt_dlsettypes): Removed. --- diff --git a/ChangeLog b/ChangeLog index 0db740be8..7b26592dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,61 @@ +2000-02-02 Gary V. Vaughan + + * NEWS: updated. + * doc/libtool.texi (Libltdl interface): Moved user defined module + loader documentation from here... + (Module loaders for libltdl) ...to here, and updated the text and + added examples. + * ltdl.m4 (AC_CHECK_FUNCS): check strcmp for lt_find_dlloader. + * libltdl/ltdl.h: Reformatted and commented for readability. + (struct lt_user_dlloader): New data type for passing + initialisation pointers to lt_add_dlloader. + (LTDL_ERROR_INVALID_LOADER): New error message when non loader + handles are passed to the user loader API. + (LTDL_ERROR_INIT_LOADER): New error when loader initialisation + fails. + (LTDL_ERROR_REMOVE_LOADER): New error when loader removal fails. + (lt_module_open_t): renamed from lt_lib_open_t. + (lt_module_close_t): renamed from lt_lib_close_t. + (lt_dlloader_exit_t): renamed from lt_dlloader_exit_t. + * libltdl/ltdl.c: Reordered builtin loaders so that the "dld" + loader no longer occurs before "dlopen" on some platforms and + after it on others. + (lt_dlloader_t): Moved here from ltdl.h, added a field, + "loader_name", for identifying the loader, and renamed from + lt_dltype_t. Renamed type variables to loader IFF of type + lt_dlloader_t. + (lt_module_t): Renamed from lt_syshandle. Renamed handle variables + to module IFF of type lt_module_t. + (LTDL_TYPE_TOP): Deleted. No longer required. + (sys_dl): Initialised as a struct lt_user_dlloader. + (sys_dl_init): Deleted. No longer required. + (sys_dl_exit): Ditto. + (sys_shl): Initialised as a struct lt_user_dlloader. + (sys_shl_init): Deleted. No longer required. + (sys_shl_exit): Ditto. + (sys_wll): Initialised as a struct lt_user_dlloader. + (sys_wll_init): Deleted. No longer required. + (sys_wll_exit): Ditto. + (sys_bedl): Initialised as a struct lt_user_dlloader. + (sys_bedl_init): Deleted. No longer required. + (sys_bedl_exit): Ditto. + (sys_dld): Initialised as a struct lt_user_dlloader. + (sys_dld_init): Deleted. No longer required. + (sys_dld_exit): Ditto. + (sys_presym): Initialised as a struct lt_user_dlloader. + (lt_mod_init_t): Moved to here from ltdl.h. + (lt_dlinit): Add builtin loaders using the user loader API. + (lt_dlexit): Unregister and free all loaders. + (lt_add_dlloader): New function to add a new module loader after the + loader specified in the argument. + (lt_remove_dlloader): New function to remove a module loader. + (lt_next_dlloader): New function for iterating over module loaders. + (lt_dlloader_name): Accessor function for name of dlloader. + (lt_find_dlloader): New function to get a reference to a registered + module loader. + (strcmp): static implementation incase the host has none. + (lt_dlgettypes, lt_dlsettypes): Removed. + 2000-02-02 Thomas Tanner * libltdl/ltdl.c: replace NULL with 0, remove unused system @@ -89,7 +147,7 @@ (lt_dlsettypes): New function to replace the list of ltdl dynamic loader types entirely -- e.g. to prepend a new type to the existing list. - (sys_dl_open, sys_dl_close, sys_dl_sym): Work with lt_syshandle.. + (sys_dl_open, sys_dl_close, sys_dl_sym): Work with lt_syshandle. (sys_shl_open, sys_shl_close, sys_shl_sym): ditto. (sys_dld_open, sys_dld_close, sys_dld_sym): ditto. (sys_wll_open, sys_wll_close, sys_wll_sym): ditto. diff --git a/NEWS b/NEWS index 066e48a07..797bd0a42 100644 --- a/NEWS +++ b/NEWS @@ -10,8 +10,9 @@ New in 1.3d: 2000-??-??; CVS version 1.3c, Libtool team: * Libtool now allows you to link shared libraries against static code. * New functions lt_dlgetdata, lt_dlsetdata, lt_dlgetinfo, lt_dlforeach in libltdl can be used to store application specific data in handles. -* New functions lt_dladdtype, lt_dlgettypes, lt_dlsettypes in libltdl - can be used for adding new types of module loading. +* New functions lt_next_dlloader, lt_dlloader_name, lt_find_dlloader, + lt_add_dlloader in libltdl can be used for adding new types of module + loader to libltdl.. * New functions lt_dladderror, lt_dlseterror in libltdl can be used to integrate user module loaders with lt_dlerror. * "-Xcompiler" and "-Wc," does now work in compile mode, too. diff --git a/doc/libtool.texi b/doc/libtool.texi index 1a7c70c2e..ce679b433 100644 --- a/doc/libtool.texi +++ b/doc/libtool.texi @@ -181,6 +181,7 @@ Using libltdl * Libltdl interface:: How to use libltdl in your programs. * Modules for libltdl:: Creating modules that can be @code{dlopen}ed. * Distributing libltdl:: How to distribute libltdl with your package. +* Module loaders for libltdl:: Creating user defined module loaders. Using libtool with other languages @@ -2785,6 +2786,7 @@ distribution terms that you use for the rest of that program. * Libltdl interface:: How to use libltdl in your programs. * Modules for libltdl:: Creating modules that can be @code{dlopen}ed. * Distributing libltdl:: How to distribute libltdl with your package. +* Module loaders for libltdl:: Creating user defined module loaders. @end menu @node Libltdl interface @@ -2823,12 +2825,6 @@ The following types are defined in @file{ltdl.h}: Every lt_dlopened module has a handle associated with it. @end deftp -@deftp {Type} lt_syshandle -@code{lt_syshandle} is a generic system module "handle". -The dynamic module loader type extensions communicate using these low level -handles. -@end deftp - @deftypefn {Type} {struct} lt_dlinfo @{ @w{char *@var{filename};} @w{char *@var{name};} @w{int @var{ref_count};} @} @code{lt_dlinfo} is used to store information about a module. The @var{filename} attribute is a null-terminated character string of the @@ -2839,51 +2835,6 @@ The @var{ref_count} attribute is a reference counter that describes how often the same module is currently loaded. @end deftypefn -@deftypefn {Type} {struct} lt_dltype_t @{ @w{struct lt_dltype_t *@var{next};} @w{const char *@var{sym_prefix};} @w{lt_mod_init_t *@var{mod_init};} @w{lt_mod_exit_t *@var{mod_exit};} @w{lt_lib_open_t *@var{lib_open};} @w{lt_lib_close_t *@var{lib_close};} @w{lt_find_sym_t *@var{find_sym};} @} -@code{lt_dltype_t} is used to store the functions used to access a dynamic -module loader type. If you want to define a new way to open dynamic modules, -and have the @code{lt_dlopen} @sc{api} use it, you need to instantiate one of -these structures and pass it to @code{lt_dladdtype()}. -@end deftypefn - -@deftypefn {Type} int lt_mod_init_t (void) -The type of an initialisation function for an @code{lt_dltype_t} module -loader. Implementation of such a function should perform any initialisation -required by the loader, and return non-zero if an error is encountered. When -used as part of an @code{lt_dltype_t} registration, if non-NULL, the function -will be called by @code{lt_dlinit}, or if it is registered after the call to -@code{lt_dlinit}, the function will be called immediately upon registration. -@end deftypefn - -@deftypefn {Type} int lt_mod_exit_t (void) -The type of the finalisation function for an @code{lt_dltype_t} module -loader. Implementation of such a function should free any resources -associated with the loader. If non-NULL, the function will be called by -@code{lt_dlexit}. -@end deftypefn - -@deftypefn {Type} lt_syshandle lt_lib_open_t (@w{const char *@var{filename}}) -The type of the loader function for an @code{lt_dltype_t} module loader. -Implementation of such a function should attempt to load the named module, and -return an @code{lt_syshandle} suitable for passing in to the associated -@code{lt_lib_close_t} and @code{lt_sym_find_t} function pointers. If the -function fails it should return NULL. -@end deftypefn - -@deftypefn {Type} int lt_lib_close_t (@w{lt_syshandle @var{handle}}) -The type of the unloader function for an @code{lt_dltype_t} module loader. -Implementatation of such a function should attempt to release any resources -tied up by the @var{handle} module, and then unload it from memory. If the -function fails for some reason, return non-zero. -@end deftypefn - -@deftypefn {Type} lt_ptr_t lt_find_sym_t (@w{lt_syshandle @var{handle},} @w{const char *@var{symbol}}) -The type of the symbol lookup function for an @code{lt_dltype_t} module -loader. Implementation of such a function should return the address of the -named @var{symbol} in the module @var{handle}, or NULL if there is no such -symbol. -@end deftypefn - @deftp {Type} lt_dlsymlist @code{lt_dlsymlist} is a symbol list for dlpreopened modules. This structure is described in @pxref{Dlpreopening}. @@ -2900,32 +2851,6 @@ and may be called several times. Return 0 on success, otherwise the number of errors. @end deftypefun -@deftypefun int lt_dladdtype (@w{lt_dltype_t *@var{dltype}}) -Append a new module loader type to the list of all types. -@var{dltype} should have its @code{next} field set to NULL. If the -@code{sym_prefix} field is set to NULL, then it will be replaced with a single -underscore if that is what the platform requires normally (use the empty -string if you want an unconditional empty prefix). The new type will be added -to the end of the module loader types list, and hence will be used only if all -of the preceding methods fail. - -If this function is used to add a type after calling @code{lt_dlinit}, then -the @var{mod_init} function (if any) will be called immediately, otherwise -it will be called at the same time as the other type initialisation function -by @code{lt_dlinit}. -@end deftypefun - -@deftypefun lt_dltype_t *lt_dlgettypes (void) -Return the list of module loader types. -@end deftypefun - -@deftypefun int lt_dlsettypes (@w{lt_dltype_t *@var{dltypes}}) -Change the list of module loader types to be @var{dltypes}. -This completely replaces the default module loader types determined by libtool -with the new linked list of types -- which should probably be a superset of -the original list. -@end deftypefun - @deftypefun int lt_dlexit (void) Shut down libltdl and close all modules. This function will only then shut down libltdl when it was called as @@ -3013,34 +2938,6 @@ Return @code{NULL} if no errors have occurred since initialization or since it was last called. @end deftypefun -@deftypefun int lt_dladderror (@w{const char *@var{diagnostic}}) -This function allows you to integrate your own error messages into -@code{lt_dlerror}. Pass in a suitable diagnostic message for return by -@code{lt_dlerror}, and an error identifier for use with @code{lt_dlseterror} -is returned. - -If the allocation of an identifier fails, this function returns -1. - -@example -int myerror = lt_dladderror ("Doh!"); -if (myerror < 0) - perror (lt_dlerror ()); -@end example -@end deftypefun - -@deftypefun int lt_dlseterror (@w{int @var{errorcode}}) -When writing your own module loaders, you should use this function to raise -errors so that they are propogated through the @code{lt_dlerror} interface. -All of the standard errors used by libltdl are declared in @file{ltdl.h}, or -you can add more of your own with @code{lt_dladderror}. This function returns -0 on success. - -@example -if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0) - perror (lt_dlerror ()); -@end example -@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 @@ -3105,8 +3002,8 @@ As soon as @var{func} returns a non-zero value for one of the handles, Otherwise 0 is returned. @end deftypefun -@deftypevar {lt_ptr_t (*} lt_dlmalloc ) (size_t size) -@deftypevarx {void (*} lt_dlfree ) (lt_ptr_t ptr) +@deftypevar {lt_ptr_t (*} lt_dlmalloc ) (size_t @var{size}) +@deftypevarx {void (*} lt_dlfree ) (lt_ptr_t @var{ptr}) These variables are set to @code{malloc} and @code{free}, by default, but you can set them to any other functions that provides equivalent functionality. However, you must not modify their values after calling @@ -3318,6 +3215,234 @@ myprog_DEPENDENCIES = $(LIBLTDL) libfoo.la ... @end example + +@node Module loaders for libltdl +@section How to create and register new module loaders + +Sometimes libltdl's many ways of gaining access to modules are not +sufficient for the purposes of a project. You can write your own +loader, and register it with libltdl so that @code{lt_dlopen} will be +able to use it. + +Writing a loader involves writing at least three functions which can be +called by @code{lt_dlopen}, @code{lt_dlsym} and @code{lt_dlclose}. +Optionally, you can provide a finalisation function to perform any +cleanup operations when @code{lt_dlexit} executes, and a symbol prefix +string which will be prepended to any symbols passed to @code{lt_dlsym}. +These functions must match the function pointer types below, after +which they can be allocated to an instance of @code{lt_user_dlloader} +and registered. + +Registering the loader requires that you choose a name for it, so that it +can be recognised by @code{lt_find_dlloader} and removed with +@code{lt_remove_dlloader}. The name you choose must be unique, and not +already in use by libltdl's builtin loaders: + +@table @asis +@item "dlopen" +The system dynamic library loader, if one exists. +@item "dld" +The @sc{gnu} dld loader, if @file{libdld} wasinstalled when libltdl was +built. +@item "dlpreload" +The loader for @code{lt_dlopen}ing of preloaded static modules. +@end table + +The prefix "dl" is reserved for loaders supplied with future versions of +libltdl, so you should not use that for your own loader names. + +@noindent +The following types are defined in @file{ltdl.h}: + +@deftp {Type} lt_module_t +@code{lt_module_t} is a dlloader dependent module. +The dynamic module loader extensions communicate using these low +level types. +@end deftp + +@deftp {Type} lt_dlloader_t +@code{lt_dlloader_t} is a handle for module loader types. +@end deftp + +@deftypefn {Type} {struct} lt_user_dlloader @{@w{const char *@var{sym_prefix};} @w{lt_module_open_t *@var{module_open};} @w{lt_module_close_t *@var{module_close};} @w{lt_find_sym_t *@var{find_sym};} @w{lt_dlloader_exit_t *@var{dlloader_exit};} @} +If you want to define a new way to open dynamic modules, and have the +@code{lt_dlopen} @sc{api} use it, you need to instantiate one of these +structures and pass it to @code{lt_add_dlloader}. +@end deftypefn + +@deftypefn {Type} lt_module_t lt_module_open_t (@w{const char *@var{filename}}) +The type of the loader function for an @code{lt_dlloader_t} module +loader. Implementation of such a function should attempt to load the +named module, and return an @code{lt_module_t} suitable for passing in +to the associated @code{lt_module_close_t} and @code{lt_sym_find_t} +function pointers. If the function fails it should return NULL, and set +the error message with @code{lt_dlseterror}. +@end deftypefn + +@deftypefn {Type} int lt_module_close_t (@w{lt_module_t @var{module}}) +The type of the unloader function for a user defined module loader. +Implementatation of such a function should attempt to release +any resources tied up by the @var{module} module, and then unload it +from memory. If the function fails for some reason, set the error +message with @code{lt_dlseterror} and return non-zero. +@end deftypefn + +@deftypefn {Type} lt_ptr_t lt_find_sym_t (@w{lt_module_t @var{module},} @w{const char *@var{symbol}}) +The type of the symbol lookup function for a user defined module loader. +Implementation of such a function should return the address of the named +@var{symbol} in the module @var{module}, or else set the error message +with @code{lt_dlseterror} and return NULL if lookup fails. +@end deftypefn + +@deftypefn {Type} int lt_dlloader_exit_t (void) +The type of the finalisation function for a user defined module loader. +Implementation of such a function should free any resources associated +with the loader. If non-NULL, the function will be called by +@code{lt_dlexit}. +@end deftypefn + +For example: + +@example +int +register_myloader (void) +@{ + lt_user_dlloader dlloader; + + /* User modules are responsible for their own initialisation. */ + if (myloader_init () != 0) + return MYLOADER_INIT_ERROR; + + dlloader.sym_prefix = NULL; + dlloader.module_open = myloader_open; + dlloader.module_close = myloader_close; + dlloader.find_sym = myloader_find_sym. + dlloader.dlloader_exit = myloader_exit; + + /* Add my loader as the default module loader. */ + if (lt_add_dlloader (lt_next_dlloader (NULL), &dlloader, "myloader") != 0) + return ERROR; + + return OK; +@} +@end example + +Note that if there is any initialisation required for the loader, +it must be performed manually before the loader is registered -- +libltdl doesn't handle user loader initialisation. + +Finalisation @emph{is} handled by libltdl however, and it is important +to ensure the @code{dlloader_exit} callback releases any resources claimed +during the initialisation phase. + +@page +@noindent +libltdl provides the following functions for writing your own module +loaders: + +@deftypefun int lt_add_dlloader (@w{lt_dlloader_t *@var{place},} @w{lt_user_dlloader *@var{dlloader},} @w{const char *@var{loader_name}}) +Add a new module loader to the list of all loaders, either as the +last loader (if @var{place} is @code{NULL}), else immediately before the +loader passed as @var{place}. @var{loader_name} will be returned by +@code{lt_dlloader_name} if it is subsequently passed a newly +registered loader. These @var{loader_name}s must be unique, or +@code{lt_remove_dlloader} and @code{lt_find_dlloader} cannot +work. Returns 0 for success. + +@example +@{ + /* Make myloader be the last one. */ + if (lt_add_dlloader (NULL, myloader) != 0) + perror (lt_dlerror ()); +@} +@end example +@end deftypefun + +@deftypefun int lt_remove_dlloader (@w{const char *@var{loader_name}}) +Remove the loader identified by the unique name, @var{loader_name}. +Before this can succeed, all modules opened by the named loader must +have been closed. Returns 0 for success, otherwise an error message can +be obtained from @code{lt_dlerror}. + +@example +@{ + /* Remove myloader. */ + if (lt_remove_dlloader ("myloader") != 0) + perror (lt_dlerror ()); +@} +@end example +@end deftypefun + +@deftypefun lt_dlloader_t *lt_next_dlloader (@w{lt_dlloader_t *@var{place}}) +Iterate over the module loaders, returning the first loader if @var{place} is +@code{NULL}, and the next one on subsequent calls. The handle is for use with +@code{lt_add_dlloader}. + +@example +@{ + /* Make myloader be the first one. */ + if (lt_add_dlloader (lt_next_dlloader (NULL), myloader) != 0) + return ERROR; +@} +@end example +@end deftypefun + +@deftypefun lt_dlloader_t *lt_find_dlloader (@w{const char *@var{loader_name}}) +Return the first loader with a matching @var{loader_name} identifier, or else +@code{NULL}, if the identifier is not found. + +The identifiers which may be used by ltdl itself, if the host +architecture supports them are @dfn{dlopen}@footnote{This is used for +the host dependent module loading @sc{api} -- @code{shl_load} and +@code{LoadLibrary} for example}, @dfn{dld} and @dfn{dlpreload}. + +@example +@{ + /* Add a user loader as the next module loader to be tried if + the standard dlopen loader were to fail when lt_dlopening. */ + if (lt_add_dlloader (lt_find_dlloader ("dlopen"), myloader) != 0) + return ERROR; +@} +@end example +@end deftypefun + +@deftypefun char *lt_dlloader_name (@w{lt_dlloader_t *@var{place}}) +Return the identifying name of @var{PLACE}, as obtained from +@code{lt_next_dlloader} or @code{lt_find_dlloader}. If this function fails, +it will return @code{NULL} and set an error for retrieval with +@code{lt_dlerror}. +@end deftypefun + +@subsection Error handling within user module loaders + +@deftypefun int lt_dladderror (@w{const char *@var{diagnostic}}) +This function allows you to integrate your own error messages into +@code{lt_dlerror}. Pass in a suitable diagnostic message for return by +@code{lt_dlerror}, and an error identifier for use with +@code{lt_dlseterror} is returned. + +If the allocation of an identifier fails, this function returns -1. + +@example +int myerror = lt_dladderror ("Doh!"); +if (myerror < 0) + perror (lt_dlerror ()); +@end example +@end deftypefun + +@deftypefun int lt_dlseterror (@w{int @var{errorcode}}) +When writing your own module loaders, you should use this function to +raise errors so that they are propogated through the @code{lt_dlerror} +interface. All of the standard errors used by libltdl are declared in +@file{ltdl.h}, or you can add more of your own with +@code{lt_dladderror}. This function returns 0 on success. + +@example +if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0) + perror (lt_dlerror ()); +@end example +@end deftypefun + @node Other languages @chapter Using libtool with other languages @cindex C, not using diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c index eb6e5d55e..76d90c2b5 100644 --- a/libltdl/ltdl.c +++ b/libltdl/ltdl.c @@ -87,6 +87,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA /* This accounts for the _LTX_ separator */ #define LTDL_SYMBOL_OVERHEAD 5 +/* NOTE: typedefed in ltdl.h + This structure is used for the list of registered loaders. */ +struct lt_dlloader_t { + struct lt_dlloader_t *next; + const char *loader_name; /* identifying name for each loader */ + const char *sym_prefix; /* prefix for symbols */ + lt_dlloader_exit_t *dlloader_exit; + lt_module_open_t *module_open; + lt_module_close_t *module_close; + lt_find_sym_t *find_sym; +}; + +typedef struct lt_dlhandle_t { + struct lt_dlhandle_t *next; + lt_dlloader_t *loader; /* dlopening interface */ + lt_dlinfo info; + int depcount; /* number of dependencies */ + lt_dlhandle *deplibs; /* dependencies */ + lt_module_t module; /* system module handle */ + lt_ptr_t system; /* system specific data */ + lt_ptr_t app_private; /* application private data */ +} lt_dlhandle_t; + static const char objdir[] = LTDL_OBJDIR; #ifdef LTDL_SHLIB_EXT static const char shlib_ext[] = LTDL_SHLIB_EXT; @@ -115,17 +138,6 @@ static const char *last_error = 0; LTDL_GLOBAL_DATA lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc; LTDL_GLOBAL_DATA void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free; -#define LTDL_TYPE_TOP 0 - -typedef struct lt_dlhandle_t { - struct lt_dlhandle_t *next; - lt_dltype_t *type; /* dlopening interface */ - lt_dlinfo info; - int depcount; /* number of dependencies */ - lt_dlhandle *deplibs; /* dependencies */ - lt_syshandle handle; /* system handle */ -} lt_dlhandle_t; - #undef strdup #define strdup xstrdup @@ -143,6 +155,32 @@ strdup(str) return tmp; } +#if ! HAVE_STRCMP + +#undef strcmp +#define strcmp xstrcmp + +static inline int +strcmp (str1, str2) + const char *str1; + const char *str2; +{ + if (str1 == str2) + return 0; + if (str1 == 0) + return -1; + if (str2 == 0) + return 1; + + for (;*str1 && *str2; str1++, str2++) + if (*str1 != *str2) + break; + + return (int)(*str1 - *str2); +} +#endif + + #if ! HAVE_STRCHR # if HAVE_INDEX @@ -244,38 +282,26 @@ strrchr(str, ch) # endif #endif -static int -sys_dl_init LTDL_PARAMS((void)) -{ - return 0; -} - -static int -sys_dl_exit LTDL_PARAMS((void)) -{ - return 0; -} - -static lt_syshandle +static lt_module_t sys_dl_open (filename) const char *filename; { - lt_ptr_t handle = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW); - if (!handle) { + lt_module_t module = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW); + if (!module) { #if HAVE_DLERROR last_error = dlerror(); #else last_error = LT_DLSTRERROR(CANNOT_OPEN); #endif } - return handle; + return module; } static int -sys_dl_close (handle) - lt_syshandle handle; +sys_dl_close (module) + lt_module_t module; { - if (dlclose(handle) != 0) { + if (dlclose(module) != 0) { #if HAVE_DLERROR last_error = dlerror(); #else @@ -287,11 +313,11 @@ sys_dl_close (handle) } static lt_ptr_t -sys_dl_sym (handle, symbol) - lt_syshandle handle; +sys_dl_sym (module, symbol) + lt_module_t module; const char *symbol; { - lt_ptr_t address = dlsym(handle, symbol); + lt_ptr_t address = dlsym(module, symbol); if (!address) #if HAVE_DLERROR @@ -302,19 +328,13 @@ sys_dl_sym (handle, symbol) return address; } -static -lt_dltype_t -#ifdef NEED_USCORE -sys_dl = { LTDL_TYPE_TOP, "_", sys_dl_init, sys_dl_exit, - sys_dl_open, sys_dl_close, sys_dl_sym }; -#else -sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit, - sys_dl_open, sys_dl_close, sys_dl_sym }; -#endif - -#undef LTDL_TYPE_TOP -#define LTDL_TYPE_TOP &sys_dl - +static struct lt_user_dlloader sys_dl = { +# ifdef NEED_USCORE + "_", +# else + 0, +# endif + sys_dl_open, sys_dl_close, sys_dl_sym, 0 }; #endif #if HAVE_SHL_LOAD @@ -360,34 +380,22 @@ sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit, #define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) -static int -sys_shl_init LTDL_PARAMS((void)) -{ - return 0; -} - -static int -sys_shl_exit LTDL_PARAMS((void)) -{ - return 0; -} - -static lt_syshandle +static lt_module_t sys_shl_open (filename) const char *filename; { - lt_syshandle handle = shl_load(filename, LTDL_BIND_FLAGS, 0L); - if (!handle) { + lt_module_t module = shl_load(filename, LTDL_BIND_FLAGS, 0L); + if (!module) { last_error = LT_DLSTRERROR(CANNOT_OPEN); } - return handle; + return module; } static int -sys_shl_close (handle) - lt_syshandle handle; +sys_shl_close (module) + lt_module_t module; { - if (shl_unload((shl_t) (handle)) != 0) { + if (shl_unload((shl_t) (module)) != 0) { last_error = LT_DLSTRERROR(CANNOT_CLOSE); return 1; } @@ -395,13 +403,13 @@ sys_shl_close (handle) } static lt_ptr_t -sys_shl_sym (handle, symbol) - lt_syshandle handle; +sys_shl_sym (module, symbol) + lt_module_t module; const char *symbol; { lt_ptr_t address; - if (handle && shl_findsym((shl_t*) &handle, + if (module && shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address) == 0) if (address) return address; @@ -409,87 +417,14 @@ sys_shl_sym (handle, symbol) return 0; } -static -lt_dltype_t -sys_shl = { LTDL_TYPE_TOP, 0, sys_shl_init, sys_shl_exit, - sys_shl_open, sys_shl_close, sys_shl_sym }; +static struct lt_user_dlloader +sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0 }; #undef LTDL_TYPE_TOP #define LTDL_TYPE_TOP &sys_shl #endif -#if HAVE_DLD - -/* dynamic linking with dld */ - -#if HAVE_DLD_H -#include -#endif - -static int -sys_dld_init LTDL_PARAMS((void)) -{ - return 0; -} - -static int -sys_dld_exit LTDL_PARAMS((void)) -{ - return 0; -} - -static lt_syshandle -sys_dld_open (filename) - const char *filename; -{ - lt_syshandle handle = strdup(filename); - if (!handle) { - last_error = LT_DLSTRERROR(NO_MEMORY); - return 0; - } - if (dld_link(filename) != 0) { - last_error = LT_DLSTRERROR(CANNOT_OPEN); - lt_dlfree(handle); - return 0; - } - return handle; -} - -static int -sys_dld_close (handle) - lt_syshandle handle; -{ - if (dld_unlink_by_file((char*)(handle), 1) != 0) { - last_error = LT_DLSTRERROR(CANNOT_CLOSE); - return 1; - } - lt_dlfree(handle); - return 0; -} - -static lt_ptr_t -sys_dld_sym (handle, symbol) - lt_syshandle handle; - const char *symbol; -{ - lt_ptr_t address = dld_get_func(symbol); - - if (!address) - last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND); - return address; -} - -static -lt_dltype_t -sys_dld = { LTDL_TYPE_TOP, 0, sys_dld_init, sys_dld_exit, - sys_dld_open, sys_dld_close, sys_dld_sym }; - -#undef LTDL_TYPE_TOP -#define LTDL_TYPE_TOP &sys_dld - -#endif - #ifdef _WIN32 /* dynamic linking for Win32 */ @@ -511,12 +446,12 @@ sys_wll_exit LTDL_PARAMS((void)) /* Forward declaration; required to implement handle search below. */ static lt_dlhandle handles; -static lt_syshandle +static lt_module_t sys_wll_open (filename) const char *filename; { lt_dlhandle cur; - lt_syshandle handle; + lt_module_t module; char *searchname = 0; char *ext = strrchr(filename, '.'); @@ -535,7 +470,7 @@ sys_wll_open (filename) strcat(searchname, "."); } - handle = LoadLibrary(searchname); + module = LoadLibrary(searchname); lt_dlfree(searchname); /* libltdl expects this function to fail if it is unable @@ -548,28 +483,28 @@ sys_wll_open (filename) find one. */ cur = handles; while (cur) { - if (!cur->handle) { + if (!cur->module) { cur = 0; break; } - if (cur->handle == handle) + if (cur->module == module) break; cur = cur->next; } - if (cur || !handle) { + if (cur || !module) { last_error = LT_DLSTRERROR(CANNOT_OPEN); return 0; } - return handle; + return module; } static int -sys_wll_close (handle) - lt_syshandle handle; +sys_wll_close (module) + lt_module_t module; { - if (FreeLibrary(handle) == 0) { + if (FreeLibrary(module) == 0) { last_error = LT_DLSTRERROR(CANNOT_CLOSE); return 1; } @@ -577,24 +512,19 @@ sys_wll_close (handle) } static lt_ptr_t -sys_wll_sym (handle, symbol) - lt_syshandle handle; +sys_wll_sym (module, symbol) + lt_module_t module; const char *symbol; { - lt_ptr_t address = GetProcAddress(handle, symbol); + lt_ptr_t address = GetProcAddress(module, symbol); if (!address) last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND); return address; } -static -lt_dltype_t -sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit, - sys_wll_open, sys_wll_close, sys_wll_sym }; - -#undef LTDL_TYPE_TOP -#define LTDL_TYPE_TOP &sys_wll +static struct lt_user_dlloader +sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0 }; #endif @@ -604,19 +534,7 @@ sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit, #include -static int -sys_bedl_init LTDL_PARAMS((void)) -{ - return 0; -} - -static int -sys_bedl_exit LTDL_PARAMS((void)) -{ - return 0; -} - -static lt_syshandle +static lt_module_t sys_bedl_open (filename) const char *filename; { @@ -635,14 +553,14 @@ sys_bedl_open (filename) return 0; } - return (lt_syshandle) image; + return (lt_module_t) image; } static int -sys_bedl_close (handle) - lt_syshandle handle; +sys_bedl_close (module) + lt_module_t module; { - if (unload_add_on((image_id)handle) != B_OK) { + if (unload_add_on((image_id)module) != B_OK) { last_error = LT_DLSTRERROR(CANNOT_CLOSE); return 1; } @@ -650,12 +568,12 @@ sys_bedl_close (handle) } static lt_ptr_t -sys_bedl_sym (handle, symbol) - lt_syshandle handle; +sys_bedl_sym (module, symbol) + lt_module_t module; const char *symbol; { lt_ptr_t address = 0; - image_id image = (image_id)handle; + image_id image = (image_id)module; if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY, &address) != B_OK) { @@ -665,13 +583,62 @@ sys_bedl_sym (handle, symbol) return address; } -static -lt_dltype_t -sys_bedl = { LTDL_TYPE_TOP, 0, sys_bedl_init, sys_bedl_exit, - sys_bedl_open, sys_bedl_close, sys_bedl_sym }; +static struct lt_user_dlloader +sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0 }; -#undef LTDL_TYPE_TOP -#define LTDL_TYPE_TOP &sys_bedl +#endif + +#if HAVE_DLD + +/* dynamic linking with dld */ + +#if HAVE_DLD_H +#include +#endif + +static lt_module_t +sys_dld_open (filename) + const char *filename; +{ + lt_module_t module = strdup(filename); + if (!module) { + last_error = LT_DLSTRERROR(NO_MEMORY); + return 0; + } + if (dld_link(filename) != 0) { + last_error = LT_DLSTRERROR(CANNOT_OPEN); + lt_dlfree(module); + return 0; + } + return module; +} + +static int +sys_dld_close (module) + lt_module_t module; +{ + if (dld_unlink_by_file((char*)(module), 1) != 0) { + last_error = LT_DLSTRERROR(CANNOT_CLOSE); + return 1; + } + lt_dlfree(module); + return 0; +} + +static lt_ptr_t +sys_dld_sym (module, symbol) + lt_module_t module; + const char *symbol; +{ + lt_ptr_t address = dld_get_func(symbol); + + if (!address) + last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND); + return address; +} + +static struct lt_user_dlloader +sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0 }; #endif @@ -740,7 +707,7 @@ presym_add_symlist (preloaded) return 0; } -static lt_syshandle +static lt_module_t presym_open (filename) const char *filename; { @@ -758,7 +725,7 @@ presym_open (filename) while (syms->name) { if (!syms->address && strcmp(syms->name, filename) == 0) { - return (lt_syshandle) syms; + return (lt_module_t) syms; } syms++; } @@ -769,20 +736,20 @@ presym_open (filename) } static int -presym_close (handle) - lt_syshandle handle; +presym_close (module) + lt_module_t module; { /* Just to silence gcc -Wall */ - handle = 0; + module = 0; return 0; } static lt_ptr_t -presym_sym (handle, symbol) - lt_syshandle handle; +presym_sym (module, symbol) + lt_module_t module; const char *symbol; { - lt_dlsymlist *syms = (lt_dlsymlist*)(handle); + lt_dlsymlist *syms = (lt_dlsymlist*)(module); syms++; while (syms->address) { @@ -794,27 +761,21 @@ presym_sym (handle, symbol) return 0; } -static -lt_dltype_t -presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit, - presym_open, presym_close, presym_sym }; +static struct lt_user_dlloader +presym = { 0, presym_open, presym_close, presym_sym, presym_exit }; -#undef LTDL_TYPE_TOP -#define LTDL_TYPE_TOP &presym static char *user_search_path = 0; +static lt_dlloader_t *loaders = 0; static lt_dlhandle handles = 0; static int initialized = 0; -static lt_dltype_t *types = LTDL_TYPE_TOP; -#undef LTDL_TYPE_TOP - int lt_dlinit LTDL_PARAMS((void)) { /* initialize libltdl */ - lt_dltype_t **type = &types; - int typecount = 0; + lt_dlloader_t **loader = &loaders; + int errors = 0; if (initialized) { /* Initialize only at first call. */ initialized++; @@ -822,82 +783,34 @@ lt_dlinit LTDL_PARAMS((void)) } handles = 0; user_search_path = 0; /* empty search path */ - - while (*type) { - if ((*type)->mod_init()) - *type = (*type)->next; /* Remove it from the list */ - else { - type = &(*type)->next; /* Keep it */ - typecount++; - } - } - if (typecount == 0) { - last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED); - return 1; - } - last_error = 0; - initialized = 1; - return 0; -} - -int -lt_dladdtype (dltype) - lt_dltype_t *dltype; -{ - lt_dltype_t *type = types; - if (dltype == 0) { /* diagnose null parameters */ - last_error = LT_DLSTRERROR(INVALID_TYPE); - return 1; - } - if (dltype->next != 0) { /* diagnose invalid contents */ - last_error = LT_DLSTRERROR(INVALID_TYPE); - return 1; - } - -#ifdef NEED_USCORE - if (dltype->sym_prefix == 0) - dltype->sym_prefix = "_"; -#else - if (dltype->sym_prefix && *dltype->sym_prefix == 0) - dltype->sym_prefix = 0; +#if HAVE_LIBDL && !defined(__CYGWIN__) + errors += lt_add_dlloader (lt_next_dlloader(0), &sys_dl, "dlopen"); #endif - - if (type == 0) { - type = dltype; - } else { - /* This function always appends to the existing list. */ - while (type->next) - type = type->next; - type->next = dltype; - } - - /* If lt_dlinit() has already been called, then initialize the - new type here. */ - if (initialized && dltype->mod_init) - if ((*dltype->mod_init)()) { - last_error = LT_DLSTRERROR(INIT_TYPE); +#if HAVE_SHL_LOAD + errors += lt_add_dlloader (lt_next_dlloader(0), &sys_shl, "dlopen"); +#endif +#ifdef _WIN32 + errors += lt_add_dlloader (lt_next_dlloader(0), &sys_wll, "dlopen"); +#endif +#ifdef __BEOS__ + errors += lt_add_dlloader (lt_next_dlloader(0), &sys_bedl, "dlopen"); +#endif +#if HAVE_DLD + errors += lt_add_dlloader (lt_next_dlloader(0), &sys_dld, "dld"); +#endif + errors += lt_add_dlloader (lt_next_dlloader(0), &presym, "dlpreload"); + if (presym_init()) { + last_error = LT_DLSTRERROR(INIT_LOADER); return 1; } - return 0; -} - -lt_dltype_t * -lt_dlgettypes LTDL_PARAMS((void)) -{ - return types; -} - -int -lt_dlsettypes (dltypes) - lt_dltype_t *dltypes; -{ - if (dltypes == 0) { /* diagnose null parameters */ - last_error = LT_DLSTRERROR(INVALID_TYPE); + if (errors != 0) { + last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED); return 1; } - types = dltypes; + last_error = 0; + initialized = 1; return 0; } @@ -925,7 +838,7 @@ int lt_dlexit LTDL_PARAMS((void)) { /* shut down libltdl */ - lt_dltype_t *type = types; + lt_dlloader_t *loader = loaders; int errors, level; if (!initialized) { @@ -948,12 +861,16 @@ lt_dlexit LTDL_PARAMS((void)) errors++; } } - initialized = 0; - while (type) { - if (type->mod_exit()) + /* close all loaders */ + while (loader) { + lt_dlloader_t *next = loader->next; + if (loader->dlloader_exit && loader->dlloader_exit()) errors++; - type = type->next; + lt_dlfree (loader); + loader = next; } + + initialized = 0; return errors; } @@ -963,7 +880,7 @@ tryall_dlopen (handle, filename) const char *filename; { lt_dlhandle cur; - lt_dltype_t *type = types; + lt_dlloader_t *loader = loaders; const char *saved_error = last_error; /* check whether the module was already opened */ @@ -992,18 +909,18 @@ tryall_dlopen (handle, filename) } } else cur->info.filename = 0; - while (type) { - cur->handle = type->lib_open(filename); - if (cur->handle != 0) + while (loader) { + cur->module = loader->module_open(filename); + if (cur->module != 0) break; - type = type->next; + loader = loader->next; } - if (!type) { + if (!loader) { if (cur->info.filename) lt_dlfree(cur->info.filename); return 1; } - cur->type = type; + cur->loader = loader; last_error = saved_error; return 0; } @@ -1679,7 +1596,7 @@ lt_dlclose (handle) last->next = handle->next; else handles = handle->next; - error = handle->type->lib_close(handle->handle); + error = handle->loader->module_close(handle->module); error += unload_deplibs(handle); if (handle->info.filename) lt_dlfree(handle->info.filename); @@ -1710,8 +1627,8 @@ lt_dlsym (handle, symbol) return 0; } lensym = strlen(symbol); - if (handle->type->sym_prefix) - lensym += strlen(handle->type->sym_prefix); + if (handle->loader->sym_prefix) + lensym += strlen(handle->loader->sym_prefix); if (handle->info.name) lensym += strlen(handle->info.name); if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH) @@ -1726,15 +1643,15 @@ lt_dlsym (handle, symbol) const char *saved_error = last_error; /* this is a libtool module */ - if (handle->type->sym_prefix) { - strcpy(sym, handle->type->sym_prefix); + if (handle->loader->sym_prefix) { + strcpy(sym, handle->loader->sym_prefix); strcat(sym, handle->info.name); } else strcpy(sym, handle->info.name); strcat(sym, "_LTX_"); strcat(sym, symbol); /* try "modulename_LTX_symbol" */ - address = handle->type->find_sym(handle->handle, sym); + address = handle->loader->find_sym(handle->module, sym); if (address) { if (sym != lsym) lt_dlfree(sym); @@ -1743,12 +1660,12 @@ lt_dlsym (handle, symbol) last_error = saved_error; } /* otherwise try "symbol" */ - if (handle->type->sym_prefix) { - strcpy(sym, handle->type->sym_prefix); + if (handle->loader->sym_prefix) { + strcpy(sym, handle->loader->sym_prefix); strcat(sym, symbol); } else strcpy(sym, symbol); - address = handle->type->find_sym(handle->handle, sym); + address = handle->loader->find_sym(handle->module, sym); if (sym != lsym) lt_dlfree(sym); return address; @@ -1838,6 +1755,138 @@ lt_dlforeach (func, data) return 0; } + +int +lt_add_dlloader (place, dlloader, loader_name) + lt_dlloader_t *place; + const struct lt_user_dlloader *dlloader; + const char *loader_name; +{ + lt_dlloader_t *node = 0, *ptr = 0; + + if ((dlloader == 0) /* diagnose null parameters */ + || (dlloader->module_open == 0) + || (dlloader->module_close == 0) + || (dlloader->find_sym == 0)) { + last_error = LT_DLSTRERROR(INVALID_LOADER); + return 1; + } + + /* Create a new dlloader node with copies of the user callbacks. */ + node = (lt_dlloader_t *) lt_dlmalloc (sizeof (lt_dlloader_t)); + if (node == 0) { + last_error = LT_DLSTRERROR(NO_MEMORY); + return 1; + } + node->next = 0; + node->loader_name = loader_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; + + if (!loaders) + /* If there are no loaders, NODE becomes the list! */ + loaders = node; + else if (!place) { + /* If PLACE is not set, 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*/; + + if (ptr->next != place) { + last_error = LT_DLSTRERROR(INVALID_LOADER); + return 1; + } + + /* Insert NODE between PTR and PLACE. */ + node->next = place; + ptr->next = node; + } + + return 0; +} + +int +lt_remove_dlloader (loader_name) + const char *loader_name; +{ + lt_dlloader_t *place = lt_find_dlloader (loader_name); + lt_dlhandle handle; + int result = 0; + + if (!place) { + last_error = LT_DLSTRERROR(INVALID_LOADER); + return 1; + } + + /* Fail if there are any open modules which use this loader. */ + for (handle = handles; handle; handle = handle->next) + if (handle->loader = place) { + last_error = LT_DLSTRERROR(REMOVE_LOADER); + return 1; + } + + if (place == loaders) + /* PLACE is the first loader in the list. */ + loaders = loaders->next; + else { + /* Find the loader before the one being removed. */ + lt_dlloader_t *prev; + for (prev = loaders; prev->next; prev = prev->next) + if (!strcmp (prev->next->loader_name, loader_name)) + break; + + place = prev->next; + prev->next = prev->next->next; + } + if (place->dlloader_exit) + result = place->dlloader_exit (); + lt_dlfree (place); + + return result; +} + +lt_dlloader_t * +lt_next_dlloader (place) + lt_dlloader_t *place; +{ + return place ? place->next : loaders; +} + +const char * +lt_dlloader_name (place) + lt_dlloader_t *place; +{ + if (!place) + last_error = LT_DLSTRERROR(INVALID_LOADER); + return place ? place->loader_name : 0; +} + +lt_dlloader_t * +lt_find_dlloader (loader_name) + const char *loader_name; +{ + lt_dlloader_t *place = 0; + + for (place = loaders; place; place = place->next) + if (strcmp (place->loader_name, loader_name) == 0) + break; + + return place; +} + + static const char **user_error_strings = 0; static int errorcode = LTDL_ERROR_MAX; @@ -1846,7 +1895,7 @@ lt_dladderror (diagnostic) const char *diagnostic; { int index = errorcode - LTDL_ERROR_MAX; - char **temp = 0; + const char **temp = 0; /* realloc is not entirely portable, so simulate it using lt_dlmalloc and lt_dlfree. */ diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h index 2e42c7f5a..605f72774 100644 --- a/libltdl/ltdl.h +++ b/libltdl/ltdl.h @@ -83,7 +83,6 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # endif #endif - #ifdef WIN32 # ifndef __CYGWIN__ /* LTDL_DIRSEP_CHAR is accepted *in addition* to '/' as a directory @@ -114,11 +113,17 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #include + +/* Defining error strings alongside their symbolic names in a macro in + this way allows us to expand the macro in different contexts with + confidence that the enumeration of symbolic names will map correctly + onto the table of error strings. */ #define ltdl_error_table \ LTDL_ERROR(UNKNOWN, "unknown error") \ LTDL_ERROR(DLOPEN_NOT_SUPPORTED, "dlopen support not available")\ - LTDL_ERROR(INVALID_TYPE, "invalid dltype") \ - LTDL_ERROR(INIT_TYPE, "dltype initialization failed") \ + LTDL_ERROR(INVALID_LOADER, "invalid loader") \ + LTDL_ERROR(INIT_LOADER, "loader initialization failed") \ + LTDL_ERROR(REMOVE_LOADER, "loader removal failed") \ LTDL_ERROR(FILE_NOT_FOUND, "file not found") \ LTDL_ERROR(DEPLIB_NOT_FOUND, "dependency library not found") \ LTDL_ERROR(NO_SYMBOLS, "no symbols defined") \ @@ -131,6 +136,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA LTDL_ERROR(INVALID_ERRORCODE, "invalid errorcode") \ LTDL_ERROR(SHUTDOWN, "library already shutdown") +/* Enumerate the symbolic error names. */ #ifdef __STDC__ # define LTDL_ERROR(name, diagnostic) LTDL_ERROR_##name, #else @@ -142,68 +148,97 @@ enum { }; #undef LTDL_ERROR + +/* An opaque handle for a successfully lt_dlopened module instance. */ #ifdef _LTDL_COMPILE_ typedef struct lt_dlhandle_t *lt_dlhandle; #else typedef lt_ptr_t lt_dlhandle; #endif -typedef lt_ptr_t lt_syshandle; - +/* A preopened symbol. Arrays of this type comprise the exported + symbols for a dlpreopened module. */ typedef struct { const char *name; lt_ptr_t address; } lt_dlsymlist; +/* Read only information pertaining to a loaded module. */ typedef struct { char *filename; /* file name */ char *name; /* module name */ - int ref_count; /* reference count */ + int ref_count; /* number of times lt_dlopened minus + number of times lt_dlclosed. */ } lt_dlinfo; -typedef int lt_mod_init_t LTDL_PARAMS((void)); -typedef int lt_mod_exit_t LTDL_PARAMS((void)); -typedef lt_syshandle lt_lib_open_t LTDL_PARAMS((const char *filename)); -typedef int lt_lib_close_t LTDL_PARAMS((lt_syshandle handle)); -typedef lt_ptr_t lt_find_sym_t LTDL_PARAMS((lt_syshandle handle, const char *symbol)); - -typedef struct lt_dltype_t { - struct lt_dltype_t *next; - const char *sym_prefix; /* prefix for symbols */ - lt_mod_init_t *mod_init; - lt_mod_exit_t *mod_exit; - lt_lib_open_t *lib_open; - lt_lib_close_t *lib_close; - lt_find_sym_t *find_sym; -} lt_dltype_t; +/* An opaque handle for a module loaded by a system call. This is only + used internally by ltdl loaders, and by user module loaders. */ +typedef lt_ptr_t lt_module_t; + +/* An opaque handle for a module loader. */ +#ifdef _LTDL_COMPILE_ +typedef struct lt_dlloader_t lt_dlloader_t; +#else +typedef lt_ptr_t lt_dlloader_t; +#endif + +/* Function pointer types for creating user defined module loaders. */ +typedef lt_module_t lt_module_open_t LTDL_PARAMS((const char *filename)); +typedef int lt_module_close_t LTDL_PARAMS((lt_module_t handle)); +typedef lt_ptr_t lt_find_sym_t LTDL_PARAMS((lt_module_t handle, const char *symbol)); +typedef int lt_dlloader_exit_t LTDL_PARAMS((void)); __BEGIN_DECLS +/* Initialisation and finalisation functions for libltdl. */ extern int lt_dlinit LTDL_PARAMS((void)); -extern int lt_dladdtype LTDL_PARAMS((lt_dltype_t *dltype)); -extern lt_dltype_t *lt_dlgettypes LTDL_PARAMS((void)); -extern int lt_dlsettypes LTDL_PARAMS((lt_dltype_t *dltypes)); -extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded)); -extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded)); extern int lt_dlexit LTDL_PARAMS((void)); + +/* Module search path manipultation. */ +extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir)); +extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path)); +extern const char *lt_dlgetsearchpath LTDL_PARAMS((void)); + +/* Portable libltdl versions of the system dlopen() API. */ extern lt_dlhandle lt_dlopen LTDL_PARAMS((const char *filename)); extern lt_dlhandle lt_dlopenext LTDL_PARAMS((const char *filename)); -extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle)); extern lt_ptr_t lt_dlsym LTDL_PARAMS((lt_dlhandle handle, const char *name)); extern const char *lt_dlerror LTDL_PARAMS((void)); -extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir)); -extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path)); -extern const char *lt_dlgetsearchpath LTDL_PARAMS((void)); -extern const lt_dlinfo *lt_dlgetinfo LTDL_PARAMS((lt_dlhandle handle)); -extern int lt_dlforeach LTDL_PARAMS(( - int (*func)(lt_dlhandle handle, lt_ptr_t data), lt_ptr_t data)); -extern int lt_dladderror LTDL_PARAMS((const char *diagnostic)); -extern int lt_dlseterror LTDL_PARAMS((int errorcode)); +extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle)); + +/* Support for preloaded modules through lt_dlopen() API. */ +extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded)); +extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded)); #define LTDL_SET_PRELOADED_SYMBOLS() LTDL_STMT_START{ \ extern const lt_dlsymlist lt_preloaded_symbols[]; \ lt_dlpreload_default(lt_preloaded_symbols); \ }LTDL_STMT_END +/* Managing user data associated with a loaded modules. */ +extern const lt_dlinfo *lt_dlgetinfo LTDL_PARAMS((lt_dlhandle handle)); +extern int lt_dlforeach LTDL_PARAMS(( + int (*func)(lt_dlhandle handle, lt_ptr_t data), lt_ptr_t data)); + + +/* User module loader API. */ +struct lt_user_dlloader { + const char *sym_prefix; + lt_module_open_t *module_open; + lt_module_close_t *module_close; + lt_find_sym_t *find_sym; + lt_dlloader_exit_t *dlloader_exit; +}; + +extern lt_dlloader_t *lt_next_dlloader LTDL_PARAMS((lt_dlloader_t *place)); +extern const char *lt_dlloader_name LTDL_PARAMS((lt_dlloader_t *place)); +extern lt_dlloader_t *lt_find_dlloader LTDL_PARAMS((const char *loader_name)); +extern int lt_add_dlloader LTDL_PARAMS((lt_dlloader_t *place, const struct lt_user_dlloader *dlloader, const char *loader_name)); + +/* Integrated lt_dlerror() messages for user loaders. */ +extern int lt_dladderror LTDL_PARAMS((const char *diagnostic)); +extern int lt_dlseterror LTDL_PARAMS((int errorcode)); + +/* Pointers to memory management functions to be used by libltdl. */ LTDL_SCOPE lt_ptr_t (*lt_dlmalloc)LTDL_PARAMS((size_t size)); LTDL_SCOPE void (*lt_dlfree)LTDL_PARAMS((lt_ptr_t ptr)); diff --git a/ltdl.m4 b/ltdl.m4 index f5590b061..d6b776a28 100644 --- a/ltdl.m4 +++ b/ltdl.m4 @@ -37,6 +37,7 @@ AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dlfcn.h dl.h dld.h) AC_CHECK_HEADERS(string.h strings.h, break) AC_CHECK_FUNCS(strchr index, break) AC_CHECK_FUNCS(strrchr rindex, break) +AC_CHECK_FUNCS(strcmp) AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl AC_REQUIRE([AC_LTDL_SHLIBEXT])dnl