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
,
2154 static int foreach_dirinpath
LT_PARAMS((const char *search_path
,
2155 const char *base_name
,
2156 foreach_callback_func
*func
,
2157 lt_ptr data1
, lt_ptr data2
));
2159 static int find_file_callback
LT_PARAMS((char *filename
, lt_ptr data
,
2161 static int find_handle_callback
LT_PARAMS((char *filename
, lt_ptr data
,
2163 static int foreachfile_callback
LT_PARAMS((char *filename
, lt_ptr data1
,
2167 static int canonicalize_path
LT_PARAMS((const char *path
,
2168 char **pcanonical
));
2169 static int argzize_path
LT_PARAMS((const char *path
,
2171 size_t *pargz_len
));
2172 static FILE *find_file
LT_PARAMS((const char *search_path
,
2173 const char *base_name
,
2175 static lt_dlhandle
*find_handle
LT_PARAMS((const char *search_path
,
2176 const char *base_name
,
2177 lt_dlhandle
*handle
));
2178 static int find_module
LT_PARAMS((lt_dlhandle
*handle
,
2182 const char *old_name
,
2184 static int free_vars
LT_PARAMS((char *dlname
, char *oldname
,
2185 char *libdir
, char *deplibs
));
2186 static int load_deplibs
LT_PARAMS((lt_dlhandle handle
,
2188 static int trim
LT_PARAMS((char **dest
,
2190 static int try_dlopen
LT_PARAMS((lt_dlhandle
*handle
,
2191 const char *filename
));
2192 static int tryall_dlopen
LT_PARAMS((lt_dlhandle
*handle
,
2193 const char *filename
));
2194 static int unload_deplibs
LT_PARAMS((lt_dlhandle handle
));
2195 static int lt_argz_insert
LT_PARAMS((char **pargz
,
2198 const char *entry
));
2199 static int lt_argz_insertinorder
LT_PARAMS((char **pargz
,
2201 const char *entry
));
2202 static int lt_argz_insertdir
LT_PARAMS((char **pargz
,
2205 struct dirent
*dp
));
2206 static int lt_dlpath_insertdir
LT_PARAMS((char **ppath
,
2209 static int list_files_by_dir
LT_PARAMS((const char *dirnam
,
2211 size_t *pargz_len
));
2212 static int file_not_found
LT_PARAMS((void));
2214 static char *user_search_path
= 0;
2215 static lt_dlloader
*loaders
= 0;
2216 static lt_dlhandle handles
= 0;
2217 static int initialized
= 0;
2219 /* Initialize libltdl. */
2227 /* Initialize only at first call. */
2228 if (++initialized
== 1)
2231 user_search_path
= 0; /* empty search path */
2234 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_dl
, "dlopen");
2237 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_shl
, "dlopen");
2240 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_wll
, "dlopen");
2243 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_bedl
, "dlopen");
2246 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_dld
, "dld");
2249 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_dyld
, "dyld");
2250 errors
+= sys_dyld_init();
2252 errors
+= lt_dlloader_add (lt_dlloader_next (0), &presym
, "dlpreload");
2254 if (presym_init (presym
.dlloader_data
))
2256 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER
));
2259 else if (errors
!= 0)
2261 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED
));
2266 LT_DLMUTEX_UNLOCK ();
2272 lt_dlpreload (preloaded
)
2273 const lt_dlsymlist
*preloaded
;
2279 errors
= presym_add_symlist (preloaded
);
2283 presym_free_symlists();
2286 if (default_preloaded_symbols
)
2288 errors
= lt_dlpreload (default_preloaded_symbols
);
2290 LT_DLMUTEX_UNLOCK ();
2297 lt_dlpreload_default (preloaded
)
2298 const lt_dlsymlist
*preloaded
;
2301 default_preloaded_symbols
= preloaded
;
2302 LT_DLMUTEX_UNLOCK ();
2309 /* shut down libltdl */
2310 lt_dlloader
*loader
;
2318 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN
));
2323 /* shut down only at last call. */
2324 if (--initialized
== 0)
2328 while (handles
&& LT_DLIS_RESIDENT (handles
))
2330 handles
= handles
->next
;
2333 /* close all modules */
2334 for (level
= 1; handles
; ++level
)
2336 lt_dlhandle cur
= handles
;
2337 int saw_nonresident
= 0;
2341 lt_dlhandle tmp
= cur
;
2343 if (!LT_DLIS_RESIDENT (tmp
))
2344 saw_nonresident
= 1;
2345 if (!LT_DLIS_RESIDENT (tmp
) && tmp
->info
.ref_count
<= level
)
2347 if (lt_dlclose (tmp
))
2351 /* Make sure that the handle pointed to by 'cur' still exists.
2352 lt_dlclose recursively closes dependent libraries which removes
2353 them from the linked list. One of these might be the one
2354 pointed to by 'cur'. */
2357 for (tmp
= handles
; tmp
; tmp
= tmp
->next
)
2365 /* done if only resident modules are left */
2366 if (!saw_nonresident
)
2370 /* close all loaders */
2373 lt_dlloader
*next
= loader
->next
;
2374 lt_user_data data
= loader
->dlloader_data
;
2375 if (loader
->dlloader_exit
&& loader
->dlloader_exit (data
))
2380 LT_DLMEM_REASSIGN (loader
, next
);
2386 LT_DLMUTEX_UNLOCK ();
2391 tryall_dlopen (handle
, filename
)
2392 lt_dlhandle
*handle
;
2393 const char *filename
;
2396 lt_dlloader
*loader
;
2397 const char *saved_error
;
2400 LT_DLMUTEX_GETERROR (saved_error
);
2406 /* check whether the module was already opened */
2409 /* try to dlopen the program itself? */
2410 if (!cur
->info
.filename
&& !filename
)
2415 if (cur
->info
.filename
&& filename
2416 && strcmp (cur
->info
.filename
, filename
) == 0)
2426 ++cur
->info
.ref_count
;
2434 /* Comment out the check of file permissions using access.
2435 This call seems to always return -1 with error EACCES.
2437 /* We need to catch missing file errors early so that
2438 file_not_found() can detect what happened.
2439 if (access (filename, R_OK) != 0)
2441 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2446 cur
->info
.filename
= lt_estrdup (filename
);
2447 if (!cur
->info
.filename
)
2455 cur
->info
.filename
= 0;
2460 lt_user_data data
= loader
->dlloader_data
;
2462 cur
->module
= loader
->module_open (data
, filename
);
2464 if (cur
->module
!= 0)
2468 loader
= loader
->next
;
2473 LT_DLFREE (cur
->info
.filename
);
2478 cur
->loader
= loader
;
2479 LT_DLMUTEX_SETERROR (saved_error
);
2482 LT_DLMUTEX_UNLOCK ();
2488 tryall_dlopen_module (handle
, prefix
, dirname
, dlname
)
2489 lt_dlhandle
*handle
;
2491 const char *dirname
;
2496 size_t filename_len
= 0;
2497 size_t dirname_len
= LT_STRLEN (dirname
);
2502 #ifdef LT_DIRSEP_CHAR
2503 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2504 should make it into this function: */
2505 assert (strchr (dirname
, LT_DIRSEP_CHAR
) == 0);
2508 if (dirname_len
> 0)
2509 if (dirname
[dirname_len
-1] == '/')
2511 filename_len
= dirname_len
+ 1 + LT_STRLEN (dlname
);
2513 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2514 The PREFIX (if any) is handled below. */
2515 filename
= LT_EMALLOC (char, dirname_len
+ 1 + filename_len
+ 1);
2519 sprintf (filename
, "%.*s/%s", (int) dirname_len
, dirname
, dlname
);
2521 /* Now that we have combined DIRNAME and MODULENAME, if there is
2522 also a PREFIX to contend with, simply recurse with the arguments
2523 shuffled. Otherwise, attempt to open FILENAME as a module. */
2526 error
+= tryall_dlopen_module (handle
,
2527 (const char *) 0, prefix
, filename
);
2529 else if (tryall_dlopen (handle
, filename
) != 0)
2534 LT_DLFREE (filename
);
2539 find_module (handle
, dir
, libdir
, dlname
, old_name
, installed
)
2540 lt_dlhandle
*handle
;
2544 const char *old_name
;
2547 /* Try to open the old library first; if it was dlpreopened,
2548 we want the preopened version of it, even if a dlopenable
2549 module is available. */
2550 if (old_name
&& tryall_dlopen (handle
, old_name
) == 0)
2555 /* Try to open the dynamic library. */
2558 /* try to open the installed module */
2559 if (installed
&& libdir
)
2561 if (tryall_dlopen_module (handle
,
2562 (const char *) 0, libdir
, dlname
) == 0)
2566 /* try to open the not-installed module */
2569 if (tryall_dlopen_module (handle
, dir
, objdir
, dlname
) == 0)
2573 /* maybe it was moved to another directory */
2575 if (dir
&& (tryall_dlopen_module (handle
,
2576 (const char *) 0, dir
, dlname
) == 0))
2586 canonicalize_path (path
, pcanonical
)
2590 char *canonical
= 0;
2592 assert (path
&& *path
);
2593 assert (pcanonical
);
2595 canonical
= LT_EMALLOC (char, 1+ LT_STRLEN (path
));
2602 for (src
= 0; path
[src
] != LT_EOS_CHAR
; ++src
)
2604 /* Path separators are not copied to the beginning or end of
2605 the destination, or if another separator would follow
2607 if (path
[src
] == LT_PATHSEP_CHAR
)
2610 || (path
[1+ src
] == LT_PATHSEP_CHAR
)
2611 || (path
[1+ src
] == LT_EOS_CHAR
))
2615 /* Anything other than a directory separator is copied verbatim. */
2616 if ((path
[src
] != '/')
2617 #ifdef LT_DIRSEP_CHAR
2618 && (path
[src
] != LT_DIRSEP_CHAR
)
2622 canonical
[dest
++] = path
[src
];
2624 /* Directory separators are converted and copied only if they are
2625 not at the end of a path -- i.e. before a path separator or
2627 else if ((path
[1+ src
] != LT_PATHSEP_CHAR
)
2628 && (path
[1+ src
] != LT_EOS_CHAR
)
2629 #ifdef LT_DIRSEP_CHAR
2630 && (path
[1+ src
] != LT_DIRSEP_CHAR
)
2632 && (path
[1+ src
] != '/'))
2634 canonical
[dest
++] = '/';
2638 /* Add an end-of-string marker at the end. */
2639 canonical
[dest
] = LT_EOS_CHAR
;
2642 /* Assign new value. */
2643 *pcanonical
= canonical
;
2649 argzize_path (path
, pargz
, pargz_len
)
2660 if ((error
= argz_create_sep (path
, LT_PATHSEP_CHAR
, pargz
, pargz_len
)))
2665 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
2668 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN
));
2678 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2679 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2680 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2681 it is appended to each SEARCH_PATH element before FUNC is called. */
2683 foreach_dirinpath (search_path
, base_name
, func
, data1
, data2
)
2684 const char *search_path
;
2685 const char *base_name
;
2686 foreach_callback_func
*func
;
2691 int filenamesize
= 0;
2692 size_t lenbase
= LT_STRLEN (base_name
);
2693 size_t argz_len
= 0;
2696 char *canonical
= 0;
2700 if (!search_path
|| !*search_path
)
2702 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
2706 if (canonicalize_path (search_path
, &canonical
) != 0)
2709 if (argzize_path (canonical
, &argz
, &argz_len
) != 0)
2714 while ((dir_name
= argz_next (argz
, argz_len
, dir_name
)))
2716 size_t lendir
= LT_STRLEN (dir_name
);
2718 if (lendir
+1 +lenbase
>= filenamesize
)
2720 LT_DLFREE (filename
);
2721 filenamesize
= lendir
+1 +lenbase
+1; /* "/d" + '/' + "f" + '\0' */
2722 filename
= LT_EMALLOC (char, filenamesize
);
2727 assert (filenamesize
> lendir
);
2728 strcpy (filename
, dir_name
);
2730 if (base_name
&& *base_name
)
2732 if (filename
[lendir
-1] != '/')
2733 filename
[lendir
++] = '/';
2734 strcpy (filename
+lendir
, base_name
);
2737 if ((result
= (*func
) (filename
, data1
, data2
)))
2746 LT_DLFREE (canonical
);
2747 LT_DLFREE (filename
);
2749 LT_DLMUTEX_UNLOCK ();
2754 /* If FILEPATH can be opened, store the name of the directory component
2755 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2756 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2758 find_file_callback (filename
, data1
, data2
)
2763 char **pdir
= (char **) data1
;
2764 FILE **pfile
= (FILE **) data2
;
2767 assert (filename
&& *filename
);
2771 if ((*pfile
= fopen (filename
, LT_READTEXT_MODE
)))
2773 char *dirend
= strrchr (filename
, '/');
2775 if (dirend
> filename
)
2776 *dirend
= LT_EOS_CHAR
;
2779 *pdir
= lt_estrdup (filename
);
2780 is_done
= (*pdir
== 0) ? -1 : 1;
2787 find_file (search_path
, base_name
, pdir
)
2788 const char *search_path
;
2789 const char *base_name
;
2794 foreach_dirinpath (search_path
, base_name
, find_file_callback
, pdir
, &file
);
2800 find_handle_callback (filename
, data
, ignored
)
2805 lt_dlhandle
*handle
= (lt_dlhandle
*) data
;
2806 int notfound
= access (filename
, R_OK
);
2808 /* Bail out if file cannot be read... */
2812 /* Try to dlopen the file, but do not continue searching in any
2814 if (tryall_dlopen (handle
, filename
) != 0)
2820 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2821 found but could not be opened, *HANDLE will be set to 0. */
2822 static lt_dlhandle
*
2823 find_handle (search_path
, base_name
, handle
)
2824 const char *search_path
;
2825 const char *base_name
;
2826 lt_dlhandle
*handle
;
2831 if (!foreach_dirinpath (search_path
, base_name
, find_handle_callback
,
2839 load_deplibs (handle
, deplibs
)
2843 #if LTDL_DLOPEN_DEPLIBS
2844 char *p
, *save_search_path
= 0;
2851 handle
->depcount
= 0;
2853 #if LTDL_DLOPEN_DEPLIBS
2861 if (user_search_path
)
2863 save_search_path
= lt_estrdup (user_search_path
);
2864 if (!save_search_path
)
2868 /* extract search paths and count deplibs */
2872 if (!isspace ((int) *p
))
2875 while (*end
&& !isspace((int) *end
))
2880 if (strncmp(p
, "-L", 2) == 0 || strncmp(p
, "-R", 2) == 0)
2883 *end
= 0; /* set a temporary string terminator */
2884 if (lt_dladdsearchdir(p
+2))
2909 names
= LT_EMALLOC (char *, depcount
* sizeof (char*));
2913 /* now only extract the actual deplibs */
2918 if (isspace ((int) *p
))
2925 while (*end
&& !isspace ((int) *end
))
2930 if (strncmp(p
, "-L", 2) != 0 && strncmp(p
, "-R", 2) != 0)
2934 *end
= 0; /* set a temporary string terminator */
2935 if (strncmp(p
, "-l", 2) == 0)
2937 size_t name_len
= 3+ /* "lib" */ LT_STRLEN (p
+ 2);
2938 name
= LT_EMALLOC (char, 1+ name_len
);
2940 sprintf (name
, "lib%s", p
+2);
2943 name
= lt_estrdup(p
);
2948 names
[depcount
++] = name
;
2955 /* load the deplibs (in reverse order)
2956 At this stage, don't worry if the deplibs do not load correctly,
2957 they may already be statically linked into the loading application
2958 for instance. There will be a more enlightening error message
2959 later on if the loaded module cannot resolve all of its symbols. */
2964 handle
->deplibs
= (lt_dlhandle
*) LT_EMALLOC (lt_dlhandle
*, depcount
);
2965 if (!handle
->deplibs
)
2968 for (i
= 0; i
< depcount
; ++i
)
2970 handle
->deplibs
[j
] = lt_dlopenext(names
[depcount
-1-i
]);
2971 if (handle
->deplibs
[j
])
2977 handle
->depcount
= j
; /* Number of successfully loaded deplibs */
2982 for (i
= 0; i
< depcount
; ++i
)
2984 LT_DLFREE (names
[i
]);
2989 /* restore the old search path */
2990 if (user_search_path
) {
2991 LT_DLFREE (user_search_path
);
2992 user_search_path
= save_search_path
;
2994 LT_DLMUTEX_UNLOCK ();
3002 unload_deplibs (handle
)
3008 if (handle
->depcount
)
3010 for (i
= 0; i
< handle
->depcount
; ++i
)
3012 if (!LT_DLIS_RESIDENT (handle
->deplibs
[i
]))
3014 errors
+= lt_dlclose (handle
->deplibs
[i
]);
3017 LT_DLFREE (handle
->deplibs
);
3028 /* remove the leading and trailing "'" from str
3029 and store the result in dest */
3030 const char *end
= strrchr (str
, '\'');
3031 size_t len
= LT_STRLEN (str
);
3039 if (len
> 3 && str
[0] == '\'')
3041 tmp
= LT_EMALLOC (char, end
- str
);
3045 strncpy(tmp
, &str
[1], (end
- str
) - 1);
3046 tmp
[len
-3] = LT_EOS_CHAR
;
3058 free_vars (dlname
, oldname
, libdir
, deplibs
)
3065 LT_DLFREE (oldname
);
3067 LT_DLFREE (deplibs
);
3073 try_dlopen (phandle
, filename
)
3074 lt_dlhandle
*phandle
;
3075 const char *filename
;
3077 const char * ext
= 0;
3078 const char * saved_error
= 0;
3079 char * canonical
= 0;
3080 char * base_name
= 0;
3084 lt_dlhandle newhandle
;
3087 assert (*phandle
== 0);
3089 LT_DLMUTEX_GETERROR (saved_error
);
3094 *phandle
= (lt_dlhandle
) LT_EMALLOC (struct lt_dlhandle_struct
, 1);
3098 memset (*phandle
, 0, sizeof(struct lt_dlhandle_struct
));
3099 newhandle
= *phandle
;
3101 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3102 LT_DLSET_FLAG (*phandle
, LT_DLRESIDENT_FLAG
);
3104 if (tryall_dlopen (&newhandle
, 0) != 0)
3106 LT_DLFREE (*phandle
);
3110 goto register_handle
;
3113 assert (filename
&& *filename
);
3115 /* Doing this immediately allows internal functions to safely
3116 assume only canonicalized paths are passed. */
3117 if (canonicalize_path (filename
, &canonical
) != 0)
3123 /* If the canonical module name is a path (relative or absolute)
3124 then split it into a directory part and a name part. */
3125 base_name
= strrchr (canonical
, '/');
3128 size_t dirlen
= (1+ base_name
) - canonical
;
3130 dir
= LT_EMALLOC (char, 1+ dirlen
);
3137 strncpy (dir
, canonical
, dirlen
);
3138 dir
[dirlen
] = LT_EOS_CHAR
;
3143 base_name
= canonical
;
3145 assert (base_name
&& *base_name
);
3147 /* Check whether we are opening a libtool module (.la extension). */
3148 ext
= strrchr (base_name
, '.');
3149 if (ext
&& strcmp (ext
, archive_ext
) == 0)
3151 /* this seems to be a libtool module */
3154 char * old_name
= 0;
3160 /* if we can't find the installed flag, it is probably an
3161 installed libtool archive, produced with an old version
3165 /* extract the module name from the file name */
3166 name
= LT_EMALLOC (char, ext
- base_name
+ 1);
3173 /* canonicalize the module name */
3176 for (i
= 0; i
< ext
- base_name
; ++i
)
3178 if (isalnum ((int)(base_name
[i
])))
3180 name
[i
] = base_name
[i
];
3187 name
[ext
- base_name
] = LT_EOS_CHAR
;
3190 /* Now try to open the .la file. If there is no directory name
3191 component, try to find it first in user_search_path and then other
3192 prescribed paths. Otherwise (or in any case if the module was not
3193 yet found) try opening just the module name as passed. */
3196 const char *search_path
;
3199 search_path
= user_search_path
;
3201 file
= find_file (user_search_path
, base_name
, &dir
);
3202 LT_DLMUTEX_UNLOCK ();
3206 search_path
= getenv (LTDL_SEARCHPATH_VAR
);
3208 file
= find_file (search_path
, base_name
, &dir
);
3211 #ifdef LTDL_SHLIBPATH_VAR
3214 search_path
= getenv (LTDL_SHLIBPATH_VAR
);
3216 file
= find_file (search_path
, base_name
, &dir
);
3219 #ifdef LTDL_SYSSEARCHPATH
3220 if (!file
&& sys_search_path
)
3222 file
= find_file (sys_search_path
, base_name
, &dir
);
3228 file
= fopen (filename
, LT_READTEXT_MODE
);
3231 /* If we didn't find the file by now, it really isn't there. Set
3232 the status flag, and bail out. */
3235 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
3240 line_len
= LT_FILENAME_MAX
;
3241 line
= LT_EMALLOC (char, line_len
);
3249 /* read the .la file */
3250 while (!feof (file
))
3252 if (!fgets (line
, (int) line_len
, file
))
3257 /* Handle the case where we occasionally need to read a line
3258 that is longer than the initial buffer size. */
3259 while ((line
[LT_STRLEN(line
) -1] != '\n') && (!feof (file
)))
3261 line
= LT_DLREALLOC (char, line
, line_len
*2);
3262 if (!fgets (&line
[line_len
-1], (int) line_len
+1, file
))
3269 if (line
[0] == '\n' || line
[0] == '#')
3275 #define STR_DLNAME "dlname="
3276 if (strncmp (line
, STR_DLNAME
, sizeof (STR_DLNAME
) - 1) == 0)
3278 errors
+= trim (&dlname
, &line
[sizeof (STR_DLNAME
) - 1]);
3281 #undef STR_OLD_LIBRARY
3282 #define STR_OLD_LIBRARY "old_library="
3283 else if (strncmp (line
, STR_OLD_LIBRARY
,
3284 sizeof (STR_OLD_LIBRARY
) - 1) == 0)
3286 errors
+= trim (&old_name
, &line
[sizeof (STR_OLD_LIBRARY
) - 1]);
3289 #define STR_LIBDIR "libdir="
3290 else if (strncmp (line
, STR_LIBDIR
, sizeof (STR_LIBDIR
) - 1) == 0)
3292 errors
+= trim (&libdir
, &line
[sizeof(STR_LIBDIR
) - 1]);
3295 #undef STR_DL_DEPLIBS
3296 #define STR_DL_DEPLIBS "dependency_libs="
3297 else if (strncmp (line
, STR_DL_DEPLIBS
,
3298 sizeof (STR_DL_DEPLIBS
) - 1) == 0)
3300 errors
+= trim (&deplibs
, &line
[sizeof (STR_DL_DEPLIBS
) - 1]);
3302 else if (strcmp (line
, "installed=yes\n") == 0)
3306 else if (strcmp (line
, "installed=no\n") == 0)
3311 #undef STR_LIBRARY_NAMES
3312 #define STR_LIBRARY_NAMES "library_names="
3313 else if (! dlname
&& strncmp (line
, STR_LIBRARY_NAMES
,
3314 sizeof (STR_LIBRARY_NAMES
) - 1) == 0)
3317 errors
+= trim (&dlname
, &line
[sizeof (STR_LIBRARY_NAMES
) - 1]);
3320 && (last_libname
= strrchr (dlname
, ' ')) != 0)
3322 last_libname
= lt_estrdup (last_libname
+ 1);
3328 LT_DLMEM_REASSIGN (dlname
, last_libname
);
3339 /* allocate the handle */
3340 *phandle
= (lt_dlhandle
) LT_EMALLOC (struct lt_dlhandle_struct
, 1);
3346 free_vars (dlname
, old_name
, libdir
, deplibs
);
3347 LT_DLFREE (*phandle
);
3353 memset (*phandle
, 0, sizeof(struct lt_dlhandle_struct
));
3354 if (load_deplibs (*phandle
, deplibs
) == 0)
3356 newhandle
= *phandle
;
3357 /* find_module may replace newhandle */
3358 if (find_module (&newhandle
, dir
, libdir
, dlname
, old_name
, installed
))
3360 unload_deplibs (*phandle
);
3369 free_vars (dlname
, old_name
, libdir
, deplibs
);
3372 LT_DLFREE (*phandle
);
3376 if (*phandle
!= newhandle
)
3378 unload_deplibs (*phandle
);
3383 /* not a libtool module */
3384 *phandle
= (lt_dlhandle
) LT_EMALLOC (struct lt_dlhandle_struct
, 1);
3391 memset (*phandle
, 0, sizeof (struct lt_dlhandle_struct
));
3392 newhandle
= *phandle
;
3394 /* If the module has no directory name component, try to find it
3395 first in user_search_path and then other prescribed paths.
3396 Otherwise (or in any case if the module was not yet found) try
3397 opening just the module name as passed. */
3398 if ((dir
|| (!find_handle (user_search_path
, base_name
, &newhandle
)
3399 && !find_handle (getenv (LTDL_SEARCHPATH_VAR
), base_name
,
3401 #ifdef LTDL_SHLIBPATH_VAR
3402 && !find_handle (getenv (LTDL_SHLIBPATH_VAR
), base_name
,
3405 #ifdef LTDL_SYSSEARCHPATH
3406 && !find_handle (sys_search_path
, base_name
, &newhandle
)
3410 if (tryall_dlopen (&newhandle
, filename
) != 0)
3418 LT_DLFREE (*phandle
);
3425 LT_DLMEM_REASSIGN (*phandle
, newhandle
);
3427 if ((*phandle
)->info
.ref_count
== 0)
3429 (*phandle
)->info
.ref_count
= 1;
3430 LT_DLMEM_REASSIGN ((*phandle
)->info
.name
, name
);
3433 (*phandle
)->next
= handles
;
3435 LT_DLMUTEX_UNLOCK ();
3438 LT_DLMUTEX_SETERROR (saved_error
);
3443 LT_DLFREE (canonical
);
3449 lt_dlopen (filename
)
3450 const char *filename
;
3452 lt_dlhandle handle
= 0;
3454 /* Just incase we missed a code path in try_dlopen() that reports
3455 an error, but forgets to reset handle... */
3456 if (try_dlopen (&handle
, filename
) != 0)
3462 /* If the last error messge store was `FILE_NOT_FOUND', then return
3467 const char *error
= 0;
3469 LT_DLMUTEX_GETERROR (error
);
3470 if (error
== LT_DLSTRERROR (FILE_NOT_FOUND
))
3476 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3477 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3478 and if a file is still not found try again with SHLIB_EXT appended
3481 lt_dlopenext (filename
)
3482 const char *filename
;
3484 lt_dlhandle handle
= 0;
3492 return lt_dlopen (filename
);
3497 len
= LT_STRLEN (filename
);
3498 ext
= strrchr (filename
, '.');
3500 /* If FILENAME already bears a suitable extension, there is no need
3501 to try appending additional extensions. */
3502 if (ext
&& ((strcmp (ext
, archive_ext
) == 0)
3503 #ifdef LTDL_SHLIB_EXT
3504 || (strcmp (ext
, shlib_ext
) == 0)
3508 return lt_dlopen (filename
);
3511 /* First try appending ARCHIVE_EXT. */
3512 tmp
= LT_EMALLOC (char, len
+ LT_STRLEN (archive_ext
) + 1);
3516 strcpy (tmp
, filename
);
3517 strcat (tmp
, archive_ext
);
3518 errors
= try_dlopen (&handle
, tmp
);
3520 /* If we found FILENAME, stop searching -- whether we were able to
3521 load the file as a module or not. If the file exists but loading
3522 failed, it is better to return an error message here than to
3523 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3524 in the module search path. */
3525 if (handle
|| ((errors
> 0) && !file_not_found ()))
3531 #ifdef LTDL_SHLIB_EXT
3532 /* Try appending SHLIB_EXT. */
3533 if (LT_STRLEN (shlib_ext
) > LT_STRLEN (archive_ext
))
3536 tmp
= LT_EMALLOC (char, len
+ LT_STRLEN (shlib_ext
) + 1);
3540 strcpy (tmp
, filename
);
3544 tmp
[len
] = LT_EOS_CHAR
;
3547 strcat(tmp
, shlib_ext
);
3548 errors
= try_dlopen (&handle
, tmp
);
3550 /* As before, if the file was found but loading failed, return now
3551 with the current error message. */
3552 if (handle
|| ((errors
> 0) && !file_not_found ()))
3559 /* Still here? Then we really did fail to locate any of the file
3561 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
3568 lt_argz_insert (pargz
, pargz_len
, before
, entry
)
3576 /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3577 pargz_len, NULL, entry) failed with EINVAL. */
3579 error
= argz_insert (pargz
, pargz_len
, before
, entry
);
3581 error
= argz_append (pargz
, pargz_len
, entry
, 1 + LT_STRLEN (entry
));
3588 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
3591 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN
));
3601 lt_argz_insertinorder (pargz
, pargz_len
, entry
)
3610 assert (entry
&& *entry
);
3613 while ((before
= argz_next (*pargz
, *pargz_len
, before
)))
3615 int cmp
= strcmp (entry
, before
);
3618 if (cmp
== 0) return 0; /* No duplicates! */
3621 return lt_argz_insert (pargz
, pargz_len
, before
, entry
);
3625 lt_argz_insertdir (pargz
, pargz_len
, dirnam
, dp
)
3634 size_t end_offset
= 0;
3642 dir_len
= LT_STRLEN (dirnam
);
3643 end
= dp
->d_name
+ LT_D_NAMLEN(dp
);
3645 /* Ignore version numbers. */
3648 for (p
= end
; p
-1 > dp
->d_name
; --p
)
3649 if (strchr (".0123456789", p
[-1]) == 0)
3656 /* Ignore filename extension. */
3659 for (p
= end
-1; p
> dp
->d_name
; --p
)
3667 /* Prepend the directory name. */
3668 end_offset
= end
- dp
->d_name
;
3669 buf_len
= dir_len
+ 1+ end_offset
;
3670 buf
= LT_EMALLOC (char, 1+ buf_len
);
3676 strcpy (buf
, dirnam
);
3678 strncat (buf
, dp
->d_name
, end_offset
);
3679 buf
[buf_len
] = LT_EOS_CHAR
;
3681 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3682 if (lt_argz_insertinorder (pargz
, pargz_len
, buf
) != 0)
3691 list_files_by_dir (dirnam
, pargz
, pargz_len
)
3699 assert (dirnam
&& *dirnam
);
3702 assert (dirnam
[LT_STRLEN(dirnam
) -1] != '/');
3704 dirp
= opendir (dirnam
);
3707 struct dirent
*dp
= 0;
3709 while ((dp
= readdir (dirp
)))
3710 if (dp
->d_name
[0] != '.')
3711 if (lt_argz_insertdir (pargz
, pargz_len
, dirnam
, dp
))
3726 /* If there are any files in DIRNAME, call the function passed in
3727 DATA1 (with the name of each file and DATA2 as arguments). */
3729 foreachfile_callback (dirname
, data1
, data2
)
3734 int (*func
) LT_PARAMS((const char *filename
, lt_ptr data
))
3735 = (int (*) LT_PARAMS((const char *filename
, lt_ptr data
))) data1
;
3739 size_t argz_len
= 0;
3741 if (list_files_by_dir (dirname
, &argz
, &argz_len
) != 0)
3748 while ((filename
= argz_next (argz
, argz_len
, filename
)))
3749 if ((is_done
= (*func
) (filename
, data2
)))
3760 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3761 with DATA. The filenames passed to FUNC would be suitable for
3762 passing to lt_dlopenext. The extensions are stripped so that
3763 individual modules do not generate several entries (e.g. libfoo.la,
3764 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3765 then the same directories that lt_dlopen would search are examined. */
3767 lt_dlforeachfile (search_path
, func
, data
)
3768 const char *search_path
;
3769 int (*func
) LT_PARAMS ((const char *filename
, lt_ptr data
));
3776 /* If a specific path was passed, search only the directories
3778 is_done
= foreach_dirinpath (search_path
, 0,
3779 foreachfile_callback
, func
, data
);
3783 /* Otherwise search the default paths. */
3784 is_done
= foreach_dirinpath (user_search_path
, 0,
3785 foreachfile_callback
, func
, data
);
3788 is_done
= foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3789 foreachfile_callback
, func
, data
);
3792 #ifdef LTDL_SHLIBPATH_VAR
3795 is_done
= foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR
), 0,
3796 foreachfile_callback
, func
, data
);
3799 #ifdef LTDL_SYSSEARCHPATH
3802 is_done
= foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH
), 0,
3803 foreachfile_callback
, func
, data
);
3815 lt_dlhandle cur
, last
;
3820 /* check whether the handle is valid */
3821 last
= cur
= handles
;
3822 while (cur
&& handle
!= cur
)
3830 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
3835 handle
->info
.ref_count
--;
3837 /* Note that even with resident modules, we must track the ref_count
3838 correctly incase the user decides to reset the residency flag
3839 later (even though the API makes no provision for that at the
3841 if (handle
->info
.ref_count
<= 0 && !LT_DLIS_RESIDENT (handle
))
3843 lt_user_data data
= handle
->loader
->dlloader_data
;
3845 if (handle
!= handles
)
3847 last
->next
= handle
->next
;
3851 handles
= handle
->next
;
3854 errors
+= handle
->loader
->module_close (data
, handle
->module
);
3855 errors
+= unload_deplibs(handle
);
3857 /* It is up to the callers to free the data itself. */
3858 LT_DLFREE (handle
->caller_data
);
3860 LT_DLFREE (handle
->info
.filename
);
3861 LT_DLFREE (handle
->info
.name
);
3867 if (LT_DLIS_RESIDENT (handle
))
3869 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE
));
3874 LT_DLMUTEX_UNLOCK ();
3880 lt_dlsym (handle
, symbol
)
3885 char lsym
[LT_SYMBOL_LENGTH
];
3892 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
3898 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
3902 lensym
= LT_STRLEN (symbol
) + LT_STRLEN (handle
->loader
->sym_prefix
)
3903 + LT_STRLEN (handle
->info
.name
);
3905 if (lensym
+ LT_SYMBOL_OVERHEAD
< LT_SYMBOL_LENGTH
)
3911 sym
= LT_EMALLOC (char, lensym
+ LT_SYMBOL_OVERHEAD
+ 1);
3914 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW
));
3919 data
= handle
->loader
->dlloader_data
;
3920 if (handle
->info
.name
)
3922 const char *saved_error
;
3924 LT_DLMUTEX_GETERROR (saved_error
);
3926 /* this is a libtool module */
3927 if (handle
->loader
->sym_prefix
)
3929 strcpy(sym
, handle
->loader
->sym_prefix
);
3930 strcat(sym
, handle
->info
.name
);
3934 strcpy(sym
, handle
->info
.name
);
3937 strcat(sym
, "_LTX_");
3938 strcat(sym
, symbol
);
3940 /* try "modulename_LTX_symbol" */
3941 address
= handle
->loader
->find_sym (data
, handle
->module
, sym
);
3950 LT_DLMUTEX_SETERROR (saved_error
);
3953 /* otherwise try "symbol" */
3954 if (handle
->loader
->sym_prefix
)
3956 strcpy(sym
, handle
->loader
->sym_prefix
);
3957 strcat(sym
, symbol
);
3961 strcpy(sym
, symbol
);
3964 address
= handle
->loader
->find_sym (data
, handle
->module
, sym
);
3978 LT_DLMUTEX_GETERROR (error
);
3979 LT_DLMUTEX_SETERROR (0);
3981 return error
? error
: NULL
;
3985 lt_dlpath_insertdir (ppath
, before
, dir
)
3991 char *canonical
= 0;
3993 size_t argz_len
= 0;
3996 assert (dir
&& *dir
);
3998 if (canonicalize_path (dir
, &canonical
) != 0)
4004 assert (canonical
&& *canonical
);
4006 /* If *PPATH is empty, set it to DIR. */
4009 assert (!before
); /* BEFORE cannot be set without PPATH. */
4010 assert (dir
); /* Without DIR, don't call this function! */
4012 *ppath
= lt_estrdup (dir
);
4019 assert (ppath
&& *ppath
);
4021 if (argzize_path (*ppath
, &argz
, &argz_len
) != 0)
4027 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
4028 if *PPATH is already canonicalized, and hence does not change length
4029 with respect to ARGZ. We canonicalize each entry as it is added to
4030 the search path, and don't call this function with (uncanonicalized)
4031 user paths, so this is a fair assumption. */
4034 assert (*ppath
<= before
);
4035 assert (before
- *ppath
<= strlen (*ppath
));
4037 before
= before
- *ppath
+ argz
;
4040 if (lt_argz_insert (&argz
, &argz_len
, before
, dir
) != 0)
4046 argz_stringify (argz
, argz_len
, LT_PATHSEP_CHAR
);
4047 LT_DLMEM_REASSIGN (*ppath
, argz
);
4050 LT_DLFREE (canonical
);
4057 lt_dladdsearchdir (search_dir
)
4058 const char *search_dir
;
4062 if (search_dir
&& *search_dir
)
4065 if (lt_dlpath_insertdir (&user_search_path
, 0, search_dir
) != 0)
4067 LT_DLMUTEX_UNLOCK ();
4074 lt_dlinsertsearchdir (before
, search_dir
)
4076 const char *search_dir
;
4083 if ((before
< user_search_path
)
4084 || (before
>= user_search_path
+ LT_STRLEN (user_search_path
)))
4086 LT_DLMUTEX_UNLOCK ();
4087 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION
));
4090 LT_DLMUTEX_UNLOCK ();
4093 if (search_dir
&& *search_dir
)
4096 if (lt_dlpath_insertdir (&user_search_path
,
4097 (char *) before
, search_dir
) != 0)
4101 LT_DLMUTEX_UNLOCK ();
4108 lt_dlsetsearchpath (search_path
)
4109 const char *search_path
;
4114 LT_DLFREE (user_search_path
);
4115 LT_DLMUTEX_UNLOCK ();
4117 if (!search_path
|| !LT_STRLEN (search_path
))
4123 if (canonicalize_path (search_path
, &user_search_path
) != 0)
4125 LT_DLMUTEX_UNLOCK ();
4131 lt_dlgetsearchpath ()
4133 const char *saved_path
;
4136 saved_path
= user_search_path
;
4137 LT_DLMUTEX_UNLOCK ();
4143 lt_dlmakeresident (handle
)
4150 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
4155 LT_DLSET_FLAG (handle
, LT_DLRESIDENT_FLAG
);
4162 lt_dlisresident (handle
)
4167 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
4171 return LT_DLIS_RESIDENT (handle
);
4177 /* --- MODULE INFORMATION --- */
4180 lt_dlgetinfo (handle
)
4185 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
4189 return &(handle
->info
);
4193 lt_dlhandle_next (place
)
4196 return place
? place
->next
: handles
;
4200 lt_dlforeach (func
, data
)
4201 int (*func
) LT_PARAMS((lt_dlhandle handle
, lt_ptr data
));
4212 lt_dlhandle tmp
= cur
;
4215 if ((*func
) (tmp
, data
))
4222 LT_DLMUTEX_UNLOCK ();
4228 lt_dlcaller_register ()
4230 static lt_dlcaller_id last_caller_id
= 0;
4234 result
= ++last_caller_id
;
4235 LT_DLMUTEX_UNLOCK ();
4241 lt_dlcaller_set_data (key
, handle
, data
)
4247 lt_ptr stale
= (lt_ptr
) 0;
4250 /* This needs to be locked so that the caller data can be updated
4251 simultaneously by different threads. */
4254 if (handle
->caller_data
)
4255 while (handle
->caller_data
[n_elements
].key
)
4258 for (i
= 0; i
< n_elements
; ++i
)
4260 if (handle
->caller_data
[i
].key
== key
)
4262 stale
= handle
->caller_data
[i
].data
;
4267 /* Ensure that there is enough room in this handle's caller_data
4268 array to accept a new element (and an empty end marker). */
4269 if (i
== n_elements
)
4271 lt_caller_data
*temp
4272 = LT_DLREALLOC (lt_caller_data
, handle
->caller_data
, 2+ n_elements
);
4280 handle
->caller_data
= temp
;
4282 /* We only need this if we needed to allocate a new caller_data. */
4283 handle
->caller_data
[i
].key
= key
;
4284 handle
->caller_data
[1+ i
].key
= 0;
4287 handle
->caller_data
[i
].data
= data
;
4290 LT_DLMUTEX_UNLOCK ();
4296 lt_dlcaller_get_data (key
, handle
)
4300 lt_ptr result
= (lt_ptr
) 0;
4302 /* This needs to be locked so that the caller data isn't updated by
4303 another thread part way through this function. */
4306 /* Locate the index of the element with a matching KEY. */
4309 for (i
= 0; handle
->caller_data
[i
].key
; ++i
)
4311 if (handle
->caller_data
[i
].key
== key
)
4313 result
= handle
->caller_data
[i
].data
;
4319 LT_DLMUTEX_UNLOCK ();
4326 /* --- USER MODULE LOADER API --- */
4330 lt_dlloader_add (place
, dlloader
, loader_name
)
4332 const struct lt_user_dlloader
*dlloader
;
4333 const char *loader_name
;
4336 lt_dlloader
*node
= 0, *ptr
= 0;
4338 if ((dlloader
== 0) /* diagnose null parameters */
4339 || (dlloader
->module_open
== 0)
4340 || (dlloader
->module_close
== 0)
4341 || (dlloader
->find_sym
== 0))
4343 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4347 /* Create a new dlloader node with copies of the user callbacks. */
4348 node
= LT_EMALLOC (lt_dlloader
, 1);
4353 node
->loader_name
= loader_name
;
4354 node
->sym_prefix
= dlloader
->sym_prefix
;
4355 node
->dlloader_exit
= dlloader
->dlloader_exit
;
4356 node
->module_open
= dlloader
->module_open
;
4357 node
->module_close
= dlloader
->module_close
;
4358 node
->find_sym
= dlloader
->find_sym
;
4359 node
->dlloader_data
= dlloader
->dlloader_data
;
4364 /* If there are no loaders, NODE becomes the list! */
4369 /* If PLACE is not set, add NODE to the end of the
4371 for (ptr
= loaders
; ptr
->next
; ptr
= ptr
->next
)
4378 else if (loaders
== place
)
4380 /* If PLACE is the first loader, NODE goes first. */
4386 /* Find the node immediately preceding PLACE. */
4387 for (ptr
= loaders
; ptr
->next
!= place
; ptr
= ptr
->next
)
4392 if (ptr
->next
!= place
)
4394 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4399 /* Insert NODE between PTR and PLACE. */
4405 LT_DLMUTEX_UNLOCK ();
4411 lt_dlloader_remove (loader_name
)
4412 const char *loader_name
;
4414 lt_dlloader
*place
= lt_dlloader_find (loader_name
);
4420 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4426 /* Fail if there are any open modules which use this loader. */
4427 for (handle
= handles
; handle
; handle
= handle
->next
)
4429 if (handle
->loader
== place
)
4431 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER
));
4437 if (place
== loaders
)
4439 /* PLACE is the first loader in the list. */
4440 loaders
= loaders
->next
;
4444 /* Find the loader before the one being removed. */
4446 for (prev
= loaders
; prev
->next
; prev
= prev
->next
)
4448 if (!strcmp (prev
->next
->loader_name
, loader_name
))
4455 prev
->next
= prev
->next
->next
;
4458 if (place
->dlloader_exit
)
4460 errors
= place
->dlloader_exit (place
->dlloader_data
);
4466 LT_DLMUTEX_UNLOCK ();
4472 lt_dlloader_next (place
)
4478 next
= place
? place
->next
: loaders
;
4479 LT_DLMUTEX_UNLOCK ();
4485 lt_dlloader_name (place
)
4488 const char *name
= 0;
4493 name
= place
? place
->loader_name
: 0;
4494 LT_DLMUTEX_UNLOCK ();
4498 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4505 lt_dlloader_data (place
)
4508 lt_user_data
*data
= 0;
4513 data
= place
? &(place
->dlloader_data
) : 0;
4514 LT_DLMUTEX_UNLOCK ();
4518 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4525 lt_dlloader_find (loader_name
)
4526 const char *loader_name
;
4528 lt_dlloader
*place
= 0;
4531 for (place
= loaders
; place
; place
= place
->next
)
4533 if (strcmp (place
->loader_name
, loader_name
) == 0)
4538 LT_DLMUTEX_UNLOCK ();