1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000 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., 59 Temple Place, Suite 330, 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 --- */
142 # define LT_GLOBAL_DATA __declspec(dllexport)
144 # define LT_GLOBAL_DATA
147 /* fopen() mode flags for reading a text file */
148 #undef LT_READTEXT_MODE
150 # define LT_READTEXT_MODE "rt"
152 # define LT_READTEXT_MODE "r"
155 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
159 #define dirent lt_dirent
171 WIN32_FIND_DATA Win32FindData;
173 struct dirent file_info;
176 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
181 /* --- MANIFEST CONSTANTS --- */
184 /* Standard libltdl search path environment variable name */
185 #undef LTDL_SEARCHPATH_VAR
186 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
188 /* Standard libtool archive file extension. */
189 #undef LTDL_ARCHIVE_EXT
190 #define LTDL_ARCHIVE_EXT ".la"
194 # define LTDL_OBJDIR LT_OBJDIR
198 #ifndef LTDL_SHLIBPATH_VAR
199 # ifdef LT_MODULE_PATH_VAR
200 # define LTDL_SHLIBPATH_VAR LT_MODULE_PATH_VAR
204 #ifndef LTDL_SHLIB_EXT
205 # ifdef LT_MODULE_EXT
206 # define LTDL_SHLIB_EXT LT_MODULE_EXT
210 #ifndef LTDL_SYSSEARCHPATH
211 # ifdef LT_DLSEARCH_PATH
212 # define LTDL_SYSSEARCHPATH LT_DLSEARCH_PATH
216 /* max. filename length */
217 #ifndef LT_FILENAME_MAX
218 # define LT_FILENAME_MAX 1024
221 /* This is the maximum symbol size that won't require malloc/free */
222 #undef LT_SYMBOL_LENGTH
223 #define LT_SYMBOL_LENGTH 128
225 /* This accounts for the _LTX_ separator */
226 #undef LT_SYMBOL_OVERHEAD
227 #define LT_SYMBOL_OVERHEAD 5
232 /* --- MEMORY HANDLING --- */
235 /* These are the functions used internally. In addition to making
236 use of the associated function pointers above, they also perform
238 static char *lt_estrdup LT_PARAMS((const char *str));
239 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
240 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
242 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
243 #define rpl_realloc realloc
245 /* These are the pointers that can be changed by the caller: */
246 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
247 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
248 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
249 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
250 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
251 = (void (*) LT_PARAMS((lt_ptr))) free;
253 /* The following macros reduce the amount of typing needed to cast
257 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
258 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
259 #define LT_DLFREE(p) \
260 LT_STMT_START { if (p) { xfree (p); (p) = 0; } } LT_STMT_END
262 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
263 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
267 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
268 #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
269 #define LT_DLFREE(p) \
270 LT_STMT_START { if (p) { lt_dlfree (p); (p) = 0; } } LT_STMT_END
272 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
273 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
277 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
278 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
282 /* --- REPLACEMENT FUNCTIONS --- */
286 #define strdup rpl_strdup
288 static char *strdup LT_PARAMS((const char *str));
291 strdup(const char *str)
297 tmp = LT_DLMALLOC (char, 1+ strlen (str));
300 strncpy(tmp, str, sizeof(tmp)-1);
311 #define strcmp rpl_strcmp
313 static int strcmp LT_PARAMS((const char *str1, const char *str2));
316 strcmp (const char *str1, const char *str2)
325 for (;*str1 && *str2; ++str1, ++str2)
331 return (int)(*str1 - *str2);
339 # define strchr index
341 # define strchr rpl_strchr
343 static const char *strchr LT_PARAMS((const char *str, int ch));
346 strchr(const char *str, int ch)
350 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
353 return (*p == (char)ch) ? p : 0;
357 #endif /* !HAVE_STRCHR */
363 # define strrchr rindex
365 # define strrchr rpl_strrchr
367 static const char *strrchr LT_PARAMS((const char *str, int ch));
370 strrchr(const char *str, int ch)
372 const char *p, *q = 0;
374 for (p = str; *p != LT_EOS_CHAR; ++p)
388 /* NOTE: Neither bcopy nor the memcpy implementation below can
389 reliably handle copying in overlapping areas of memory. Use
390 memmove (for which there is a fallback implementation below)
391 if you need that behaviour. */
395 # define memcpy(dest, src, size) bcopy (src, dest, size)
397 # define memcpy rpl_memcpy
399 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
402 memcpy (lt_ptr dest, const lt_ptr src, size_t size)
406 unsigned char *dest1 = (unsigned char *)dest;
407 unsigned char *src1 = (unsigned char *)src;
409 for (i = 0; i < size; ++i)
417 # endif /* !HAVE_BCOPY */
418 #endif /* !HAVE_MEMCPY */
421 # define memmove rpl_memmove
423 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
426 memmove (lt_ptr dest, const lt_ptr src, size_t size)
430 unsigned char *dest1 = (unsigned char *)dest;
431 unsigned char *src1 = (unsigned char *)src;
434 for (i = 0; i < size; ++i)
439 for (i = size -1; i >= 0; --i)
447 #endif /* !HAVE_MEMMOVE */
449 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
451 static void closedir LT_PARAMS((DIR *entry));
456 assert(entry != (DIR *) NULL);
457 FindClose(entry->hSearch);
458 lt_dlfree((lt_ptr)entry);
462 static DIR * opendir LT_PARAMS((const char *path));
465 opendir (const char *path)
467 char file_specification[LT_FILENAME_MAX];
470 assert(path != (char *) NULL);
471 (void) strncpy(file_specification,path,LT_FILENAME_MAX-1);
472 (void) strcat(file_specification,"\\");
473 entry = LT_DLMALLOC (DIR,sizeof(DIR));
474 if (entry != (DIR *) 0)
476 entry->firsttime = TRUE;
477 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
479 if (entry->hSearch == INVALID_HANDLE_VALUE)
481 (void) strcat(file_specification,"\\*.*");
482 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
483 if (entry->hSearch == INVALID_HANDLE_VALUE)
493 static struct dirent *readdir LT_PARAMS((DIR *entry));
495 static struct dirent *readdir(DIR *entry)
500 if (entry == (DIR *) 0)
501 return((struct dirent *) 0);
502 if (!entry->firsttime)
504 status = FindNextFile(entry->hSearch,&entry->Win32FindData);
506 return((struct dirent *) 0);
508 entry->firsttime = FALSE;
509 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
511 entry->file_info.d_namlen = strlen(entry->file_info.d_name);
512 return(&entry->file_info);
515 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
517 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
518 ``realloc is not entirely portable''
519 In any case we want to use the allocator supplied by the user without
520 burdening them with an lt_dlrealloc function pointer to maintain.
521 Instead implement our own version (with known boundary conditions)
522 using lt_dlmalloc and lt_dlfree. */
525 #define realloc rpl_realloc
528 /* You can't (re)define realloc unless you also (re)define malloc.
529 Right now, this code uses the size of the *destination* to decide
530 how much to copy. That's not right, but you can't know the size
531 of the source unless you know enough about, or wrote malloc. So
532 this code is disabled... */
541 /* For zero or less bytes, free the original memory */
551 /* Allow reallocation of a NULL pointer. */
552 return lt_dlmalloc (size);
556 /* Allocate a new block, copy and free the old block. */
557 lt_ptr mem = lt_dlmalloc (size);
561 memcpy (mem, ptr, size);
565 /* Note that the contents of PTR are not damaged if there is
566 insufficient memory to realloc. */
573 #if ! HAVE_ARGZ_APPEND
574 # define argz_append rpl_argz_append
576 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
577 const char *buf, size_t buf_len));
580 argz_append (char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)
587 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
589 /* If nothing needs to be appended, no more work is required. */
593 /* Ensure there is enough room to append BUF_LEN. */
594 argz_len = *pargz_len + buf_len;
595 argz = LT_DLREALLOC (char, *pargz, argz_len);
599 /* Copy characters from BUF after terminating '\0' in ARGZ. */
600 memcpy (argz + *pargz_len, buf, buf_len);
602 /* Assign new values. */
604 *pargz_len = argz_len;
608 #endif /* !HAVE_ARGZ_APPEND */
611 #if ! HAVE_ARGZ_CREATE_SEP
612 # define argz_create_sep rpl_argz_create_sep
614 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
615 char **pargz, size_t *pargz_len));
618 argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
627 /* Make a copy of STR, but replacing each occurence of
629 argz_len = 1+ LT_STRLEN (str);
635 argz = LT_DLMALLOC (char, argz_len);
639 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
643 /* Ignore leading delimiters, and fold consecutive
644 delimiters in STR into a single '\0' in ARGZ. */
645 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
653 /* Copy terminating LT_EOS_CHAR. */
657 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
661 /* Assign new values. */
663 *pargz_len = argz_len;
667 #endif /* !HAVE_ARGZ_CREATE_SEP */
670 #if ! HAVE_ARGZ_INSERT
671 # define argz_insert rpl_argz_insert
673 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
674 char *before, const char *entry));
677 argz_insert (char **pargz, size_t *pargz_len, char *before, const char *entry)
681 assert (entry && *entry);
683 /* No BEFORE address indicates ENTRY should be inserted after the
684 current last element. */
686 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
688 /* This probably indicates a programmer error, but to preserve
689 semantics, scan back to the start of an entry if BEFORE points
690 into the middle of it. */
691 while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
695 size_t entry_len = 1+ LT_STRLEN (entry);
696 size_t argz_len = *pargz_len + entry_len;
697 size_t offset = before - *pargz;
698 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
703 /* Make BEFORE point to the equivalent offset in ARGZ that it
704 used to have in *PARGZ incase realloc() moved the block. */
705 before = argz + offset;
707 /* Move the ARGZ entries starting at BEFORE up into the new
708 space at the end -- making room to copy ENTRY into the
710 memmove (before + entry_len, before, *pargz_len - offset);
711 memcpy (before, entry, entry_len);
713 /* Assign new values. */
715 *pargz_len = argz_len;
720 #endif /* !HAVE_ARGZ_INSERT */
724 # define argz_next rpl_argz_next
726 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
730 argz_next (char *argz, size_t argz_len, const char *entry)
732 assert ((argz && argz_len) || (!argz && !argz_len));
736 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
737 within the ARGZ vector. */
738 assert ((!argz && !argz_len)
739 || ((argz <= entry) && (entry < (argz + argz_len))));
741 /* Move to the char immediately after the terminating
743 entry = 1+ strchr (entry, LT_EOS_CHAR);
745 /* Return either the new ENTRY, or else NULL if ARGZ is
747 return (entry >= argz + argz_len) ? 0 : (char *) entry;
751 /* This should probably be flagged as a programmer error,
752 since starting an argz_next loop with the iterator set
753 to ARGZ is safer. To preserve semantics, handle the NULL
754 case by returning the start of ARGZ (if any). */
761 #endif /* !HAVE_ARGZ_NEXT */
765 #if ! HAVE_ARGZ_STRINGIFY
766 # define argz_stringify rpl_argz_stringify
768 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
772 argz_stringify (char *argz, size_t argz_len, int sep)
774 assert ((argz && argz_len) || (!argz && !argz_len));
778 --argz_len; /* don't stringify the terminating EOS */
779 while (--argz_len > 0)
781 if (argz[argz_len] == LT_EOS_CHAR)
782 argz[argz_len] = sep;
786 #endif /* !HAVE_ARGZ_STRINGIFY */
791 /* --- TYPE DEFINITIONS -- */
794 /* This type is used for the array of caller data sets in each handler. */
803 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
806 /* Extract the diagnostic strings from the error table macro in the same
807 order as the enumerated indices in ltdl.h. */
809 static const char *lt_dlerror_strings[] =
811 #define LT_ERROR(name, diagnostic) (diagnostic),
818 /* This structure is used for the list of registered loaders. */
820 struct lt_dlloader *next;
821 const char *loader_name; /* identifying name for each loader */
822 const char *sym_prefix; /* prefix for symbols */
823 lt_module_open *module_open;
824 lt_module_close *module_close;
825 lt_find_sym *find_sym;
826 lt_dlloader_exit *dlloader_exit;
827 lt_user_data dlloader_data;
830 struct lt_dlhandle_struct {
831 struct lt_dlhandle_struct *next;
832 lt_dlloader *loader; /* dlopening interface */
834 int depcount; /* number of dependencies */
835 lt_dlhandle *deplibs; /* dependencies */
836 lt_module module; /* system module handle */
837 lt_ptr system; /* system specific data */
838 lt_caller_data *caller_data; /* per caller associated data */
839 int flags; /* various boolean stats */
842 /* Various boolean flags can be stored in the flags field of an
843 lt_dlhandle_struct... */
844 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
845 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
847 #define LT_DLRESIDENT_FLAG (0x01 << 0)
848 /* ...add more flags here... */
850 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
853 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
855 static const char objdir[] = LTDL_OBJDIR;
856 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
857 #ifdef LTDL_SHLIB_EXT
858 static const char shlib_ext[] = LTDL_SHLIB_EXT;
860 #ifdef LTDL_SYSSEARCHPATH
861 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
867 /* --- MUTEX LOCKING --- */
870 /* Macros to make it easier to run the lock functions only if they have
871 been registered. The reason for the complicated lock macro is to
872 ensure that the stored error message from the last error is not
873 accidentally erased if the current function doesn't generate an
875 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
876 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
878 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
879 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
881 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
882 if (lt_dlmutex_seterror_func) \
883 (*lt_dlmutex_seterror_func) (errormsg); \
884 else lt_dllast_error = (errormsg); } LT_STMT_END
885 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
886 if (lt_dlmutex_seterror_func) \
887 (errormsg) = (*lt_dlmutex_geterror_func) (); \
888 else (errormsg) = lt_dllast_error; } LT_STMT_END
890 /* The mutex functions stored here are global, and are necessarily the
891 same for all threads that wish to share access to libltdl. */
892 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
893 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
894 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
895 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
896 static const char *lt_dllast_error = 0;
899 /* Either set or reset the mutex functions. Either all the arguments must
900 be valid functions, or else all can be NULL to turn off locking entirely.
901 The registered functions should be manipulating a static global lock
902 from the lock() and unlock() callbacks, which needs to be reentrant. */
904 lt_dlmutex_register (
905 lt_dlmutex_lock *lock,
906 lt_dlmutex_unlock *unlock,
907 lt_dlmutex_seterror *seterror,
908 lt_dlmutex_geterror *geterror)
910 lt_dlmutex_unlock *old_unlock = unlock;
913 /* Lock using the old lock() callback, if any. */
916 if ((lock && unlock && seterror && geterror)
917 || !(lock || unlock || seterror || geterror))
919 lt_dlmutex_lock_func = lock;
920 lt_dlmutex_unlock_func = unlock;
921 lt_dlmutex_geterror_func = geterror;
925 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
929 /* Use the old unlock() callback we saved earlier, if any. Otherwise
930 record any errors using internal storage. */
934 /* Return the number of errors encountered during the execution of
942 /* --- ERROR HANDLING --- */
945 static const char **user_error_strings = 0;
946 static int errorcount = LT_ERROR_MAX;
949 lt_dladderror (const char *diagnostic)
953 const char **temp = (const char **) 0;
959 errindex = errorcount - LT_ERROR_MAX;
960 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
963 user_error_strings = temp;
964 user_error_strings[errindex] = diagnostic;
965 result = errorcount++;
968 LT_DLMUTEX_UNLOCK ();
974 lt_dlseterror (int errindex)
980 if (errindex >= errorcount || errindex < 0)
982 /* Ack! Error setting the error message! */
983 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
986 else if (errindex < LT_ERROR_MAX)
988 /* No error setting the error message! */
989 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
993 /* No error setting the error message! */
994 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
997 LT_DLMUTEX_UNLOCK ();
1003 lt_emalloc (size_t size)
1005 lt_ptr mem = lt_dlmalloc (size);
1007 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1012 lt_erealloc (lt_ptr addr, size_t size)
1014 lt_ptr mem = lt_dlrealloc (addr, size);
1016 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1021 lt_estrdup (const char *str)
1023 char *copy = strdup (str);
1024 if (LT_STRLEN (str) && !copy)
1025 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1032 /* --- DLOPEN() INTERFACE LOADER --- */
1037 /* dynamic linking with dlopen/dlsym */
1044 # include <sys/dl.h>
1048 # define LT_GLOBAL RTLD_GLOBAL
1051 # define LT_GLOBAL DL_GLOBAL
1053 #endif /* !RTLD_GLOBAL */
1055 # define LT_GLOBAL 0
1056 #endif /* !LT_GLOBAL */
1058 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1059 find out it does not work in some platform. */
1060 #ifndef LT_LAZY_OR_NOW
1062 # define LT_LAZY_OR_NOW RTLD_LAZY
1065 # define LT_LAZY_OR_NOW DL_LAZY
1067 # endif /* !RTLD_LAZY */
1069 #ifndef LT_LAZY_OR_NOW
1071 # define LT_LAZY_OR_NOW RTLD_NOW
1074 # define LT_LAZY_OR_NOW DL_NOW
1076 # endif /* !RTLD_NOW */
1078 #ifndef LT_LAZY_OR_NOW
1079 # define LT_LAZY_OR_NOW 0
1080 #endif /* !LT_LAZY_OR_NOW */
1083 # define DLERROR(arg) dlerror ()
1085 # define DLERROR(arg) LT_DLSTRERROR (arg)
1089 sys_dl_open (lt_user_data loader_data, const char *filename)
1091 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1095 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1102 sys_dl_close (lt_user_data loader_data, lt_module module)
1106 if (dlclose (module) != 0)
1108 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1117 lt_user_data loader_data,
1121 lt_ptr address = dlsym (module, symbol);
1125 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1131 static struct lt_user_dlloader sys_dl =
1138 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1141 #endif /* HAVE_LIBDL */
1145 /* --- SHL_LOAD() INTERFACE LOADER --- */
1149 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1155 /* some flags are missing on some systems, so we provide
1156 * harmless defaults.
1159 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1160 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1163 * BIND_FIRST - Place the library at the head of the symbol search
1165 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1166 * unsatisfied symbols as fatal. This flag allows
1167 * binding of unsatisfied code symbols to be deferred
1169 * [Perl: For certain libraries, like DCE, deferred
1170 * binding often causes run time problems. Adding
1171 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1172 * unresolved references in situations like this.]
1173 * BIND_NOSTART - Do not call the initializer for the shared library
1174 * when the library is loaded, nor on a future call to
1176 * BIND_VERBOSE - Print verbose messages concerning possible
1177 * unsatisfied symbols.
1179 * hp9000s700/hp9000s800:
1180 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1181 * present at library load time.
1182 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1183 * library specified by the path argument.
1186 #ifndef DYNAMIC_PATH
1187 # define DYNAMIC_PATH 0
1189 #ifndef BIND_RESTRICTED
1190 # define BIND_RESTRICTED 0
1193 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1196 sys_shl_open (lt_user_data loader_data, const char *filename)
1198 static shl_t self = (shl_t) 0;
1199 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1201 /* Since searching for a symbol against a NULL module handle will also
1202 look in everything else that was already loaded and exported with
1203 the -E compiler flag, we always cache a handle saved before any
1204 modules are loaded. */
1208 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1217 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1221 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1229 sys_shl_close (lt_user_data loader_data, lt_module module)
1233 if (module && (shl_unload ((shl_t) (module)) != 0))
1235 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1244 lt_user_data loader_data,
1250 /* sys_shl_open should never return a NULL module handle */
1251 if (module == (lt_module) 0)
1253 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1255 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1259 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1266 static struct lt_user_dlloader sys_shl = {
1267 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1270 #endif /* HAVE_SHL_LOAD */
1275 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1279 /* dynamic linking for Win32 */
1281 #include <windows.h>
1283 /* Forward declaration; required to implement handle search below. */
1284 static lt_dlhandle handles;
1287 sys_wll_open (lt_user_data loader_data, const char *filename)
1290 lt_module module = 0;
1291 const char *errormsg = 0;
1292 char *searchname = 0;
1294 char self_name_buf[MAX_PATH];
1298 /* Get the name of main module */
1300 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1301 filename = ext = self_name_buf;
1305 ext = strrchr (filename, '.');
1310 /* FILENAME already has an extension. */
1311 searchname = lt_estrdup (filename);
1315 /* Append a `.' to stop Windows from adding an
1316 implicit `.dll' extension. */
1317 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1319 sprintf (searchname, "%s.", filename);
1326 char wpath[MAX_PATH];
1327 cygwin_conv_to_full_win32_path(searchname, wpath);
1328 module = LoadLibrary(wpath);
1331 module = LoadLibrary (searchname);
1333 LT_DLFREE (searchname);
1335 /* libltdl expects this function to fail if it is unable
1336 to physically load the library. Sadly, LoadLibrary
1337 will search the loaded libraries for a match and return
1338 one of them if the path search load fails.
1340 We check whether LoadLibrary is returning a handle to
1341 an already loaded module, and simulate failure if we
1353 if (cur->module == module)
1360 LT_DLMUTEX_UNLOCK ();
1364 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1372 sys_wll_close (lt_user_data loader_data, lt_module module)
1376 if (FreeLibrary(module) == 0)
1378 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1387 lt_user_data loader_data,
1391 lt_ptr address = GetProcAddress (module, symbol);
1395 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1401 static struct lt_user_dlloader sys_wll = {
1402 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1405 #endif /* __WINDOWS__ */
1410 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1415 /* dynamic linking for BeOS */
1417 #include <kernel/image.h>
1420 sys_bedl_open (lt_user_data loader_data, const char *filename)
1426 image = load_add_on (filename);
1432 if (get_next_image_info (0, &cookie, &info) == B_OK)
1433 image = load_add_on (info.name);
1438 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1442 return (lt_module) image;
1446 sys_bedl_close (lt_user_data loader_data, lt_module module)
1450 if (unload_add_on ((image_id) module) != B_OK)
1452 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1461 lt_user_data loader_data,
1466 image_id image = (image_id) module;
1468 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1470 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1477 static struct lt_user_dlloader sys_bedl = {
1478 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1481 #endif /* __BEOS__ */
1486 /* --- DLD_LINK() INTERFACE LOADER --- */
1491 /* dynamic linking with dld */
1498 sys_dld_open (lt_user_data loader_data, const char *filename)
1500 lt_module module = strdup (filename);
1502 if (dld_link (filename) != 0)
1504 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1513 sys_dld_close (lt_user_data loader_data, lt_module module)
1517 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1519 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1532 lt_user_data loader_data,
1536 lt_ptr address = dld_get_func (symbol);
1540 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1546 static struct lt_user_dlloader sys_dld = {
1547 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1550 #endif /* HAVE_DLD */
1552 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1556 #if HAVE_MACH_O_DYLD_H
1557 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1558 /* Is this correct? Does it still function properly? */
1559 #define __private_extern__ extern
1561 # include <mach-o/dyld.h>
1563 #include <mach-o/getsect.h>
1565 /* We have to put some stuff here that isn't in older dyld.h files */
1566 #ifndef ENUM_DYLD_BOOL
1567 # define ENUM_DYLD_BOOL
1576 # define LC_REQ_DYLD 0x80000000
1578 #ifndef LC_LOAD_WEAK_DYLIB
1579 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1581 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1582 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1583 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1584 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1586 #ifndef NSADDIMAGE_OPTION_NONE
1587 #define NSADDIMAGE_OPTION_NONE 0x0
1589 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1590 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1592 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1593 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1595 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1596 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1598 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1599 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1601 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1602 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1604 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1605 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1607 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1608 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1610 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1611 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1616 lt_int_dyld_error(char* othererror)
1618 /* return the dyld error string, or the passed in error string if none */
1619 NSLinkEditErrors ler;
1623 NSLinkEditError(&ler,&lerno,&file,&errstr);
1624 if (!errstr || !strlen(errstr)) errstr = othererror;
1628 static const struct mach_header *
1629 lt_int_dyld_get_mach_header_from_nsmodule(NSModule module)
1631 /* There should probably be an apple dyld api for this */
1632 int i=_dyld_image_count();
1634 const char *modname=NSNameOfModule(module);
1635 const struct mach_header *mh=NULL;
1636 if (!modname) return NULL;
1637 for (j = 0; j < i; j++)
1639 if (!strcmp(_dyld_get_image_name(j),modname))
1641 mh=_dyld_get_image_header(j);
1648 static const char* lt_int_dyld_lib_install_name(const struct mach_header *mh)
1650 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1651 is installed, for uninstalled libs we need to check the install_names against
1652 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1653 different lib was loaded as a result
1656 struct load_command *lc;
1657 unsigned long offset = sizeof(struct mach_header);
1658 const char* retStr=NULL;
1659 for (j = 0; j < mh->ncmds; j++)
1661 lc = (struct load_command*)(((unsigned long)mh) + offset);
1662 if (LC_ID_DYLIB == lc->cmd)
1664 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1667 offset += lc->cmdsize;
1672 static const struct mach_header *
1673 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1675 int i=_dyld_image_count();
1677 const struct mach_header *mh=NULL;
1678 const char *id=NULL;
1679 for (j = 0; j < i; j++)
1681 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1682 if ((id) && (!strcmp(id,name)))
1684 mh=_dyld_get_image_header(j);
1692 lt_int_dyld_NSlookupSymbolInLinkedLibs(const char *symbol, const struct mach_header *mh)
1694 /* Safe to assume our mh is good */
1696 struct load_command *lc;
1697 unsigned long offset = sizeof(struct mach_header);
1698 NSSymbol retSym = 0;
1699 const struct mach_header *mh1;
1700 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1702 for (j = 0; j < mh->ncmds; j++)
1704 lc = (struct load_command*)(((unsigned long)mh) + offset);
1705 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1707 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1708 (unsigned long)lc));
1711 /* Maybe NSAddImage can find it */
1712 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1714 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1715 NSADDIMAGE_OPTION_WITH_SEARCHING +
1716 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1720 retSym = ltdl_NSLookupSymbolInImage(mh1,
1722 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1723 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1728 offset += lc->cmdsize;
1739 if (!_dyld_present()) {
1743 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage);
1744 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage);
1745 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage);
1746 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic);
1752 sys_dyld_open (lt_user_data loader_data, const char *filename)
1754 lt_module module = 0;
1755 NSObjectFileImage ofi = 0;
1756 NSObjectFileImageReturnCode ofirc;
1759 return (lt_module)-1;
1760 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1763 case NSObjectFileImageSuccess:
1764 module = NSLinkModule(ofi, filename,
1765 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1766 | NSLINKMODULE_OPTION_PRIVATE
1767 | NSLINKMODULE_OPTION_BINDNOW);
1768 NSDestroyObjectFileImage(ofi);
1770 ltdl_NSMakePrivateModulePublic(module);
1772 case NSObjectFileImageInappropriateFile:
1773 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1775 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1779 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1782 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1787 sys_dyld_close (lt_user_data loader_data, lt_module module)
1791 if (module == (lt_module)-1) return 0;
1792 #ifdef __BIG_ENDIAN__
1793 if (((struct mach_header *)module)->magic == MH_MAGIC)
1795 if (((struct mach_header *)module)->magic == MH_CIGAM)
1798 LT_DLMUTEX_SETERROR("Can not close a dylib");
1804 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1805 get a segfault in atexit(), due to compiler and dynamic loader differences of
1806 opinion, this works around that.
1808 if ((const struct section *)NULL !=
1809 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1810 "__DATA","__mod_term_func"))
1812 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1816 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1818 if (!NSUnLinkModule(module,flags))
1821 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1830 lt_user_data loader_data,
1835 NSSymbol *nssym = 0;
1837 const struct mach_header *mh=NULL;
1838 char saveError[256] = "Symbol not found";
1839 if (module == (lt_module)-1)
1841 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1844 #ifdef __BIG_ENDIAN__
1845 if (((struct mach_header *)module)->magic == MH_MAGIC)
1847 if (((struct mach_header *)module)->magic == MH_CIGAM)
1850 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1853 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1855 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1857 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1858 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1865 nssym = NSLookupSymbolInModule(module, symbol);
1869 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1871 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1872 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1876 LT_DLMUTEX_SETERROR (saveError);
1879 return NSAddressOfSymbol(nssym);
1882 static struct lt_user_dlloader sys_dyld =
1883 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1886 #endif /* HAVE_DYLD */
1889 /* --- DLPREOPEN() INTERFACE LOADER --- */
1892 /* emulate dynamic linking using preloaded_symbols */
1894 typedef struct lt_dlsymlists_t
1896 struct lt_dlsymlists_t *next;
1897 const lt_dlsymlist *syms;
1900 static const lt_dlsymlist *default_preloaded_symbols = 0;
1901 static lt_dlsymlists_t *preloaded_symbols = 0;
1904 presym_init (lt_user_data loader_data)
1910 preloaded_symbols = 0;
1911 if (default_preloaded_symbols)
1913 errors = lt_dlpreload (default_preloaded_symbols);
1916 LT_DLMUTEX_UNLOCK ();
1922 presym_free_symlists ()
1924 lt_dlsymlists_t *lists;
1928 lists = preloaded_symbols;
1931 lt_dlsymlists_t *tmp = lists;
1933 lists = lists->next;
1936 preloaded_symbols = 0;
1938 LT_DLMUTEX_UNLOCK ();
1944 presym_exit (lt_user_data loader_data)
1946 presym_free_symlists ();
1951 presym_add_symlist (const lt_dlsymlist *preloaded)
1953 lt_dlsymlists_t *tmp;
1954 lt_dlsymlists_t *lists;
1959 lists = preloaded_symbols;
1962 if (lists->syms == preloaded)
1966 lists = lists->next;
1969 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
1972 memset (tmp, 0, sizeof(lt_dlsymlists_t));
1973 tmp->syms = preloaded;
1974 tmp->next = preloaded_symbols;
1975 preloaded_symbols = tmp;
1983 LT_DLMUTEX_UNLOCK ();
1988 presym_open (lt_user_data loader_data, const char *filename)
1990 lt_dlsymlists_t *lists;
1991 lt_module module = (lt_module) 0;
1994 lists = preloaded_symbols;
1998 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2002 /* Can't use NULL as the reflective symbol header, as NULL is
2003 used to mark the end of the entire symbol list. Self-dlpreopened
2004 symbols follow this magic number, chosen to be an unlikely
2005 clash with a real module name. */
2008 filename = "@PROGRAM@";
2013 const lt_dlsymlist *syms = lists->syms;
2017 if (!syms->address && strcmp(syms->name, filename) == 0)
2019 module = syms->address;
2025 lists = lists->next;
2028 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2031 LT_DLMUTEX_UNLOCK ();
2036 presym_close (lt_user_data loader_data, lt_module module)
2038 /* Just to silence gcc -Wall */
2045 lt_user_data loader_data,
2049 lt_dlsymlist *syms = (lt_dlsymlist*) module;
2052 while (syms->address)
2054 if (strcmp(syms->name, symbol) == 0)
2056 return syms->address;
2062 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2067 static struct lt_user_dlloader presym = {
2068 0, presym_open, presym_close, presym_sym, presym_exit, 0
2075 /* --- DYNAMIC MODULE LOADING --- */
2078 /* The type of a function used at each iteration of foreach_dirinpath(). */
2079 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2082 static int foreach_dirinpath LT_PARAMS((const char *search_path,
2083 const char *base_name,
2084 foreach_callback_func *func,
2085 lt_ptr data1, lt_ptr data2));
2087 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2089 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2091 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2095 static int canonicalize_path LT_PARAMS((const char *path,
2096 char **pcanonical));
2097 static int argzize_path LT_PARAMS((const char *path,
2099 size_t *pargz_len));
2100 static FILE *find_file LT_PARAMS((const char *search_path,
2101 const char *base_name,
2103 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2104 const char *base_name,
2105 lt_dlhandle *handle));
2106 static int find_module LT_PARAMS((lt_dlhandle *handle,
2110 const char *old_name,
2112 static int free_vars LT_PARAMS((char *dlname, char *oldname,
2113 char *libdir, char *deplibs));
2114 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2116 static int trim LT_PARAMS((char **dest,
2118 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2119 const char *filename));
2120 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2121 const char *filename));
2122 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2123 static int lt_argz_insert LT_PARAMS((char **pargz,
2126 const char *entry));
2127 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2129 const char *entry));
2130 static int lt_argz_insertdir LT_PARAMS((char **pargz,
2133 struct dirent *dp));
2134 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2137 static int list_files_by_dir LT_PARAMS((const char *dirnam,
2139 size_t *pargz_len));
2140 static int file_not_found LT_PARAMS((void));
2142 static char *user_search_path= 0;
2143 static lt_dlloader *loaders = 0;
2144 static lt_dlhandle handles = 0;
2145 static int initialized = 0;
2147 /* Initialize libltdl. */
2155 /* Initialize only at first call. */
2156 if (++initialized == 1)
2159 user_search_path = 0; /* empty search path */
2162 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2165 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2168 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2171 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2174 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2177 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2178 errors += sys_dyld_init();
2180 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2182 if (presym_init (presym.dlloader_data))
2184 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2187 else if (errors != 0)
2189 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2194 LT_DLMUTEX_UNLOCK ();
2200 lt_dlpreload (const lt_dlsymlist *preloaded)
2206 errors = presym_add_symlist (preloaded);
2210 presym_free_symlists();
2213 if (default_preloaded_symbols)
2215 errors = lt_dlpreload (default_preloaded_symbols);
2217 LT_DLMUTEX_UNLOCK ();
2224 lt_dlpreload_default (const lt_dlsymlist *preloaded)
2227 default_preloaded_symbols = preloaded;
2228 LT_DLMUTEX_UNLOCK ();
2235 /* shut down libltdl */
2236 lt_dlloader *loader;
2244 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2249 /* shut down only at last call. */
2250 if (--initialized == 0)
2254 while (handles && LT_DLIS_RESIDENT (handles))
2256 handles = handles->next;
2259 /* close all modules */
2260 for (level = 1; handles; ++level)
2262 lt_dlhandle cur = handles;
2263 int saw_nonresident = 0;
2267 lt_dlhandle tmp = cur;
2269 if (!LT_DLIS_RESIDENT (tmp))
2270 saw_nonresident = 1;
2271 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2273 if (lt_dlclose (tmp))
2279 /* done if only resident modules are left */
2280 if (!saw_nonresident)
2284 /* close all loaders */
2287 lt_dlloader *next = loader->next;
2288 lt_user_data data = loader->dlloader_data;
2289 if (loader->dlloader_exit && loader->dlloader_exit (data))
2294 LT_DLMEM_REASSIGN (loader, next);
2300 LT_DLMUTEX_UNLOCK ();
2305 tryall_dlopen (lt_dlhandle *handle, const char *filename)
2308 lt_dlloader *loader;
2309 const char *saved_error;
2312 LT_DLMUTEX_GETERROR (saved_error);
2318 /* check whether the module was already opened */
2321 /* try to dlopen the program itself? */
2322 if (!cur->info.filename && !filename)
2327 if (cur->info.filename && filename
2328 && strcmp (cur->info.filename, filename) == 0)
2338 ++cur->info.ref_count;
2346 /* Comment out the check of file permissions using access.
2347 This call seems to always return -1 with error EACCES.
2349 /* We need to catch missing file errors early so that
2350 file_not_found() can detect what happened.
2351 if (access (filename, R_OK) != 0)
2353 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2358 cur->info.filename = lt_estrdup (filename);
2359 if (!cur->info.filename)
2367 cur->info.filename = 0;
2372 lt_user_data data = loader->dlloader_data;
2374 cur->module = loader->module_open (data, filename);
2376 if (cur->module != 0)
2380 loader = loader->next;
2385 LT_DLFREE (cur->info.filename);
2390 cur->loader = loader;
2391 LT_DLMUTEX_SETERROR (saved_error);
2394 LT_DLMUTEX_UNLOCK ();
2400 tryall_dlopen_module (
2401 lt_dlhandle *handle,
2403 const char *dirname,
2408 size_t filename_len = 0;
2409 size_t dirname_len = LT_STRLEN (dirname);
2414 #ifdef LT_DIRSEP_CHAR
2415 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2416 should make it into this function: */
2417 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2420 if (dirname_len > 0)
2421 if (dirname[dirname_len -1] == '/')
2423 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2425 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2426 The PREFIX (if any) is handled below. */
2427 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2431 snprintf (filename, dirname_len + 1 + filename_len + 1, "%.*s/%s", (int) dirname_len, dirname, dlname);
2433 /* Now that we have combined DIRNAME and MODULENAME, if there is
2434 also a PREFIX to contend with, simply recurse with the arguments
2435 shuffled. Otherwise, attempt to open FILENAME as a module. */
2438 error += tryall_dlopen_module (handle,
2439 (const char *) 0, prefix, filename);
2441 else if (tryall_dlopen (handle, filename) != 0)
2446 LT_DLFREE (filename);
2452 lt_dlhandle *handle,
2456 const char *old_name,
2459 /* Try to open the old library first; if it was dlpreopened,
2460 we want the preopened version of it, even if a dlopenable
2461 module is available. */
2462 if (old_name && tryall_dlopen (handle, old_name) == 0)
2467 /* Try to open the dynamic library. */
2470 /* try to open the installed module */
2471 if (installed && libdir)
2473 if (tryall_dlopen_module (handle,
2474 (const char *) 0, libdir, dlname) == 0)
2478 /* try to open the not-installed module */
2481 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2485 /* maybe it was moved to another directory */
2487 if (tryall_dlopen_module (handle,
2488 (const char *) 0, dir, dlname) == 0)
2502 char *canonical = 0;
2504 assert (path && *path);
2505 assert (pcanonical);
2507 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2514 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2516 /* Path separators are not copied to the beginning or end of
2517 the destination, or if another separator would follow
2519 if (path[src] == LT_PATHSEP_CHAR)
2522 || (path[1+ src] == LT_PATHSEP_CHAR)
2523 || (path[1+ src] == LT_EOS_CHAR))
2527 /* Anything other than a directory separator is copied verbatim. */
2528 if ((path[src] != '/')
2529 #ifdef LT_DIRSEP_CHAR
2530 && (path[src] != LT_DIRSEP_CHAR)
2534 canonical[dest++] = path[src];
2536 /* Directory separators are converted and copied only if they are
2537 not at the end of a path -- i.e. before a path separator or
2539 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2540 && (path[1+ src] != LT_EOS_CHAR)
2541 #ifdef LT_DIRSEP_CHAR
2542 && (path[1+ src] != LT_DIRSEP_CHAR)
2544 && (path[1+ src] != '/'))
2546 canonical[dest++] = '/';
2550 /* Add an end-of-string marker at the end. */
2551 canonical[dest] = LT_EOS_CHAR;
2554 /* Assign new value. */
2555 *pcanonical = canonical;
2572 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2577 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2580 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2590 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2591 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2592 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2593 it is appended to each SEARCH_PATH element before FUNC is called. */
2596 const char *search_path,
2597 const char *base_name,
2598 foreach_callback_func *func,
2603 int filenamesize = 0;
2604 size_t lenbase = LT_STRLEN (base_name);
2605 size_t argz_len = 0;
2608 char *canonical = 0;
2612 if (!search_path || !*search_path)
2614 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2618 if (canonicalize_path (search_path, &canonical) != 0)
2621 if (argzize_path (canonical, &argz, &argz_len) != 0)
2626 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2628 size_t lendir = LT_STRLEN (dir_name);
2630 if ((int)(lendir +1 +lenbase) >= filenamesize)
2632 LT_DLFREE (filename);
2633 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2634 filename = LT_EMALLOC (char, filenamesize);
2639 assert ((int)lendir > 0);
2640 assert (filenamesize > (int)lendir);
2641 strncpy (filename, dir_name, filenamesize);
2643 if (base_name && *base_name)
2645 if (filename[lendir -1] != '/')
2646 filename[lendir++] = '/';
2648 strncpy (filename + lendir, base_name, filenamesize - lendir);
2651 if ((result = (*func) (filename, data1, data2)))
2660 LT_DLFREE (canonical);
2661 LT_DLFREE (filename);
2663 LT_DLMUTEX_UNLOCK ();
2668 /* If FILEPATH can be opened, store the name of the directory component
2669 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2670 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2672 find_file_callback (
2677 char **pdir = (char **) data1;
2678 FILE **pfile = (FILE **) data2;
2681 assert (filename && *filename);
2685 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2687 char *dirend = const_cast<char *>(strrchr (filename, '/'));
2690 *dirend = LT_EOS_CHAR;
2693 *pdir = lt_estrdup (filename);
2694 is_done = (*pdir == 0) ? -1 : 1;
2702 const char *search_path,
2703 const char *base_name,
2708 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2714 find_handle_callback (
2719 lt_dlhandle *handle = (lt_dlhandle *) data;
2720 int notfound = access (filename, R_OK);
2722 /* Bail out if file cannot be read... */
2726 /* Try to dlopen the file, but do not continue searching in any
2728 if (tryall_dlopen (handle, filename) != 0)
2734 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2735 found but could not be opened, *HANDLE will be set to 0. */
2736 static lt_dlhandle *
2738 const char *search_path,
2739 const char *base_name,
2740 lt_dlhandle *handle)
2745 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2757 #if LTDL_DLOPEN_DEPLIBS
2758 char *p, *save_search_path = 0;
2765 handle->depcount = 0;
2767 #if LTDL_DLOPEN_DEPLIBS
2775 if (user_search_path)
2777 save_search_path = lt_estrdup (user_search_path);
2778 if (!save_search_path)
2782 /* extract search paths and count deplibs */
2786 if (!isspace ((int) *p))
2789 while (*end && !isspace((int) *end))
2794 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2797 *end = 0; /* set a temporary string terminator */
2798 if (lt_dladdsearchdir(p+2))
2817 /* restore the old search path */
2818 LT_DLFREE (user_search_path);
2819 user_search_path = save_search_path;
2821 LT_DLMUTEX_UNLOCK ();
2829 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2833 /* now only extract the actual deplibs */
2838 if (isspace ((int) *p))
2845 while (*end && !isspace ((int) *end))
2850 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2854 *end = 0; /* set a temporary string terminator */
2855 if (strncmp(p, "-l", 2) == 0)
2857 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2858 name = LT_EMALLOC (char, 1+ name_len);
2860 sprintf (name, "lib%s", p+2);
2863 name = lt_estrdup(p);
2868 names[depcount++] = name;
2875 /* load the deplibs (in reverse order)
2876 At this stage, don't worry if the deplibs do not load correctly,
2877 they may already be statically linked into the loading application
2878 for instance. There will be a more enlightening error message
2879 later on if the loaded module cannot resolve all of its symbols. */
2884 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2885 if (!handle->deplibs)
2888 for (i = 0; i < depcount; ++i)
2890 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2891 if (handle->deplibs[j])
2897 handle->depcount = j; /* Number of successfully loaded deplibs */
2902 for (i = 0; i < depcount; ++i)
2904 LT_DLFREE (names[i]);
2921 if (handle->depcount)
2923 for (i = 0; i < handle->depcount; ++i)
2925 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2927 errors += lt_dlclose (handle->deplibs[i]);
2940 /* remove the leading and trailing "'" from str
2941 and store the result in dest */
2942 const char *end = strrchr (str, '\'');
2943 size_t len = LT_STRLEN (str);
2948 if (len > 3 && str[0] == '\'')
2950 tmp = LT_EMALLOC (char, end - str);
2954 strncpy(tmp, &str[1], (end - str) - 1);
2955 tmp[len-3] = LT_EOS_CHAR;
2974 LT_DLFREE (oldname);
2976 LT_DLFREE (deplibs);
2983 lt_dlhandle *phandle,
2984 const char *filename)
2986 const char * ext = 0;
2987 const char * saved_error = 0;
2988 char * canonical = 0;
2989 char * base_name = 0;
2993 lt_dlhandle newhandle;
2996 assert (*phandle == 0);
2998 LT_DLMUTEX_GETERROR (saved_error);
3003 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3007 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3008 newhandle = *phandle;
3010 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3011 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3013 if (tryall_dlopen (&newhandle, 0) != 0)
3015 LT_DLFREE (*phandle);
3019 goto register_handle;
3022 assert (filename && *filename);
3024 /* Doing this immediately allows internal functions to safely
3025 assume only canonicalized paths are passed. */
3026 if (canonicalize_path (filename, &canonical) != 0)
3032 /* If the canonical module name is a path (relative or absolute)
3033 then split it into a directory part and a name part. */
3034 base_name = const_cast<char *>(strrchr (canonical, '/'));
3037 size_t dirlen = (1+ base_name) - canonical;
3039 dir = LT_EMALLOC (char, 1+ dirlen);
3046 strncpy (dir, canonical, dirlen);
3047 dir[dirlen] = LT_EOS_CHAR;
3053 LT_DLMEM_REASSIGN (base_name, canonical);
3054 canonical = base_name;
3057 assert (base_name && *base_name);
3059 /* Check whether we are opening a libtool module (.la extension). */
3060 ext = strrchr (base_name, '.');
3061 if (ext && strcmp (ext, archive_ext) == 0)
3063 /* this seems to be a libtool module */
3066 char * old_name = 0;
3072 /* if we can't find the installed flag, it is probably an
3073 installed libtool archive, produced with an old version
3077 /* extract the module name from the file name */
3078 name = LT_EMALLOC (char, ext - base_name + 1);
3085 /* canonicalize the module name */
3088 for (i = 0; i < ext - base_name; ++i)
3090 if (isalnum ((int)(base_name[i])))
3092 name[i] = base_name[i];
3099 name[ext - base_name] = LT_EOS_CHAR;
3102 /* Now try to open the .la file. If there is no directory name
3103 component, try to find it first in user_search_path and then other
3104 prescribed paths. Otherwise (or in any case if the module was not
3105 yet found) try opening just the module name as passed. */
3108 const char *search_path;
3111 search_path = user_search_path;
3113 file = find_file (user_search_path, base_name, &dir);
3114 LT_DLMUTEX_UNLOCK ();
3118 search_path = getenv (LTDL_SEARCHPATH_VAR);
3120 file = find_file (search_path, base_name, &dir);
3123 #ifdef LTDL_SHLIBPATH_VAR
3126 search_path = getenv (LTDL_SHLIBPATH_VAR);
3128 file = find_file (search_path, base_name, &dir);
3131 #ifdef LTDL_SYSSEARCHPATH
3134 file = find_file (sys_search_path, base_name, &dir);
3140 file = fopen (filename, LT_READTEXT_MODE);
3143 /* If we didn't find the file by now, it really isn't there. Set
3144 the status flag, and bail out. */
3147 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3152 line_len = LT_FILENAME_MAX;
3153 line = LT_EMALLOC (char, line_len);
3161 /* read the .la file */
3162 while (!feof (file))
3164 if (!fgets (line, (int) line_len, file))
3169 /* Handle the case where we occasionally need to read a line
3170 that is longer than the initial buffer size. */
3171 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3173 line = LT_DLREALLOC (char, line, line_len *2);
3174 if (!fgets (&line[line_len -1], (int) line_len +1, file))
3181 if (line[0] == '\n' || line[0] == '#')
3187 #define STR_DLNAME "dlname="
3188 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3190 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3193 #undef STR_OLD_LIBRARY
3194 #define STR_OLD_LIBRARY "old_library="
3195 else if (strncmp (line, STR_OLD_LIBRARY,
3196 sizeof (STR_OLD_LIBRARY) - 1) == 0)
3198 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3201 #define STR_LIBDIR "libdir="
3202 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3204 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3207 #undef STR_DL_DEPLIBS
3208 #define STR_DL_DEPLIBS "dependency_libs="
3209 else if (strncmp (line, STR_DL_DEPLIBS,
3210 sizeof (STR_DL_DEPLIBS) - 1) == 0)
3212 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3214 else if (strcmp (line, "installed=yes\n") == 0)
3218 else if (strcmp (line, "installed=no\n") == 0)
3223 #undef STR_LIBRARY_NAMES
3224 #define STR_LIBRARY_NAMES "library_names="
3225 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3226 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3229 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3232 && (last_libname = const_cast<char *>(strrchr (dlname, ' '))) != 0)
3234 last_libname = lt_estrdup (last_libname + 1);
3241 LT_DLMEM_REASSIGN (dlname, last_libname);
3252 /* allocate the handle */
3253 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3259 free_vars (dlname, old_name, libdir, deplibs);
3260 LT_DLFREE (*phandle);
3266 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3267 if (load_deplibs (*phandle, deplibs) == 0)
3269 newhandle = *phandle;
3270 /* find_module may replace newhandle */
3271 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3273 unload_deplibs (*phandle);
3282 free_vars (dlname, old_name, libdir, deplibs);
3285 LT_DLFREE (*phandle);
3289 if (*phandle != newhandle)
3291 unload_deplibs (*phandle);
3296 /* not a libtool module */
3297 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3304 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3305 newhandle = *phandle;
3307 /* If the module has no directory name component, try to find it
3308 first in user_search_path and then other prescribed paths.
3309 Otherwise (or in any case if the module was not yet found) try
3310 opening just the module name as passed. */
3311 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3312 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3314 #ifdef LTDL_SHLIBPATH_VAR
3315 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3318 #ifdef LTDL_SYSSEARCHPATH
3319 && !find_handle (sys_search_path, base_name, &newhandle)
3323 if (tryall_dlopen (&newhandle, filename) != 0)
3331 LT_DLFREE (*phandle);
3338 LT_DLMEM_REASSIGN (*phandle, newhandle);
3340 if ((*phandle)->info.ref_count == 0)
3342 (*phandle)->info.ref_count = 1;
3343 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3346 (*phandle)->next = handles;
3348 LT_DLMUTEX_UNLOCK ();
3351 LT_DLMUTEX_SETERROR (saved_error);
3356 LT_DLFREE (canonical);
3363 const char *filename)
3365 lt_dlhandle handle = 0;
3367 /* Just incase we missed a code path in try_dlopen() that reports
3368 an error, but forgets to reset handle... */
3369 if (try_dlopen (&handle, filename) != 0)
3375 /* If the last error messge store was `FILE_NOT_FOUND', then return
3380 const char *error = 0;
3382 LT_DLMUTEX_GETERROR (error);
3383 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3389 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3390 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3391 and if a file is still not found try again with SHLIB_EXT appended
3395 const char *filename)
3397 lt_dlhandle handle = 0;
3405 return lt_dlopen (filename);
3410 len = LT_STRLEN (filename);
3411 ext = const_cast<char *>(strrchr (const_cast<char *>(filename), '.'));
3413 /* If FILENAME already bears a suitable extension, there is no need
3414 to try appending additional extensions. */
3415 if (ext && ((strcmp (ext, archive_ext) == 0)
3416 #ifdef LTDL_SHLIB_EXT
3417 || (strcmp (ext, shlib_ext) == 0)
3421 return lt_dlopen (filename);
3424 /* First try appending ARCHIVE_EXT. */
3425 tmp = LT_EMALLOC (char, len + strlen (archive_ext) + 1);
3429 strncpy (tmp, filename, len + strlen (archive_ext) + 1);
3430 strncat (tmp, archive_ext, (len + strlen (archive_ext) + 1) - strlen (tmp) - 1);
3431 tmp[len + strlen (archive_ext)] = LT_EOS_CHAR;
3432 errors = try_dlopen (&handle, tmp);
3434 /* If we found FILENAME, stop searching -- whether we were able to
3435 load the file as a module or not. If the file exists but loading
3436 failed, it is better to return an error message here than to
3437 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3438 in the module search path. */
3439 if (handle || ((errors > 0) && !file_not_found ()))
3445 #ifdef LTDL_SHLIB_EXT
3446 /* Try appending SHLIB_EXT. */
3447 if (strlen (shlib_ext) > strlen (archive_ext))
3450 tmp = LT_EMALLOC (char, len + strlen (shlib_ext) + 1);
3454 strncpy (tmp, filename, len + strlen (shlib_ext) + 1);
3458 tmp[len] = LT_EOS_CHAR;
3461 strncat(tmp, shlib_ext,(len + strlen (shlib_ext) + 1) - strlen (tmp) - 1);
3462 tmp[len + strlen (shlib_ext)] = LT_EOS_CHAR;
3463 errors = try_dlopen (&handle, tmp);
3465 /* As before, if the file was found but loading failed, return now
3466 with the current error message. */
3467 if (handle || ((errors > 0) && !file_not_found ()))
3474 /* Still here? Then we really did fail to locate any of the file
3476 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3491 if ((error = argz_insert (pargz, pargz_len, before, entry)))
3496 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3499 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3509 lt_argz_insertinorder (
3518 assert (entry && *entry);
3521 while ((before = argz_next (*pargz, *pargz_len, before)))
3523 int cmp = strcmp (entry, before);
3526 if (cmp == 0) return 0; /* No duplicates! */
3529 return lt_argz_insert (pargz, pargz_len, before, entry);
3542 size_t end_offset = 0;
3550 dir_len = LT_STRLEN (dirnam);
3551 end = dp->d_name + LT_D_NAMLEN(dp);
3553 /* Ignore version numbers. */
3556 for (p = end; p -1 > dp->d_name; --p)
3557 if (strchr (".0123456789", p[-1]) == 0)
3564 /* Ignore filename extension. */
3567 for (p = end -1; p > dp->d_name; --p)
3575 /* Prepend the directory name. */
3576 end_offset = end - dp->d_name;
3577 buf_len = dir_len + 1+ end_offset;
3578 buf = LT_EMALLOC (char, 1+ buf_len);
3584 strncpy (buf, dirnam, 1+ buf_len);
3585 strncat (buf, "/", (1+ buf_len) - strlen(buf) - 1);
3586 strncat (buf, dp->d_name, end_offset);
3587 buf[buf_len] = LT_EOS_CHAR;
3589 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3590 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3607 assert (dirnam && *dirnam);
3610 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3612 dirp = opendir (dirnam);
3615 struct dirent *dp = 0;
3617 while ((dp = readdir (dirp)))
3618 if (dp->d_name[0] != '.')
3619 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3634 /* If there are any files in DIRNAME, call the function passed in
3635 DATA1 (with the name of each file and DATA2 as arguments). */
3637 foreachfile_callback (
3642 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3643 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3647 size_t argz_len = 0;
3649 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3656 while ((filename = argz_next (argz, argz_len, filename)))
3657 if ((is_done = (*func) (filename, data2)))
3668 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3669 with DATA. The filenames passed to FUNC would be suitable for
3670 passing to lt_dlopenext. The extensions are stripped so that
3671 individual modules do not generate several entries (e.g. libfoo.la,
3672 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3673 then the same directories that lt_dlopen would search are examined. */
3676 const char *search_path,
3677 int (*func) LT_PARAMS ((const char *filename, lt_ptr data)),
3684 /* If a specific path was passed, search only the directories
3686 is_done = foreach_dirinpath (search_path, 0,
3687 foreachfile_callback, (void*)func, data);
3691 /* Otherwise search the default paths. */
3692 is_done = foreach_dirinpath (user_search_path, 0,
3693 foreachfile_callback, (void*)func, data);
3696 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3697 foreachfile_callback, (void*)func, data);
3700 #ifdef LTDL_SHLIBPATH_VAR
3703 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3704 foreachfile_callback, (void*)func, data);
3707 #ifdef LTDL_SYSSEARCHPATH
3710 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3711 foreachfile_callback, (void*)func, data);
3723 lt_dlhandle cur, last;
3728 /* check whether the handle is valid */
3729 last = cur = handles;
3730 while (cur && handle != cur)
3738 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3743 handle->info.ref_count--;
3745 /* Note that even with resident modules, we must track the ref_count
3746 correctly incase the user decides to reset the residency flag
3747 later (even though the API makes no provision for that at the
3749 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3751 lt_user_data data = handle->loader->dlloader_data;
3753 if (handle != handles)
3755 last->next = handle->next;
3759 handles = handle->next;
3762 errors += handle->loader->module_close (data, handle->module);
3763 errors += unload_deplibs(handle);
3765 /* It is up to the callers to free the data itself. */
3766 LT_DLFREE (handle->caller_data);
3768 LT_DLFREE (handle->info.filename);
3769 LT_DLFREE (handle->info.name);
3775 if (LT_DLIS_RESIDENT (handle))
3777 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3782 LT_DLMUTEX_UNLOCK ();
3793 char lsym[LT_SYMBOL_LENGTH];
3800 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3806 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3810 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3811 + LT_STRLEN (handle->info.name);
3813 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3816 lensym = LT_SYMBOL_LENGTH;
3820 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3821 lensym = lensym + LT_SYMBOL_OVERHEAD + 1;
3824 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3829 data = handle->loader->dlloader_data;
3830 if (handle->info.name)
3832 const char *saved_error;
3834 LT_DLMUTEX_GETERROR (saved_error);
3836 /* this is a libtool module */
3837 if (handle->loader->sym_prefix)
3839 strncpy(sym, handle->loader->sym_prefix, lensym - 1);
3840 strncat(sym, handle->info.name, lensym - strlen(sym) - 1);
3844 strncpy(sym, handle->info.name, lensym - 1);
3847 strncat(sym, "_LTX_", lensym - strlen(sym) - 1);
3848 strncat(sym, symbol, lensym - strlen(sym) - 1);
3850 /* try "modulename_LTX_symbol" */
3851 address = handle->loader->find_sym (data, handle->module, sym);
3860 LT_DLMUTEX_SETERROR (saved_error);
3863 /* otherwise try "symbol" */
3864 if (handle->loader->sym_prefix)
3866 strncpy(sym, handle->loader->sym_prefix, lensym - 1);
3867 strncat(sym, symbol, lensym - strlen(sym) - 1);
3871 strncpy(sym, symbol, lensym - 1);
3874 address = handle->loader->find_sym (data, handle->module, sym);
3888 LT_DLMUTEX_GETERROR (error);
3889 LT_DLMUTEX_SETERROR (0);
3891 return error ? error : NULL;
3895 lt_dlpath_insertdir (
3901 char *canonical = 0;
3903 size_t argz_len = 0;
3906 assert (dir && *dir);
3908 if (canonicalize_path (dir, &canonical) != 0)
3914 assert (canonical && *canonical);
3916 /* If *PPATH is empty, set it to DIR. */
3919 assert (!before); /* BEFORE cannot be set without PPATH. */
3920 assert (dir); /* Without DIR, don't call this function! */
3922 *ppath = lt_estrdup (dir);
3929 assert (ppath && *ppath);
3931 if (argzize_path (*ppath, &argz, &argz_len) != 0)
3937 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
3938 if *PPATH is already canonicalized, and hence does not change length
3939 with respect to ARGZ. We canonicalize each entry as it is added to
3940 the search path, and don't call this function with (uncanonicalized)
3941 user paths, so this is a fair assumption. */
3944 assert (*ppath <= before);
3945 assert (before - *ppath <= (int)strlen (*ppath));
3947 before = before - *ppath + argz;
3950 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3956 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3957 LT_DLMEM_REASSIGN (*ppath, argz);
3960 LT_DLFREE (canonical);
3968 const char *search_dir)
3972 if (search_dir && *search_dir)
3975 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
3977 LT_DLMUTEX_UNLOCK ();
3984 lt_dlinsertsearchdir (
3986 const char *search_dir)
3993 if ((before < user_search_path)
3994 || (before >= user_search_path + LT_STRLEN (user_search_path)))
3996 LT_DLMUTEX_UNLOCK ();
3997 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4000 LT_DLMUTEX_UNLOCK ();
4003 if (search_dir && *search_dir)
4006 if (lt_dlpath_insertdir (&user_search_path,
4007 const_cast<char*>(before), search_dir) != 0)
4011 LT_DLMUTEX_UNLOCK ();
4018 lt_dlsetsearchpath (
4019 const char *search_path)
4024 LT_DLFREE (user_search_path);
4025 LT_DLMUTEX_UNLOCK ();
4027 if (!search_path || !LT_STRLEN (search_path))
4033 if (canonicalize_path (search_path, &user_search_path) != 0)
4035 LT_DLMUTEX_UNLOCK ();
4041 lt_dlgetsearchpath ()
4043 const char *saved_path;
4046 saved_path = user_search_path;
4047 LT_DLMUTEX_UNLOCK ();
4060 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4065 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4077 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4081 return LT_DLIS_RESIDENT (handle);
4087 /* --- MODULE INFORMATION --- */
4095 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4099 return &(handle->info);
4106 return place ? place->next : handles;
4111 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)),
4122 lt_dlhandle tmp = cur;
4125 if ((*func) (tmp, data))
4132 LT_DLMUTEX_UNLOCK ();
4138 lt_dlcaller_register ()
4140 static lt_dlcaller_id last_caller_id = 0;
4144 result = ++last_caller_id;
4145 LT_DLMUTEX_UNLOCK ();
4151 lt_dlcaller_set_data (
4157 lt_ptr stale = (lt_ptr) 0;
4160 /* This needs to be locked so that the caller data can be updated
4161 simultaneously by different threads. */
4164 if (handle->caller_data)
4165 while (handle->caller_data[n_elements].key)
4168 for (i = 0; i < n_elements; ++i)
4170 if (handle->caller_data[i].key == key)
4172 stale = handle->caller_data[i].data;
4177 /* Ensure that there is enough room in this handle's caller_data
4178 array to accept a new element (and an empty end marker). */
4179 if (i == n_elements)
4181 lt_caller_data *temp
4182 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4190 handle->caller_data = temp;
4192 /* We only need this if we needed to allocate a new caller_data. */
4193 handle->caller_data[i].key = key;
4194 handle->caller_data[1+ i].key = 0;
4197 handle->caller_data[i].data = data;
4200 LT_DLMUTEX_UNLOCK ();
4206 lt_dlcaller_get_data (
4210 lt_ptr result = (lt_ptr) 0;
4212 /* This needs to be locked so that the caller data isn't updated by
4213 another thread part way through this function. */
4216 /* Locate the index of the element with a matching KEY. */
4219 for (i = 0; handle->caller_data[i].key; ++i)
4221 if (handle->caller_data[i].key == key)
4223 result = handle->caller_data[i].data;
4229 LT_DLMUTEX_UNLOCK ();
4236 /* --- USER MODULE LOADER API --- */
4242 const struct lt_user_dlloader *dlloader,
4243 const char *loader_name)
4246 lt_dlloader *node = 0, *ptr = 0;
4248 if ((dlloader == 0) /* diagnose null parameters */
4249 || (dlloader->module_open == 0)
4250 || (dlloader->module_close == 0)
4251 || (dlloader->find_sym == 0))
4253 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4257 /* Create a new dlloader node with copies of the user callbacks. */
4258 node = LT_EMALLOC (lt_dlloader, 1);
4263 node->loader_name = loader_name;
4264 node->sym_prefix = dlloader->sym_prefix;
4265 node->dlloader_exit = dlloader->dlloader_exit;
4266 node->module_open = dlloader->module_open;
4267 node->module_close = dlloader->module_close;
4268 node->find_sym = dlloader->find_sym;
4269 node->dlloader_data = dlloader->dlloader_data;
4274 /* If there are no loaders, NODE becomes the list! */
4279 /* If PLACE is not set, add NODE to the end of the
4281 for (ptr = loaders; ptr->next; ptr = ptr->next)
4288 else if (loaders == place)
4290 /* If PLACE is the first loader, NODE goes first. */
4296 /* Find the node immediately preceding PLACE. */
4297 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4302 if (ptr->next != place)
4304 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4309 /* Insert NODE between PTR and PLACE. */
4315 LT_DLMUTEX_UNLOCK ();
4321 lt_dlloader_remove (
4322 const char *loader_name)
4324 lt_dlloader *place = lt_dlloader_find (loader_name);
4330 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4336 /* Fail if there are any open modules which use this loader. */
4337 for (handle = handles; handle; handle = handle->next)
4339 if (handle->loader == place)
4341 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4347 if (place == loaders)
4349 /* PLACE is the first loader in the list. */
4350 loaders = loaders->next;
4354 /* Find the loader before the one being removed. */
4356 for (prev = loaders; prev->next; prev = prev->next)
4358 if (!strcmp (prev->next->loader_name, loader_name))
4365 if (prev->next) prev->next = prev->next->next;
4368 if (place && place->dlloader_exit)
4370 errors = place->dlloader_exit (place->dlloader_data);
4376 LT_DLMUTEX_UNLOCK ();
4388 next = place ? place->next : loaders;
4389 LT_DLMUTEX_UNLOCK ();
4398 const char *name = 0;
4403 name = place->loader_name;
4404 LT_DLMUTEX_UNLOCK ();
4408 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4418 lt_user_data *data = 0;
4423 data = &(place->dlloader_data);
4424 LT_DLMUTEX_UNLOCK ();
4428 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4436 const char *loader_name)
4438 lt_dlloader *place = 0;
4441 for (place = loaders; place; place = place->next)
4443 if (strcmp (place->loader_name, loader_name) == 0)
4448 LT_DLMUTEX_UNLOCK ();