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