1
/* ltdl.c -- system independent dlopen wrapper
2
Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3
Originally by Thomas Tanner <tanner@ffii.org>
4
This file is part of GNU Libtool.
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
11
As a special exception to the GNU Lesser General Public License,
12
if you distribute this file as part of a program or library that
13
is built using GNU libtool, you may include it under the same
14
distribution terms that you use for the rest of that program.
16
This library is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
Lesser General Public License for more details.
21
You should have received a copy of the GNU Lesser General Public
22
License along with this library; if not, write to the Free Software
23
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40
/* Include the header defining malloc. On K&R C compilers,
41
that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */
78
#undef LT_USE_POSIX_DIRENT
83
# define LT_USE_POSIX_DIRENT
84
# endif /* HAVE_DIRENT_H */
85
# endif /* HAVE_READDIR */
86
# endif /* HAVE_OPENDIR */
87
#endif /* HAVE_CLOSEDIR */
90
#undef LT_USE_WINDOWS_DIRENT_EMULATION
91
#ifndef LT_USE_POSIX_DIRENT
93
# define LT_USE_WINDOWS_DIRENT_EMULATION
94
# endif /* __WINDOWS__ */
95
#endif /* LT_USE_POSIX_DIRENT */
98
#ifdef LT_USE_POSIX_DIRENT
100
# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
102
# ifdef LT_USE_WINDOWS_DIRENT_EMULATION
103
# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
105
# define dirent direct
106
# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
108
# include <sys/ndir.h>
111
# include <sys/dir.h>
126
# define assert(arg) ((void) 0)
132
# include <dmalloc.h>
138
/* --- WINDOWS SUPPORT --- */
140
/* DLL building support on win32 hosts; mostly to workaround their
141
ridiculous implementation of data symbol exporting. */
142
#ifndef LT_GLOBAL_DATA
143
# if defined(__WINDOWS__) || defined(__CYGWIN__)
144
# ifdef DLL_EXPORT /* defined by libtool (if required) */
145
# define LT_GLOBAL_DATA __declspec(dllexport)
148
# ifndef LT_GLOBAL_DATA /* static linking or !__WINDOWS__ */
149
# define LT_GLOBAL_DATA
153
/* fopen() mode flags for reading a text file */
154
#undef LT_READTEXT_MODE
155
#if defined(__WINDOWS__) || defined(__CYGWIN__)
156
# define LT_READTEXT_MODE "rt"
158
# define LT_READTEXT_MODE "r"
161
#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
165
#define dirent lt_dirent
177
WIN32_FIND_DATA Win32FindData;
179
struct dirent file_info;
182
#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
185
/* --- MANIFEST CONSTANTS --- */
188
/* Standard libltdl search path environment variable name */
189
#undef LTDL_SEARCHPATH_VAR
190
#define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
192
/* Standard libtool archive file extension. */
193
#undef LTDL_ARCHIVE_EXT
194
#define LTDL_ARCHIVE_EXT ".la"
196
/* max. filename length */
197
#ifndef LT_FILENAME_MAX
198
# define LT_FILENAME_MAX 1024
201
/* This is the maximum symbol size that won't require malloc/free */
202
#undef LT_SYMBOL_LENGTH
203
#define LT_SYMBOL_LENGTH 128
205
/* This accounts for the _LTX_ separator */
206
#undef LT_SYMBOL_OVERHEAD
207
#define LT_SYMBOL_OVERHEAD 5
212
/* --- MEMORY HANDLING --- */
215
/* These are the functions used internally. In addition to making
216
use of the associated function pointers above, they also perform
218
static char *lt_estrdup LT_PARAMS((const char *str));
219
static lt_ptr lt_emalloc LT_PARAMS((size_t size));
220
static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
222
/* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
223
#define rpl_realloc realloc
225
/* These are the pointers that can be changed by the caller: */
226
LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
227
= (lt_ptr (*) LT_PARAMS((size_t))) malloc;
228
LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
229
= (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
230
LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
231
= (void (*) LT_PARAMS((lt_ptr))) free;
233
/* The following macros reduce the amount of typing needed to cast
237
#define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
238
#define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
239
#define LT_DLFREE(p) \
240
LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
242
#define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
243
#define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
247
#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
248
#define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
249
#define LT_DLFREE(p) \
250
LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
252
#define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
253
#define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
257
#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
258
if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
262
/* --- REPLACEMENT FUNCTIONS --- */
266
#define strdup rpl_strdup
268
static char *strdup LT_PARAMS((const char *str));
278
tmp = LT_DLMALLOC (char, 1+ strlen (str));
292
#define strcmp rpl_strcmp
294
static int strcmp LT_PARAMS((const char *str1, const char *str2));
308
for (;*str1 && *str2; ++str1, ++str2)
314
return (int)(*str1 - *str2);
322
# define strchr index
324
# define strchr rpl_strchr
326
static const char *strchr LT_PARAMS((const char *str, int ch));
335
for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
338
return (*p == (char)ch) ? p : 0;
342
#endif /* !HAVE_STRCHR */
348
# define strrchr rindex
350
# define strrchr rpl_strrchr
352
static const char *strrchr LT_PARAMS((const char *str, int ch));
359
const char *p, *q = 0;
361
for (p = str; *p != LT_EOS_CHAR; ++p)
375
/* NOTE: Neither bcopy nor the memcpy implementation below can
376
reliably handle copying in overlapping areas of memory. Use
377
memmove (for which there is a fallback implmentation below)
378
if you need that behaviour. */
382
# define memcpy(dest, src, size) bcopy (src, dest, size)
384
# define memcpy rpl_memcpy
386
static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
389
memcpy (dest, src, size)
394
const char * s = src;
398
for (i = 0; i < size; ++i)
406
# endif /* !HAVE_BCOPY */
407
#endif /* !HAVE_MEMCPY */
410
# define memmove rpl_memmove
412
static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
415
memmove (dest, src, size)
420
const char * s = src;
425
for (i = 0; i < size; ++i)
429
else if (d > s && size > 0)
430
for (i = size -1; ; --i)
440
#endif /* !HAVE_MEMMOVE */
442
#ifdef LT_USE_WINDOWS_DIRENT_EMULATION
444
static void closedir LT_PARAMS((DIR *entry));
450
assert(entry != (DIR *) NULL);
451
FindClose(entry->hSearch);
452
lt_dlfree((lt_ptr)entry);
456
static DIR * opendir LT_PARAMS((const char *path));
462
char file_specification[LT_FILENAME_MAX];
465
assert(path != (char *) NULL);
466
/* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
467
(void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
468
file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
469
(void) strcat(file_specification,"\\");
470
entry = LT_DLMALLOC (DIR,sizeof(DIR));
471
if (entry != (DIR *) 0)
473
entry->firsttime = TRUE;
474
entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
476
if (entry->hSearch == INVALID_HANDLE_VALUE)
478
(void) strcat(file_specification,"\\*.*");
479
entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
480
if (entry->hSearch == INVALID_HANDLE_VALUE)
490
static struct dirent *readdir LT_PARAMS((DIR *entry));
492
static struct dirent *readdir(entry)
498
if (entry == (DIR *) 0)
499
return((struct dirent *) 0);
500
if (!entry->firsttime)
502
status = FindNextFile(entry->hSearch,&entry->Win32FindData);
504
return((struct dirent *) 0);
506
entry->firsttime = FALSE;
507
(void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
509
entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
510
entry->file_info.d_namlen = strlen(entry->file_info.d_name);
511
return(&entry->file_info);
514
#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
516
/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
517
``realloc is not entirely portable''
518
In any case we want to use the allocator supplied by the user without
519
burdening them with an lt_dlrealloc function pointer to maintain.
520
Instead implement our own version (with known boundary conditions)
521
using lt_dlmalloc and lt_dlfree. */
524
#define realloc rpl_realloc
527
/* You can't (re)define realloc unless you also (re)define malloc.
528
Right now, this code uses the size of the *destination* to decide
529
how much to copy. That's not right, but you can't know the size
530
of the source unless you know enough about, or wrote malloc. So
531
this code is disabled... */
540
/* For zero or less bytes, free the original memory */
550
/* Allow reallocation of a NULL pointer. */
551
return lt_dlmalloc (size);
555
/* Allocate a new block, copy and free the old block. */
556
lt_ptr mem = lt_dlmalloc (size);
560
memcpy (mem, ptr, size);
564
/* Note that the contents of PTR are not damaged if there is
565
insufficient memory to realloc. */
572
#if ! HAVE_ARGZ_APPEND
573
# define argz_append rpl_argz_append
575
static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
576
const char *buf, size_t buf_len));
579
argz_append (pargz, pargz_len, buf, buf_len)
590
assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
592
/* If nothing needs to be appended, no more work is required. */
596
/* Ensure there is enough room to append BUF_LEN. */
597
argz_len = *pargz_len + buf_len;
598
argz = LT_DLREALLOC (char, *pargz, argz_len);
602
/* Copy characters from BUF after terminating '\0' in ARGZ. */
603
memcpy (argz + *pargz_len, buf, buf_len);
605
/* Assign new values. */
607
*pargz_len = argz_len;
611
#endif /* !HAVE_ARGZ_APPEND */
614
#if ! HAVE_ARGZ_CREATE_SEP
615
# define argz_create_sep rpl_argz_create_sep
617
static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
618
char **pargz, size_t *pargz_len));
621
argz_create_sep (str, delim, pargz, pargz_len)
634
/* Make a copy of STR, but replacing each occurrence of
636
argz_len = 1+ LT_STRLEN (str);
642
argz = LT_DLMALLOC (char, argz_len);
646
for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
650
/* Ignore leading delimiters, and fold consecutive
651
delimiters in STR into a single '\0' in ARGZ. */
652
if ((q > argz) && (q[-1] != LT_EOS_CHAR))
660
/* Copy terminating LT_EOS_CHAR. */
664
/* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
668
/* Assign new values. */
670
*pargz_len = argz_len;
674
#endif /* !HAVE_ARGZ_CREATE_SEP */
677
#if ! HAVE_ARGZ_INSERT
678
# define argz_insert rpl_argz_insert
680
static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
681
char *before, const char *entry));
684
argz_insert (pargz, pargz_len, before, entry)
692
assert (entry && *entry);
694
/* No BEFORE address indicates ENTRY should be inserted after the
695
current last element. */
697
return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
699
/* This probably indicates a programmer error, but to preserve
700
semantics, scan back to the start of an entry if BEFORE points
701
into the middle of it. */
702
while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
706
size_t entry_len = 1+ LT_STRLEN (entry);
707
size_t argz_len = *pargz_len + entry_len;
708
size_t offset = before - *pargz;
709
char *argz = LT_DLREALLOC (char, *pargz, argz_len);
714
/* Make BEFORE point to the equivalent offset in ARGZ that it
715
used to have in *PARGZ incase realloc() moved the block. */
716
before = argz + offset;
718
/* Move the ARGZ entries starting at BEFORE up into the new
719
space at the end -- making room to copy ENTRY into the
721
memmove (before + entry_len, before, *pargz_len - offset);
722
memcpy (before, entry, entry_len);
724
/* Assign new values. */
726
*pargz_len = argz_len;
731
#endif /* !HAVE_ARGZ_INSERT */
735
# define argz_next rpl_argz_next
737
static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
741
argz_next (argz, argz_len, entry)
746
assert ((argz && argz_len) || (!argz && !argz_len));
750
/* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
751
within the ARGZ vector. */
752
assert ((!argz && !argz_len)
753
|| ((argz <= entry) && (entry < (argz + argz_len))));
755
/* Move to the char immediately after the terminating
757
entry = 1+ strchr (entry, LT_EOS_CHAR);
759
/* Return either the new ENTRY, or else NULL if ARGZ is
761
return (entry >= argz + argz_len) ? 0 : (char *) entry;
765
/* This should probably be flagged as a programmer error,
766
since starting an argz_next loop with the iterator set
767
to ARGZ is safer. To preserve semantics, handle the NULL
768
case by returning the start of ARGZ (if any). */
775
#endif /* !HAVE_ARGZ_NEXT */
779
#if ! HAVE_ARGZ_STRINGIFY
780
# define argz_stringify rpl_argz_stringify
782
static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
786
argz_stringify (argz, argz_len, sep)
791
assert ((argz && argz_len) || (!argz && !argz_len));
795
--argz_len; /* don't stringify the terminating EOS */
796
while (--argz_len > 0)
798
if (argz[argz_len] == LT_EOS_CHAR)
799
argz[argz_len] = sep;
803
#endif /* !HAVE_ARGZ_STRINGIFY */
808
/* --- TYPE DEFINITIONS -- */
811
/* This type is used for the array of caller data sets in each handler. */
820
/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
823
/* Extract the diagnostic strings from the error table macro in the same
824
order as the enumerated indices in ltdl.h. */
826
static const char *lt_dlerror_strings[] =
828
#define LT_ERROR(name, diagnostic) (diagnostic),
835
/* This structure is used for the list of registered loaders. */
837
struct lt_dlloader *next;
838
const char *loader_name; /* identifying name for each loader */
839
const char *sym_prefix; /* prefix for symbols */
840
lt_module_open *module_open;
841
lt_module_close *module_close;
842
lt_find_sym *find_sym;
843
lt_dlloader_exit *dlloader_exit;
844
lt_user_data dlloader_data;
847
struct lt_dlhandle_struct {
848
struct lt_dlhandle_struct *next;
849
lt_dlloader *loader; /* dlopening interface */
851
int depcount; /* number of dependencies */
852
lt_dlhandle *deplibs; /* dependencies */
853
lt_module module; /* system module handle */
854
lt_ptr system; /* system specific data */
855
lt_caller_data *caller_data; /* per caller associated data */
856
int flags; /* various boolean stats */
859
/* Various boolean flags can be stored in the flags field of an
860
lt_dlhandle_struct... */
861
#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
862
#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
864
#define LT_DLRESIDENT_FLAG (0x01 << 0)
865
/* ...add more flags here... */
867
#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
870
#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
872
static const char objdir[] = LTDL_OBJDIR;
873
static const char archive_ext[] = LTDL_ARCHIVE_EXT;
874
#ifdef LTDL_SHLIB_EXT
875
static const char shlib_ext[] = LTDL_SHLIB_EXT;
877
#ifdef LTDL_SYSSEARCHPATH
878
static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
884
/* --- MUTEX LOCKING --- */
887
/* Macros to make it easier to run the lock functions only if they have
888
been registered. The reason for the complicated lock macro is to
889
ensure that the stored error message from the last error is not
890
accidentally erased if the current function doesn't generate an
892
#define LT_DLMUTEX_LOCK() LT_STMT_START { \
893
if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
895
#define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
896
if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
898
#define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
899
if (lt_dlmutex_seterror_func) \
900
(*lt_dlmutex_seterror_func) (errormsg); \
901
else lt_dllast_error = (errormsg); } LT_STMT_END
902
#define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
903
if (lt_dlmutex_geterror_func) \
904
(errormsg) = (*lt_dlmutex_geterror_func) (); \
905
else (errormsg) = lt_dllast_error; } LT_STMT_END
907
/* The mutex functions stored here are global, and are necessarily the
908
same for all threads that wish to share access to libltdl. */
909
static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
910
static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
911
static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
912
static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
913
static const char *lt_dllast_error = 0;
916
/* Either set or reset the mutex functions. Either all the arguments must
917
be valid functions, or else all can be NULL to turn off locking entirely.
918
The registered functions should be manipulating a static global lock
919
from the lock() and unlock() callbacks, which needs to be reentrant. */
921
lt_dlmutex_register (lock, unlock, seterror, geterror)
922
lt_dlmutex_lock *lock;
923
lt_dlmutex_unlock *unlock;
924
lt_dlmutex_seterror *seterror;
925
lt_dlmutex_geterror *geterror;
927
lt_dlmutex_unlock *old_unlock = lt_dlmutex_unlock_func;
930
/* Lock using the old lock() callback, if any. */
933
if ((lock && unlock && seterror && geterror)
934
|| !(lock || unlock || seterror || geterror))
936
lt_dlmutex_lock_func = lock;
937
lt_dlmutex_unlock_func = unlock;
938
lt_dlmutex_seterror_func = seterror;
939
lt_dlmutex_geterror_func = geterror;
943
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
947
/* Use the old unlock() callback we saved earlier, if any. Otherwise
948
record any errors using internal storage. */
952
/* Return the number of errors encountered during the execution of
960
/* --- ERROR HANDLING --- */
963
static const char **user_error_strings = 0;
964
static int errorcount = LT_ERROR_MAX;
967
lt_dladderror (diagnostic)
968
const char *diagnostic;
972
const char **temp = (const char **) 0;
978
errindex = errorcount - LT_ERROR_MAX;
979
temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
982
user_error_strings = temp;
983
user_error_strings[errindex] = diagnostic;
984
result = errorcount++;
987
LT_DLMUTEX_UNLOCK ();
993
lt_dlseterror (errindex)
1000
if (errindex >= errorcount || errindex < 0)
1002
/* Ack! Error setting the error message! */
1003
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
1006
else if (errindex < LT_ERROR_MAX)
1008
/* No error setting the error message! */
1009
LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
1013
/* No error setting the error message! */
1014
LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
1017
LT_DLMUTEX_UNLOCK ();
1026
lt_ptr mem = lt_dlmalloc (size);
1028
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1033
lt_erealloc (addr, size)
1037
lt_ptr mem = lt_dlrealloc (addr, size);
1039
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1047
char *copy = strdup (str);
1048
if (LT_STRLEN (str) && !copy)
1049
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1056
/* --- DLOPEN() INTERFACE LOADER --- */
1061
/* dynamic linking with dlopen/dlsym */
1068
# include <sys/dl.h>
1072
# define LT_GLOBAL RTLD_GLOBAL
1075
# define LT_GLOBAL DL_GLOBAL
1077
#endif /* !RTLD_GLOBAL */
1079
# define LT_GLOBAL 0
1080
#endif /* !LT_GLOBAL */
1082
/* We may have to define LT_LAZY_OR_NOW in the command line if we
1083
find out it does not work in some platform. */
1084
#ifndef LT_LAZY_OR_NOW
1086
# define LT_LAZY_OR_NOW RTLD_LAZY
1089
# define LT_LAZY_OR_NOW DL_LAZY
1091
# endif /* !RTLD_LAZY */
1093
#ifndef LT_LAZY_OR_NOW
1095
# define LT_LAZY_OR_NOW RTLD_NOW
1098
# define LT_LAZY_OR_NOW DL_NOW
1100
# endif /* !RTLD_NOW */
1102
#ifndef LT_LAZY_OR_NOW
1103
# define LT_LAZY_OR_NOW 0
1104
#endif /* !LT_LAZY_OR_NOW */
1107
# define DLERROR(arg) dlerror ()
1109
# define DLERROR(arg) LT_DLSTRERROR (arg)
1113
sys_dl_open (loader_data, filename)
1114
lt_user_data loader_data;
1115
const char *filename;
1117
lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1121
LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1128
sys_dl_close (loader_data, module)
1129
lt_user_data loader_data;
1134
if (dlclose (module) != 0)
1136
LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1144
sys_dl_sym (loader_data, module, symbol)
1145
lt_user_data loader_data;
1149
lt_ptr address = dlsym (module, symbol);
1153
LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1159
static struct lt_user_dlloader sys_dl =
1166
sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1169
#endif /* HAVE_LIBDL */
1173
/* --- SHL_LOAD() INTERFACE LOADER --- */
1177
/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1183
/* some flags are missing on some systems, so we provide
1184
* harmless defaults.
1187
* BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1188
* BIND_DEFERRED - Delay code symbol resolution until actual reference.
1191
* BIND_FIRST - Place the library at the head of the symbol search
1193
* BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1194
* unsatisfied symbols as fatal. This flag allows
1195
* binding of unsatisfied code symbols to be deferred
1197
* [Perl: For certain libraries, like DCE, deferred
1198
* binding often causes run time problems. Adding
1199
* BIND_NONFATAL to BIND_IMMEDIATE still allows
1200
* unresolved references in situations like this.]
1201
* BIND_NOSTART - Do not call the initializer for the shared library
1202
* when the library is loaded, nor on a future call to
1204
* BIND_VERBOSE - Print verbose messages concerning possible
1205
* unsatisfied symbols.
1207
* hp9000s700/hp9000s800:
1208
* BIND_RESTRICTED - Restrict symbols visible by the library to those
1209
* present at library load time.
1210
* DYNAMIC_PATH - Allow the loader to dynamically search for the
1211
* library specified by the path argument.
1214
#ifndef DYNAMIC_PATH
1215
# define DYNAMIC_PATH 0
1217
#ifndef BIND_RESTRICTED
1218
# define BIND_RESTRICTED 0
1221
#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1224
sys_shl_open (loader_data, filename)
1225
lt_user_data loader_data;
1226
const char *filename;
1228
static shl_t self = (shl_t) 0;
1229
lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1231
/* Since searching for a symbol against a NULL module handle will also
1232
look in everything else that was already loaded and exported with
1233
the -E compiler flag, we always cache a handle saved before any
1234
modules are loaded. */
1238
shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1247
module = shl_load (filename, LT_BIND_FLAGS, 0L);
1251
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1259
sys_shl_close (loader_data, module)
1260
lt_user_data loader_data;
1265
if (module && (shl_unload ((shl_t) (module)) != 0))
1267
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1275
sys_shl_sym (loader_data, module, symbol)
1276
lt_user_data loader_data;
1282
/* sys_shl_open should never return a NULL module handle */
1283
if (module == (lt_module) 0)
1285
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1287
else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1291
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1298
static struct lt_user_dlloader sys_shl = {
1299
0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1302
#endif /* HAVE_SHL_LOAD */
1307
/* --- LOADLIBRARY() INTERFACE LOADER --- */
1311
/* dynamic linking for Win32 */
1313
#include <windows.h>
1315
/* Forward declaration; required to implement handle search below. */
1316
static lt_dlhandle handles;
1319
sys_wll_open (loader_data, filename)
1320
lt_user_data loader_data;
1321
const char *filename;
1324
lt_module module = 0;
1325
const char *errormsg = 0;
1326
char *searchname = 0;
1328
char self_name_buf[MAX_PATH];
1332
/* Get the name of main module */
1334
GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1335
filename = ext = self_name_buf;
1339
ext = strrchr (filename, '.');
1344
/* FILENAME already has an extension. */
1345
searchname = lt_estrdup (filename);
1349
/* Append a `.' to stop Windows from adding an
1350
implicit `.dll' extension. */
1351
searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1353
sprintf (searchname, "%s.", filename);
1359
/* Silence dialog from LoadLibrary on some failures.
1360
No way to get the error mode, but to set it,
1361
so set it twice to preserve any previous flags. */
1362
UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
1363
SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
1365
#if defined(__CYGWIN__)
1367
char wpath[MAX_PATH];
1368
cygwin_conv_to_full_win32_path (searchname, wpath);
1369
module = LoadLibrary (wpath);
1372
module = LoadLibrary (searchname);
1375
/* Restore the error mode. */
1376
SetErrorMode(errormode);
1379
LT_DLFREE (searchname);
1381
/* libltdl expects this function to fail if it is unable
1382
to physically load the library. Sadly, LoadLibrary
1383
will search the loaded libraries for a match and return
1384
one of them if the path search load fails.
1386
We check whether LoadLibrary is returning a handle to
1387
an already loaded module, and simulate failure if we
1399
if (cur->module == module)
1406
LT_DLMUTEX_UNLOCK ();
1410
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1418
sys_wll_close (loader_data, module)
1419
lt_user_data loader_data;
1424
if (FreeLibrary(module) == 0)
1426
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1434
sys_wll_sym (loader_data, module, symbol)
1435
lt_user_data loader_data;
1439
lt_ptr address = GetProcAddress (module, symbol);
1443
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1449
static struct lt_user_dlloader sys_wll = {
1450
0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1453
#endif /* __WINDOWS__ */
1458
/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1463
/* dynamic linking for BeOS */
1465
#include <kernel/image.h>
1468
sys_bedl_open (loader_data, filename)
1469
lt_user_data loader_data;
1470
const char *filename;
1476
image = load_add_on (filename);
1482
if (get_next_image_info (0, &cookie, &info) == B_OK)
1483
image = load_add_on (info.name);
1488
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1492
return (lt_module) image;
1496
sys_bedl_close (loader_data, module)
1497
lt_user_data loader_data;
1502
if (unload_add_on ((image_id) module) != B_OK)
1504
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1512
sys_bedl_sym (loader_data, module, symbol)
1513
lt_user_data loader_data;
1518
image_id image = (image_id) module;
1520
if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1522
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1529
static struct lt_user_dlloader sys_bedl = {
1530
0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1533
#endif /* __BEOS__ */
1538
/* --- DLD_LINK() INTERFACE LOADER --- */
1543
/* dynamic linking with dld */
1550
sys_dld_open (loader_data, filename)
1551
lt_user_data loader_data;
1552
const char *filename;
1554
lt_module module = strdup (filename);
1556
if (dld_link (filename) != 0)
1558
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1567
sys_dld_close (loader_data, module)
1568
lt_user_data loader_data;
1573
if (dld_unlink_by_file ((char*)(module), 1) != 0)
1575
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1587
sys_dld_sym (loader_data, module, symbol)
1588
lt_user_data loader_data;
1592
lt_ptr address = dld_get_func (symbol);
1596
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1602
static struct lt_user_dlloader sys_dld = {
1603
0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1606
#endif /* HAVE_DLD */
1608
/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1612
#if HAVE_MACH_O_DYLD_H
1613
#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1614
/* Is this correct? Does it still function properly? */
1615
#define __private_extern__ extern
1617
# include <mach-o/dyld.h>
1619
#include <mach-o/getsect.h>
1621
/* We have to put some stuff here that isn't in older dyld.h files */
1622
#ifndef ENUM_DYLD_BOOL
1623
# define ENUM_DYLD_BOOL
1632
# define LC_REQ_DYLD 0x80000000
1634
#ifndef LC_LOAD_WEAK_DYLIB
1635
# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1637
static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1638
static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1639
static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1640
static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1642
#ifndef NSADDIMAGE_OPTION_NONE
1643
#define NSADDIMAGE_OPTION_NONE 0x0
1645
#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1646
#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1648
#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1649
#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1651
#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1652
#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1654
#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1655
#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1657
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1658
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1660
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1661
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1663
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1664
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1666
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1667
#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1672
lt_int_dyld_error(othererror)
1675
/* return the dyld error string, or the passed in error string if none */
1676
NSLinkEditErrors ler;
1680
NSLinkEditError(&ler,&lerno,&file,&errstr);
1681
if (!errstr || !strlen(errstr)) errstr = othererror;
1685
static const struct mach_header *
1686
lt_int_dyld_get_mach_header_from_nsmodule(module)
1689
/* There should probably be an apple dyld api for this */
1690
int i=_dyld_image_count();
1692
const char *modname=NSNameOfModule(module);
1693
const struct mach_header *mh=NULL;
1694
if (!modname) return NULL;
1695
for (j = 0; j < i; j++)
1697
if (!strcmp(_dyld_get_image_name(j),modname))
1699
mh=_dyld_get_image_header(j);
1706
static const char* lt_int_dyld_lib_install_name(mh)
1707
const struct mach_header *mh;
1709
/* NSAddImage is also used to get the loaded image, but it only works if the lib
1710
is installed, for uninstalled libs we need to check the install_names against
1711
each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1712
different lib was loaded as a result
1715
struct load_command *lc;
1716
unsigned long offset = sizeof(struct mach_header);
1717
const char* retStr=NULL;
1718
for (j = 0; j < mh->ncmds; j++)
1720
lc = (struct load_command*)(((unsigned long)mh) + offset);
1721
if (LC_ID_DYLIB == lc->cmd)
1723
retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1726
offset += lc->cmdsize;
1731
static const struct mach_header *
1732
lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1734
int i=_dyld_image_count();
1736
const struct mach_header *mh=NULL;
1737
const char *id=NULL;
1738
for (j = 0; j < i; j++)
1740
id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1741
if ((id) && (!strcmp(id,name)))
1743
mh=_dyld_get_image_header(j);
1751
lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1753
const struct mach_header *mh;
1755
/* Safe to assume our mh is good */
1757
struct load_command *lc;
1758
unsigned long offset = sizeof(struct mach_header);
1759
NSSymbol retSym = 0;
1760
const struct mach_header *mh1;
1761
if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1763
for (j = 0; j < mh->ncmds; j++)
1765
lc = (struct load_command*)(((unsigned long)mh) + offset);
1766
if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1768
mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1769
(unsigned long)lc));
1772
/* Maybe NSAddImage can find it */
1773
mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1775
NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1776
NSADDIMAGE_OPTION_WITH_SEARCHING +
1777
NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1781
retSym = ltdl_NSLookupSymbolInImage(mh1,
1783
NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1784
| NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1789
offset += lc->cmdsize;
1800
if (!_dyld_present()) {
1804
err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage);
1805
err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage);
1806
err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage);
1807
err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic);
1813
sys_dyld_open (loader_data, filename)
1814
lt_user_data loader_data;
1815
const char *filename;
1817
lt_module module = 0;
1818
NSObjectFileImage ofi = 0;
1819
NSObjectFileImageReturnCode ofirc;
1822
return (lt_module)-1;
1823
ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1826
case NSObjectFileImageSuccess:
1827
module = NSLinkModule(ofi, filename,
1828
NSLINKMODULE_OPTION_RETURN_ON_ERROR
1829
| NSLINKMODULE_OPTION_PRIVATE
1830
| NSLINKMODULE_OPTION_BINDNOW);
1831
NSDestroyObjectFileImage(ofi);
1833
ltdl_NSMakePrivateModulePublic(module);
1835
case NSObjectFileImageInappropriateFile:
1836
if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1838
module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1842
LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1845
if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1850
sys_dyld_close (loader_data, module)
1851
lt_user_data loader_data;
1856
if (module == (lt_module)-1) return 0;
1857
#ifdef __BIG_ENDIAN__
1858
if (((struct mach_header *)module)->magic == MH_MAGIC)
1860
if (((struct mach_header *)module)->magic == MH_CIGAM)
1863
LT_DLMUTEX_SETERROR("Can not close a dylib");
1869
/* Currently, if a module contains c++ static destructors and it is unloaded, we
1870
get a segfault in atexit(), due to compiler and dynamic loader differences of
1871
opinion, this works around that.
1873
if ((const struct section *)NULL !=
1874
getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1875
"__DATA","__mod_term_func"))
1877
flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1881
flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1883
if (!NSUnLinkModule(module,flags))
1886
LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1894
sys_dyld_sym (loader_data, module, symbol)
1895
lt_user_data loader_data;
1900
NSSymbol *nssym = 0;
1902
const struct mach_header *mh=NULL;
1903
char saveError[256] = "Symbol not found";
1904
if (module == (lt_module)-1)
1906
_dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1909
#ifdef __BIG_ENDIAN__
1910
if (((struct mach_header *)module)->magic == MH_MAGIC)
1912
if (((struct mach_header *)module)->magic == MH_CIGAM)
1915
if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1918
if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1920
nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1922
NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1923
| NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1930
nssym = NSLookupSymbolInModule(module, symbol);
1934
strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1936
if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1937
nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1941
LT_DLMUTEX_SETERROR (saveError);
1944
return NSAddressOfSymbol(nssym);
1947
static struct lt_user_dlloader sys_dyld =
1948
{ "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1951
#endif /* HAVE_DYLD */
1954
/* --- DLPREOPEN() INTERFACE LOADER --- */
1957
/* emulate dynamic linking using preloaded_symbols */
1959
typedef struct lt_dlsymlists_t
1961
struct lt_dlsymlists_t *next;
1962
const lt_dlsymlist *syms;
1965
static const lt_dlsymlist *default_preloaded_symbols = 0;
1966
static lt_dlsymlists_t *preloaded_symbols = 0;
1969
presym_init (loader_data)
1970
lt_user_data loader_data;
1976
preloaded_symbols = 0;
1977
if (default_preloaded_symbols)
1979
errors = lt_dlpreload (default_preloaded_symbols);
1982
LT_DLMUTEX_UNLOCK ();
1988
presym_free_symlists ()
1990
lt_dlsymlists_t *lists;
1994
lists = preloaded_symbols;
1997
lt_dlsymlists_t *tmp = lists;
1999
lists = lists->next;
2002
preloaded_symbols = 0;
2004
LT_DLMUTEX_UNLOCK ();
2010
presym_exit (loader_data)
2011
lt_user_data loader_data;
2013
presym_free_symlists ();
2018
presym_add_symlist (preloaded)
2019
const lt_dlsymlist *preloaded;
2021
lt_dlsymlists_t *tmp;
2022
lt_dlsymlists_t *lists;
2027
lists = preloaded_symbols;
2030
if (lists->syms == preloaded)
2034
lists = lists->next;
2037
tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2040
memset (tmp, 0, sizeof(lt_dlsymlists_t));
2041
tmp->syms = preloaded;
2042
tmp->next = preloaded_symbols;
2043
preloaded_symbols = tmp;
2051
LT_DLMUTEX_UNLOCK ();
2056
presym_open (loader_data, filename)
2057
lt_user_data loader_data;
2058
const char *filename;
2060
lt_dlsymlists_t *lists;
2061
lt_module module = (lt_module) 0;
2064
lists = preloaded_symbols;
2068
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2072
/* Can't use NULL as the reflective symbol header, as NULL is
2073
used to mark the end of the entire symbol list. Self-dlpreopened
2074
symbols follow this magic number, chosen to be an unlikely
2075
clash with a real module name. */
2078
filename = "@PROGRAM@";
2083
const lt_dlsymlist *syms = lists->syms;
2087
if (!syms->address && strcmp(syms->name, filename) == 0)
2089
module = (lt_module) syms;
2095
lists = lists->next;
2098
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2101
LT_DLMUTEX_UNLOCK ();
2106
presym_close (loader_data, module)
2107
lt_user_data loader_data;
2110
/* Just to silence gcc -Wall */
2116
presym_sym (loader_data, module, symbol)
2117
lt_user_data loader_data;
2121
lt_dlsymlist *syms = (lt_dlsymlist*) module;
2124
while (syms->address)
2126
if (strcmp(syms->name, symbol) == 0)
2128
return syms->address;
2134
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2139
static struct lt_user_dlloader presym = {
2140
0, presym_open, presym_close, presym_sym, presym_exit, 0
2147
/* --- DYNAMIC MODULE LOADING --- */
2150
/* The type of a function used at each iteration of foreach_dirinpath(). */
2151
typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2153
/* foreachfile_callback itself calls a function of this type: */
2154
typedef int file_worker_func LT_PARAMS((const char *filename, void *data));
2156
static int foreach_dirinpath LT_PARAMS((const char *search_path,
2157
const char *base_name,
2158
foreach_callback_func *func,
2159
lt_ptr data1, lt_ptr data2));
2161
static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2163
static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2165
static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2169
static int canonicalize_path LT_PARAMS((const char *path,
2170
char **pcanonical));
2171
static int argzize_path LT_PARAMS((const char *path,
2173
size_t *pargz_len));
2174
static FILE *find_file LT_PARAMS((const char *search_path,
2175
const char *base_name,
2177
static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2178
const char *base_name,
2179
lt_dlhandle *handle));
2180
static int find_module LT_PARAMS((lt_dlhandle *handle,
2184
const char *old_name,
2186
static int free_vars LT_PARAMS((char *dlname, char *oldname,
2187
char *libdir, char *deplibs));
2188
static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2190
static int trim LT_PARAMS((char **dest,
2192
static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2193
const char *filename));
2194
static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2195
const char *filename));
2196
static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2197
static int lt_argz_insert LT_PARAMS((char **pargz,
2200
const char *entry));
2201
static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2203
const char *entry));
2204
static int lt_argz_insertdir LT_PARAMS((char **pargz,
2207
struct dirent *dp));
2208
static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2211
static int list_files_by_dir LT_PARAMS((const char *dirnam,
2213
size_t *pargz_len));
2214
static int file_not_found LT_PARAMS((void));
2216
static char *user_search_path= 0;
2217
static lt_dlloader *loaders = 0;
2218
static lt_dlhandle handles = 0;
2219
static int initialized = 0;
2221
/* Initialize libltdl. */
2229
/* Initialize only at first call. */
2230
if (++initialized == 1)
2233
user_search_path = 0; /* empty search path */
2236
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2239
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2242
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2245
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2248
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2251
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2252
errors += sys_dyld_init();
2254
errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2256
if (presym_init (presym.dlloader_data))
2258
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2261
else if (errors != 0)
2263
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2268
LT_DLMUTEX_UNLOCK ();
2274
lt_dlpreload (preloaded)
2275
const lt_dlsymlist *preloaded;
2281
errors = presym_add_symlist (preloaded);
2285
presym_free_symlists();
2288
if (default_preloaded_symbols)
2290
errors = lt_dlpreload (default_preloaded_symbols);
2292
LT_DLMUTEX_UNLOCK ();
2299
lt_dlpreload_default (preloaded)
2300
const lt_dlsymlist *preloaded;
2303
default_preloaded_symbols = preloaded;
2304
LT_DLMUTEX_UNLOCK ();
2311
/* shut down libltdl */
2312
lt_dlloader *loader;
2320
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2325
/* shut down only at last call. */
2326
if (--initialized == 0)
2330
while (handles && LT_DLIS_RESIDENT (handles))
2332
handles = handles->next;
2335
/* close all modules */
2336
for (level = 1; handles; ++level)
2338
lt_dlhandle cur = handles;
2339
int saw_nonresident = 0;
2343
lt_dlhandle tmp = cur;
2345
if (!LT_DLIS_RESIDENT (tmp))
2346
saw_nonresident = 1;
2347
if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2349
if (lt_dlclose (tmp))
2353
/* Make sure that the handle pointed to by 'cur' still exists.
2354
lt_dlclose recursively closes dependent libraries which removes
2355
them from the linked list. One of these might be the one
2356
pointed to by 'cur'. */
2359
for (tmp = handles; tmp; tmp = tmp->next)
2367
/* done if only resident modules are left */
2368
if (!saw_nonresident)
2372
/* close all loaders */
2375
lt_dlloader *next = loader->next;
2376
lt_user_data data = loader->dlloader_data;
2377
if (loader->dlloader_exit && loader->dlloader_exit (data))
2382
LT_DLMEM_REASSIGN (loader, next);
2388
LT_DLMUTEX_UNLOCK ();
2393
tryall_dlopen (handle, filename)
2394
lt_dlhandle *handle;
2395
const char *filename;
2398
lt_dlloader *loader;
2399
const char *saved_error;
2402
LT_DLMUTEX_GETERROR (saved_error);
2408
/* check whether the module was already opened */
2411
/* try to dlopen the program itself? */
2412
if (!cur->info.filename && !filename)
2417
if (cur->info.filename && filename
2418
&& strcmp (cur->info.filename, filename) == 0)
2428
++cur->info.ref_count;
2436
/* Comment out the check of file permissions using access.
2437
This call seems to always return -1 with error EACCES.
2439
/* We need to catch missing file errors early so that
2440
file_not_found() can detect what happened.
2441
if (access (filename, R_OK) != 0)
2443
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2448
cur->info.filename = lt_estrdup (filename);
2449
if (!cur->info.filename)
2457
cur->info.filename = 0;
2462
lt_user_data data = loader->dlloader_data;
2464
cur->module = loader->module_open (data, filename);
2466
if (cur->module != 0)
2470
loader = loader->next;
2475
LT_DLFREE (cur->info.filename);
2480
cur->loader = loader;
2481
LT_DLMUTEX_SETERROR (saved_error);
2484
LT_DLMUTEX_UNLOCK ();
2490
tryall_dlopen_module (handle, prefix, dirname, dlname)
2491
lt_dlhandle *handle;
2493
const char *dirname;
2498
size_t filename_len = 0;
2499
size_t dirname_len = LT_STRLEN (dirname);
2504
#ifdef LT_DIRSEP_CHAR
2505
/* Only canonicalized names (i.e. with DIRSEP chars already converted)
2506
should make it into this function: */
2507
assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2510
if (dirname_len > 0)
2511
if (dirname[dirname_len -1] == '/')
2513
filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2515
/* Allocate memory, and combine DIRNAME and MODULENAME into it.
2516
The PREFIX (if any) is handled below. */
2517
filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2521
sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2523
/* Now that we have combined DIRNAME and MODULENAME, if there is
2524
also a PREFIX to contend with, simply recurse with the arguments
2525
shuffled. Otherwise, attempt to open FILENAME as a module. */
2528
error += tryall_dlopen_module (handle,
2529
(const char *) 0, prefix, filename);
2531
else if (tryall_dlopen (handle, filename) != 0)
2536
LT_DLFREE (filename);
2541
find_module (handle, dir, libdir, dlname, old_name, installed)
2542
lt_dlhandle *handle;
2546
const char *old_name;
2549
/* Try to open the old library first; if it was dlpreopened,
2550
we want the preopened version of it, even if a dlopenable
2551
module is available. */
2552
if (old_name && tryall_dlopen (handle, old_name) == 0)
2557
/* Try to open the dynamic library. */
2560
/* try to open the installed module */
2561
if (installed && libdir)
2563
if (tryall_dlopen_module (handle,
2564
(const char *) 0, libdir, dlname) == 0)
2568
/* try to open the not-installed module */
2571
if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2575
/* maybe it was moved to another directory */
2577
if (dir && (tryall_dlopen_module (handle,
2578
(const char *) 0, dir, dlname) == 0))
2588
canonicalize_path (path, pcanonical)
2592
char *canonical = 0;
2594
assert (path && *path);
2595
assert (pcanonical);
2597
canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2604
for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2606
/* Path separators are not copied to the beginning or end of
2607
the destination, or if another separator would follow
2609
if (path[src] == LT_PATHSEP_CHAR)
2612
|| (path[1+ src] == LT_PATHSEP_CHAR)
2613
|| (path[1+ src] == LT_EOS_CHAR))
2617
/* Anything other than a directory separator is copied verbatim. */
2618
if ((path[src] != '/')
2619
#ifdef LT_DIRSEP_CHAR
2620
&& (path[src] != LT_DIRSEP_CHAR)
2624
canonical[dest++] = path[src];
2626
/* Directory separators are converted and copied only if they are
2627
not at the end of a path -- i.e. before a path separator or
2629
else if ((path[1+ src] != LT_PATHSEP_CHAR)
2630
&& (path[1+ src] != LT_EOS_CHAR)
2631
#ifdef LT_DIRSEP_CHAR
2632
&& (path[1+ src] != LT_DIRSEP_CHAR)
2634
&& (path[1+ src] != '/'))
2636
canonical[dest++] = '/';
2640
/* Add an end-of-string marker at the end. */
2641
canonical[dest] = LT_EOS_CHAR;
2644
/* Assign new value. */
2645
*pcanonical = canonical;
2651
argzize_path (path, pargz, pargz_len)
2662
if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2667
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2670
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2680
/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2681
of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2682
non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2683
it is appended to each SEARCH_PATH element before FUNC is called. */
2685
foreach_dirinpath (search_path, base_name, func, data1, data2)
2686
const char *search_path;
2687
const char *base_name;
2688
foreach_callback_func *func;
2693
int filenamesize = 0;
2694
size_t lenbase = LT_STRLEN (base_name);
2695
size_t argz_len = 0;
2698
char *canonical = 0;
2702
if (!search_path || !*search_path)
2704
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2708
if (canonicalize_path (search_path, &canonical) != 0)
2711
if (argzize_path (canonical, &argz, &argz_len) != 0)
2716
while ((dir_name = argz_next (argz, argz_len, dir_name)))
2718
size_t lendir = LT_STRLEN (dir_name);
2720
if (lendir +1 +lenbase >= filenamesize)
2722
LT_DLFREE (filename);
2723
filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2724
filename = LT_EMALLOC (char, filenamesize);
2729
assert (filenamesize > lendir);
2730
strcpy (filename, dir_name);
2732
if (base_name && *base_name)
2734
if (filename[lendir -1] != '/')
2735
filename[lendir++] = '/';
2736
strcpy (filename +lendir, base_name);
2739
if ((result = (*func) (filename, data1, data2)))
2748
LT_DLFREE (canonical);
2749
LT_DLFREE (filename);
2751
LT_DLMUTEX_UNLOCK ();
2756
/* If FILEPATH can be opened, store the name of the directory component
2757
in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2758
DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2760
find_file_callback (filename, data1, data2)
2765
char **pdir = (char **) data1;
2766
FILE **pfile = (FILE **) data2;
2769
assert (filename && *filename);
2773
if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2775
char *dirend = strrchr (filename, '/');
2777
if (dirend > filename)
2778
*dirend = LT_EOS_CHAR;
2781
*pdir = lt_estrdup (filename);
2782
is_done = (*pdir == 0) ? -1 : 1;
2789
find_file (search_path, base_name, pdir)
2790
const char *search_path;
2791
const char *base_name;
2796
foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2802
find_handle_callback (filename, data, ignored)
2807
lt_dlhandle *handle = (lt_dlhandle *) data;
2808
int notfound = access (filename, R_OK);
2810
/* Bail out if file cannot be read... */
2814
/* Try to dlopen the file, but do not continue searching in any
2816
if (tryall_dlopen (handle, filename) != 0)
2822
/* If HANDLE was found return it, otherwise return 0. If HANDLE was
2823
found but could not be opened, *HANDLE will be set to 0. */
2824
static lt_dlhandle *
2825
find_handle (search_path, base_name, handle)
2826
const char *search_path;
2827
const char *base_name;
2828
lt_dlhandle *handle;
2833
if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2841
load_deplibs (handle, deplibs)
2845
#if LTDL_DLOPEN_DEPLIBS
2846
char *p, *save_search_path = 0;
2853
handle->depcount = 0;
2855
#if LTDL_DLOPEN_DEPLIBS
2863
if (user_search_path)
2865
save_search_path = lt_estrdup (user_search_path);
2866
if (!save_search_path)
2870
/* extract search paths and count deplibs */
2874
if (!isspace ((int) *p))
2877
while (*end && !isspace((int) *end))
2882
if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2885
*end = 0; /* set a temporary string terminator */
2886
if (lt_dladdsearchdir(p+2))
2911
names = LT_EMALLOC (char *, depcount * sizeof (char*));
2915
/* now only extract the actual deplibs */
2920
if (isspace ((int) *p))
2927
while (*end && !isspace ((int) *end))
2932
if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2936
*end = 0; /* set a temporary string terminator */
2937
if (strncmp(p, "-l", 2) == 0)
2939
size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2940
name = LT_EMALLOC (char, 1+ name_len);
2942
sprintf (name, "lib%s", p+2);
2945
name = lt_estrdup(p);
2950
names[depcount++] = name;
2957
/* load the deplibs (in reverse order)
2958
At this stage, don't worry if the deplibs do not load correctly,
2959
they may already be statically linked into the loading application
2960
for instance. There will be a more enlightening error message
2961
later on if the loaded module cannot resolve all of its symbols. */
2966
handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2967
if (!handle->deplibs)
2970
for (i = 0; i < depcount; ++i)
2972
handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2973
if (handle->deplibs[j])
2979
handle->depcount = j; /* Number of successfully loaded deplibs */
2984
for (i = 0; i < depcount; ++i)
2986
LT_DLFREE (names[i]);
2991
/* restore the old search path */
2992
if (user_search_path) {
2993
LT_DLFREE (user_search_path);
2994
user_search_path = save_search_path;
2996
LT_DLMUTEX_UNLOCK ();
3004
unload_deplibs (handle)
3010
if (handle->depcount)
3012
for (i = 0; i < handle->depcount; ++i)
3014
if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
3016
errors += lt_dlclose (handle->deplibs[i]);
3019
LT_DLFREE (handle->deplibs);
3030
/* remove the leading and trailing "'" from str
3031
and store the result in dest */
3032
const char *end = strrchr (str, '\'');
3033
size_t len = LT_STRLEN (str);
3041
if (len > 3 && str[0] == '\'')
3043
tmp = LT_EMALLOC (char, end - str);
3047
strncpy(tmp, &str[1], (end - str) - 1);
3048
tmp[(end - str) - 1] = LT_EOS_CHAR;
3060
free_vars (dlname, oldname, libdir, deplibs)
3067
LT_DLFREE (oldname);
3069
LT_DLFREE (deplibs);
3075
try_dlopen (phandle, filename)
3076
lt_dlhandle *phandle;
3077
const char *filename;
3079
const char * ext = 0;
3080
const char * saved_error = 0;
3081
char * canonical = 0;
3082
char * base_name = 0;
3086
lt_dlhandle newhandle;
3089
assert (*phandle == 0);
3091
LT_DLMUTEX_GETERROR (saved_error);
3096
*phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3100
memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3101
newhandle = *phandle;
3103
/* lt_dlclose()ing yourself is very bad! Disallow it. */
3104
LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3106
if (tryall_dlopen (&newhandle, 0) != 0)
3108
LT_DLFREE (*phandle);
3112
goto register_handle;
3115
assert (filename && *filename);
3117
/* Doing this immediately allows internal functions to safely
3118
assume only canonicalized paths are passed. */
3119
if (canonicalize_path (filename, &canonical) != 0)
3125
/* If the canonical module name is a path (relative or absolute)
3126
then split it into a directory part and a name part. */
3127
base_name = strrchr (canonical, '/');
3130
size_t dirlen = (1+ base_name) - canonical;
3132
dir = LT_EMALLOC (char, 1+ dirlen);
3139
strncpy (dir, canonical, dirlen);
3140
dir[dirlen] = LT_EOS_CHAR;
3145
base_name = canonical;
3147
assert (base_name && *base_name);
3149
/* Check whether we are opening a libtool module (.la extension). */
3150
ext = strrchr (base_name, '.');
3151
if (ext && strcmp (ext, archive_ext) == 0)
3153
/* this seems to be a libtool module */
3156
char * old_name = 0;
3162
/* if we can't find the installed flag, it is probably an
3163
installed libtool archive, produced with an old version
3167
/* extract the module name from the file name */
3168
name = LT_EMALLOC (char, ext - base_name + 1);
3175
/* canonicalize the module name */
3178
for (i = 0; i < ext - base_name; ++i)
3180
if (isalnum ((int)(base_name[i])))
3182
name[i] = base_name[i];
3189
name[ext - base_name] = LT_EOS_CHAR;
3192
/* Now try to open the .la file. If there is no directory name
3193
component, try to find it first in user_search_path and then other
3194
prescribed paths. Otherwise (or in any case if the module was not
3195
yet found) try opening just the module name as passed. */
3198
const char *search_path;
3201
search_path = user_search_path;
3203
file = find_file (user_search_path, base_name, &dir);
3204
LT_DLMUTEX_UNLOCK ();
3208
search_path = getenv (LTDL_SEARCHPATH_VAR);
3210
file = find_file (search_path, base_name, &dir);
3213
#ifdef LTDL_SHLIBPATH_VAR
3216
search_path = getenv (LTDL_SHLIBPATH_VAR);
3218
file = find_file (search_path, base_name, &dir);
3221
#ifdef LTDL_SYSSEARCHPATH
3222
if (!file && *sys_search_path)
3224
file = find_file (sys_search_path, base_name, &dir);
3230
file = fopen (filename, LT_READTEXT_MODE);
3233
/* If we didn't find the file by now, it really isn't there. Set
3234
the status flag, and bail out. */
3237
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3242
line_len = LT_FILENAME_MAX;
3243
line = LT_EMALLOC (char, line_len);
3251
/* read the .la file */
3252
while (!feof (file))
3254
line[line_len-2] = '\0';
3255
if (!fgets (line, (int) line_len, file))
3260
/* Handle the case where we occasionally need to read a line
3261
that is longer than the initial buffer size.
3262
Behave even if the file contains NUL bytes due to corruption. */
3263
while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
3265
line = LT_DLREALLOC (char, line, line_len *2);
3266
line[line_len*2 - 2] = '\0';
3267
if (!fgets (&line[line_len -1], (int) line_len +1, file))
3274
if (line[0] == '\n' || line[0] == '#')
3280
#define STR_DLNAME "dlname="
3281
if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3283
errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3286
#undef STR_OLD_LIBRARY
3287
#define STR_OLD_LIBRARY "old_library="
3288
else if (strncmp (line, STR_OLD_LIBRARY,
3289
sizeof (STR_OLD_LIBRARY) - 1) == 0)
3291
errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3294
#define STR_LIBDIR "libdir="
3295
else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3297
errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3300
#undef STR_DL_DEPLIBS
3301
#define STR_DL_DEPLIBS "dependency_libs="
3302
else if (strncmp (line, STR_DL_DEPLIBS,
3303
sizeof (STR_DL_DEPLIBS) - 1) == 0)
3305
errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3307
else if (strcmp (line, "installed=yes\n") == 0)
3311
else if (strcmp (line, "installed=no\n") == 0)
3316
#undef STR_LIBRARY_NAMES
3317
#define STR_LIBRARY_NAMES "library_names="
3318
else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3319
sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3322
errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3325
&& (last_libname = strrchr (dlname, ' ')) != 0)
3327
last_libname = lt_estrdup (last_libname + 1);
3333
LT_DLMEM_REASSIGN (dlname, last_libname);
3344
/* allocate the handle */
3345
*phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3351
free_vars (dlname, old_name, libdir, deplibs);
3352
LT_DLFREE (*phandle);
3358
memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3359
if (load_deplibs (*phandle, deplibs) == 0)
3361
newhandle = *phandle;
3362
/* find_module may replace newhandle */
3363
if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3365
unload_deplibs (*phandle);
3374
free_vars (dlname, old_name, libdir, deplibs);
3377
LT_DLFREE (*phandle);
3381
if (*phandle != newhandle)
3383
unload_deplibs (*phandle);
3388
/* not a libtool module */
3389
*phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3396
memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3397
newhandle = *phandle;
3399
/* If the module has no directory name component, try to find it
3400
first in user_search_path and then other prescribed paths.
3401
Otherwise (or in any case if the module was not yet found) try
3402
opening just the module name as passed. */
3403
if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3404
&& !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3406
#ifdef LTDL_SHLIBPATH_VAR
3407
&& !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3410
#ifdef LTDL_SYSSEARCHPATH
3411
&& !find_handle (sys_search_path, base_name, &newhandle)
3415
if (tryall_dlopen (&newhandle, filename) != 0)
3423
LT_DLFREE (*phandle);
3430
LT_DLMEM_REASSIGN (*phandle, newhandle);
3432
if ((*phandle)->info.ref_count == 0)
3434
(*phandle)->info.ref_count = 1;
3435
LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3438
(*phandle)->next = handles;
3440
LT_DLMUTEX_UNLOCK ();
3443
LT_DLMUTEX_SETERROR (saved_error);
3448
LT_DLFREE (canonical);
3454
lt_dlopen (filename)
3455
const char *filename;
3457
lt_dlhandle handle = 0;
3459
/* Just incase we missed a code path in try_dlopen() that reports
3460
an error, but forgets to reset handle... */
3461
if (try_dlopen (&handle, filename) != 0)
3467
/* If the last error messge store was `FILE_NOT_FOUND', then return
3472
const char *error = 0;
3474
LT_DLMUTEX_GETERROR (error);
3475
if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3481
/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3482
open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3483
and if a file is still not found try again with SHLIB_EXT appended
3486
lt_dlopenext (filename)
3487
const char *filename;
3489
lt_dlhandle handle = 0;
3497
return lt_dlopen (filename);
3502
len = LT_STRLEN (filename);
3503
ext = strrchr (filename, '.');
3505
/* If FILENAME already bears a suitable extension, there is no need
3506
to try appending additional extensions. */
3507
if (ext && ((strcmp (ext, archive_ext) == 0)
3508
#ifdef LTDL_SHLIB_EXT
3509
|| (strcmp (ext, shlib_ext) == 0)
3513
return lt_dlopen (filename);
3516
/* First try appending ARCHIVE_EXT. */
3517
tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3521
strcpy (tmp, filename);
3522
strcat (tmp, archive_ext);
3523
errors = try_dlopen (&handle, tmp);
3525
/* If we found FILENAME, stop searching -- whether we were able to
3526
load the file as a module or not. If the file exists but loading
3527
failed, it is better to return an error message here than to
3528
report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3529
in the module search path. */
3530
if (handle || ((errors > 0) && !file_not_found ()))
3536
#ifdef LTDL_SHLIB_EXT
3537
/* Try appending SHLIB_EXT. */
3538
if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3541
tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3545
strcpy (tmp, filename);
3549
tmp[len] = LT_EOS_CHAR;
3552
strcat(tmp, shlib_ext);
3553
errors = try_dlopen (&handle, tmp);
3555
/* As before, if the file was found but loading failed, return now
3556
with the current error message. */
3557
if (handle || ((errors > 0) && !file_not_found ()))
3564
/* Still here? Then we really did fail to locate any of the file
3566
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3573
lt_argz_insert (pargz, pargz_len, before, entry)
3581
/* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3582
pargz_len, NULL, entry) failed with EINVAL. */
3584
error = argz_insert (pargz, pargz_len, before, entry);
3586
error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
3593
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3596
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3606
lt_argz_insertinorder (pargz, pargz_len, entry)
3615
assert (entry && *entry);
3618
while ((before = argz_next (*pargz, *pargz_len, before)))
3620
int cmp = strcmp (entry, before);
3623
if (cmp == 0) return 0; /* No duplicates! */
3626
return lt_argz_insert (pargz, pargz_len, before, entry);
3630
lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3639
size_t end_offset = 0;
3647
dir_len = LT_STRLEN (dirnam);
3648
end = dp->d_name + LT_D_NAMLEN(dp);
3650
/* Ignore version numbers. */
3653
for (p = end; p -1 > dp->d_name; --p)
3654
if (strchr (".0123456789", p[-1]) == 0)
3661
/* Ignore filename extension. */
3664
for (p = end -1; p > dp->d_name; --p)
3672
/* Prepend the directory name. */
3673
end_offset = end - dp->d_name;
3674
buf_len = dir_len + 1+ end_offset;
3675
buf = LT_EMALLOC (char, 1+ buf_len);
3681
strcpy (buf, dirnam);
3683
strncat (buf, dp->d_name, end_offset);
3684
buf[buf_len] = LT_EOS_CHAR;
3686
/* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3687
if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3696
list_files_by_dir (dirnam, pargz, pargz_len)
3704
assert (dirnam && *dirnam);
3707
assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3709
dirp = opendir (dirnam);
3712
struct dirent *dp = 0;
3714
while ((dp = readdir (dirp)))
3715
if (dp->d_name[0] != '.')
3716
if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3731
/* If there are any files in DIRNAME, call the function passed in
3732
DATA1 (with the name of each file and DATA2 as arguments). */
3734
foreachfile_callback (dirname, data1, data2)
3739
file_worker_func *func = *(file_worker_func **) data1;
3743
size_t argz_len = 0;
3745
if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3752
while ((filename = argz_next (argz, argz_len, filename)))
3753
if ((is_done = (*func) (filename, data2)))
3764
/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3765
with DATA. The filenames passed to FUNC would be suitable for
3766
passing to lt_dlopenext. The extensions are stripped so that
3767
individual modules do not generate several entries (e.g. libfoo.la,
3768
libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3769
then the same directories that lt_dlopen would search are examined. */
3771
lt_dlforeachfile (search_path, func, data)
3772
const char *search_path;
3773
int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3777
file_worker_func **fpptr = &func;
3781
/* If a specific path was passed, search only the directories
3783
is_done = foreach_dirinpath (search_path, 0,
3784
foreachfile_callback, fpptr, data);
3788
/* Otherwise search the default paths. */
3789
is_done = foreach_dirinpath (user_search_path, 0,
3790
foreachfile_callback, fpptr, data);
3793
is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3794
foreachfile_callback, fpptr, data);
3797
#ifdef LTDL_SHLIBPATH_VAR
3800
is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3801
foreachfile_callback, fpptr, data);
3804
#ifdef LTDL_SYSSEARCHPATH
3807
is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3808
foreachfile_callback, fpptr, data);
3820
lt_dlhandle cur, last;
3825
/* check whether the handle is valid */
3826
last = cur = handles;
3827
while (cur && handle != cur)
3835
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3840
handle->info.ref_count--;
3842
/* Note that even with resident modules, we must track the ref_count
3843
correctly incase the user decides to reset the residency flag
3844
later (even though the API makes no provision for that at the
3846
if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3848
lt_user_data data = handle->loader->dlloader_data;
3850
if (handle != handles)
3852
last->next = handle->next;
3856
handles = handle->next;
3859
errors += handle->loader->module_close (data, handle->module);
3860
errors += unload_deplibs(handle);
3862
/* It is up to the callers to free the data itself. */
3863
LT_DLFREE (handle->caller_data);
3865
LT_DLFREE (handle->info.filename);
3866
LT_DLFREE (handle->info.name);
3872
if (LT_DLIS_RESIDENT (handle))
3874
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3879
LT_DLMUTEX_UNLOCK ();
3885
lt_dlsym (handle, symbol)
3890
char lsym[LT_SYMBOL_LENGTH];
3897
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3903
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3907
lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3908
+ LT_STRLEN (handle->info.name);
3910
if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3916
sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3919
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3924
data = handle->loader->dlloader_data;
3925
if (handle->info.name)
3927
const char *saved_error;
3929
LT_DLMUTEX_GETERROR (saved_error);
3931
/* this is a libtool module */
3932
if (handle->loader->sym_prefix)
3934
strcpy(sym, handle->loader->sym_prefix);
3935
strcat(sym, handle->info.name);
3939
strcpy(sym, handle->info.name);
3942
strcat(sym, "_LTX_");
3943
strcat(sym, symbol);
3945
/* try "modulename_LTX_symbol" */
3946
address = handle->loader->find_sym (data, handle->module, sym);
3955
LT_DLMUTEX_SETERROR (saved_error);
3958
/* otherwise try "symbol" */
3959
if (handle->loader->sym_prefix)
3961
strcpy(sym, handle->loader->sym_prefix);
3962
strcat(sym, symbol);
3966
strcpy(sym, symbol);
3969
address = handle->loader->find_sym (data, handle->module, sym);
3983
LT_DLMUTEX_GETERROR (error);
3984
LT_DLMUTEX_SETERROR (0);
3986
return error ? error : NULL;
3990
lt_dlpath_insertdir (ppath, before, dir)
3996
char *canonical = 0;
3998
size_t argz_len = 0;
4001
assert (dir && *dir);
4003
if (canonicalize_path (dir, &canonical) != 0)
4009
assert (canonical && *canonical);
4011
/* If *PPATH is empty, set it to DIR. */
4014
assert (!before); /* BEFORE cannot be set without PPATH. */
4015
assert (dir); /* Without DIR, don't call this function! */
4017
*ppath = lt_estrdup (dir);
4024
assert (ppath && *ppath);
4026
if (argzize_path (*ppath, &argz, &argz_len) != 0)
4032
/* Convert BEFORE into an equivalent offset into ARGZ. This only works
4033
if *PPATH is already canonicalized, and hence does not change length
4034
with respect to ARGZ. We canonicalize each entry as it is added to
4035
the search path, and don't call this function with (uncanonicalized)
4036
user paths, so this is a fair assumption. */
4039
assert (*ppath <= before);
4040
assert (before - *ppath <= strlen (*ppath));
4042
before = before - *ppath + argz;
4045
if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
4051
argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
4052
LT_DLMEM_REASSIGN (*ppath, argz);
4055
LT_DLFREE (canonical);
4062
lt_dladdsearchdir (search_dir)
4063
const char *search_dir;
4067
if (search_dir && *search_dir)
4070
if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4072
LT_DLMUTEX_UNLOCK ();
4079
lt_dlinsertsearchdir (before, search_dir)
4081
const char *search_dir;
4088
if ((before < user_search_path)
4089
|| (before >= user_search_path + LT_STRLEN (user_search_path)))
4091
LT_DLMUTEX_UNLOCK ();
4092
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4095
LT_DLMUTEX_UNLOCK ();
4098
if (search_dir && *search_dir)
4101
if (lt_dlpath_insertdir (&user_search_path,
4102
(char *) before, search_dir) != 0)
4106
LT_DLMUTEX_UNLOCK ();
4113
lt_dlsetsearchpath (search_path)
4114
const char *search_path;
4119
LT_DLFREE (user_search_path);
4120
LT_DLMUTEX_UNLOCK ();
4122
if (!search_path || !LT_STRLEN (search_path))
4128
if (canonicalize_path (search_path, &user_search_path) != 0)
4130
LT_DLMUTEX_UNLOCK ();
4136
lt_dlgetsearchpath ()
4138
const char *saved_path;
4141
saved_path = user_search_path;
4142
LT_DLMUTEX_UNLOCK ();
4148
lt_dlmakeresident (handle)
4155
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4160
LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4167
lt_dlisresident (handle)
4172
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4176
return LT_DLIS_RESIDENT (handle);
4182
/* --- MODULE INFORMATION --- */
4185
lt_dlgetinfo (handle)
4190
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4194
return &(handle->info);
4198
lt_dlhandle_next (place)
4201
return place ? place->next : handles;
4205
lt_dlforeach (func, data)
4206
int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4217
lt_dlhandle tmp = cur;
4220
if ((*func) (tmp, data))
4227
LT_DLMUTEX_UNLOCK ();
4233
lt_dlcaller_register ()
4235
static lt_dlcaller_id last_caller_id = 0;
4239
result = ++last_caller_id;
4240
LT_DLMUTEX_UNLOCK ();
4246
lt_dlcaller_set_data (key, handle, data)
4252
lt_ptr stale = (lt_ptr) 0;
4255
/* This needs to be locked so that the caller data can be updated
4256
simultaneously by different threads. */
4259
if (handle->caller_data)
4260
while (handle->caller_data[n_elements].key)
4263
for (i = 0; i < n_elements; ++i)
4265
if (handle->caller_data[i].key == key)
4267
stale = handle->caller_data[i].data;
4272
/* Ensure that there is enough room in this handle's caller_data
4273
array to accept a new element (and an empty end marker). */
4274
if (i == n_elements)
4276
lt_caller_data *temp
4277
= LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4285
handle->caller_data = temp;
4287
/* We only need this if we needed to allocate a new caller_data. */
4288
handle->caller_data[i].key = key;
4289
handle->caller_data[1+ i].key = 0;
4292
handle->caller_data[i].data = data;
4295
LT_DLMUTEX_UNLOCK ();
4301
lt_dlcaller_get_data (key, handle)
4305
lt_ptr result = (lt_ptr) 0;
4307
/* This needs to be locked so that the caller data isn't updated by
4308
another thread part way through this function. */
4311
/* Locate the index of the element with a matching KEY. */
4312
if (handle->caller_data)
4315
for (i = 0; handle->caller_data[i].key; ++i)
4317
if (handle->caller_data[i].key == key)
4319
result = handle->caller_data[i].data;
4325
LT_DLMUTEX_UNLOCK ();
4332
/* --- USER MODULE LOADER API --- */
4336
lt_dlloader_add (place, dlloader, loader_name)
4338
const struct lt_user_dlloader *dlloader;
4339
const char *loader_name;
4342
lt_dlloader *node = 0, *ptr = 0;
4344
if ((dlloader == 0) /* diagnose null parameters */
4345
|| (dlloader->module_open == 0)
4346
|| (dlloader->module_close == 0)
4347
|| (dlloader->find_sym == 0))
4349
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4353
/* Create a new dlloader node with copies of the user callbacks. */
4354
node = LT_EMALLOC (lt_dlloader, 1);
4359
node->loader_name = loader_name;
4360
node->sym_prefix = dlloader->sym_prefix;
4361
node->dlloader_exit = dlloader->dlloader_exit;
4362
node->module_open = dlloader->module_open;
4363
node->module_close = dlloader->module_close;
4364
node->find_sym = dlloader->find_sym;
4365
node->dlloader_data = dlloader->dlloader_data;
4370
/* If there are no loaders, NODE becomes the list! */
4375
/* If PLACE is not set, add NODE to the end of the
4377
for (ptr = loaders; ptr->next; ptr = ptr->next)
4384
else if (loaders == place)
4386
/* If PLACE is the first loader, NODE goes first. */
4392
/* Find the node immediately preceding PLACE. */
4393
for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4398
if (ptr->next != place)
4400
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4405
/* Insert NODE between PTR and PLACE. */
4411
LT_DLMUTEX_UNLOCK ();
4417
lt_dlloader_remove (loader_name)
4418
const char *loader_name;
4420
lt_dlloader *place = lt_dlloader_find (loader_name);
4426
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4432
/* Fail if there are any open modules which use this loader. */
4433
for (handle = handles; handle; handle = handle->next)
4435
if (handle->loader == place)
4437
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4443
if (place == loaders)
4445
/* PLACE is the first loader in the list. */
4446
loaders = loaders->next;
4450
/* Find the loader before the one being removed. */
4452
for (prev = loaders; prev->next; prev = prev->next)
4454
if (!strcmp (prev->next->loader_name, loader_name))
4461
prev->next = prev->next->next;
4464
if (place->dlloader_exit)
4466
errors = place->dlloader_exit (place->dlloader_data);
4472
LT_DLMUTEX_UNLOCK ();
4478
lt_dlloader_next (place)
4484
next = place ? place->next : loaders;
4485
LT_DLMUTEX_UNLOCK ();
4491
lt_dlloader_name (place)
4494
const char *name = 0;
4499
name = place ? place->loader_name : 0;
4500
LT_DLMUTEX_UNLOCK ();
4504
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4511
lt_dlloader_data (place)
4514
lt_user_data *data = 0;
4519
data = place ? &(place->dlloader_data) : 0;
4520
LT_DLMUTEX_UNLOCK ();
4524
LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4531
lt_dlloader_find (loader_name)
4532
const char *loader_name;
4534
lt_dlloader *place = 0;
4537
for (place = loaders; place; place = place->next)
4539
if (strcmp (place->loader_name, loader_name) == 0)
4544
LT_DLMUTEX_UNLOCK ();