under dramatic changes...
This commit is contained in:
158
libltdl/loaders/dld_link.c
Normal file
158
libltdl/loaders/dld_link.c
Normal file
@ -0,0 +1,158 @@
|
||||
/* loader-dld_link.c -- dynamic linking with dld
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2006,
|
||||
2007, 2008 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 LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED loader_data, const char *filename,
|
||||
lt_dladvise LT__UNUSED advise)
|
||||
{
|
||||
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 LT__UNUSED loader_data, lt_module module)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (dld_unlink_by_file ((char*)(module), 1) != 0)
|
||||
{
|
||||
LT__SETERROR (CANNOT_CLOSE);
|
||||
++errors;
|
||||
}
|
||||
else
|
||||
{
|
||||
FREE (module);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/* A function called through the vtable to get the address of
|
||||
a symbol loaded from a particular module. */
|
||||
static void *
|
||||
vm_sym (lt_user_data LT__UNUSED loader_data, lt_module LT__UNUSED module,
|
||||
const char *name)
|
||||
{
|
||||
void *address = dld_get_func (name);
|
||||
|
||||
if (!address)
|
||||
{
|
||||
LT__SETERROR (SYMBOL_NOT_FOUND);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
235
libltdl/loaders/dlopen.c
Normal file
235
libltdl/loaders/dlopen.c
Normal file
@ -0,0 +1,235 @@
|
||||
/* loader-dlopen.c -- dynamic linking with dlopen/dlsym
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2006,
|
||||
2007, 2008 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 LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED loader_data, const char *filename,
|
||||
lt_dladvise advise)
|
||||
{
|
||||
int module_flags = LT_LAZY_OR_NOW;
|
||||
lt_module module;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
module = dlopen (filename, module_flags);
|
||||
|
||||
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 LT__UNUSED loader_data, 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 LT__UNUSED loader_data, lt_module module, const char *name)
|
||||
{
|
||||
void *address = dlsym (module, name);
|
||||
|
||||
if (!address)
|
||||
{
|
||||
DL__SETERROR (SYMBOL_NOT_FOUND);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
511
libltdl/loaders/dyld.c
Normal file
511
libltdl/loaders/dyld.c
Normal file
@ -0,0 +1,511 @@
|
||||
/* loader-dyld.c -- dynamic linking on darwin and OS X
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2006,
|
||||
2007, 2008 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 LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED advise)
|
||||
{
|
||||
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)
|
||||
{
|
||||
strncpy (saveError, dylderror (LT__STRERROR (SYMBOL_NOT_FOUND)), 255);
|
||||
saveError[255] = 0;
|
||||
if (!mh)
|
||||
{
|
||||
mh = (mach_header *)lt__nsmodule_get_header (module);
|
||||
}
|
||||
nssym = lt__linkedlib_symbol (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;
|
||||
}
|
167
libltdl/loaders/load_add_on.c
Normal file
167
libltdl/loaders/load_add_on.c
Normal file
@ -0,0 +1,167 @@
|
||||
/* loader-load_add_on.c -- dynamic linking for BeOS
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2006,
|
||||
2007, 2008 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 LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED loader_data, const char *filename,
|
||||
lt_dladvise LT__UNUSED advise)
|
||||
{
|
||||
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 LT__UNUSED loader_data, lt_module module)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (unload_add_on ((image_id) module) != B_OK)
|
||||
{
|
||||
LT__SETERROR (CANNOT_CLOSE);
|
||||
++errors;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
/* A function called through the vtable to get the address of
|
||||
a symbol loaded from a particular module. */
|
||||
static void *
|
||||
vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
|
||||
{
|
||||
void *address = 0;
|
||||
image_id image = (image_id) module;
|
||||
|
||||
if (get_image_symbol (image, name, B_SYMBOL_TYPE_ANY, address) != B_OK)
|
||||
{
|
||||
LT__SETERROR (SYMBOL_NOT_FOUND);
|
||||
address = 0;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
369
libltdl/loaders/loadlibrary.c
Normal file
369
libltdl/loaders/loadlibrary.c
Normal file
@ -0,0 +1,369 @@
|
||||
/* loader-loadlibrary.c -- dynamic linking for Win32
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
|
||||
2007, 2008, 2010 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 LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED loader_data, const char *filename,
|
||||
lt_dladvise LT__UNUSED advise)
|
||||
{
|
||||
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 LT__UNUSED loader_data, 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 LT__UNUSED loader_data, 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 which 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 which 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;
|
||||
}
|
375
libltdl/loaders/preopen.c
Normal file
375
libltdl/loaders/preopen.c
Normal file
@ -0,0 +1,375 @@
|
||||
/* loader-preopen.c -- emulate dynamic linking using preloaded_symbols
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2006,
|
||||
2007, 2008 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 LT__UNUSED loader_data)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
preloaded_symlists = 0;
|
||||
if (default_preloaded_symbols)
|
||||
{
|
||||
errors = lt_dlpreload (default_preloaded_symbols);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
/* A function called through the vtable when this loader is no
|
||||
longer needed by the application. */
|
||||
static int
|
||||
vl_exit (lt_user_data LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED loader_data, const char *filename,
|
||||
lt_dladvise LT__UNUSED advise)
|
||||
{
|
||||
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 LT__UNUSED loader_data, lt_module LT__UNUSED module)
|
||||
{
|
||||
/* Just to silence gcc -Wall */
|
||||
module = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* A function called through the vtable to get the address of
|
||||
a symbol loaded from a particular module. */
|
||||
static void *
|
||||
vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
|
||||
{
|
||||
lt_dlsymlist *symbol = (lt_dlsymlist*) module;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
222
libltdl/loaders/shl_load.c
Normal file
222
libltdl/loaders/shl_load.c
Normal file
@ -0,0 +1,222 @@
|
||||
/* loader-shl_load.c -- dynamic linking with shl_load (HP-UX)
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2004, 2006,
|
||||
2007, 2008 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 LT__UNUSED loader_data)
|
||||
{
|
||||
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 LT__UNUSED loader_data, const char *filename,
|
||||
lt_dladvise LT__UNUSED advise)
|
||||
{
|
||||
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 LT__UNUSED loader_data, 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 LT__UNUSED loader_data, 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;
|
||||
}
|
Reference in New Issue
Block a user