Shared LT DL library sources
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libltdl/ltdl.c

3433 lines
68 KiB

/* ltdl.c -- system independent dlopen wrapper
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
Originally by Thomas Tanner <tanner@ffii.org>
This file is part of GNU Libtool.
This library 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 it under the same
distribution terms that you use for the rest of that program.
This library 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 this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#if HAVE_STDIO_H
# include <stdio.h>
#endif
#if HAVE_STDLIB_H
# include <stdlib.h>
#endif
#if HAVE_STRING_H
# include <string.h>
#else
# if HAVE_STRINGS_H
# include <strings.h>
# endif
#endif
#if HAVE_CTYPE_H
# include <ctype.h>
#endif
#if HAVE_MALLOC_H
# include <malloc.h>
#endif
#if HAVE_MEMORY_H
# include <memory.h>
#endif
#ifdef _AIX
#include <errno.h>
#include <strings.h>
#include <sys/ldr.h>
#endif /* _AIX */
#include "ltdl.h"
/* Bah. We don't want inline. Needs autoconf check, which we don't want. */
#ifdef inline
# undef inline
#endif
#define inline
/* --- WINDOWS SUPPORT --- */
#ifdef DLL_EXPORT
# define LT_GLOBAL_DATA __declspec(dllexport)
#else
# define LT_GLOBAL_DATA
#endif
/* fopen() mode flags for reading a text file */
#undef LT_READTEXT_MODE
#ifdef __WINDOWS__
# define LT_READTEXT_MODE "rt"
#else
# define LT_READTEXT_MODE "r"
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
# include "ltdl_win.h"
#endif
/* --- MANIFEST CONSTANTS --- */
/* max. filename length */
#ifndef LT_FILENAME_MAX
# define LT_FILENAME_MAX 1024
#endif
/* This is the maximum symbol size that won't require malloc/free */
#undef LT_SYMBOL_LENGTH
#define LT_SYMBOL_LENGTH 128
/* This accounts for the _LTX_ separator */
#undef LT_SYMBOL_OVERHEAD
#define LT_SYMBOL_OVERHEAD 5
/* --- TYPE DEFINITIONS -- */
/* This type is used for the array of caller data sets in each handler. */
typedef struct {
lt_dlcaller_id key;
lt_ptr data;
} lt_caller_data;
/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
/* Extract the diagnostic strings from the error table macro in the same
order as the enumberated indices in ltdl.h. */
static const char *lt_dlerror_strings[] =
{
#define LT_ERROR(name, diagnostic) (diagnostic),
lt_dlerror_table
#undef LT_ERROR
0
};
/* This structure is used for the list of registered loaders. */
struct lt_dlloader {
struct lt_dlloader *next;
const char *loader_name; /* identifying name for each loader */
const char *sym_prefix; /* prefix for symbols */
lt_module_open *module_open;
lt_module_close *module_close;
lt_find_sym *find_sym;
lt_dlloader_exit *dlloader_exit;
lt_user_data dlloader_data;
};
struct lt_dlhandle_struct {
struct lt_dlhandle_struct *next;
lt_dlloader *loader; /* dlopening interface */
lt_dlinfo info;
int depcount; /* number of dependencies */
lt_dlhandle *deplibs; /* dependencies */
lt_module module; /* system module handle */
lt_ptr system; /* system specific data */
lt_caller_data *caller_data; /* per caller associated data */
int flags; /* various boolean stats */
};
/* Various boolean flags can be stored in the flags field of an
lt_dlhandle_struct... */
#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
#define LT_DLRESIDENT_FLAG (0x01 << 0)
#ifdef _AIX
#define LT_DLNOTFOUND_FLAG (0x01 << 1) /* may be linked statically */
#define LT_DLMEMBER_FLAG RTLD_MEMBER
#endif /* _AIX */
/* ...add more flags here... */
#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
static const char objdir[] = LTDL_OBJDIR;
#define LTDL_SHLIB_EXT ".so"
#ifdef LTDL_SHLIB_EXT
static const char shlib_ext[] = LTDL_SHLIB_EXT;
#endif
#ifdef LTDL_SYSSEARCHPATH
static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
#endif
/* --- MUTEX LOCKING --- */
/* Macros to make it easier to run the lock functions only if they have
been registered. The reason for the complicated lock macro is to
ensure that the stored error message from the last error is not
accidentally erased if the current function doesn't generate an
error of its own. */
#define MUTEX_LOCK() LT_STMT_START { \
if (mutex_lock) (*mutex_lock)(); } LT_STMT_END
#define MUTEX_UNLOCK() LT_STMT_START { \
if (mutex_unlock) (*mutex_unlock)(); } LT_STMT_END
#define MUTEX_SETERROR(errormsg) LT_STMT_START { \
if (mutex_seterror) (*mutex_seterror) (errormsg); \
else last_error = (errormsg); } LT_STMT_END
#define MUTEX_GETERROR(errormsg) LT_STMT_START { \
if (mutex_seterror) errormsg = (*mutex_geterror)(); \
else (errormsg) = last_error; } LT_STMT_END
/* The mutex functions stored here are global, and are necessarily the
same for all threads that wish to share access to libltdl. */
static lt_dlmutex_lock *mutex_lock = 0;
static lt_dlmutex_unlock *mutex_unlock = 0;
static lt_dlmutex_seterror *mutex_seterror = 0;
static lt_dlmutex_geterror *mutex_geterror = 0;
static const char *last_error = 0;
/* Either set or reset the mutex functions. Either all the arguments must
be valid functions, or else all can be NULL to turn off locking entirely.
The registered functions should be manipulating a static global lock
from the lock() and unlock() callbacks, which needs to be reentrant. */
int
lt_dlmutex_register (lock, unlock, seterror, geterror)
lt_dlmutex_lock *lock;
lt_dlmutex_unlock *unlock;
lt_dlmutex_seterror *seterror;
lt_dlmutex_geterror *geterror;
{
lt_dlmutex_unlock *old_unlock = unlock;
int errors = 0;
/* Lock using the old lock() callback, if any. */
MUTEX_LOCK ();
if ((lock && unlock && seterror && geterror)
|| !(lock || unlock || seterror || geterror))
{
mutex_lock = lock;
mutex_unlock = unlock;
mutex_geterror = geterror;
}
else
{
MUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
++errors;
}
/* Use the old unlock() callback we saved earlier, if any. Otherwise
record any errors using internal storage. */
if (old_unlock)
(*old_unlock) ();
/* Return the number of errors encountered during the execution of
this function. */
return errors;
}
/* --- MEMORY HANDLING --- */
LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
= (lt_ptr (*) LT_PARAMS((size_t))) malloc;
LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
= (void (*) LT_PARAMS((lt_ptr))) free;
static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr,
size_t size));
#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
#define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
#define LT_DLFREE(p) \
LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
if ((p) != (q)) { lt_dlfree (p); (p) = (q); } \
} LT_STMT_END
/* --- ERROR MESSAGES --- */
static const char **user_error_strings = 0;
static int errorcount = LT_ERROR_MAX;
int
lt_dladderror (diagnostic)
const char *diagnostic;
{
int _index = 0;
int result = -1;
const char **temp = (const char **) 0;
MUTEX_LOCK ();
_index = errorcount - LT_ERROR_MAX;
temp = LT_DLREALLOC (const char *, user_error_strings, 1 + _index);
if (temp == 0)
{
MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
}
else
{
user_error_strings = temp;
user_error_strings[_index] = diagnostic;
result = errorcount++;
}
MUTEX_UNLOCK ();
return result;
}
int
lt_dlseterror (_index)
int _index;
{
int errors = 0;
MUTEX_LOCK ();
if (_index >= errorcount || _index < 0)
{
/* Ack! Error setting the error message! */
MUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
++errors;
}
else if (_index < LT_ERROR_MAX)
{
/* No error setting the error message! */
MUTEX_SETERROR (lt_dlerror_strings[errorcount]);
}
else
{
/* No error setting the error message! */
MUTEX_SETERROR (user_error_strings[errorcount - LT_ERROR_MAX]);
}
MUTEX_UNLOCK ();
return errors;
}
/* --- REPLACEMENT FUNCTIONS --- */
#undef strdup
#define strdup rpl_strdup
static inline char *
strdup(str)
const char *str;
{
char *tmp = 0;
if (str)
{
tmp = LT_DLMALLOC (char, 1+ strlen (str));
if (tmp)
{
strcpy(tmp, str);
}
}
return tmp;
}
#if ! HAVE_STRCMP
#undef strcmp
#define strcmp rpl_strcmp
static inline int
strcmp (str1, str2)
const char *str1;
const char *str2;
{
if (str1 == str2)
return 0;
if (str1 == 0)
return -1;
if (str2 == 0)
return 1;
for (;*str1 && *str2; ++str1, ++str2)
{
if (*str1 != *str2)
break;
}
return (int)(*str1 - *str2);
}
#endif
#if ! HAVE_STRCHR
# if HAVE_INDEX
# define strchr index
# else
# define strchr rpl_strchr
static inline const char*
strchr(str, ch)
const char *str;
int ch;
{
const char *p;
for (p = str; *p != (char)ch && *p != '\0'; ++p)
/*NOWORK*/;
return (*p == (char)ch) ? p : 0;
}
# endif
#endif /* !HAVE_STRCHR */
#if ! HAVE_STRRCHR
# if HAVE_RINDEX
# define strrchr rindex
# else
# define strrchr rpl_strrchr
static inline const char*
strrchr(str, ch)
const char *str;
int ch;
{
const char *p, *q = 0;
for (p = str; *p != '\0'; ++p)
{
if (*p == (char) ch)
{
q = p;
}
}
return q;
}
# endif
#endif
/* NOTE: Neither bcopy nor the memcpy implementation below can
reliably handle copying in overlapping areas of memory, so
do not rely on this behavior when invoking memcpy later. */
#if ! HAVE_MEMCPY
# if HAVE_BCOPY
# define memcpy(dest, src, size) bcopy (src, dest, size)
# else
# define memcpy rpl_memcpy
static inline char *
memcpy (dest, src, size)
char *dest;
const char *src;
size_t size;
{
size_t i = 0;
for (i = 0; i < size; ++i)
{
dest[i] = src[i];
}
return dest;
}
# endif
#endif
/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
``realloc is not entirely portable''
In any case we want to use the allocator supplied by the user without
burdening them with an lt_dlrealloc function pointer to maintain.
Instead implement our own version (with known boundary conditions)
using lt_dlmalloc and lt_dlfree. */
static lt_ptr
rpl_realloc (ptr, size)
lt_ptr ptr;
size_t size;
{
if (size < 1)
{
/* For zero or less bytes, free the original memory */
if (ptr != 0)
{
lt_dlfree (ptr);
}
return (lt_ptr) 0;
}
else if (ptr == 0)
{
/* Allow reallocation of a NULL pointer. */
return lt_dlmalloc (size);
}
else
{
/* Allocate a new block, copy and free the old block. */
lt_ptr mem = (lt_ptr) realloc (ptr, size);
/* Note that the contents of PTR are not damaged if there is
insufficient memory to realloc. */
return mem;
}
}
/* --- DLOPEN() INTERFACE LOADER --- */
/* The Cygwin dlopen implementation prints a spurious error message to
stderr if its call to LoadLibrary() fails for any reason. We can
mitigate this by not using the Cygwin implementation, and falling
back to our own LoadLibrary() wrapper. */
#if HAVE_LIBDL && !defined(__CYGWIN__)
/* dynamic linking with dlopen/dlsym */
#if HAVE_DLFCN_H
# include <dlfcn.h>
#endif
#ifdef RTLD_GLOBAL
# define LT_GLOBAL RTLD_GLOBAL
#else
# ifdef DL_GLOBAL
# define LT_GLOBAL DL_GLOBAL
# endif
#endif /* !RTLD_GLOBAL */
#ifndef LT_GLOBAL
# define LT_GLOBAL 0
#endif /* !LT_GLOBAL */
/* We may have to define LT_LAZY_OR_NOW in the command line if we
find out it does not work in some platform. */
#ifndef LT_LAZY_OR_NOW
# ifdef RTLD_LAZY
# define LT_LAZY_OR_NOW RTLD_LAZY
# else
# ifdef DL_LAZY
# define LT_LAZY_OR_NOW DL_LAZY
# endif
# endif /* !RTLD_LAZY */
#endif
#ifndef LT_LAZY_OR_NOW
# ifdef RTLD_NOW
# define LT_LAZY_OR_NOW RTLD_NOW
# else
# ifdef DL_NOW
# define LT_LAZY_OR_NOW DL_NOW
# endif
# endif /* !RTLD_NOW */
#endif
#ifndef LT_LAZY_OR_NOW
# define LT_LAZY_OR_NOW 0
#endif /* !LT_LAZY_OR_NOW */
#if HAVE_DLERROR
# define DLERROR(arg) dlerror ()
#else
# define DLERROR(arg) LT_DLSTRERROR (arg)
#endif
int lt_dlopen_flag = LT_LAZY_OR_NOW;
#ifdef _AIX
/*------------------------------------------------------------------*/
/* implementations found at the end */
/*------------------------------------------------------------------*/
static void
sys_dl_init( );
static lt_dlhandle
sys_dl_search_by_name( const char* name );
static void
sys_dl_not_found_entry( const char* tmp );
#endif /* _AIX */
static lt_module
sys_dl_open (loader_data, filename)
lt_user_data loader_data;
const char *filename;
{
lt_module module;
#ifdef _AIX
/* If the basename is of the form "libname.a(member)",
set the appropriate flag. */
if (strrchr(filename, '('))
lt_dlopen_flag |= LT_DLMEMBER_FLAG;
#endif
module = dlopen (filename, lt_dlopen_flag);
if (!module)
{
char *error;
if ((error = dlerror()) != NULL) {
printf ("The Trinity ltdl loader was unable to dlopen() the shared library '%s' : '%s'\n\r", filename, error);
}
MUTEX_SETERROR (DLERROR (CANNOT_OPEN));
}
return module;
}
static int
sys_dl_close (loader_data, module)
lt_user_data loader_data;
lt_module module;
{
int errors = 0;
if (dlclose (module) != 0)
{
MUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
++errors;
}
return errors;
}
static lt_ptr
sys_dl_sym (loader_data, module, symbol)
lt_user_data loader_data;
lt_module module;
const char *symbol;
{
lt_ptr address = dlsym (module, symbol);
if (!address)
{
MUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
}
return address;
}
static struct lt_user_dlloader sys_dl =
{
# ifdef NEED_USCORE
"_",
# else
0,
# endif
sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
#else
int lt_dlopen_flag = 0;
#endif /* HAVE_LIBDL */
/* --- SHL_LOAD() INTERFACE LOADER --- */
#if HAVE_SHL_LOAD
/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
#ifdef 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.
*/
#ifndef DYNAMIC_PATH
# define DYNAMIC_PATH 0
#endif
#ifndef BIND_RESTRICTED
# define BIND_RESTRICTED 0
#endif
#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
static lt_module
sys_shl_open (loader_data, filename)
lt_user_data loader_data;
const char *filename;
{
/* A NULL handle is used to get symbols from self and everything
else already loaded that was exported with -E compiler flag. */
lt_module module = (lt_module) 0;
if (filename)
{
module = shl_load (filename, LT_BIND_FLAGS, 0L);
if (!module)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
}
}
return module;
}
static int
sys_shl_close (loader_data, module)
lt_user_data loader_data;
lt_module module;
{
int errors = 0;
if (module && (shl_unload ((shl_t) (module)) != 0))
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
++errors;
}
return errors;
}
static lt_ptr
sys_shl_sym (loader_data, module, symbol)
lt_user_data loader_data;
lt_module module;
const char *symbol;
{
int is_module_self = (module == (lt_module) 0);
lt_ptr address = 0;
/* shl_findsym considers zero valued MODULE as an indicator to search
for a symbol among all loaded (and exported) symbols including those
in the main executable. However, it sets MODULE to a valid module
address which breaks the semantics of libltdl's module management. */
if (shl_findsym ((shl_t*) &module, symbol, TYPE_UNDEFINED, &address) == 0)
{
if (!address)
{
MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
}
}
if (is_module_self)
module = (lt_module) 0;
return address;
}
static struct lt_user_dlloader sys_shl = {
0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
};
#endif /* HAVE_SHL_LOAD */
/* --- LOADLIBRARY() INTERFACE LOADER --- */
#if defined(__WINDOWS__) || defined(__CYGWIN__)
/* dynamic linking for Win32 */
#include <windows.h>
/* Forward declaration; required to implement handle search below. */
static lt_dlhandle handles;
static lt_module
sys_wll_open (loader_data, filename)
lt_user_data loader_data;
const char *filename;
{
lt_dlhandle cur;
lt_module module = 0;
const char *errormsg = 0;
char *searchname = 0;
char *ext;
char self_name_buf[MAX_PATH];
if (!filename)
{
/* Get the name of main module */
*self_name_buf = 0;
GetModuleFileName (NULL, (unsigned short*)self_name_buf, sizeof (self_name_buf));
filename = ext = self_name_buf;
}
else
{
ext = (char *)strrchr (filename, '.');
}
if (ext)
{
/* FILENAME already has an extension. */
searchname = strdup (filename);
}
else
{
/* Append a `.' to stop Windows from adding an
implicit `.dll' extension. */
searchname = LT_DLMALLOC (char, 2+ strlen (filename));
if (!searchname)
{
MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 0;
}
strcpy (searchname, filename);
strcat (searchname, ".");
}
#if __CYGWIN__
{
char wpath[MAX_PATH];
cygwin_conv_to_full_win32_path(searchname, wpath);
module = LoadLibrary(wpath);
}
#elif defined(_WIN32)
{
char wpath[MAX_PATH];
strncpy(wpath, searchname, MAX_PATH);
win32_backslashify( wpath );
win32_mapSo2Dll( wpath );
//fprintf (stderr, "LoadLibraryA(\"%s\")\n", wpath);
module = LoadLibraryA( wpath );
}
#else
module = LoadLibrary (searchname);
#endif
LT_DLFREE (searchname);
/* 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. */
MUTEX_LOCK ();
cur = handles;
while (cur)
{
if (!cur->module)
{
cur = 0;
break;
}
if (cur->module == module)
{
break;
}
cur = cur->next;
}
MUTEX_UNLOCK ();
if (cur || !module)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
module = 0;
}
return module;
}
static int
sys_wll_close (loader_data, module)
lt_user_data loader_data;
lt_module module;
{
int errors = 0;
if (FreeLibrary(module) == 0)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
++errors;
}
return errors;
}
static lt_ptr
sys_wll_sym (loader_data, module, symbol)
lt_user_data loader_data;
lt_module module;
const char *symbol;
{
lt_ptr address = GetProcAddress (module, symbol);
if (!address)
{
MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
}
return address;
}
static struct lt_user_dlloader sys_wll = {
0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
};
#endif /* __WINDOWS__ */
/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
#ifdef __BEOS__
/* dynamic linking for BeOS */
#include <kernel/image.h>
static lt_module
sys_bedl_open (loader_data, filename)
lt_user_data loader_data;
const char *filename;
{
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)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
image = 0;
}
return (lt_module) image;
}
static int
sys_bedl_close (loader_data, module)
lt_user_data loader_data;
lt_module module;
{
int errors = 0;
if (unload_add_on ((image_id) module) != B_OK)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
++errors;
}
return errors;
}
static lt_ptr
sys_bedl_sym (loader_data, module, symbol)
lt_user_data loader_data;
lt_module module;
const char *symbol;
{
lt_ptr address = 0;
image_id image = (image_id) module;
if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
{
MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
address = 0;
}
return address;
}
static struct lt_user_dlloader sys_bedl = {
0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
};
#endif /* __BEOS__ */
/* --- DLD_LINK() INTERFACE LOADER --- */
#if HAVE_DLD
/* dynamic linking with dld */
#if HAVE_DLD_H
#include <dld.h>
#endif
static lt_module
sys_dld_open (loader_data, filename)
lt_user_data loader_data;
const char *filename;
{
lt_module module = strdup (filename);
if (!module)
{
MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
module = 0;
}
else if (dld_link (filename) != 0)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
LT_DLFREE (module);
module = 0;
}
return module;
}
static int
sys_dld_close (loader_data, module)
lt_user_data loader_data;
lt_module module;
{
int errors = 0;
if (dld_unlink_by_file ((char*)(module), 1) != 0)
{
MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
++errors;
}
else
{
LT_DLFREE (module);
}
return errors;
}
static lt_ptr
sys_dld_sym (loader_data, module, symbol)
lt_user_data loader_data;
lt_module module;
const char *symbol;
{
lt_ptr address = dld_get_func (symbol);
if (!address)
{
MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
}
return address;
}
static struct lt_user_dlloader sys_dld = {
0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
};
#endif /* HAVE_DLD */
/* --- DLPREOPEN() INTERFACE LOADER --- */ </