diff options
Diffstat (limited to 'libltdl/loaders')
-rw-r--r-- | libltdl/loaders/._dld_link.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/._dlopen.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/._dyld.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/._load_add_on.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/._loadlibrary.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/._preopen.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/._shl_load.c | bin | 0 -> 239 bytes | |||
-rw-r--r-- | libltdl/loaders/dld_link.c | 158 | ||||
-rw-r--r-- | libltdl/loaders/dlopen.c | 275 | ||||
-rw-r--r-- | libltdl/loaders/dyld.c | 511 | ||||
-rw-r--r-- | libltdl/loaders/load_add_on.c | 167 | ||||
-rw-r--r-- | libltdl/loaders/loadlibrary.c | 369 | ||||
-rw-r--r-- | libltdl/loaders/preopen.c | 387 | ||||
-rw-r--r-- | libltdl/loaders/shl_load.c | 222 |
14 files changed, 2089 insertions, 0 deletions
diff --git a/libltdl/loaders/._dld_link.c b/libltdl/loaders/._dld_link.c Binary files differnew file mode 100644 index 0000000..dc37a7d --- /dev/null +++ b/libltdl/loaders/._dld_link.c diff --git a/libltdl/loaders/._dlopen.c b/libltdl/loaders/._dlopen.c Binary files differnew file mode 100644 index 0000000..b6065a8 --- /dev/null +++ b/libltdl/loaders/._dlopen.c diff --git a/libltdl/loaders/._dyld.c b/libltdl/loaders/._dyld.c Binary files differnew file mode 100644 index 0000000..cb66abf --- /dev/null +++ b/libltdl/loaders/._dyld.c diff --git a/libltdl/loaders/._load_add_on.c b/libltdl/loaders/._load_add_on.c Binary files differnew file mode 100644 index 0000000..56fa75a --- /dev/null +++ b/libltdl/loaders/._load_add_on.c diff --git a/libltdl/loaders/._loadlibrary.c b/libltdl/loaders/._loadlibrary.c Binary files differnew file mode 100644 index 0000000..1f4d3e3 --- /dev/null +++ b/libltdl/loaders/._loadlibrary.c diff --git a/libltdl/loaders/._preopen.c b/libltdl/loaders/._preopen.c Binary files differnew file mode 100644 index 0000000..dde533b --- /dev/null +++ b/libltdl/loaders/._preopen.c diff --git a/libltdl/loaders/._shl_load.c b/libltdl/loaders/._shl_load.c Binary files differnew file mode 100644 index 0000000..dacc74d --- /dev/null +++ b/libltdl/loaders/._shl_load.c diff --git a/libltdl/loaders/dld_link.c b/libltdl/loaders/dld_link.c new file mode 100644 index 0000000..a73880f --- /dev/null +++ b/libltdl/loaders/dld_link.c @@ -0,0 +1,158 @@ +/* loader-dld_link.c -- dynamic linking with dld + + Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software + Foundation, Inc. + Written by Thomas Tanner, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename, + lt_dladvise advise); +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); + +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (vtable && !vtable->name) + { + vtable->name = "lt_dld_link"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable && (vtable->dlloader_data != loader_data)) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#if defined HAVE_DLD_H +# include <dld.h> +#endif + +/* 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 LT__UNUSED) +{ + vtable = NULL; + 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 LT__UNUSED, const char *filename, + lt_dladvise advise LT__UNUSED) +{ + 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__UNUSED, 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__UNUSED, lt_module module LT__UNUSED, + const char *name) +{ + void *address = dld_get_func (name); + + if (!address) + { + LT__SETERROR (SYMBOL_NOT_FOUND); + } + + return address; +} diff --git a/libltdl/loaders/dlopen.c b/libltdl/loaders/dlopen.c new file mode 100644 index 0000000..0bc562c --- /dev/null +++ b/libltdl/loaders/dlopen.c @@ -0,0 +1,275 @@ +/* loader-dlopen.c -- dynamic linking with dlopen/dlsym + + Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software + Foundation, Inc. + Written by Thomas Tanner, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename, + lt_dladvise advise); +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); + +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable); + } + + if (vtable && !vtable->name) + { + vtable->name = "lt_dlopen"; +#if defined DLSYM_USCORE + vtable->sym_prefix = "_"; +#endif + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_PREPEND; + } + + if (vtable && (vtable->dlloader_data != loader_data)) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#if defined HAVE_DLFCN_H +# include <dlfcn.h> +#endif + +#if defined HAVE_SYS_DL_H +# include <sys/dl.h> +#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 +# if defined RTLD_LAZY +# define LT_LAZY_OR_NOW RTLD_LAZY +# else +# if defined DL_LAZY +# define LT_LAZY_OR_NOW DL_LAZY +# endif +# endif /* !RTLD_LAZY */ +#endif +#if !defined LT_LAZY_OR_NOW +# if defined RTLD_NOW +# define LT_LAZY_OR_NOW RTLD_NOW +# else +# if defined DL_NOW +# define LT_LAZY_OR_NOW DL_NOW +# endif +# endif /* !RTLD_NOW */ +#endif +#if !defined LT_LAZY_OR_NOW +# define LT_LAZY_OR_NOW 0 +#endif /* !LT_LAZY_OR_NOW */ + +/* We only support local and global symbols from modules for loaders + that provide such a thing, otherwise the system default is used. */ +#if !defined RTLD_GLOBAL +# if defined DL_GLOBAL +# define RTLD_GLOBAL DL_GLOBAL +# endif +#endif /* !RTLD_GLOBAL */ +#if !defined RTLD_LOCAL +# if defined DL_LOCAL +# define RTLD_LOCAL DL_LOCAL +# endif +#endif /* !RTLD_LOCAL */ + +#if defined HAVE_DLERROR +# define DLERROR(arg) dlerror () +#else +# define DLERROR(arg) LT__STRERROR (arg) +#endif + +#define DL__SETERROR(errorcode) \ + LT__SETERRORSTR (DLERROR (errorcode)) + + +/* 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 LT__UNUSED) +{ + vtable = NULL; + 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 LT__UNUSED, const char *filename, + lt_dladvise advise) +{ + int module_flags = LT_LAZY_OR_NOW; + lt_module module; +#ifdef RTLD_MEMBER + int len = LT_STRLEN (filename); +#endif + + if (advise) + { +#ifdef RTLD_GLOBAL + /* If there is some means of asking for global symbol resolution, + do so. */ + if (advise->is_symglobal) + module_flags |= RTLD_GLOBAL; +#else + /* Otherwise, reset that bit so the caller can tell it wasn't + acted on. */ + advise->is_symglobal = 0; +#endif + +/* And similarly for local only symbol resolution. */ +#ifdef RTLD_LOCAL + if (advise->is_symlocal) + module_flags |= RTLD_LOCAL; +#else + advise->is_symlocal = 0; +#endif + } + +#ifdef RTLD_MEMBER /* AIX */ + if (len >= 4) /* at least "l(m)" */ + { + /* Advise loading an archive member only if the filename really + contains both the opening and closing parent, and a member. */ + if (filename[len-1] == ')') + { + const char *opening = strrchr(filename, '('); + if (opening && opening < (filename+len-2) && strchr(opening+1, '/') == NULL) + module_flags |= RTLD_MEMBER; + } + } +#endif + + module = dlopen (filename, module_flags); + +#if defined RTLD_MEMBER && defined LT_SHARED_LIB_MEMBER + if (!module && len && !(module_flags & RTLD_MEMBER) && errno == ENOEXEC) + { + /* Loading without a member specified failed with "Exec format error". + So the file is there, but either has wrong bitwidth, or is an + archive eventually containing the default shared archive member. + Retry with default member, getting same error in worst case. */ + const char *member = LT_SHARED_LIB_MEMBER; + + char *attempt = MALLOC (char, len + strlen (member) + 1); + if (!attempt) + { + LT__SETERROR (NO_MEMORY); + return module; + } + + sprintf (attempt, "%s%s", filename, member); + module = vm_open (loader_data, attempt, advise); + FREE (attempt); + return module; + } +#endif + + if (!module) + { + DL__SETERROR (CANNOT_OPEN); + } + + 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__UNUSED, lt_module module) +{ + int errors = 0; + + if (dlclose (module) != 0) + { + DL__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__UNUSED, lt_module module, const char *name) +{ + void *address = dlsym (module, name); + + if (!address) + { + DL__SETERROR (SYMBOL_NOT_FOUND); + } + + return address; +} diff --git a/libltdl/loaders/dyld.c b/libltdl/loaders/dyld.c new file mode 100644 index 0000000..6c099e0 --- /dev/null +++ b/libltdl/loaders/dyld.c @@ -0,0 +1,511 @@ +/* loader-dyld.c -- dynamic linking on darwin and OS X + + Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software + Foundation, Inc. + Written by Peter O'Gorman, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* 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, + lt_dladvise advise); +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); + +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (vtable && !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_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable && (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__ + /* Is this correct? Does it still function properly? */ +# define __private_extern__ extern +# endif +# include <mach-o/dyld.h> +#endif + +#include <mach-o/getsect.h> + +/* We have to put some stuff here that isn't in older dyld.h files */ +#if !defined ENUM_DYLD_BOOL +# define ENUM_DYLD_BOOL +# undef FALSE +# undef TRUE + enum DYLD_BOOL { + FALSE, + TRUE + }; +#endif +#if !defined LC_REQ_DYLD +# define LC_REQ_DYLD 0x80000000 +#endif +#if !defined LC_LOAD_WEAK_DYLIB +# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) +#endif + +#if !defined NSADDIMAGE_OPTION_NONE +# define NSADDIMAGE_OPTION_NONE 0x0 +#endif +#if !defined NSADDIMAGE_OPTION_RETURN_ON_ERROR +# define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 +#endif +#if !defined NSADDIMAGE_OPTION_WITH_SEARCHING +# define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2 +#endif +#if !defined NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +# define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 +#endif +#if !defined NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME +# define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 +#endif + +#if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND +# define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 +#endif +#if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW +# define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1 +#endif +#if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY +# define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2 +#endif +#if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR +# define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 +#endif + +#define LT__SYMLOOKUP_OPTS (NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW \ + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) + +#if defined __BIG_ENDIAN__ +# define LT__MAGIC MH_MAGIC +#else +# define LT__MAGIC MH_CIGAM +#endif + +#define DYLD__SETMYERROR(errmsg) LT__SETERRORSTR (dylderror (errmsg)) +#define DYLD__SETERROR(errcode) DYLD__SETMYERROR (LT__STRERROR (errcode)) + +typedef struct mach_header mach_header; +typedef struct dylib_command dylib_command; + +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); + +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; + + +/* 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 LT__UNUSED) +{ + vtable = NULL; + return 0; +} + +/* A function called through the vtable to initialise this loader. */ +static int +vl_init (lt_user_data loader_data) +{ + int errors = 0; + + if (! dyld_cannot_close) + { + if (!_dyld_present ()) + { + ++errors; + } + else + { + (void) _dyld_func_lookup ("__dyld_NSAddImage", + (unsigned long*) <__addimage); + (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage", + (unsigned long*)<__image_symbol); + (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage", + (unsigned long*) <__image_symbol_p); + (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic", + (unsigned long*) <__module_export); + dyld_cannot_close = lt_dladderror ("can't close a dylib"); + } + } + + 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 +vm_open (lt_user_data loader_data, const char *filename, + lt_dladvise advise LT__UNUSED) +{ + lt_module module = 0; + NSObjectFileImage ofi = 0; + + if (!filename) + { + return (lt_module) -1; + } + + switch (NSCreateObjectFileImageFromFile (filename, &ofi)) + { + case NSObjectFileImageSuccess: + module = NSLinkModule (ofi, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR + | NSLINKMODULE_OPTION_PRIVATE + | NSLINKMODULE_OPTION_BINDNOW); + NSDestroyObjectFileImage (ofi); + + if (module) + { + lt__module_export (module); + } + break; + + case NSObjectFileImageInappropriateFile: + if (lt__image_symbol_p && lt__image_symbol) + { + module = (lt_module) lt__addimage(filename, + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + break; + + case NSObjectFileImageFailure: + case NSObjectFileImageArch: + case NSObjectFileImageFormat: + case NSObjectFileImageAccess: + /*NOWORK*/ + break; + } + + if (!module) + { + DYLD__SETERROR (CANNOT_OPEN); + } + + 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 (module != (lt_module) -1) + { + const mach_header *mh = (const mach_header *) module; + int flags = 0; + if (mh->magic == LT__MAGIC) + { + lt_dlseterror (dyld_cannot_close); + ++errors; + } + else + { + /* Currently, if a module contains c++ static destructors and it + is unloaded, we get a segfault in atexit(), due to compiler and + dynamic loader differences of opinion, this works around that. */ + if ((const struct section *) NULL != + getsectbynamefromheader (lt__nsmodule_get_header (module), + "__DATA", "__mod_term_func")) + { + flags |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; + } +#if defined __ppc__ + flags |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; +#endif + if (!NSUnLinkModule (module, flags)) + { + DYLD__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) +{ + NSSymbol *nssym = 0; + const mach_header *mh = (const mach_header *) module; + char saveError[256] = "Symbol not found"; + + if (module == (lt_module) -1) + { + void *address, *unused; + _dyld_lookup_and_bind (name, (unsigned long*) &address, &unused); + return address; + } + + if (mh->magic == LT__MAGIC) + { + if (lt__image_symbol_p && lt__image_symbol) + { + if (lt__image_symbol_p (mh, name)) + { + nssym = lt__image_symbol (mh, name, LT__SYMLOOKUP_OPTS); + } + } + + } + else + { + nssym = NSLookupSymbolInModule (module, name); + } + + if (!nssym) + { + strlcpy (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 (name, mh); + } + + if (!nssym) + { + LT__SETERRORSTR (saveError); + } + + return nssym ? NSAddressOfSymbol (nssym) : 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 (strneq (_dyld_get_image_name (i), modname)) + { + 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 && strneq (id, name)) + { + 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 0000000..b070906 --- /dev/null +++ b/libltdl/loaders/load_add_on.c @@ -0,0 +1,167 @@ +/* loader-load_add_on.c -- dynamic linking for BeOS + + Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software + Foundation, Inc. + Written by Thomas Tanner, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename, + lt_dladvise advise); +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); + +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (vtable && !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_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable && (vtable->dlloader_data != loader_data)) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#include <kernel/image.h> + +/* 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 LT__UNUSED) +{ + vtable = NULL; + 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 LT__UNUSED, const char *filename, + lt_dladvise advise LT__UNUSED) +{ + 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__UNUSED, 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__UNUSED, 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/loaders/loadlibrary.c b/libltdl/loaders/loadlibrary.c new file mode 100644 index 0000000..0891f6d --- /dev/null +++ b/libltdl/loaders/loadlibrary.c @@ -0,0 +1,369 @@ +/* loader-loadlibrary.c -- dynamic linking for Win32 + + Copyright (C) 1998-2000, 2004-2008, 2010-2015 Free Software + Foundation, Inc. + Written by Thomas Tanner, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "lt__private.h" +#include "lt_dlloader.h" + +#if defined __CYGWIN__ +# include <sys/cygwin.h> +#endif + +/* Use the preprocessor to rename non-static symbols to avoid namespace + collisions when the loader code is statically linked into libltdl. + Use the "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename, + lt_dladvise advise); +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); + +static lt_dlinterface_id iface_id = 0; +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable); + iface_id = lt_dlinterface_register ("ltdl loadlibrary", NULL); + } + + if (vtable && !vtable->name) + { + vtable->name = "lt_loadlibrary"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable && (vtable->dlloader_data != loader_data)) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#include <windows.h> + +#define LOCALFREE(mem) LT_STMT_START { \ + if (mem) { LocalFree ((void *)mem); mem = NULL; } } LT_STMT_END +#define LOADLIB__SETERROR(errmsg) LT__SETERRORSTR (loadlibraryerror (errmsg)) +#define LOADLIB_SETERROR(errcode) LOADLIB__SETERROR (LT__STRERROR (errcode)) + +static const char *loadlibraryerror (const char *default_errmsg); +static DWORD WINAPI wrap_getthreaderrormode (void); +static DWORD WINAPI fallback_getthreaderrormode (void); +static BOOL WINAPI wrap_setthreaderrormode (DWORD mode, DWORD *oldmode); +static BOOL WINAPI fallback_setthreaderrormode (DWORD mode, DWORD *oldmode); + +typedef DWORD (WINAPI getthreaderrormode_type) (void); +typedef BOOL (WINAPI setthreaderrormode_type) (DWORD, DWORD *); + +static getthreaderrormode_type *getthreaderrormode = wrap_getthreaderrormode; +static setthreaderrormode_type *setthreaderrormode = wrap_setthreaderrormode; +static char *error_message = 0; + + +/* 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 LT__UNUSED) +{ + vtable = NULL; + LOCALFREE (error_message); + 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 LT__UNUSED, const char *filename, + lt_dladvise advise LT__UNUSED) +{ + lt_module module = 0; + char *ext; + char wpath[MAX_PATH]; + size_t len; + + if (!filename) + { + /* Get the name of main module */ + *wpath = 0; + GetModuleFileName (NULL, wpath, sizeof (wpath)); + filename = wpath; + } + else + { + len = LT_STRLEN (filename); + + if (len >= MAX_PATH) + { + LT__SETERROR (CANNOT_OPEN); + return 0; + } + +#if HAVE_DECL_CYGWIN_CONV_PATH + if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, filename, wpath, MAX_PATH)) + { + LT__SETERROR (CANNOT_OPEN); + return 0; + } + len = 0; +#elif defined __CYGWIN__ + cygwin_conv_to_full_win32_path (filename, wpath); + len = 0; +#else + strcpy(wpath, filename); +#endif + + ext = strrchr (wpath, '.'); + if (!ext) + { + /* Append a '.' to stop Windows from adding an + implicit '.dll' extension. */ + if (!len) + len = strlen (wpath); + + if (len + 1 >= MAX_PATH) + { + LT__SETERROR (CANNOT_OPEN); + return 0; + } + + wpath[len] = '.'; + wpath[len+1] = '\0'; + } + } + + { + /* Silence dialog from LoadLibrary on some failures. */ + DWORD errormode = getthreaderrormode (); + DWORD last_error; + + setthreaderrormode (errormode | SEM_FAILCRITICALERRORS, NULL); + + module = LoadLibrary (wpath); + + /* Restore the error mode. */ + last_error = GetLastError (); + setthreaderrormode (errormode, NULL); + SetLastError (last_error); + } + + /* libltdl expects this function to fail if it is unable + to physically load the library. Sadly, LoadLibrary + will search the loaded libraries for a match and return + one of them if the path search load fails. + + We check whether LoadLibrary is returning a handle to + an already loaded module, and simulate failure if we + find one. */ + { + lt_dlhandle cur = 0; + + while ((cur = lt_dlhandle_iterate (iface_id, cur))) + { + if (!cur->module) + { + cur = 0; + break; + } + + if (cur->module == module) + { + break; + } + } + + if (!module) + LOADLIB_SETERROR (CANNOT_OPEN); + else if (cur) + { + LT__SETERROR (CANNOT_OPEN); + module = 0; + } + } + + 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__UNUSED, lt_module module) +{ + int errors = 0; + + if (FreeLibrary ((HMODULE) module) == 0) + { + LOADLIB_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__UNUSED, lt_module module, const char *name) +{ + void *address = (void *) GetProcAddress ((HMODULE) module, name); + + if (!address) + { + LOADLIB_SETERROR (SYMBOL_NOT_FOUND); + } + + return address; +} + + + +/* --- HELPER FUNCTIONS --- */ + + +/* Return the windows error message, or the passed in error message on + failure. */ +static const char * +loadlibraryerror (const char *default_errmsg) +{ + size_t len; + LOCALFREE (error_message); + + FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError (), + 0, + (char *) &error_message, + 0, NULL); + + /* Remove trailing CRNL */ + len = LT_STRLEN (error_message); + if (len && error_message[len - 1] == '\n') + error_message[--len] = LT_EOS_CHAR; + if (len && error_message[len - 1] == '\r') + error_message[--len] = LT_EOS_CHAR; + + return len ? error_message : default_errmsg; +} + +/* A function called through the getthreaderrormode variable that checks + if the system supports GetThreadErrorMode (or GetErrorMode) and arranges + for it or a fallback implementation to be called directly in the future. + The selected version is then called. */ +static DWORD WINAPI +wrap_getthreaderrormode (void) +{ + HMODULE kernel32 = GetModuleHandleA ("kernel32.dll"); + getthreaderrormode + = (getthreaderrormode_type *) GetProcAddress (kernel32, + "GetThreadErrorMode"); + if (!getthreaderrormode) + getthreaderrormode + = (getthreaderrormode_type *) GetProcAddress (kernel32, + "GetErrorMode"); + if (!getthreaderrormode) + getthreaderrormode = fallback_getthreaderrormode; + return getthreaderrormode (); +} + +/* A function called through the getthreaderrormode variable for cases + where the system does not support GetThreadErrorMode or GetErrorMode */ +static DWORD WINAPI +fallback_getthreaderrormode (void) +{ + /* Prior to Windows Vista, the only way to get the current error + mode was to set a new one. In our case, we are setting a new + error mode right after "getting" it while ignoring the error + mode in effect when setting the new error mode, so that's + fairly ok. */ + return (DWORD) SetErrorMode (SEM_FAILCRITICALERRORS); +} + +/* A function called through the setthreaderrormode variable that checks + if the system supports SetThreadErrorMode and arranges for it or a + fallback implementation to be called directly in the future. + The selected version is then called. */ +static BOOL WINAPI +wrap_setthreaderrormode (DWORD mode, DWORD *oldmode) +{ + HMODULE kernel32 = GetModuleHandleA ("kernel32.dll"); + setthreaderrormode + = (setthreaderrormode_type *) GetProcAddress (kernel32, + "SetThreadErrorMode"); + if (!setthreaderrormode) + setthreaderrormode = fallback_setthreaderrormode; + return setthreaderrormode (mode, oldmode); +} + +/* A function called through the setthreaderrormode variable for cases + where the system does not support SetThreadErrorMode. */ +static BOOL WINAPI +fallback_setthreaderrormode (DWORD mode, DWORD *oldmode) +{ + /* Prior to Windows 7, there was no way to set the thread local error + mode, so set the process global error mode instead. */ + DWORD old = (DWORD) SetErrorMode (mode); + if (oldmode) + *oldmode = old; + return TRUE; +} diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c new file mode 100644 index 0000000..139e373 --- /dev/null +++ b/libltdl/loaders/preopen.c @@ -0,0 +1,387 @@ +/* loader-preopen.c -- emulate dynamic linking using preloaded_symbols + + Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software + Foundation, Inc. + Written by Thomas Tanner, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* 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, + lt_dladvise advise); +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); + +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable); + } + + if (vtable && !vtable->name) + { + vtable->name = "lt_preopen"; + vtable->sym_prefix = 0; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_init = vl_init; + vtable->dlloader_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_PREPEND; + } + + if (vtable && (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 LT__UNUSED) +{ + 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 LT__UNUSED) +{ + vtable = NULL; + 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 LT__UNUSED, const char *filename, + lt_dladvise advise LT__UNUSED) +{ + 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_dlsymlist *symbol; + for (symbol= lists->symlist; symbol->name; ++symbol) + { + if (!symbol->address && STREQ (symbol->name, filename)) + { + /* If the next symbol's name and address is 0, it means + the module just contains the originator and no symbols. + In this case we pretend that we never saw the module and + hope that some other loader will be able to load the module + and have access to its symbols */ + const lt_dlsymlist *next_symbol = symbol +1; + if (next_symbol->address && next_symbol->name) + { + 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__UNUSED, lt_module module LT__UNUSED) +{ + /* 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__UNUSED, lt_module module, const char *name) +{ + lt_dlsymlist *symbol = (lt_dlsymlist*) module; + + if (symbol[1].name && STREQ (symbol[1].name, "@INIT@")) + { + symbol++; /* Skip optional init entry. */ + } + + symbol +=2; /* Skip header (originator then libname). */ + + while (symbol->name) + { + if (STREQ (symbol->name, name)) + { + 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 = (symlist_chain *) lt__zalloc (sizeof *tmp); + + if (tmp) + { + tmp->symlist = symlist; + tmp->next = preloaded_symlists; + preloaded_symlists = tmp; + + if (symlist[1].name && STREQ (symlist[1].name, "@INIT@")) + { + void (*init_symlist)(void); + *(void **)(&init_symlist) = symlist[1].address; + (*init_symlist)(); + } + } + 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. If ORIGINATOR is NULL, then call FUNC for + each preloaded module from the program itself. */ +int +lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func) +{ + 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 ((originator && STREQ (list->symlist->name, originator)) + || (!originator && STREQ (list->symlist->name, "@PROGRAM@"))) + { + const lt_dlsymlist *symbol; + unsigned int idx = 0; + + ++found; + + /* ...load the symbols per source compilation unit: + (we preincrement the index to skip over the originator entry) */ + while ((symbol = &list->symlist[++idx])->name != 0) + { + if ((symbol->address == 0) + && (STRNEQ (symbol->name, "@PROGRAM@"))) + { + 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/loaders/shl_load.c b/libltdl/loaders/shl_load.c new file mode 100644 index 0000000..960386b --- /dev/null +++ b/libltdl/loaders/shl_load.c @@ -0,0 +1,222 @@ +/* loader-shl_load.c -- dynamic linking with shl_load (HP-UX) + + Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2015 Free Software + Foundation, Inc. + Written by Thomas Tanner, 1998 + + NOTE: The canonical source of this file is maintained with the + GNU Libtool package. Report bugs to bug-libtool@gnu.org. + +GNU Libltdl 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 this file under the +same distribution terms that you use for the rest of that program. + +GNU Libltdl 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 GNU Libltdl; see the file COPYING.LIB. If not, a +copy can be downloaded from http://www.gnu.org/licenses/lgpl.html, +or obtained by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "<module_name>_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 + +LT_BEGIN_C_DECLS +LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data); +LT_END_C_DECLS + + +/* Boilerplate code to set up the vtable for hooking this loader into + libltdl's loader list: */ +static int vl_exit (lt_user_data loader_data); +static lt_module vm_open (lt_user_data loader_data, const char *filename, + lt_dladvise advise); +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); + +static lt_dlvtable *vtable = 0; + +/* Return the vtable for this loader, only the name and sym_prefix + attributes (plus the virtual function implementations, obviously) + change between loaders. */ +lt_dlvtable * +get_vtable (lt_user_data loader_data) +{ + if (!vtable) + { + vtable = lt__zalloc (sizeof *vtable); + } + + if (vtable && !vtable->name) + { + vtable->name = "lt_shl_load"; + vtable->module_open = vm_open; + vtable->module_close = vm_close; + vtable->find_sym = vm_sym; + vtable->dlloader_exit = vl_exit; + vtable->dlloader_data = loader_data; + vtable->priority = LT_DLLOADER_APPEND; + } + + if (vtable && (vtable->dlloader_data != loader_data)) + { + LT__SETERROR (INIT_LOADER); + return 0; + } + + return vtable; +} + + + +/* --- IMPLEMENTATION --- */ + + +#if defined HAVE_DL_H +# include <dl.h> +#endif + +/* some flags are missing on some systems, so we provide + * harmless defaults. + * + * Mandatory: + * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. + * BIND_DEFERRED - Delay code symbol resolution until actual reference. + * + * Optionally: + * BIND_FIRST - Place the library at the head of the symbol search + * order. + * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all + * unsatisfied symbols as fatal. This flag allows + * binding of unsatisfied code symbols to be deferred + * until use. + * [Perl: For certain libraries, like DCE, deferred + * binding often causes run time problems. Adding + * BIND_NONFATAL to BIND_IMMEDIATE still allows + * unresolved references in situations like this.] + * BIND_NOSTART - Do not call the initializer for the shared library + * when the library is loaded, nor on a future call to + * shl_unload(). + * BIND_VERBOSE - Print verbose messages concerning possible + * unsatisfied symbols. + * + * hp9000s700/hp9000s800: + * BIND_RESTRICTED - Restrict symbols visible by the library to those + * present at library load time. + * DYNAMIC_PATH - Allow the loader to dynamically search for the + * library specified by the path argument. + */ + +#if !defined DYNAMIC_PATH +# define DYNAMIC_PATH 0 +#endif +#if !defined BIND_RESTRICTED +# define BIND_RESTRICTED 0 +#endif + +#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) + + +/* 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 LT__UNUSED) +{ + vtable = NULL; + 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 LT__UNUSED, const char *filename, + lt_dladvise advise LT__UNUSED) +{ + static shl_t self = (shl_t) 0; + lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); + + /* Since searching for a symbol against a NULL module handle will also + look in everything else that was already loaded and exported with + the -E compiler flag, we always cache a handle saved before any + modules are loaded. */ + if (!self) + { + void *address; + shl_findsym (&self, "main", TYPE_UNDEFINED, &address); + } + + if (!filename) + { + module = self; + } + else + { + module = shl_load (filename, LT_BIND_FLAGS, 0L); + + if (!module) + { + LT__SETERROR (CANNOT_OPEN); + } + } + + 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__UNUSED, lt_module module) +{ + int errors = 0; + + if (module && (shl_unload ((shl_t) (module)) != 0)) + { + 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__UNUSED, lt_module module, const char *name) +{ + void *address = 0; + + /* sys_shl_open should never return a NULL module handle */ + if (module == (lt_module) 0) + { + LT__SETERROR (INVALID_HANDLE); + } + else if (!shl_findsym((shl_t*) &module, name, TYPE_UNDEFINED, &address)) + { + if (!address) + { + LT__SETERROR (SYMBOL_NOT_FOUND); + } + } + + return address; +} |