summaryrefslogtreecommitdiff
path: root/libltdl/loaders
diff options
context:
space:
mode:
Diffstat (limited to 'libltdl/loaders')
-rw-r--r--libltdl/loaders/._dld_link.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/._dlopen.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/._dyld.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/._load_add_on.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/._loadlibrary.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/._preopen.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/._shl_load.cbin0 -> 239 bytes
-rw-r--r--libltdl/loaders/dld_link.c158
-rw-r--r--libltdl/loaders/dlopen.c275
-rw-r--r--libltdl/loaders/dyld.c511
-rw-r--r--libltdl/loaders/load_add_on.c167
-rw-r--r--libltdl/loaders/loadlibrary.c369
-rw-r--r--libltdl/loaders/preopen.c387
-rw-r--r--libltdl/loaders/shl_load.c222
14 files changed, 2089 insertions, 0 deletions
diff --git a/libltdl/loaders/._dld_link.c b/libltdl/loaders/._dld_link.c
new file mode 100644
index 0000000..dc37a7d
--- /dev/null
+++ b/libltdl/loaders/._dld_link.c
Binary files differ
diff --git a/libltdl/loaders/._dlopen.c b/libltdl/loaders/._dlopen.c
new file mode 100644
index 0000000..b6065a8
--- /dev/null
+++ b/libltdl/loaders/._dlopen.c
Binary files differ
diff --git a/libltdl/loaders/._dyld.c b/libltdl/loaders/._dyld.c
new file mode 100644
index 0000000..cb66abf
--- /dev/null
+++ b/libltdl/loaders/._dyld.c
Binary files differ
diff --git a/libltdl/loaders/._load_add_on.c b/libltdl/loaders/._load_add_on.c
new file mode 100644
index 0000000..56fa75a
--- /dev/null
+++ b/libltdl/loaders/._load_add_on.c
Binary files differ
diff --git a/libltdl/loaders/._loadlibrary.c b/libltdl/loaders/._loadlibrary.c
new file mode 100644
index 0000000..1f4d3e3
--- /dev/null
+++ b/libltdl/loaders/._loadlibrary.c
Binary files differ
diff --git a/libltdl/loaders/._preopen.c b/libltdl/loaders/._preopen.c
new file mode 100644
index 0000000..dde533b
--- /dev/null
+++ b/libltdl/loaders/._preopen.c
Binary files differ
diff --git a/libltdl/loaders/._shl_load.c b/libltdl/loaders/._shl_load.c
new file mode 100644
index 0000000..dacc74d
--- /dev/null
+++ b/libltdl/loaders/._shl_load.c
Binary files differ
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*) &lt__addimage);
+ (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
+ (unsigned long*)&lt__image_symbol);
+ (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
+ (unsigned long*) &lt__image_symbol_p);
+ (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic",
+ (unsigned long*) &lt__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;
+}