1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000, 2004, 2005 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
28 #include "llvm/Config/config.h"
42 /* Include the header defining malloc. On K&R C compilers,
43 that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */
80 #undef LT_USE_POSIX_DIRENT
85 # define LT_USE_POSIX_DIRENT
86 # endif /* HAVE_DIRENT_H */
87 # endif /* HAVE_READDIR */
88 # endif /* HAVE_OPENDIR */
89 #endif /* HAVE_CLOSEDIR */
92 #undef LT_USE_WINDOWS_DIRENT_EMULATION
93 #ifndef LT_USE_POSIX_DIRENT
95 # define LT_USE_WINDOWS_DIRENT_EMULATION
96 # endif /* __WINDOWS__ */
97 #endif /* LT_USE_POSIX_DIRENT */
100 #ifdef LT_USE_POSIX_DIRENT
102 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
104 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
105 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
107 # define dirent direct
108 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
110 # include <sys/ndir.h>
113 # include <sys/dir.h>
128 # define assert(arg) ((void) 0)
134 # include <dmalloc.h>
140 /* --- WINDOWS SUPPORT --- */
144 # define LT_GLOBAL_DATA __declspec(dllexport)
146 # define LT_GLOBAL_DATA
149 /* fopen() mode flags for reading a text file */
150 #undef LT_READTEXT_MODE
152 # define LT_READTEXT_MODE "rt"
154 # define LT_READTEXT_MODE "r"
157 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
161 #define dirent lt_dirent
173 WIN32_FIND_DATA Win32FindData
;
175 struct dirent file_info
;
178 #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"
192 /* max. filename length */
193 #ifndef LT_FILENAME_MAX
194 # define LT_FILENAME_MAX 1024
197 /* This is the maximum symbol size that won't require malloc/free */
198 #undef LT_SYMBOL_LENGTH
199 #define LT_SYMBOL_LENGTH 128
201 /* This accounts for the _LTX_ separator */
202 #undef LT_SYMBOL_OVERHEAD
203 #define LT_SYMBOL_OVERHEAD 5
208 /* --- MEMORY HANDLING --- */
211 /* These are the functions used internally. In addition to making
212 use of the associated function pointers above, they also perform
214 static char *lt_estrdup
LT_PARAMS((const char *str
));
215 static lt_ptr lt_emalloc
LT_PARAMS((size_t size
));
216 static lt_ptr lt_erealloc
LT_PARAMS((lt_ptr addr
, size_t size
));
218 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
219 #define rpl_realloc realloc
221 /* These are the pointers that can be changed by the caller: */
222 LT_GLOBAL_DATA
lt_ptr (*lt_dlmalloc
) LT_PARAMS((size_t size
))
223 = (lt_ptr (*) LT_PARAMS((size_t))) malloc
;
224 LT_GLOBAL_DATA
lt_ptr (*lt_dlrealloc
) LT_PARAMS((lt_ptr ptr
, size_t size
))
225 = (lt_ptr (*) LT_PARAMS((lt_ptr
, size_t))) rpl_realloc
;
226 LT_GLOBAL_DATA
void (*lt_dlfree
) LT_PARAMS((lt_ptr ptr
))
227 = (void (*) LT_PARAMS((lt_ptr
))) free
;
229 /* The following macros reduce the amount of typing needed to cast
233 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
234 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
235 #define LT_DLFREE(p) \
236 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
238 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
239 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
243 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
244 #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
245 #define LT_DLFREE(p) \
246 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
248 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
249 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
253 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
254 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
258 /* --- REPLACEMENT FUNCTIONS --- */
262 #define strdup rpl_strdup
264 static char *strdup
LT_PARAMS((const char *str
));
274 tmp
= LT_DLMALLOC (char, 1+ strlen (str
));
288 #define strcmp rpl_strcmp
290 static int strcmp
LT_PARAMS((const char *str1
, const char *str2
));
304 for (;*str1
&& *str2
; ++str1
, ++str2
)
310 return (int)(*str1
- *str2
);
318 # define strchr index
320 # define strchr rpl_strchr
322 static const char *strchr
LT_PARAMS((const char *str
, int ch
));
331 for (p
= str
; *p
!= (char)ch
&& *p
!= LT_EOS_CHAR
; ++p
)
334 return (*p
== (char)ch
) ? p
: 0;
338 #endif /* !HAVE_STRCHR */
344 # define strrchr rindex
346 # define strrchr rpl_strrchr
348 static const char *strrchr
LT_PARAMS((const char *str
, int ch
));
355 const char *p
, *q
= 0;
357 for (p
= str
; *p
!= LT_EOS_CHAR
; ++p
)
371 /* NOTE: Neither bcopy nor the memcpy implementation below can
372 reliably handle copying in overlapping areas of memory. Use
373 memmove (for which there is a fallback implmentation below)
374 if you need that behaviour. */
378 # define memcpy(dest, src, size) bcopy (src, dest, size)
380 # define memcpy rpl_memcpy
382 static lt_ptr memcpy
LT_PARAMS((lt_ptr dest
, const lt_ptr src
, size_t size
));
385 memcpy (dest
, src
, size
)
390 const char * s
= src
;
394 for (i
= 0; i
< size
; ++i
)
402 # endif /* !HAVE_BCOPY */
403 #endif /* !HAVE_MEMCPY */
406 # define memmove rpl_memmove
408 static lt_ptr memmove
LT_PARAMS((lt_ptr dest
, const lt_ptr src
, size_t size
));
411 memmove (dest
, src
, size
)
416 const char * s
= src
;
421 for (i
= 0; i
< size
; ++i
)
425 else if (d
> s
&& size
> 0)
426 for (i
= size
-1; ; --i
)
436 #endif /* !HAVE_MEMMOVE */
438 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
440 static void closedir
LT_PARAMS((DIR *entry
));
446 assert(entry
!= (DIR *) NULL
);
447 FindClose(entry
->hSearch
);
448 lt_dlfree((lt_ptr
)entry
);
452 static DIR * opendir
LT_PARAMS((const char *path
));
458 char file_specification
[LT_FILENAME_MAX
];
461 assert(path
!= (char *) NULL
);
462 /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
463 (void) strncpy (file_specification
, path
, LT_FILENAME_MAX
-6);
464 file_specification
[LT_FILENAME_MAX
-6] = LT_EOS_CHAR
;
465 (void) strcat(file_specification
,"\\");
466 entry
= LT_DLMALLOC (DIR,sizeof(DIR));
467 if (entry
!= (DIR *) 0)
469 entry
->firsttime
= TRUE
;
470 entry
->hSearch
= FindFirstFile(file_specification
,&entry
->Win32FindData
);
472 if (entry
->hSearch
== INVALID_HANDLE_VALUE
)
474 (void) strcat(file_specification
,"\\*.*");
475 entry
->hSearch
= FindFirstFile(file_specification
,&entry
->Win32FindData
);
476 if (entry
->hSearch
== INVALID_HANDLE_VALUE
)
486 static struct dirent
*readdir
LT_PARAMS((DIR *entry
));
488 static struct dirent
*readdir(entry
)
494 if (entry
== (DIR *) 0)
495 return((struct dirent
*) 0);
496 if (!entry
->firsttime
)
498 status
= FindNextFile(entry
->hSearch
,&entry
->Win32FindData
);
500 return((struct dirent
*) 0);
502 entry
->firsttime
= FALSE
;
503 (void) strncpy(entry
->file_info
.d_name
,entry
->Win32FindData
.cFileName
,
505 entry
->file_info
.d_name
[LT_FILENAME_MAX
- 1] = LT_EOS_CHAR
;
506 entry
->file_info
.d_namlen
= strlen(entry
->file_info
.d_name
);
507 return(&entry
->file_info
);
510 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
512 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
513 ``realloc is not entirely portable''
514 In any case we want to use the allocator supplied by the user without
515 burdening them with an lt_dlrealloc function pointer to maintain.
516 Instead implement our own version (with known boundary conditions)
517 using lt_dlmalloc and lt_dlfree. */
520 #define realloc rpl_realloc
523 /* You can't (re)define realloc unless you also (re)define malloc.
524 Right now, this code uses the size of the *destination* to decide
525 how much to copy. That's not right, but you can't know the size
526 of the source unless you know enough about, or wrote malloc. So
527 this code is disabled... */
536 /* For zero or less bytes, free the original memory */
546 /* Allow reallocation of a NULL pointer. */
547 return lt_dlmalloc (size
);
551 /* Allocate a new block, copy and free the old block. */
552 lt_ptr mem
= lt_dlmalloc (size
);
556 memcpy (mem
, ptr
, size
);
560 /* Note that the contents of PTR are not damaged if there is
561 insufficient memory to realloc. */
568 #if ! HAVE_ARGZ_APPEND
569 # define argz_append rpl_argz_append
571 static error_t argz_append
LT_PARAMS((char **pargz
, size_t *pargz_len
,
572 const char *buf
, size_t buf_len
));
575 argz_append (pargz
, pargz_len
, buf
, buf_len
)
586 assert ((*pargz
&& *pargz_len
) || (!*pargz
&& !*pargz_len
));
588 /* If nothing needs to be appended, no more work is required. */
592 /* Ensure there is enough room to append BUF_LEN. */
593 argz_len
= *pargz_len
+ buf_len
;
594 argz
= LT_DLREALLOC (char, *pargz
, argz_len
);
598 /* Copy characters from BUF after terminating '\0' in ARGZ. */
599 memcpy (argz
+ *pargz_len
, buf
, buf_len
);
601 /* Assign new values. */
603 *pargz_len
= argz_len
;
607 #endif /* !HAVE_ARGZ_APPEND */
610 #if ! HAVE_ARGZ_CREATE_SEP
611 # define argz_create_sep rpl_argz_create_sep
613 static error_t argz_create_sep
LT_PARAMS((const char *str
, int delim
,
614 char **pargz
, size_t *pargz_len
));
617 argz_create_sep (str
, delim
, pargz
, pargz_len
)
630 /* Make a copy of STR, but replacing each occurrence of
632 argz_len
= 1+ LT_STRLEN (str
);
638 argz
= LT_DLMALLOC (char, argz_len
);
642 for (p
= str
, q
= argz
; *p
!= LT_EOS_CHAR
; ++p
)
646 /* Ignore leading delimiters, and fold consecutive
647 delimiters in STR into a single '\0' in ARGZ. */
648 if ((q
> argz
) && (q
[-1] != LT_EOS_CHAR
))
656 /* Copy terminating LT_EOS_CHAR. */
660 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
664 /* Assign new values. */
666 *pargz_len
= argz_len
;
670 #endif /* !HAVE_ARGZ_CREATE_SEP */
673 #if ! HAVE_ARGZ_INSERT
674 # define argz_insert rpl_argz_insert
676 static error_t argz_insert
LT_PARAMS((char **pargz
, size_t *pargz_len
,
677 char *before
, const char *entry
));
680 argz_insert (pargz
, pargz_len
, before
, entry
)
688 assert (entry
&& *entry
);
690 /* No BEFORE address indicates ENTRY should be inserted after the
691 current last element. */
693 return argz_append (pargz
, pargz_len
, entry
, 1+ LT_STRLEN (entry
));
695 /* This probably indicates a programmer error, but to preserve
696 semantics, scan back to the start of an entry if BEFORE points
697 into the middle of it. */
698 while ((before
> *pargz
) && (before
[-1] != LT_EOS_CHAR
))
702 size_t entry_len
= 1+ LT_STRLEN (entry
);
703 size_t argz_len
= *pargz_len
+ entry_len
;
704 size_t offset
= before
- *pargz
;
705 char *argz
= LT_DLREALLOC (char, *pargz
, argz_len
);
710 /* Make BEFORE point to the equivalent offset in ARGZ that it
711 used to have in *PARGZ incase realloc() moved the block. */
712 before
= argz
+ offset
;
714 /* Move the ARGZ entries starting at BEFORE up into the new
715 space at the end -- making room to copy ENTRY into the
717 memmove (before
+ entry_len
, before
, *pargz_len
- offset
);
718 memcpy (before
, entry
, entry_len
);
720 /* Assign new values. */
722 *pargz_len
= argz_len
;
727 #endif /* !HAVE_ARGZ_INSERT */
731 # define argz_next rpl_argz_next
733 static char *argz_next
LT_PARAMS((char *argz
, size_t argz_len
,
737 argz_next (argz
, argz_len
, entry
)
742 assert ((argz
&& argz_len
) || (!argz
&& !argz_len
));
746 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
747 within the ARGZ vector. */
748 assert ((!argz
&& !argz_len
)
749 || ((argz
<= entry
) && (entry
< (argz
+ argz_len
))));
751 /* Move to the char immediately after the terminating
753 entry
= 1+ strchr (entry
, LT_EOS_CHAR
);
755 /* Return either the new ENTRY, or else NULL if ARGZ is
757 return (entry
>= argz
+ argz_len
) ? 0 : (char *) entry
;
761 /* This should probably be flagged as a programmer error,
762 since starting an argz_next loop with the iterator set
763 to ARGZ is safer. To preserve semantics, handle the NULL
764 case by returning the start of ARGZ (if any). */
771 #endif /* !HAVE_ARGZ_NEXT */
775 #if ! HAVE_ARGZ_STRINGIFY
776 # define argz_stringify rpl_argz_stringify
778 static void argz_stringify
LT_PARAMS((char *argz
, size_t argz_len
,
782 argz_stringify (argz
, argz_len
, sep
)
787 assert ((argz
&& argz_len
) || (!argz
&& !argz_len
));
791 --argz_len
; /* don't stringify the terminating EOS */
792 while (--argz_len
> 0)
794 if (argz
[argz_len
] == LT_EOS_CHAR
)
795 argz
[argz_len
] = sep
;
799 #endif /* !HAVE_ARGZ_STRINGIFY */
804 /* --- TYPE DEFINITIONS -- */
807 /* This type is used for the array of caller data sets in each handler. */
816 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
819 /* Extract the diagnostic strings from the error table macro in the same
820 order as the enumerated indices in ltdl.h. */
822 static const char *lt_dlerror_strings
[] =
824 #define LT_ERROR(name, diagnostic) (diagnostic),
831 /* This structure is used for the list of registered loaders. */
833 struct lt_dlloader
*next
;
834 const char *loader_name
; /* identifying name for each loader */
835 const char *sym_prefix
; /* prefix for symbols */
836 lt_module_open
*module_open
;
837 lt_module_close
*module_close
;
838 lt_find_sym
*find_sym
;
839 lt_dlloader_exit
*dlloader_exit
;
840 lt_user_data dlloader_data
;
843 struct lt_dlhandle_struct
{
844 struct lt_dlhandle_struct
*next
;
845 lt_dlloader
*loader
; /* dlopening interface */
847 int depcount
; /* number of dependencies */
848 lt_dlhandle
*deplibs
; /* dependencies */
849 lt_module module
; /* system module handle */
850 lt_ptr system
; /* system specific data */
851 lt_caller_data
*caller_data
; /* per caller associated data */
852 int flags
; /* various boolean stats */
855 /* Various boolean flags can be stored in the flags field of an
856 lt_dlhandle_struct... */
857 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
858 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
860 #define LT_DLRESIDENT_FLAG (0x01 << 0)
861 /* ...add more flags here... */
863 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
866 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
868 static const char objdir
[] = LTDL_OBJDIR
;
869 static const char archive_ext
[] = LTDL_ARCHIVE_EXT
;
870 #ifdef LTDL_SHLIB_EXT
871 static const char shlib_ext
[] = LTDL_SHLIB_EXT
;
873 #ifdef LTDL_SYSSEARCHPATH
874 static const char sys_search_path
[] = LTDL_SYSSEARCHPATH
;
880 /* --- MUTEX LOCKING --- */
883 /* Macros to make it easier to run the lock functions only if they have
884 been registered. The reason for the complicated lock macro is to
885 ensure that the stored error message from the last error is not
886 accidentally erased if the current function doesn't generate an
888 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
889 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
891 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
892 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
894 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
895 if (lt_dlmutex_seterror_func) \
896 (*lt_dlmutex_seterror_func) (errormsg); \
897 else lt_dllast_error = (errormsg); } LT_STMT_END
898 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
899 if (lt_dlmutex_seterror_func) \
900 (errormsg) = (*lt_dlmutex_geterror_func) (); \
901 else (errormsg) = lt_dllast_error; } LT_STMT_END
903 /* The mutex functions stored here are global, and are necessarily the
904 same for all threads that wish to share access to libltdl. */
905 static lt_dlmutex_lock
*lt_dlmutex_lock_func
= 0;
906 static lt_dlmutex_unlock
*lt_dlmutex_unlock_func
= 0;
907 static lt_dlmutex_seterror
*lt_dlmutex_seterror_func
= 0;
908 static lt_dlmutex_geterror
*lt_dlmutex_geterror_func
= 0;
909 static const char *lt_dllast_error
= 0;
912 /* Either set or reset the mutex functions. Either all the arguments must
913 be valid functions, or else all can be NULL to turn off locking entirely.
914 The registered functions should be manipulating a static global lock
915 from the lock() and unlock() callbacks, which needs to be reentrant. */
917 lt_dlmutex_register (lock
, unlock
, seterror
, geterror
)
918 lt_dlmutex_lock
*lock
;
919 lt_dlmutex_unlock
*unlock
;
920 lt_dlmutex_seterror
*seterror
;
921 lt_dlmutex_geterror
*geterror
;
923 lt_dlmutex_unlock
*old_unlock
= unlock
;
926 /* Lock using the old lock() callback, if any. */
929 if ((lock
&& unlock
&& seterror
&& geterror
)
930 || !(lock
|| unlock
|| seterror
|| geterror
))
932 lt_dlmutex_lock_func
= lock
;
933 lt_dlmutex_unlock_func
= unlock
;
934 lt_dlmutex_geterror_func
= geterror
;
938 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS
));
942 /* Use the old unlock() callback we saved earlier, if any. Otherwise
943 record any errors using internal storage. */
947 /* Return the number of errors encountered during the execution of
955 /* --- ERROR HANDLING --- */
958 static const char **user_error_strings
= 0;
959 static int errorcount
= LT_ERROR_MAX
;
962 lt_dladderror (diagnostic
)
963 const char *diagnostic
;
967 const char **temp
= (const char **) 0;
973 errindex
= errorcount
- LT_ERROR_MAX
;
974 temp
= LT_EREALLOC (const char *, user_error_strings
, 1 + errindex
);
977 user_error_strings
= temp
;
978 user_error_strings
[errindex
] = diagnostic
;
979 result
= errorcount
++;
982 LT_DLMUTEX_UNLOCK ();
988 lt_dlseterror (errindex
)
995 if (errindex
>= errorcount
|| errindex
< 0)
997 /* Ack! Error setting the error message! */
998 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE
));
1001 else if (errindex
< LT_ERROR_MAX
)
1003 /* No error setting the error message! */
1004 LT_DLMUTEX_SETERROR (lt_dlerror_strings
[errindex
]);
1008 /* No error setting the error message! */
1009 LT_DLMUTEX_SETERROR (user_error_strings
[errindex
- LT_ERROR_MAX
]);
1012 LT_DLMUTEX_UNLOCK ();
1021 lt_ptr mem
= lt_dlmalloc (size
);
1023 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
1028 lt_erealloc (addr
, size
)
1032 lt_ptr mem
= lt_dlrealloc (addr
, size
);
1034 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
1042 char *copy
= strdup (str
);
1043 if (LT_STRLEN (str
) && !copy
)
1044 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
1051 /* --- DLOPEN() INTERFACE LOADER --- */
1056 /* dynamic linking with dlopen/dlsym */
1063 # include <sys/dl.h>
1067 # define LT_GLOBAL RTLD_GLOBAL
1070 # define LT_GLOBAL DL_GLOBAL
1072 #endif /* !RTLD_GLOBAL */
1074 # define LT_GLOBAL 0
1075 #endif /* !LT_GLOBAL */
1077 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1078 find out it does not work in some platform. */
1079 #ifndef LT_LAZY_OR_NOW
1081 # define LT_LAZY_OR_NOW RTLD_LAZY
1084 # define LT_LAZY_OR_NOW DL_LAZY
1086 # endif /* !RTLD_LAZY */
1088 #ifndef LT_LAZY_OR_NOW
1090 # define LT_LAZY_OR_NOW RTLD_NOW
1093 # define LT_LAZY_OR_NOW DL_NOW
1095 # endif /* !RTLD_NOW */
1097 #ifndef LT_LAZY_OR_NOW
1098 # define LT_LAZY_OR_NOW 0
1099 #endif /* !LT_LAZY_OR_NOW */
1102 # define DLERROR(arg) dlerror ()
1104 # define DLERROR(arg) LT_DLSTRERROR (arg)
1108 sys_dl_open (loader_data
, filename
)
1109 lt_user_data loader_data
;
1110 const char *filename
;
1112 lt_module module
= dlopen (filename
, LT_GLOBAL
| LT_LAZY_OR_NOW
);
1116 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN
));
1123 sys_dl_close (loader_data
, module
)
1124 lt_user_data loader_data
;
1129 if (dlclose (module
) != 0)
1131 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE
));
1139 sys_dl_sym (loader_data
, module
, symbol
)
1140 lt_user_data loader_data
;
1144 lt_ptr address
= dlsym (module
, symbol
);
1148 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND
));
1154 static struct lt_user_dlloader sys_dl
=
1161 sys_dl_open
, sys_dl_close
, sys_dl_sym
, 0, 0 };
1164 #endif /* HAVE_LIBDL */
1168 /* --- SHL_LOAD() INTERFACE LOADER --- */
1172 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1178 /* some flags are missing on some systems, so we provide
1179 * harmless defaults.
1182 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1183 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1186 * BIND_FIRST - Place the library at the head of the symbol search
1188 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1189 * unsatisfied symbols as fatal. This flag allows
1190 * binding of unsatisfied code symbols to be deferred
1192 * [Perl: For certain libraries, like DCE, deferred
1193 * binding often causes run time problems. Adding
1194 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1195 * unresolved references in situations like this.]
1196 * BIND_NOSTART - Do not call the initializer for the shared library
1197 * when the library is loaded, nor on a future call to
1199 * BIND_VERBOSE - Print verbose messages concerning possible
1200 * unsatisfied symbols.
1202 * hp9000s700/hp9000s800:
1203 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1204 * present at library load time.
1205 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1206 * library specified by the path argument.
1209 #ifndef DYNAMIC_PATH
1210 # define DYNAMIC_PATH 0
1212 #ifndef BIND_RESTRICTED
1213 # define BIND_RESTRICTED 0
1216 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1219 sys_shl_open (loader_data
, filename
)
1220 lt_user_data loader_data
;
1221 const char *filename
;
1223 static shl_t self
= (shl_t
) 0;
1224 lt_module module
= shl_load (filename
, LT_BIND_FLAGS
, 0L);
1226 /* Since searching for a symbol against a NULL module handle will also
1227 look in everything else that was already loaded and exported with
1228 the -E compiler flag, we always cache a handle saved before any
1229 modules are loaded. */
1233 shl_findsym (&self
, "main", TYPE_UNDEFINED
, &address
);
1242 module
= shl_load (filename
, LT_BIND_FLAGS
, 0L);
1246 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN
));
1254 sys_shl_close (loader_data
, module
)
1255 lt_user_data loader_data
;
1260 if (module
&& (shl_unload ((shl_t
) (module
)) != 0))
1262 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE
));
1270 sys_shl_sym (loader_data
, module
, symbol
)
1271 lt_user_data loader_data
;
1277 /* sys_shl_open should never return a NULL module handle */
1278 if (module
== (lt_module
) 0)
1280 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
1282 else if (!shl_findsym((shl_t
*) &module
, symbol
, TYPE_UNDEFINED
, &address
))
1286 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
1293 static struct lt_user_dlloader sys_shl
= {
1294 0, sys_shl_open
, sys_shl_close
, sys_shl_sym
, 0, 0
1297 #endif /* HAVE_SHL_LOAD */
1302 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1306 /* dynamic linking for Win32 */
1308 #include <windows.h>
1310 /* Forward declaration; required to implement handle search below. */
1311 static lt_dlhandle handles
;
1314 sys_wll_open (loader_data
, filename
)
1315 lt_user_data loader_data
;
1316 const char *filename
;
1319 lt_module module
= 0;
1320 const char *errormsg
= 0;
1321 char *searchname
= 0;
1323 char self_name_buf
[MAX_PATH
];
1327 /* Get the name of main module */
1329 GetModuleFileName (NULL
, self_name_buf
, sizeof (self_name_buf
));
1330 filename
= ext
= self_name_buf
;
1334 ext
= strrchr (filename
, '.');
1339 /* FILENAME already has an extension. */
1340 searchname
= lt_estrdup (filename
);
1344 /* Append a `.' to stop Windows from adding an
1345 implicit `.dll' extension. */
1346 searchname
= LT_EMALLOC (char, 2+ LT_STRLEN (filename
));
1348 sprintf (searchname
, "%s.", filename
);
1354 /* Silence dialog from LoadLibrary on some failures.
1355 No way to get the error mode, but to set it,
1356 so set it twice to preserve any previous flags. */
1357 UINT errormode
= SetErrorMode(SEM_FAILCRITICALERRORS
);
1358 SetErrorMode(errormode
| SEM_FAILCRITICALERRORS
);
1360 #if defined(__CYGWIN__)
1362 char wpath
[MAX_PATH
];
1363 cygwin_conv_to_full_win32_path (searchname
, wpath
);
1364 module
= LoadLibrary (wpath
);
1367 module
= LoadLibrary (searchname
);
1370 /* Restore the error mode. */
1371 SetErrorMode(errormode
);
1374 LT_DLFREE (searchname
);
1376 /* libltdl expects this function to fail if it is unable
1377 to physically load the library. Sadly, LoadLibrary
1378 will search the loaded libraries for a match and return
1379 one of them if the path search load fails.
1381 We check whether LoadLibrary is returning a handle to
1382 an already loaded module, and simulate failure if we
1394 if (cur
->module
== module
)
1401 LT_DLMUTEX_UNLOCK ();
1405 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN
));
1413 sys_wll_close (loader_data
, module
)
1414 lt_user_data loader_data
;
1419 if (FreeLibrary(module
) == 0)
1421 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE
));
1429 sys_wll_sym (loader_data
, module
, symbol
)
1430 lt_user_data loader_data
;
1434 lt_ptr address
= GetProcAddress (module
, symbol
);
1438 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
1444 static struct lt_user_dlloader sys_wll
= {
1445 0, sys_wll_open
, sys_wll_close
, sys_wll_sym
, 0, 0
1448 #endif /* __WINDOWS__ */
1453 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1458 /* dynamic linking for BeOS */
1460 #include <kernel/image.h>
1463 sys_bedl_open (loader_data
, filename
)
1464 lt_user_data loader_data
;
1465 const char *filename
;
1471 image
= load_add_on (filename
);
1477 if (get_next_image_info (0, &cookie
, &info
) == B_OK
)
1478 image
= load_add_on (info
.name
);
1483 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN
));
1487 return (lt_module
) image
;
1491 sys_bedl_close (loader_data
, module
)
1492 lt_user_data loader_data
;
1497 if (unload_add_on ((image_id
) module
) != B_OK
)
1499 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE
));
1507 sys_bedl_sym (loader_data
, module
, symbol
)
1508 lt_user_data loader_data
;
1513 image_id image
= (image_id
) module
;
1515 if (get_image_symbol (image
, symbol
, B_SYMBOL_TYPE_ANY
, address
) != B_OK
)
1517 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
1524 static struct lt_user_dlloader sys_bedl
= {
1525 0, sys_bedl_open
, sys_bedl_close
, sys_bedl_sym
, 0, 0
1528 #endif /* __BEOS__ */
1533 /* --- DLD_LINK() INTERFACE LOADER --- */
1538 /* dynamic linking with dld */
1545 sys_dld_open (loader_data
, filename
)
1546 lt_user_data loader_data
;
1547 const char *filename
;
1549 lt_module module
= strdup (filename
);
1551 if (dld_link (filename
) != 0)
1553 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN
));
1562 sys_dld_close (loader_data
, module
)
1563 lt_user_data loader_data
;
1568 if (dld_unlink_by_file ((char*)(module
), 1) != 0)
1570 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE
));
1582 sys_dld_sym (loader_data
, module
, symbol
)
1583 lt_user_data loader_data
;
1587 lt_ptr address
= dld_get_func (symbol
);
1591 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
1597 static struct lt_user_dlloader sys_dld
= {
1598 0, sys_dld_open
, sys_dld_close
, sys_dld_sym
, 0, 0
1601 #endif /* HAVE_DLD */
1603 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1607 #if HAVE_MACH_O_DYLD_H
1608 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1609 /* Is this correct? Does it still function properly? */
1610 #define __private_extern__ extern
1612 # include <mach-o/dyld.h>
1614 #include <mach-o/getsect.h>
1616 /* We have to put some stuff here that isn't in older dyld.h files */
1617 #ifndef ENUM_DYLD_BOOL
1618 # define ENUM_DYLD_BOOL
1627 # define LC_REQ_DYLD 0x80000000
1629 #ifndef LC_LOAD_WEAK_DYLIB
1630 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1632 static const struct mach_header
* (*ltdl_NSAddImage
)(const char *image_name
, unsigned long options
) = 0;
1633 static NSSymbol (*ltdl_NSLookupSymbolInImage
)(const struct mach_header
*image
,const char *symbolName
, unsigned long options
) = 0;
1634 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage
)(const struct mach_header
*image
, const char *symbolName
) = 0;
1635 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic
)(NSModule module
) = 0;
1637 #ifndef NSADDIMAGE_OPTION_NONE
1638 #define NSADDIMAGE_OPTION_NONE 0x0
1640 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1641 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1643 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1644 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1646 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1647 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1649 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1650 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1652 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1653 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1655 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1656 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1658 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1659 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1661 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1662 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1667 lt_int_dyld_error(othererror
)
1670 /* return the dyld error string, or the passed in error string if none */
1671 NSLinkEditErrors ler
;
1675 NSLinkEditError(&ler
,&lerno
,&file
,&errstr
);
1676 if (!errstr
|| !strlen(errstr
)) errstr
= othererror
;
1680 static const struct mach_header
*
1681 lt_int_dyld_get_mach_header_from_nsmodule(module
)
1684 /* There should probably be an apple dyld api for this */
1685 int i
=_dyld_image_count();
1687 const char *modname
=NSNameOfModule(module
);
1688 const struct mach_header
*mh
=NULL
;
1689 if (!modname
) return NULL
;
1690 for (j
= 0; j
< i
; j
++)
1692 if (!strcmp(_dyld_get_image_name(j
),modname
))
1694 mh
=_dyld_get_image_header(j
);
1701 static const char* lt_int_dyld_lib_install_name(mh
)
1702 const struct mach_header
*mh
;
1704 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1705 is installed, for uninstalled libs we need to check the install_names against
1706 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1707 different lib was loaded as a result
1710 struct load_command
*lc
;
1711 unsigned long offset
= sizeof(struct mach_header
);
1712 const char* retStr
=NULL
;
1713 for (j
= 0; j
< mh
->ncmds
; j
++)
1715 lc
= (struct load_command
*)(((unsigned long)mh
) + offset
);
1716 if (LC_ID_DYLIB
== lc
->cmd
)
1718 retStr
=(char*)(((struct dylib_command
*)lc
)->dylib
.name
.offset
+
1721 offset
+= lc
->cmdsize
;
1726 static const struct mach_header
*
1727 lt_int_dyld_match_loaded_lib_by_install_name(const char *name
)
1729 int i
=_dyld_image_count();
1731 const struct mach_header
*mh
=NULL
;
1732 const char *id
=NULL
;
1733 for (j
= 0; j
< i
; j
++)
1735 id
=lt_int_dyld_lib_install_name(_dyld_get_image_header(j
));
1736 if ((id
) && (!strcmp(id
,name
)))
1738 mh
=_dyld_get_image_header(j
);
1746 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol
,mh
)
1748 const struct mach_header
*mh
;
1750 /* Safe to assume our mh is good */
1752 struct load_command
*lc
;
1753 unsigned long offset
= sizeof(struct mach_header
);
1754 NSSymbol retSym
= 0;
1755 const struct mach_header
*mh1
;
1756 if ((ltdl_NSLookupSymbolInImage
) && NSIsSymbolNameDefined(symbol
) )
1758 for (j
= 0; j
< mh
->ncmds
; j
++)
1760 lc
= (struct load_command
*)(((unsigned long)mh
) + offset
);
1761 if ((LC_LOAD_DYLIB
== lc
->cmd
) || (LC_LOAD_WEAK_DYLIB
== lc
->cmd
))
1763 mh1
=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command
*)lc
)->dylib
.name
.offset
+
1764 (unsigned long)lc
));
1767 /* Maybe NSAddImage can find it */
1768 mh1
=ltdl_NSAddImage((char*)(((struct dylib_command
*)lc
)->dylib
.name
.offset
+
1770 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+
1771 NSADDIMAGE_OPTION_WITH_SEARCHING
+
1772 NSADDIMAGE_OPTION_RETURN_ON_ERROR
);
1776 retSym
= ltdl_NSLookupSymbolInImage(mh1
,
1778 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1779 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1784 offset
+= lc
->cmdsize
;
1795 if (!_dyld_present()) {
1799 err
= _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage
);
1800 err
= _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage
);
1801 err
= _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage
);
1802 err
= _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic
);
1808 sys_dyld_open (loader_data
, filename
)
1809 lt_user_data loader_data
;
1810 const char *filename
;
1812 lt_module module
= 0;
1813 NSObjectFileImage ofi
= 0;
1814 NSObjectFileImageReturnCode ofirc
;
1817 return (lt_module
)-1;
1818 ofirc
= NSCreateObjectFileImageFromFile(filename
, &ofi
);
1821 case NSObjectFileImageSuccess
:
1822 module
= NSLinkModule(ofi
, filename
,
1823 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1824 | NSLINKMODULE_OPTION_PRIVATE
1825 | NSLINKMODULE_OPTION_BINDNOW
);
1826 NSDestroyObjectFileImage(ofi
);
1828 ltdl_NSMakePrivateModulePublic(module
);
1830 case NSObjectFileImageInappropriateFile
:
1831 if (ltdl_NSIsSymbolNameDefinedInImage
&& ltdl_NSLookupSymbolInImage
)
1833 module
= (lt_module
)ltdl_NSAddImage(filename
, NSADDIMAGE_OPTION_RETURN_ON_ERROR
);
1837 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN
)));
1840 if (!module
) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN
)));
1845 sys_dyld_close (loader_data
, module
)
1846 lt_user_data loader_data
;
1851 if (module
== (lt_module
)-1) return 0;
1852 #ifdef __BIG_ENDIAN__
1853 if (((struct mach_header
*)module
)->magic
== MH_MAGIC
)
1855 if (((struct mach_header
*)module
)->magic
== MH_CIGAM
)
1858 LT_DLMUTEX_SETERROR("Can not close a dylib");
1864 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1865 get a segfault in atexit(), due to compiler and dynamic loader differences of
1866 opinion, this works around that.
1868 if ((const struct section
*)NULL
!=
1869 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module
),
1870 "__DATA","__mod_term_func"))
1872 flags
+= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
;
1876 flags
+= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
;
1878 if (!NSUnLinkModule(module
,flags
))
1881 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE
)));
1889 sys_dyld_sym (loader_data
, module
, symbol
)
1890 lt_user_data loader_data
;
1895 NSSymbol
*nssym
= 0;
1897 const struct mach_header
*mh
=NULL
;
1898 char saveError
[256] = "Symbol not found";
1899 if (module
== (lt_module
)-1)
1901 _dyld_lookup_and_bind(symbol
,(unsigned long*)&address
,&unused
);
1904 #ifdef __BIG_ENDIAN__
1905 if (((struct mach_header
*)module
)->magic
== MH_MAGIC
)
1907 if (((struct mach_header
*)module
)->magic
== MH_CIGAM
)
1910 if (ltdl_NSIsSymbolNameDefinedInImage
&& ltdl_NSLookupSymbolInImage
)
1913 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header
*)module
,symbol
))
1915 nssym
= ltdl_NSLookupSymbolInImage((struct mach_header
*)module
,
1917 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1918 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1925 nssym
= NSLookupSymbolInModule(module
, symbol
);
1929 strncpy(saveError
, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND
)), 255);
1931 if (!mh
) mh
=lt_int_dyld_get_mach_header_from_nsmodule(module
);
1932 nssym
= lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol
,mh
);
1936 LT_DLMUTEX_SETERROR (saveError
);
1939 return NSAddressOfSymbol(nssym
);
1942 static struct lt_user_dlloader sys_dyld
=
1943 { "_", sys_dyld_open
, sys_dyld_close
, sys_dyld_sym
, 0, 0 };
1946 #endif /* HAVE_DYLD */
1949 /* --- DLPREOPEN() INTERFACE LOADER --- */
1952 /* emulate dynamic linking using preloaded_symbols */
1954 typedef struct lt_dlsymlists_t
1956 struct lt_dlsymlists_t
*next
;
1957 const lt_dlsymlist
*syms
;
1960 static const lt_dlsymlist
*default_preloaded_symbols
= 0;
1961 static lt_dlsymlists_t
*preloaded_symbols
= 0;
1964 presym_init (loader_data
)
1965 lt_user_data loader_data
;
1971 preloaded_symbols
= 0;
1972 if (default_preloaded_symbols
)
1974 errors
= lt_dlpreload (default_preloaded_symbols
);
1977 LT_DLMUTEX_UNLOCK ();
1983 presym_free_symlists ()
1985 lt_dlsymlists_t
*lists
;
1989 lists
= preloaded_symbols
;
1992 lt_dlsymlists_t
*tmp
= lists
;
1994 lists
= lists
->next
;
1997 preloaded_symbols
= 0;
1999 LT_DLMUTEX_UNLOCK ();
2005 presym_exit (loader_data
)
2006 lt_user_data loader_data
;
2008 presym_free_symlists ();
2013 presym_add_symlist (preloaded
)
2014 const lt_dlsymlist
*preloaded
;
2016 lt_dlsymlists_t
*tmp
;
2017 lt_dlsymlists_t
*lists
;
2022 lists
= preloaded_symbols
;
2025 if (lists
->syms
== preloaded
)
2029 lists
= lists
->next
;
2032 tmp
= LT_EMALLOC (lt_dlsymlists_t
, 1);
2035 memset (tmp
, 0, sizeof(lt_dlsymlists_t
));
2036 tmp
->syms
= preloaded
;
2037 tmp
->next
= preloaded_symbols
;
2038 preloaded_symbols
= tmp
;
2046 LT_DLMUTEX_UNLOCK ();
2051 presym_open (loader_data
, filename
)
2052 lt_user_data loader_data
;
2053 const char *filename
;
2055 lt_dlsymlists_t
*lists
;
2056 lt_module module
= (lt_module
) 0;
2059 lists
= preloaded_symbols
;
2063 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS
));
2067 /* Can't use NULL as the reflective symbol header, as NULL is
2068 used to mark the end of the entire symbol list. Self-dlpreopened
2069 symbols follow this magic number, chosen to be an unlikely
2070 clash with a real module name. */
2073 filename
= "@PROGRAM@";
2078 const lt_dlsymlist
*syms
= lists
->syms
;
2082 if (!syms
->address
&& strcmp(syms
->name
, filename
) == 0)
2084 module
= (lt_module
) syms
;
2090 lists
= lists
->next
;
2093 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
2096 LT_DLMUTEX_UNLOCK ();
2101 presym_close (loader_data
, module
)
2102 lt_user_data loader_data
;
2105 /* Just to silence gcc -Wall */
2111 presym_sym (loader_data
, module
, symbol
)
2112 lt_user_data loader_data
;
2116 lt_dlsymlist
*syms
= (lt_dlsymlist
*) module
;
2119 while (syms
->address
)
2121 if (strcmp(syms
->name
, symbol
) == 0)
2123 return syms
->address
;
2129 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
2134 static struct lt_user_dlloader presym
= {
2135 0, presym_open
, presym_close
, presym_sym
, presym_exit
, 0
2142 /* --- DYNAMIC MODULE LOADING --- */
2145 /* The type of a function used at each iteration of foreach_dirinpath(). */
2146 typedef int foreach_callback_func
LT_PARAMS((char *filename
, lt_ptr data1
,
2149 static int foreach_dirinpath
LT_PARAMS((const char *search_path
,
2150 const char *base_name
,
2151 foreach_callback_func
*func
,
2152 lt_ptr data1
, lt_ptr data2
));
2154 static int find_file_callback
LT_PARAMS((char *filename
, lt_ptr data
,
2156 static int find_handle_callback
LT_PARAMS((char *filename
, lt_ptr data
,
2158 static int foreachfile_callback
LT_PARAMS((char *filename
, lt_ptr data1
,
2162 static int canonicalize_path
LT_PARAMS((const char *path
,
2163 char **pcanonical
));
2164 static int argzize_path
LT_PARAMS((const char *path
,
2166 size_t *pargz_len
));
2167 static FILE *find_file
LT_PARAMS((const char *search_path
,
2168 const char *base_name
,
2170 static lt_dlhandle
*find_handle
LT_PARAMS((const char *search_path
,
2171 const char *base_name
,
2172 lt_dlhandle
*handle
));
2173 static int find_module
LT_PARAMS((lt_dlhandle
*handle
,
2177 const char *old_name
,
2179 static int free_vars
LT_PARAMS((char *dlname
, char *oldname
,
2180 char *libdir
, char *deplibs
));
2181 static int load_deplibs
LT_PARAMS((lt_dlhandle handle
,
2183 static int trim
LT_PARAMS((char **dest
,
2185 static int try_dlopen
LT_PARAMS((lt_dlhandle
*handle
,
2186 const char *filename
));
2187 static int tryall_dlopen
LT_PARAMS((lt_dlhandle
*handle
,
2188 const char *filename
));
2189 static int unload_deplibs
LT_PARAMS((lt_dlhandle handle
));
2190 static int lt_argz_insert
LT_PARAMS((char **pargz
,
2193 const char *entry
));
2194 static int lt_argz_insertinorder
LT_PARAMS((char **pargz
,
2196 const char *entry
));
2197 static int lt_argz_insertdir
LT_PARAMS((char **pargz
,
2200 struct dirent
*dp
));
2201 static int lt_dlpath_insertdir
LT_PARAMS((char **ppath
,
2204 static int list_files_by_dir
LT_PARAMS((const char *dirnam
,
2206 size_t *pargz_len
));
2207 static int file_not_found
LT_PARAMS((void));
2209 static char *user_search_path
= 0;
2210 static lt_dlloader
*loaders
= 0;
2211 static lt_dlhandle handles
= 0;
2212 static int initialized
= 0;
2214 /* Initialize libltdl. */
2222 /* Initialize only at first call. */
2223 if (++initialized
== 1)
2226 user_search_path
= 0; /* empty search path */
2229 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_dl
, "dlopen");
2232 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_shl
, "dlopen");
2235 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_wll
, "dlopen");
2238 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_bedl
, "dlopen");
2241 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_dld
, "dld");
2244 errors
+= lt_dlloader_add (lt_dlloader_next (0), &sys_dyld
, "dyld");
2245 errors
+= sys_dyld_init();
2247 errors
+= lt_dlloader_add (lt_dlloader_next (0), &presym
, "dlpreload");
2249 if (presym_init (presym
.dlloader_data
))
2251 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER
));
2254 else if (errors
!= 0)
2256 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED
));
2261 LT_DLMUTEX_UNLOCK ();
2267 lt_dlpreload (preloaded
)
2268 const lt_dlsymlist
*preloaded
;
2274 errors
= presym_add_symlist (preloaded
);
2278 presym_free_symlists();
2281 if (default_preloaded_symbols
)
2283 errors
= lt_dlpreload (default_preloaded_symbols
);
2285 LT_DLMUTEX_UNLOCK ();
2292 lt_dlpreload_default (preloaded
)
2293 const lt_dlsymlist
*preloaded
;
2296 default_preloaded_symbols
= preloaded
;
2297 LT_DLMUTEX_UNLOCK ();
2304 /* shut down libltdl */
2305 lt_dlloader
*loader
;
2313 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN
));
2318 /* shut down only at last call. */
2319 if (--initialized
== 0)
2323 while (handles
&& LT_DLIS_RESIDENT (handles
))
2325 handles
= handles
->next
;
2328 /* close all modules */
2329 for (level
= 1; handles
; ++level
)
2331 lt_dlhandle cur
= handles
;
2332 int saw_nonresident
= 0;
2336 lt_dlhandle tmp
= cur
;
2338 if (!LT_DLIS_RESIDENT (tmp
))
2339 saw_nonresident
= 1;
2340 if (!LT_DLIS_RESIDENT (tmp
) && tmp
->info
.ref_count
<= level
)
2342 if (lt_dlclose (tmp
))
2348 /* done if only resident modules are left */
2349 if (!saw_nonresident
)
2353 /* close all loaders */
2356 lt_dlloader
*next
= loader
->next
;
2357 lt_user_data data
= loader
->dlloader_data
;
2358 if (loader
->dlloader_exit
&& loader
->dlloader_exit (data
))
2363 LT_DLMEM_REASSIGN (loader
, next
);
2369 LT_DLMUTEX_UNLOCK ();
2374 tryall_dlopen (handle
, filename
)
2375 lt_dlhandle
*handle
;
2376 const char *filename
;
2379 lt_dlloader
*loader
;
2380 const char *saved_error
;
2383 LT_DLMUTEX_GETERROR (saved_error
);
2389 /* check whether the module was already opened */
2392 /* try to dlopen the program itself? */
2393 if (!cur
->info
.filename
&& !filename
)
2398 if (cur
->info
.filename
&& filename
2399 && strcmp (cur
->info
.filename
, filename
) == 0)
2409 ++cur
->info
.ref_count
;
2417 /* Comment out the check of file permissions using access.
2418 This call seems to always return -1 with error EACCES.
2420 /* We need to catch missing file errors early so that
2421 file_not_found() can detect what happened.
2422 if (access (filename, R_OK) != 0)
2424 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2429 cur
->info
.filename
= lt_estrdup (filename
);
2430 if (!cur
->info
.filename
)
2438 cur
->info
.filename
= 0;
2443 lt_user_data data
= loader
->dlloader_data
;
2445 cur
->module
= loader
->module_open (data
, filename
);
2447 if (cur
->module
!= 0)
2451 loader
= loader
->next
;
2456 LT_DLFREE (cur
->info
.filename
);
2461 cur
->loader
= loader
;
2462 LT_DLMUTEX_SETERROR (saved_error
);
2465 LT_DLMUTEX_UNLOCK ();
2471 tryall_dlopen_module (handle
, prefix
, dirname
, dlname
)
2472 lt_dlhandle
*handle
;
2474 const char *dirname
;
2479 size_t filename_len
= 0;
2480 size_t dirname_len
= LT_STRLEN (dirname
);
2485 #ifdef LT_DIRSEP_CHAR
2486 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2487 should make it into this function: */
2488 assert (strchr (dirname
, LT_DIRSEP_CHAR
) == 0);
2491 if (dirname_len
> 0)
2492 if (dirname
[dirname_len
-1] == '/')
2494 filename_len
= dirname_len
+ 1 + LT_STRLEN (dlname
);
2496 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2497 The PREFIX (if any) is handled below. */
2498 filename
= LT_EMALLOC (char, dirname_len
+ 1 + filename_len
+ 1);
2502 sprintf (filename
, "%.*s/%s", (int) dirname_len
, dirname
, dlname
);
2504 /* Now that we have combined DIRNAME and MODULENAME, if there is
2505 also a PREFIX to contend with, simply recurse with the arguments
2506 shuffled. Otherwise, attempt to open FILENAME as a module. */
2509 error
+= tryall_dlopen_module (handle
,
2510 (const char *) 0, prefix
, filename
);
2512 else if (tryall_dlopen (handle
, filename
) != 0)
2517 LT_DLFREE (filename
);
2522 find_module (handle
, dir
, libdir
, dlname
, old_name
, installed
)
2523 lt_dlhandle
*handle
;
2527 const char *old_name
;
2530 /* Try to open the old library first; if it was dlpreopened,
2531 we want the preopened version of it, even if a dlopenable
2532 module is available. */
2533 if (old_name
&& tryall_dlopen (handle
, old_name
) == 0)
2538 /* Try to open the dynamic library. */
2541 /* try to open the installed module */
2542 if (installed
&& libdir
)
2544 if (tryall_dlopen_module (handle
,
2545 (const char *) 0, libdir
, dlname
) == 0)
2549 /* try to open the not-installed module */
2552 if (tryall_dlopen_module (handle
, dir
, objdir
, dlname
) == 0)
2556 /* maybe it was moved to another directory */
2558 if (dir
&& (tryall_dlopen_module (handle
,
2559 (const char *) 0, dir
, dlname
) == 0))
2569 canonicalize_path (path
, pcanonical
)
2573 char *canonical
= 0;
2575 assert (path
&& *path
);
2576 assert (pcanonical
);
2578 canonical
= LT_EMALLOC (char, 1+ LT_STRLEN (path
));
2585 for (src
= 0; path
[src
] != LT_EOS_CHAR
; ++src
)
2587 /* Path separators are not copied to the beginning or end of
2588 the destination, or if another separator would follow
2590 if (path
[src
] == LT_PATHSEP_CHAR
)
2593 || (path
[1+ src
] == LT_PATHSEP_CHAR
)
2594 || (path
[1+ src
] == LT_EOS_CHAR
))
2598 /* Anything other than a directory separator is copied verbatim. */
2599 if ((path
[src
] != '/')
2600 #ifdef LT_DIRSEP_CHAR
2601 && (path
[src
] != LT_DIRSEP_CHAR
)
2605 canonical
[dest
++] = path
[src
];
2607 /* Directory separators are converted and copied only if they are
2608 not at the end of a path -- i.e. before a path separator or
2610 else if ((path
[1+ src
] != LT_PATHSEP_CHAR
)
2611 && (path
[1+ src
] != LT_EOS_CHAR
)
2612 #ifdef LT_DIRSEP_CHAR
2613 && (path
[1+ src
] != LT_DIRSEP_CHAR
)
2615 && (path
[1+ src
] != '/'))
2617 canonical
[dest
++] = '/';
2621 /* Add an end-of-string marker at the end. */
2622 canonical
[dest
] = LT_EOS_CHAR
;
2625 /* Assign new value. */
2626 *pcanonical
= canonical
;
2632 argzize_path (path
, pargz
, pargz_len
)
2643 if ((error
= argz_create_sep (path
, LT_PATHSEP_CHAR
, pargz
, pargz_len
)))
2648 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
2651 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN
));
2661 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2662 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2663 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2664 it is appended to each SEARCH_PATH element before FUNC is called. */
2666 foreach_dirinpath (search_path
, base_name
, func
, data1
, data2
)
2667 const char *search_path
;
2668 const char *base_name
;
2669 foreach_callback_func
*func
;
2674 int filenamesize
= 0;
2675 size_t lenbase
= LT_STRLEN (base_name
);
2676 size_t argz_len
= 0;
2679 char *canonical
= 0;
2683 if (!search_path
|| !*search_path
)
2685 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
2689 if (canonicalize_path (search_path
, &canonical
) != 0)
2692 if (argzize_path (canonical
, &argz
, &argz_len
) != 0)
2697 while ((dir_name
= argz_next (argz
, argz_len
, dir_name
)))
2699 size_t lendir
= LT_STRLEN (dir_name
);
2701 if (lendir
+1 +lenbase
>= (size_t)filenamesize
)
2703 LT_DLFREE (filename
);
2704 filenamesize
= lendir
+1 +lenbase
+1; /* "/d" + '/' + "f" + '\0' */
2705 filename
= LT_EMALLOC (char, filenamesize
);
2710 assert ((size_t)filenamesize
> lendir
);
2711 strcpy (filename
, dir_name
);
2713 if (base_name
&& *base_name
)
2715 if (filename
[lendir
-1] != '/')
2716 filename
[lendir
++] = '/';
2717 strcpy (filename
+lendir
, base_name
);
2720 if ((result
= (*func
) (filename
, data1
, data2
)))
2729 LT_DLFREE (canonical
);
2730 LT_DLFREE (filename
);
2732 LT_DLMUTEX_UNLOCK ();
2737 /* If FILEPATH can be opened, store the name of the directory component
2738 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2739 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2741 find_file_callback (filename
, data1
, data2
)
2746 char **pdir
= (char **) data1
;
2747 FILE **pfile
= (FILE **) data2
;
2750 assert (filename
&& *filename
);
2754 if ((*pfile
= fopen (filename
, LT_READTEXT_MODE
)))
2756 char *dirend
= strrchr (filename
, '/');
2758 if (dirend
> filename
)
2759 *dirend
= LT_EOS_CHAR
;
2762 *pdir
= lt_estrdup (filename
);
2763 is_done
= (*pdir
== 0) ? -1 : 1;
2770 find_file (search_path
, base_name
, pdir
)
2771 const char *search_path
;
2772 const char *base_name
;
2777 foreach_dirinpath (search_path
, base_name
, find_file_callback
, pdir
, &file
);
2783 find_handle_callback (filename
, data
, ignored
)
2788 lt_dlhandle
*handle
= (lt_dlhandle
*) data
;
2789 int notfound
= access (filename
, R_OK
);
2791 /* Bail out if file cannot be read... */
2795 /* Try to dlopen the file, but do not continue searching in any
2797 if (tryall_dlopen (handle
, filename
) != 0)
2803 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2804 found but could not be opened, *HANDLE will be set to 0. */
2805 static lt_dlhandle
*
2806 find_handle (search_path
, base_name
, handle
)
2807 const char *search_path
;
2808 const char *base_name
;
2809 lt_dlhandle
*handle
;
2814 if (!foreach_dirinpath (search_path
, base_name
, find_handle_callback
,
2822 load_deplibs (handle
, deplibs
)
2826 #if LTDL_DLOPEN_DEPLIBS
2827 char *p
, *save_search_path
= 0;
2834 handle
->depcount
= 0;
2836 #if LTDL_DLOPEN_DEPLIBS
2844 if (user_search_path
)
2846 save_search_path
= lt_estrdup (user_search_path
);
2847 if (!save_search_path
)
2851 /* extract search paths and count deplibs */
2855 if (!isspace ((int) *p
))
2858 while (*end
&& !isspace((int) *end
))
2863 if (strncmp(p
, "-L", 2) == 0 || strncmp(p
, "-R", 2) == 0)
2866 *end
= 0; /* set a temporary string terminator */
2867 if (lt_dladdsearchdir(p
+2))
2892 names
= LT_EMALLOC (char *, depcount
* sizeof (char*));
2896 /* now only extract the actual deplibs */
2901 if (isspace ((int) *p
))
2908 while (*end
&& !isspace ((int) *end
))
2913 if (strncmp(p
, "-L", 2) != 0 && strncmp(p
, "-R", 2) != 0)
2917 *end
= 0; /* set a temporary string terminator */
2918 if (strncmp(p
, "-l", 2) == 0)
2920 size_t name_len
= 3+ /* "lib" */ LT_STRLEN (p
+ 2);
2921 name
= LT_EMALLOC (char, 1+ name_len
);
2923 sprintf (name
, "lib%s", p
+2);
2926 name
= lt_estrdup(p
);
2931 names
[depcount
++] = name
;
2938 /* load the deplibs (in reverse order)
2939 At this stage, don't worry if the deplibs do not load correctly,
2940 they may already be statically linked into the loading application
2941 for instance. There will be a more enlightening error message
2942 later on if the loaded module cannot resolve all of its symbols. */
2947 handle
->deplibs
= (lt_dlhandle
*) LT_EMALLOC (lt_dlhandle
*, depcount
);
2948 if (!handle
->deplibs
)
2951 for (i
= 0; i
< depcount
; ++i
)
2953 handle
->deplibs
[j
] = lt_dlopenext(names
[depcount
-1-i
]);
2954 if (handle
->deplibs
[j
])
2960 handle
->depcount
= j
; /* Number of successfully loaded deplibs */
2965 for (i
= 0; i
< depcount
; ++i
)
2967 LT_DLFREE (names
[i
]);
2972 /* restore the old search path */
2973 if (user_search_path
) {
2974 LT_DLFREE (user_search_path
);
2975 user_search_path
= save_search_path
;
2977 LT_DLMUTEX_UNLOCK ();
2985 unload_deplibs (handle
)
2991 if (handle
->depcount
)
2993 for (i
= 0; i
< handle
->depcount
; ++i
)
2995 if (!LT_DLIS_RESIDENT (handle
->deplibs
[i
]))
2997 errors
+= lt_dlclose (handle
->deplibs
[i
]);
3010 /* remove the leading and trailing "'" from str
3011 and store the result in dest */
3012 const char *end
= strrchr (str
, '\'');
3013 size_t len
= LT_STRLEN (str
);
3021 if (len
> 3 && str
[0] == '\'')
3023 tmp
= LT_EMALLOC (char, end
- str
);
3027 strncpy(tmp
, &str
[1], (end
- str
) - 1);
3028 tmp
[len
-3] = LT_EOS_CHAR
;
3040 free_vars (dlname
, oldname
, libdir
, deplibs
)
3047 LT_DLFREE (oldname
);
3049 LT_DLFREE (deplibs
);
3055 try_dlopen (phandle
, filename
)
3056 lt_dlhandle
*phandle
;
3057 const char *filename
;
3059 const char * ext
= 0;
3060 const char * saved_error
= 0;
3061 char * canonical
= 0;
3062 char * base_name
= 0;
3066 lt_dlhandle newhandle
;
3069 assert (*phandle
== 0);
3071 LT_DLMUTEX_GETERROR (saved_error
);
3076 *phandle
= (lt_dlhandle
) LT_EMALLOC (struct lt_dlhandle_struct
, 1);
3080 memset (*phandle
, 0, sizeof(struct lt_dlhandle_struct
));
3081 newhandle
= *phandle
;
3083 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3084 LT_DLSET_FLAG (*phandle
, LT_DLRESIDENT_FLAG
);
3086 if (tryall_dlopen (&newhandle
, 0) != 0)
3088 LT_DLFREE (*phandle
);
3092 goto register_handle
;
3095 assert (filename
&& *filename
);
3097 /* Doing this immediately allows internal functions to safely
3098 assume only canonicalized paths are passed. */
3099 if (canonicalize_path (filename
, &canonical
) != 0)
3105 /* If the canonical module name is a path (relative or absolute)
3106 then split it into a directory part and a name part. */
3107 base_name
= strrchr (canonical
, '/');
3110 size_t dirlen
= (1+ base_name
) - canonical
;
3112 dir
= LT_EMALLOC (char, 1+ dirlen
);
3119 strncpy (dir
, canonical
, dirlen
);
3120 dir
[dirlen
] = LT_EOS_CHAR
;
3125 base_name
= canonical
;
3127 assert (base_name
&& *base_name
);
3129 /* Check whether we are opening a libtool module (.la extension). */
3130 ext
= strrchr (base_name
, '.');
3131 if (ext
&& strcmp (ext
, archive_ext
) == 0)
3133 /* this seems to be a libtool module */
3136 char * old_name
= 0;
3142 /* if we can't find the installed flag, it is probably an
3143 installed libtool archive, produced with an old version
3147 /* extract the module name from the file name */
3148 name
= LT_EMALLOC (char, ext
- base_name
+ 1);
3155 /* canonicalize the module name */
3158 for (i
= 0; i
< (size_t)(ext
- base_name
); ++i
)
3160 if (isalnum ((int)(base_name
[i
])))
3162 name
[i
] = base_name
[i
];
3169 name
[ext
- base_name
] = LT_EOS_CHAR
;
3172 /* Now try to open the .la file. If there is no directory name
3173 component, try to find it first in user_search_path and then other
3174 prescribed paths. Otherwise (or in any case if the module was not
3175 yet found) try opening just the module name as passed. */
3178 const char *search_path
;
3181 search_path
= user_search_path
;
3183 file
= find_file (user_search_path
, base_name
, &dir
);
3184 LT_DLMUTEX_UNLOCK ();
3188 search_path
= getenv (LTDL_SEARCHPATH_VAR
);
3190 file
= find_file (search_path
, base_name
, &dir
);
3193 #ifdef LTDL_SHLIBPATH_VAR
3196 search_path
= getenv (LTDL_SHLIBPATH_VAR
);
3198 file
= find_file (search_path
, base_name
, &dir
);
3201 #ifdef LTDL_SYSSEARCHPATH
3202 if (!file
&& sys_search_path
)
3204 file
= find_file (sys_search_path
, base_name
, &dir
);
3210 file
= fopen (filename
, LT_READTEXT_MODE
);
3213 /* If we didn't find the file by now, it really isn't there. Set
3214 the status flag, and bail out. */
3217 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
3222 line_len
= LT_FILENAME_MAX
;
3223 line
= LT_EMALLOC (char, line_len
);
3231 /* read the .la file */
3232 while (!feof (file
))
3234 if (!fgets (line
, (int) line_len
, file
))
3239 /* Handle the case where we occasionally need to read a line
3240 that is longer than the initial buffer size. */
3241 while ((line
[LT_STRLEN(line
) -1] != '\n') && (!feof (file
)))
3243 line
= LT_DLREALLOC (char, line
, line_len
*2);
3244 if (!fgets (&line
[line_len
-1], (int) line_len
+1, file
))
3251 if (line
[0] == '\n' || line
[0] == '#')
3257 #define STR_DLNAME "dlname="
3258 if (strncmp (line
, STR_DLNAME
, sizeof (STR_DLNAME
) - 1) == 0)
3260 errors
+= trim (&dlname
, &line
[sizeof (STR_DLNAME
) - 1]);
3263 #undef STR_OLD_LIBRARY
3264 #define STR_OLD_LIBRARY "old_library="
3265 else if (strncmp (line
, STR_OLD_LIBRARY
,
3266 sizeof (STR_OLD_LIBRARY
) - 1) == 0)
3268 errors
+= trim (&old_name
, &line
[sizeof (STR_OLD_LIBRARY
) - 1]);
3271 #define STR_LIBDIR "libdir="
3272 else if (strncmp (line
, STR_LIBDIR
, sizeof (STR_LIBDIR
) - 1) == 0)
3274 errors
+= trim (&libdir
, &line
[sizeof(STR_LIBDIR
) - 1]);
3277 #undef STR_DL_DEPLIBS
3278 #define STR_DL_DEPLIBS "dependency_libs="
3279 else if (strncmp (line
, STR_DL_DEPLIBS
,
3280 sizeof (STR_DL_DEPLIBS
) - 1) == 0)
3282 errors
+= trim (&deplibs
, &line
[sizeof (STR_DL_DEPLIBS
) - 1]);
3284 else if (strcmp (line
, "installed=yes\n") == 0)
3288 else if (strcmp (line
, "installed=no\n") == 0)
3293 #undef STR_LIBRARY_NAMES
3294 #define STR_LIBRARY_NAMES "library_names="
3295 else if (! dlname
&& strncmp (line
, STR_LIBRARY_NAMES
,
3296 sizeof (STR_LIBRARY_NAMES
) - 1) == 0)
3299 errors
+= trim (&dlname
, &line
[sizeof (STR_LIBRARY_NAMES
) - 1]);
3302 && (last_libname
= strrchr (dlname
, ' ')) != 0)
3304 last_libname
= lt_estrdup (last_libname
+ 1);
3310 LT_DLMEM_REASSIGN (dlname
, last_libname
);
3321 /* allocate the handle */
3322 *phandle
= (lt_dlhandle
) LT_EMALLOC (struct lt_dlhandle_struct
, 1);
3328 free_vars (dlname
, old_name
, libdir
, deplibs
);
3329 LT_DLFREE (*phandle
);
3335 memset (*phandle
, 0, sizeof(struct lt_dlhandle_struct
));
3336 if (load_deplibs (*phandle
, deplibs
) == 0)
3338 newhandle
= *phandle
;
3339 /* find_module may replace newhandle */
3340 if (find_module (&newhandle
, dir
, libdir
, dlname
, old_name
, installed
))
3342 unload_deplibs (*phandle
);
3351 free_vars (dlname
, old_name
, libdir
, deplibs
);
3354 LT_DLFREE (*phandle
);
3358 if (*phandle
!= newhandle
)
3360 unload_deplibs (*phandle
);
3365 /* not a libtool module */
3366 *phandle
= (lt_dlhandle
) LT_EMALLOC (struct lt_dlhandle_struct
, 1);
3373 memset (*phandle
, 0, sizeof (struct lt_dlhandle_struct
));
3374 newhandle
= *phandle
;
3376 /* If the module has no directory name component, try to find it
3377 first in user_search_path and then other prescribed paths.
3378 Otherwise (or in any case if the module was not yet found) try
3379 opening just the module name as passed. */
3380 if ((dir
|| (!find_handle (user_search_path
, base_name
, &newhandle
)
3381 && !find_handle (getenv (LTDL_SEARCHPATH_VAR
), base_name
,
3383 #ifdef LTDL_SHLIBPATH_VAR
3384 && !find_handle (getenv (LTDL_SHLIBPATH_VAR
), base_name
,
3387 #ifdef LTDL_SYSSEARCHPATH
3388 && !find_handle (sys_search_path
, base_name
, &newhandle
)
3392 if (tryall_dlopen (&newhandle
, filename
) != 0)
3400 LT_DLFREE (*phandle
);
3407 LT_DLMEM_REASSIGN (*phandle
, newhandle
);
3409 if ((*phandle
)->info
.ref_count
== 0)
3411 (*phandle
)->info
.ref_count
= 1;
3412 LT_DLMEM_REASSIGN ((*phandle
)->info
.name
, name
);
3415 (*phandle
)->next
= handles
;
3417 LT_DLMUTEX_UNLOCK ();
3420 LT_DLMUTEX_SETERROR (saved_error
);
3425 LT_DLFREE (canonical
);
3431 lt_dlopen (filename
)
3432 const char *filename
;
3434 lt_dlhandle handle
= 0;
3436 /* Just incase we missed a code path in try_dlopen() that reports
3437 an error, but forgets to reset handle... */
3438 if (try_dlopen (&handle
, filename
) != 0)
3444 /* If the last error messge store was `FILE_NOT_FOUND', then return
3449 const char *error
= 0;
3451 LT_DLMUTEX_GETERROR (error
);
3452 if (error
== LT_DLSTRERROR (FILE_NOT_FOUND
))
3458 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3459 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3460 and if a file is still not found try again with SHLIB_EXT appended
3463 lt_dlopenext (filename
)
3464 const char *filename
;
3466 lt_dlhandle handle
= 0;
3474 return lt_dlopen (filename
);
3479 len
= LT_STRLEN (filename
);
3480 ext
= strrchr (filename
, '.');
3482 /* If FILENAME already bears a suitable extension, there is no need
3483 to try appending additional extensions. */
3484 if (ext
&& ((strcmp (ext
, archive_ext
) == 0)
3485 #ifdef LTDL_SHLIB_EXT
3486 || (strcmp (ext
, shlib_ext
) == 0)
3490 return lt_dlopen (filename
);
3493 /* First try appending ARCHIVE_EXT. */
3494 tmp
= LT_EMALLOC (char, len
+ LT_STRLEN (archive_ext
) + 1);
3498 strcpy (tmp
, filename
);
3499 strcat (tmp
, archive_ext
);
3500 errors
= try_dlopen (&handle
, tmp
);
3502 /* If we found FILENAME, stop searching -- whether we were able to
3503 load the file as a module or not. If the file exists but loading
3504 failed, it is better to return an error message here than to
3505 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3506 in the module search path. */
3507 if (handle
|| ((errors
> 0) && !file_not_found ()))
3513 #ifdef LTDL_SHLIB_EXT
3514 /* Try appending SHLIB_EXT. */
3515 if (LT_STRLEN (shlib_ext
) > LT_STRLEN (archive_ext
))
3518 tmp
= LT_EMALLOC (char, len
+ LT_STRLEN (shlib_ext
) + 1);
3522 strcpy (tmp
, filename
);
3526 tmp
[len
] = LT_EOS_CHAR
;
3529 strcat(tmp
, shlib_ext
);
3530 errors
= try_dlopen (&handle
, tmp
);
3532 /* As before, if the file was found but loading failed, return now
3533 with the current error message. */
3534 if (handle
|| ((errors
> 0) && !file_not_found ()))
3541 /* Still here? Then we really did fail to locate any of the file
3543 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND
));
3550 lt_argz_insert (pargz
, pargz_len
, before
, entry
)
3558 /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3559 pargz_len, NULL, entry) failed with EINVAL. */
3561 error
= argz_insert (pargz
, pargz_len
, before
, entry
);
3563 error
= argz_append (pargz
, pargz_len
, entry
, 1 + LT_STRLEN (entry
));
3570 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY
));
3573 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN
));
3583 lt_argz_insertinorder (pargz
, pargz_len
, entry
)
3592 assert (entry
&& *entry
);
3595 while ((before
= argz_next (*pargz
, *pargz_len
, before
)))
3597 int cmp
= strcmp (entry
, before
);
3600 if (cmp
== 0) return 0; /* No duplicates! */
3603 return lt_argz_insert (pargz
, pargz_len
, before
, entry
);
3607 lt_argz_insertdir (pargz
, pargz_len
, dirnam
, dp
)
3616 size_t end_offset
= 0;
3624 dir_len
= LT_STRLEN (dirnam
);
3625 end
= dp
->d_name
+ LT_D_NAMLEN(dp
);
3627 /* Ignore version numbers. */
3630 for (p
= end
; p
-1 > dp
->d_name
; --p
)
3631 if (strchr (".0123456789", p
[-1]) == 0)
3638 /* Ignore filename extension. */
3641 for (p
= end
-1; p
> dp
->d_name
; --p
)
3649 /* Prepend the directory name. */
3650 end_offset
= end
- dp
->d_name
;
3651 buf_len
= dir_len
+ 1+ end_offset
;
3652 buf
= LT_EMALLOC (char, 1+ buf_len
);
3658 strcpy (buf
, dirnam
);
3660 strncat (buf
, dp
->d_name
, end_offset
);
3661 buf
[buf_len
] = LT_EOS_CHAR
;
3663 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3664 if (lt_argz_insertinorder (pargz
, pargz_len
, buf
) != 0)
3673 list_files_by_dir (dirnam
, pargz
, pargz_len
)
3681 assert (dirnam
&& *dirnam
);
3684 assert (dirnam
[LT_STRLEN(dirnam
) -1] != '/');
3686 dirp
= opendir (dirnam
);
3689 struct dirent
*dp
= 0;
3691 while ((dp
= readdir (dirp
)))
3692 if (dp
->d_name
[0] != '.')
3693 if (lt_argz_insertdir (pargz
, pargz_len
, dirnam
, dp
))
3708 /* If there are any files in DIRNAME, call the function passed in
3709 DATA1 (with the name of each file and DATA2 as arguments). */
3711 foreachfile_callback (dirname
, data1
, data2
)
3716 int (*func
) LT_PARAMS((const char *filename
, lt_ptr data
))
3717 = (int (*) LT_PARAMS((const char *filename
, lt_ptr data
))) data1
;
3721 size_t argz_len
= 0;
3723 if (list_files_by_dir (dirname
, &argz
, &argz_len
) != 0)
3730 while ((filename
= argz_next (argz
, argz_len
, filename
)))
3731 if ((is_done
= (*func
) (filename
, data2
)))
3742 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3743 with DATA. The filenames passed to FUNC would be suitable for
3744 passing to lt_dlopenext. The extensions are stripped so that
3745 individual modules do not generate several entries (e.g. libfoo.la,
3746 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3747 then the same directories that lt_dlopen would search are examined. */
3749 lt_dlforeachfile (search_path
, func
, data
)
3750 const char *search_path
;
3751 int (*func
) LT_PARAMS ((const char *filename
, lt_ptr data
));
3758 /* If a specific path was passed, search only the directories
3760 is_done
= foreach_dirinpath (search_path
, 0,
3761 foreachfile_callback
, func
, data
);
3765 /* Otherwise search the default paths. */
3766 is_done
= foreach_dirinpath (user_search_path
, 0,
3767 foreachfile_callback
, func
, data
);
3770 is_done
= foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3771 foreachfile_callback
, func
, data
);
3774 #ifdef LTDL_SHLIBPATH_VAR
3777 is_done
= foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR
), 0,
3778 foreachfile_callback
, func
, data
);
3781 #ifdef LTDL_SYSSEARCHPATH
3784 is_done
= foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH
), 0,
3785 foreachfile_callback
, func
, data
);
3797 lt_dlhandle cur
, last
;
3802 /* check whether the handle is valid */
3803 last
= cur
= handles
;
3804 while (cur
&& handle
!= cur
)
3812 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
3817 handle
->info
.ref_count
--;
3819 /* Note that even with resident modules, we must track the ref_count
3820 correctly incase the user decides to reset the residency flag
3821 later (even though the API makes no provision for that at the
3823 if (handle
->info
.ref_count
<= 0 && !LT_DLIS_RESIDENT (handle
))
3825 lt_user_data data
= handle
->loader
->dlloader_data
;
3827 if (handle
!= handles
)
3829 last
->next
= handle
->next
;
3833 handles
= handle
->next
;
3836 errors
+= handle
->loader
->module_close (data
, handle
->module
);
3837 errors
+= unload_deplibs(handle
);
3839 /* It is up to the callers to free the data itself. */
3840 LT_DLFREE (handle
->caller_data
);
3842 LT_DLFREE (handle
->info
.filename
);
3843 LT_DLFREE (handle
->info
.name
);
3849 if (LT_DLIS_RESIDENT (handle
))
3851 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE
));
3856 LT_DLMUTEX_UNLOCK ();
3862 lt_dlsym (handle
, symbol
)
3867 char lsym
[LT_SYMBOL_LENGTH
];
3874 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
3880 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND
));
3884 lensym
= LT_STRLEN (symbol
) + LT_STRLEN (handle
->loader
->sym_prefix
)
3885 + LT_STRLEN (handle
->info
.name
);
3887 if (lensym
+ LT_SYMBOL_OVERHEAD
< LT_SYMBOL_LENGTH
)
3893 sym
= LT_EMALLOC (char, lensym
+ LT_SYMBOL_OVERHEAD
+ 1);
3896 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW
));
3901 data
= handle
->loader
->dlloader_data
;
3902 if (handle
->info
.name
)
3904 const char *saved_error
;
3906 LT_DLMUTEX_GETERROR (saved_error
);
3908 /* this is a libtool module */
3909 if (handle
->loader
->sym_prefix
)
3911 strcpy(sym
, handle
->loader
->sym_prefix
);
3912 strcat(sym
, handle
->info
.name
);
3916 strcpy(sym
, handle
->info
.name
);
3919 strcat(sym
, "_LTX_");
3920 strcat(sym
, symbol
);
3922 /* try "modulename_LTX_symbol" */
3923 address
= handle
->loader
->find_sym (data
, handle
->module
, sym
);
3932 LT_DLMUTEX_SETERROR (saved_error
);
3935 /* otherwise try "symbol" */
3936 if (handle
->loader
->sym_prefix
)
3938 strcpy(sym
, handle
->loader
->sym_prefix
);
3939 strcat(sym
, symbol
);
3943 strcpy(sym
, symbol
);
3946 address
= handle
->loader
->find_sym (data
, handle
->module
, sym
);
3960 LT_DLMUTEX_GETERROR (error
);
3961 LT_DLMUTEX_SETERROR (0);
3963 return error
? error
: NULL
;
3967 lt_dlpath_insertdir (ppath
, before
, dir
)
3973 char *canonical
= 0;
3975 size_t argz_len
= 0;
3978 assert (dir
&& *dir
);
3980 if (canonicalize_path (dir
, &canonical
) != 0)
3986 assert (canonical
&& *canonical
);
3988 /* If *PPATH is empty, set it to DIR. */
3991 assert (!before
); /* BEFORE cannot be set without PPATH. */
3992 assert (dir
); /* Without DIR, don't call this function! */
3994 *ppath
= lt_estrdup (dir
);
4001 assert (ppath
&& *ppath
);
4003 if (argzize_path (*ppath
, &argz
, &argz_len
) != 0)
4009 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
4010 if *PPATH is already canonicalized, and hence does not change length
4011 with respect to ARGZ. We canonicalize each entry as it is added to
4012 the search path, and don't call this function with (uncanonicalized)
4013 user paths, so this is a fair assumption. */
4016 assert (*ppath
<= before
);
4017 assert ((size_t)(before
- *ppath
) <= strlen (*ppath
));
4019 before
= before
- *ppath
+ argz
;
4022 if (lt_argz_insert (&argz
, &argz_len
, before
, dir
) != 0)
4028 argz_stringify (argz
, argz_len
, LT_PATHSEP_CHAR
);
4029 LT_DLMEM_REASSIGN (*ppath
, argz
);
4032 LT_DLFREE (canonical
);
4039 lt_dladdsearchdir (search_dir
)
4040 const char *search_dir
;
4044 if (search_dir
&& *search_dir
)
4047 if (lt_dlpath_insertdir (&user_search_path
, 0, search_dir
) != 0)
4049 LT_DLMUTEX_UNLOCK ();
4056 lt_dlinsertsearchdir (before
, search_dir
)
4058 const char *search_dir
;
4065 if ((before
< user_search_path
)
4066 || (before
>= user_search_path
+ LT_STRLEN (user_search_path
)))
4068 LT_DLMUTEX_UNLOCK ();
4069 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION
));
4072 LT_DLMUTEX_UNLOCK ();
4075 if (search_dir
&& *search_dir
)
4078 if (lt_dlpath_insertdir (&user_search_path
,
4079 (char *) before
, search_dir
) != 0)
4083 LT_DLMUTEX_UNLOCK ();
4090 lt_dlsetsearchpath (search_path
)
4091 const char *search_path
;
4096 LT_DLFREE (user_search_path
);
4097 LT_DLMUTEX_UNLOCK ();
4099 if (!search_path
|| !LT_STRLEN (search_path
))
4105 if (canonicalize_path (search_path
, &user_search_path
) != 0)
4107 LT_DLMUTEX_UNLOCK ();
4113 lt_dlgetsearchpath ()
4115 const char *saved_path
;
4118 saved_path
= user_search_path
;
4119 LT_DLMUTEX_UNLOCK ();
4125 lt_dlmakeresident (handle
)
4132 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
4137 LT_DLSET_FLAG (handle
, LT_DLRESIDENT_FLAG
);
4144 lt_dlisresident (handle
)
4149 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
4153 return LT_DLIS_RESIDENT (handle
);
4159 /* --- MODULE INFORMATION --- */
4162 lt_dlgetinfo (handle
)
4167 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE
));
4171 return &(handle
->info
);
4175 lt_dlhandle_next (place
)
4178 return place
? place
->next
: handles
;
4182 lt_dlforeach (func
, data
)
4183 int (*func
) LT_PARAMS((lt_dlhandle handle
, lt_ptr data
));
4194 lt_dlhandle tmp
= cur
;
4197 if ((*func
) (tmp
, data
))
4204 LT_DLMUTEX_UNLOCK ();
4210 lt_dlcaller_register ()
4212 static lt_dlcaller_id last_caller_id
= 0;
4216 result
= ++last_caller_id
;
4217 LT_DLMUTEX_UNLOCK ();
4223 lt_dlcaller_set_data (key
, handle
, data
)
4229 lt_ptr stale
= (lt_ptr
) 0;
4232 /* This needs to be locked so that the caller data can be updated
4233 simultaneously by different threads. */
4236 if (handle
->caller_data
)
4237 while (handle
->caller_data
[n_elements
].key
)
4240 for (i
= 0; i
< n_elements
; ++i
)
4242 if (handle
->caller_data
[i
].key
== key
)
4244 stale
= handle
->caller_data
[i
].data
;
4249 /* Ensure that there is enough room in this handle's caller_data
4250 array to accept a new element (and an empty end marker). */
4251 if (i
== n_elements
)
4253 lt_caller_data
*temp
4254 = LT_DLREALLOC (lt_caller_data
, handle
->caller_data
, 2+ n_elements
);
4262 handle
->caller_data
= temp
;
4264 /* We only need this if we needed to allocate a new caller_data. */
4265 handle
->caller_data
[i
].key
= key
;
4266 handle
->caller_data
[1+ i
].key
= 0;
4269 handle
->caller_data
[i
].data
= data
;
4272 LT_DLMUTEX_UNLOCK ();
4278 lt_dlcaller_get_data (key
, handle
)
4282 lt_ptr result
= (lt_ptr
) 0;
4284 /* This needs to be locked so that the caller data isn't updated by
4285 another thread part way through this function. */
4288 /* Locate the index of the element with a matching KEY. */
4291 for (i
= 0; handle
->caller_data
[i
].key
; ++i
)
4293 if (handle
->caller_data
[i
].key
== key
)
4295 result
= handle
->caller_data
[i
].data
;
4301 LT_DLMUTEX_UNLOCK ();
4308 /* --- USER MODULE LOADER API --- */
4312 lt_dlloader_add (place
, dlloader
, loader_name
)
4314 const struct lt_user_dlloader
*dlloader
;
4315 const char *loader_name
;
4318 lt_dlloader
*node
= 0, *ptr
= 0;
4320 if ((dlloader
== 0) /* diagnose null parameters */
4321 || (dlloader
->module_open
== 0)
4322 || (dlloader
->module_close
== 0)
4323 || (dlloader
->find_sym
== 0))
4325 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4329 /* Create a new dlloader node with copies of the user callbacks. */
4330 node
= LT_EMALLOC (lt_dlloader
, 1);
4335 node
->loader_name
= loader_name
;
4336 node
->sym_prefix
= dlloader
->sym_prefix
;
4337 node
->dlloader_exit
= dlloader
->dlloader_exit
;
4338 node
->module_open
= dlloader
->module_open
;
4339 node
->module_close
= dlloader
->module_close
;
4340 node
->find_sym
= dlloader
->find_sym
;
4341 node
->dlloader_data
= dlloader
->dlloader_data
;
4346 /* If there are no loaders, NODE becomes the list! */
4351 /* If PLACE is not set, add NODE to the end of the
4353 for (ptr
= loaders
; ptr
->next
; ptr
= ptr
->next
)
4360 else if (loaders
== place
)
4362 /* If PLACE is the first loader, NODE goes first. */
4368 /* Find the node immediately preceding PLACE. */
4369 for (ptr
= loaders
; ptr
->next
!= place
; ptr
= ptr
->next
)
4374 if (ptr
->next
!= place
)
4376 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4381 /* Insert NODE between PTR and PLACE. */
4387 LT_DLMUTEX_UNLOCK ();
4393 lt_dlloader_remove (loader_name
)
4394 const char *loader_name
;
4396 lt_dlloader
*place
= lt_dlloader_find (loader_name
);
4402 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4408 /* Fail if there are any open modules which use this loader. */
4409 for (handle
= handles
; handle
; handle
= handle
->next
)
4411 if (handle
->loader
== place
)
4413 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER
));
4419 if (place
== loaders
)
4421 /* PLACE is the first loader in the list. */
4422 loaders
= loaders
->next
;
4426 /* Find the loader before the one being removed. */
4428 for (prev
= loaders
; prev
->next
; prev
= prev
->next
)
4430 if (!strcmp (prev
->next
->loader_name
, loader_name
))
4437 prev
->next
= prev
->next
->next
;
4440 if (place
->dlloader_exit
)
4442 errors
= place
->dlloader_exit (place
->dlloader_data
);
4448 LT_DLMUTEX_UNLOCK ();
4454 lt_dlloader_next (place
)
4460 next
= place
? place
->next
: loaders
;
4461 LT_DLMUTEX_UNLOCK ();
4467 lt_dlloader_name (place
)
4470 const char *name
= 0;
4475 name
= place
? place
->loader_name
: 0;
4476 LT_DLMUTEX_UNLOCK ();
4480 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4487 lt_dlloader_data (place
)
4490 lt_user_data
*data
= 0;
4495 data
= place
? &(place
->dlloader_data
) : 0;
4496 LT_DLMUTEX_UNLOCK ();
4500 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER
));
4507 lt_dlloader_find (loader_name
)
4508 const char *loader_name
;
4510 lt_dlloader
*place
= 0;
4513 for (place
= loaders
; place
; place
= place
->next
)
4515 if (strcmp (place
->loader_name
, loader_name
) == 0)
4520 LT_DLMUTEX_UNLOCK ();