LLVM API Documentation
00001 /* ltdl.c -- system independent dlopen wrapper 00002 Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. 00003 Originally by Thomas Tanner <tanner@ffii.org> 00004 This file is part of GNU Libtool. 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 As a special exception to the GNU Lesser General Public License, 00012 if you distribute this file as part of a program or library that 00013 is built using GNU libtool, you may include it under the same 00014 distribution terms that you use for the rest of that program. 00015 00016 This library is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 Lesser General Public License for more details. 00020 00021 You should have received a copy of the GNU Lesser General Public 00022 License along with this library; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 00024 02111-1307 USA 00025 00026 */ 00027 00028 #include "llvm/Config/config.h" 00029 /* 00030 #if HAVE_CONFIG_H 00031 # include <config.h> 00032 #endif 00033 */ 00034 00035 #if HAVE_UNISTD_H 00036 # include <unistd.h> 00037 #endif 00038 00039 #if HAVE_STDIO_H 00040 # include <stdio.h> 00041 #endif 00042 00043 /* Include the header defining malloc. On K&R C compilers, 00044 that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */ 00045 #if HAVE_STDLIB_H 00046 # include <stdlib.h> 00047 #else 00048 # if HAVE_MALLOC_H 00049 # include <malloc.h> 00050 # endif 00051 #endif 00052 00053 #if HAVE_STRING_H 00054 # include <string.h> 00055 #else 00056 # if HAVE_STRINGS_H 00057 # include <strings.h> 00058 # endif 00059 #endif 00060 00061 #if HAVE_CTYPE_H 00062 # include <ctype.h> 00063 #endif 00064 00065 #if HAVE_MEMORY_H 00066 # include <memory.h> 00067 #endif 00068 00069 #if HAVE_ERRNO_H 00070 # include <errno.h> 00071 #endif 00072 00073 00074 #ifndef __WINDOWS__ 00075 # ifdef __WIN32__ 00076 # define __WINDOWS__ 00077 # endif 00078 #endif 00079 00080 00081 #undef LT_USE_POSIX_DIRENT 00082 #ifdef HAVE_CLOSEDIR 00083 # ifdef HAVE_OPENDIR 00084 # ifdef HAVE_READDIR 00085 # ifdef HAVE_DIRENT_H 00086 # define LT_USE_POSIX_DIRENT 00087 # endif /* HAVE_DIRENT_H */ 00088 # endif /* HAVE_READDIR */ 00089 # endif /* HAVE_OPENDIR */ 00090 #endif /* HAVE_CLOSEDIR */ 00091 00092 00093 #undef LT_USE_WINDOWS_DIRENT_EMULATION 00094 #ifndef LT_USE_POSIX_DIRENT 00095 # ifdef __WINDOWS__ 00096 # define LT_USE_WINDOWS_DIRENT_EMULATION 00097 # endif /* __WINDOWS__ */ 00098 #endif /* LT_USE_POSIX_DIRENT */ 00099 00100 00101 #ifdef LT_USE_POSIX_DIRENT 00102 # include <dirent.h> 00103 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) 00104 #else 00105 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION 00106 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) 00107 # else 00108 # define dirent direct 00109 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) 00110 # if HAVE_SYS_NDIR_H 00111 # include <sys/ndir.h> 00112 # endif 00113 # if HAVE_SYS_DIR_H 00114 # include <sys/dir.h> 00115 # endif 00116 # if HAVE_NDIR_H 00117 # include <ndir.h> 00118 # endif 00119 # endif 00120 #endif 00121 00122 #if HAVE_ARGZ_H 00123 # include <argz.h> 00124 #endif 00125 00126 #if HAVE_ASSERT_H 00127 # include <assert.h> 00128 #else 00129 # define assert(arg) ((void) 0) 00130 #endif 00131 00132 #include "ltdl.h" 00133 00134 #if WITH_DMALLOC 00135 # include <dmalloc.h> 00136 #endif 00137 00138 00139 00140 00141 /* --- WINDOWS SUPPORT --- */ 00142 00143 00144 #ifdef DLL_EXPORT 00145 # define LT_GLOBAL_DATA __declspec(dllexport) 00146 #else 00147 # define LT_GLOBAL_DATA 00148 #endif 00149 00150 /* fopen() mode flags for reading a text file */ 00151 #undef LT_READTEXT_MODE 00152 #ifdef __WINDOWS__ 00153 # define LT_READTEXT_MODE "rt" 00154 #else 00155 # define LT_READTEXT_MODE "r" 00156 #endif 00157 00158 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION 00159 00160 #include <windows.h> 00161 00162 #define dirent lt_dirent 00163 #define DIR lt_DIR 00164 00165 struct dirent 00166 { 00167 char d_name[2048]; 00168 int d_namlen; 00169 }; 00170 00171 typedef struct _DIR 00172 { 00173 HANDLE hSearch; 00174 WIN32_FIND_DATA Win32FindData; 00175 BOOL firsttime; 00176 struct dirent file_info; 00177 } DIR; 00178 00179 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ 00180 00181 00182 /* --- MANIFEST CONSTANTS --- */ 00183 00184 00185 /* Standard libltdl search path environment variable name */ 00186 #undef LTDL_SEARCHPATH_VAR 00187 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" 00188 00189 /* Standard libtool archive file extension. */ 00190 #undef LTDL_ARCHIVE_EXT 00191 #define LTDL_ARCHIVE_EXT ".la" 00192 00193 /* max. filename length */ 00194 #ifndef LT_FILENAME_MAX 00195 # define LT_FILENAME_MAX 1024 00196 #endif 00197 00198 /* This is the maximum symbol size that won't require malloc/free */ 00199 #undef LT_SYMBOL_LENGTH 00200 #define LT_SYMBOL_LENGTH 128 00201 00202 /* This accounts for the _LTX_ separator */ 00203 #undef LT_SYMBOL_OVERHEAD 00204 #define LT_SYMBOL_OVERHEAD 5 00205 00206 00207 00208 00209 /* --- MEMORY HANDLING --- */ 00210 00211 00212 /* These are the functions used internally. In addition to making 00213 use of the associated function pointers above, they also perform 00214 error handling. */ 00215 static char *lt_estrdup LT_PARAMS((const char *str)); 00216 static lt_ptr lt_emalloc LT_PARAMS((size_t size)); 00217 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); 00218 00219 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */ 00220 #define rpl_realloc realloc 00221 00222 /* These are the pointers that can be changed by the caller: */ 00223 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) 00224 = (lt_ptr (*) LT_PARAMS((size_t))) malloc; 00225 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) 00226 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; 00227 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) 00228 = (void (*) LT_PARAMS((lt_ptr))) free; 00229 00230 /* The following macros reduce the amount of typing needed to cast 00231 assigned memory. */ 00232 #if WITH_DMALLOC 00233 00234 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) 00235 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) 00236 #define LT_DLFREE(p) \ 00237 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END 00238 00239 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) 00240 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) 00241 00242 #else 00243 00244 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) 00245 #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp))) 00246 #define LT_DLFREE(p) \ 00247 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END 00248 00249 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) 00250 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) 00251 00252 #endif 00253 00254 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ 00255 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \ 00256 } LT_STMT_END 00257 00258 00259 /* --- REPLACEMENT FUNCTIONS --- */ 00260 00261 00262 #undef strdup 00263 #define strdup rpl_strdup 00264 00265 static char *strdup LT_PARAMS((const char *str)); 00266 00267 static char * 00268 strdup(str) 00269 const char *str; 00270 { 00271 char *tmp = 0; 00272 00273 if (str) 00274 { 00275 tmp = LT_DLMALLOC (char, 1+ strlen (str)); 00276 if (tmp) 00277 { 00278 strcpy(tmp, str); 00279 } 00280 } 00281 00282 return tmp; 00283 } 00284 00285 00286 #if ! HAVE_STRCMP 00287 00288 #undef strcmp 00289 #define strcmp rpl_strcmp 00290 00291 static int strcmp LT_PARAMS((const char *str1, const char *str2)); 00292 00293 static int 00294 strcmp (str1, str2) 00295 const char *str1; 00296 const char *str2; 00297 { 00298 if (str1 == str2) 00299 return 0; 00300 if (str1 == 0) 00301 return -1; 00302 if (str2 == 0) 00303 return 1; 00304 00305 for (;*str1 && *str2; ++str1, ++str2) 00306 { 00307 if (*str1 != *str2) 00308 break; 00309 } 00310 00311 return (int)(*str1 - *str2); 00312 } 00313 #endif 00314 00315 00316 #if ! HAVE_STRCHR 00317 00318 # if HAVE_INDEX 00319 # define strchr index 00320 # else 00321 # define strchr rpl_strchr 00322 00323 static const char *strchr LT_PARAMS((const char *str, int ch)); 00324 00325 static const char* 00326 strchr(str, ch) 00327 const char *str; 00328 int ch; 00329 { 00330 const char *p; 00331 00332 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) 00333 /*NOWORK*/; 00334 00335 return (*p == (char)ch) ? p : 0; 00336 } 00337 00338 # endif 00339 #endif /* !HAVE_STRCHR */ 00340 00341 00342 #if ! HAVE_STRRCHR 00343 00344 # if HAVE_RINDEX 00345 # define strrchr rindex 00346 # else 00347 # define strrchr rpl_strrchr 00348 00349 static const char *strrchr LT_PARAMS((const char *str, int ch)); 00350 00351 static const char* 00352 strrchr(str, ch) 00353 const char *str; 00354 int ch; 00355 { 00356 const char *p, *q = 0; 00357 00358 for (p = str; *p != LT_EOS_CHAR; ++p) 00359 { 00360 if (*p == (char) ch) 00361 { 00362 q = p; 00363 } 00364 } 00365 00366 return q; 00367 } 00368 00369 # endif 00370 #endif 00371 00372 /* NOTE: Neither bcopy nor the memcpy implementation below can 00373 reliably handle copying in overlapping areas of memory. Use 00374 memmove (for which there is a fallback implmentation below) 00375 if you need that behaviour. */ 00376 #if ! HAVE_MEMCPY 00377 00378 # if HAVE_BCOPY 00379 # define memcpy(dest, src, size) bcopy (src, dest, size) 00380 # else 00381 # define memcpy rpl_memcpy 00382 00383 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); 00384 00385 static lt_ptr 00386 memcpy (dest, src, size) 00387 lt_ptr dest; 00388 const lt_ptr src; 00389 size_t size; 00390 { 00391 const char * s = src; 00392 char * d = dest; 00393 size_t i = 0; 00394 00395 for (i = 0; i < size; ++i) 00396 { 00397 d[i] = s[i]; 00398 } 00399 00400 return dest; 00401 } 00402 00403 # endif /* !HAVE_BCOPY */ 00404 #endif /* !HAVE_MEMCPY */ 00405 00406 #if ! HAVE_MEMMOVE 00407 # define memmove rpl_memmove 00408 00409 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); 00410 00411 static lt_ptr 00412 memmove (dest, src, size) 00413 lt_ptr dest; 00414 const lt_ptr src; 00415 size_t size; 00416 { 00417 const char * s = src; 00418 char * d = dest; 00419 size_t i; 00420 00421 if (d < s) 00422 for (i = 0; i < size; ++i) 00423 { 00424 d[i] = s[i]; 00425 } 00426 else if (d > s && size > 0) 00427 for (i = size -1; ; --i) 00428 { 00429 d[i] = s[i]; 00430 if (i == 0) 00431 break; 00432 } 00433 00434 return dest; 00435 } 00436 00437 #endif /* !HAVE_MEMMOVE */ 00438 00439 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION 00440 00441 static void closedir LT_PARAMS((DIR *entry)); 00442 00443 static void 00444 closedir(entry) 00445 DIR *entry; 00446 { 00447 assert(entry != (DIR *) NULL); 00448 FindClose(entry->hSearch); 00449 lt_dlfree((lt_ptr)entry); 00450 } 00451 00452 00453 static DIR * opendir LT_PARAMS((const char *path)); 00454 00455 static DIR* 00456 opendir (path) 00457 const char *path; 00458 { 00459 char file_specification[LT_FILENAME_MAX]; 00460 DIR *entry; 00461 00462 assert(path != (char *) NULL); 00463 (void) strncpy(file_specification,path,LT_FILENAME_MAX-1); 00464 (void) strcat(file_specification,"\\"); 00465 entry = LT_DLMALLOC (DIR,sizeof(DIR)); 00466 if (entry != (DIR *) 0) 00467 { 00468 entry->firsttime = TRUE; 00469 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); 00470 } 00471 if (entry->hSearch == INVALID_HANDLE_VALUE) 00472 { 00473 (void) strcat(file_specification,"\\*.*"); 00474 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); 00475 if (entry->hSearch == INVALID_HANDLE_VALUE) 00476 { 00477 LT_DLFREE (entry); 00478 return (DIR *) 0; 00479 } 00480 } 00481 return(entry); 00482 } 00483 00484 00485 static struct dirent *readdir LT_PARAMS((DIR *entry)); 00486 00487 static struct dirent *readdir(entry) 00488 DIR *entry; 00489 { 00490 int 00491 status; 00492 00493 if (entry == (DIR *) 0) 00494 return((struct dirent *) 0); 00495 if (!entry->firsttime) 00496 { 00497 status = FindNextFile(entry->hSearch,&entry->Win32FindData); 00498 if (status == 0) 00499 return((struct dirent *) 0); 00500 } 00501 entry->firsttime = FALSE; 00502 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName, 00503 LT_FILENAME_MAX-1); 00504 entry->file_info.d_namlen = strlen(entry->file_info.d_name); 00505 return(&entry->file_info); 00506 } 00507 00508 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ 00509 00510 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>, 00511 ``realloc is not entirely portable'' 00512 In any case we want to use the allocator supplied by the user without 00513 burdening them with an lt_dlrealloc function pointer to maintain. 00514 Instead implement our own version (with known boundary conditions) 00515 using lt_dlmalloc and lt_dlfree. */ 00516 00517 /* #undef realloc 00518 #define realloc rpl_realloc 00519 */ 00520 #if 0 00521 /* You can't (re)define realloc unless you also (re)define malloc. 00522 Right now, this code uses the size of the *destination* to decide 00523 how much to copy. That's not right, but you can't know the size 00524 of the source unless you know enough about, or wrote malloc. So 00525 this code is disabled... */ 00526 00527 static lt_ptr 00528 realloc (ptr, size) 00529 lt_ptr ptr; 00530 size_t size; 00531 { 00532 if (size == 0) 00533 { 00534 /* For zero or less bytes, free the original memory */ 00535 if (ptr != 0) 00536 { 00537 lt_dlfree (ptr); 00538 } 00539 00540 return (lt_ptr) 0; 00541 } 00542 else if (ptr == 0) 00543 { 00544 /* Allow reallocation of a NULL pointer. */ 00545 return lt_dlmalloc (size); 00546 } 00547 else 00548 { 00549 /* Allocate a new block, copy and free the old block. */ 00550 lt_ptr mem = lt_dlmalloc (size); 00551 00552 if (mem) 00553 { 00554 memcpy (mem, ptr, size); 00555 lt_dlfree (ptr); 00556 } 00557 00558 /* Note that the contents of PTR are not damaged if there is 00559 insufficient memory to realloc. */ 00560 return mem; 00561 } 00562 } 00563 #endif 00564 00565 00566 #if ! HAVE_ARGZ_APPEND 00567 # define argz_append rpl_argz_append 00568 00569 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, 00570 const char *buf, size_t buf_len)); 00571 00572 static error_t 00573 argz_append (pargz, pargz_len, buf, buf_len) 00574 char **pargz; 00575 size_t *pargz_len; 00576 const char *buf; 00577 size_t buf_len; 00578 { 00579 size_t argz_len; 00580 char *argz; 00581 00582 assert (pargz); 00583 assert (pargz_len); 00584 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); 00585 00586 /* If nothing needs to be appended, no more work is required. */ 00587 if (buf_len == 0) 00588 return 0; 00589 00590 /* Ensure there is enough room to append BUF_LEN. */ 00591 argz_len = *pargz_len + buf_len; 00592 argz = LT_DLREALLOC (char, *pargz, argz_len); 00593 if (!argz) 00594 return ENOMEM; 00595 00596 /* Copy characters from BUF after terminating '\0' in ARGZ. */ 00597 memcpy (argz + *pargz_len, buf, buf_len); 00598 00599 /* Assign new values. */ 00600 *pargz = argz; 00601 *pargz_len = argz_len; 00602 00603 return 0; 00604 } 00605 #endif /* !HAVE_ARGZ_APPEND */ 00606 00607 00608 #if ! HAVE_ARGZ_CREATE_SEP 00609 # define argz_create_sep rpl_argz_create_sep 00610 00611 static error_t argz_create_sep LT_PARAMS((const char *str, int delim, 00612 char **pargz, size_t *pargz_len)); 00613 00614 static error_t 00615 argz_create_sep (str, delim, pargz, pargz_len) 00616 const char *str; 00617 int delim; 00618 char **pargz; 00619 size_t *pargz_len; 00620 { 00621 size_t argz_len; 00622 char *argz = 0; 00623 00624 assert (str); 00625 assert (pargz); 00626 assert (pargz_len); 00627 00628 /* Make a copy of STR, but replacing each occurence of 00629 DELIM with '\0'. */ 00630 argz_len = 1+ LT_STRLEN (str); 00631 if (argz_len) 00632 { 00633 const char *p; 00634 char *q; 00635 00636 argz = LT_DLMALLOC (char, argz_len); 00637 if (!argz) 00638 return ENOMEM; 00639 00640 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) 00641 { 00642 if (*p == delim) 00643 { 00644 /* Ignore leading delimiters, and fold consecutive 00645 delimiters in STR into a single '\0' in ARGZ. */ 00646 if ((q > argz) && (q[-1] != LT_EOS_CHAR)) 00647 *q++ = LT_EOS_CHAR; 00648 else 00649 --argz_len; 00650 } 00651 else 00652 *q++ = *p; 00653 } 00654 /* Copy terminating LT_EOS_CHAR. */ 00655 *q = *p; 00656 } 00657 00658 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ 00659 if (!argz_len) 00660 LT_DLFREE (argz); 00661 00662 /* Assign new values. */ 00663 *pargz = argz; 00664 *pargz_len = argz_len; 00665 00666 return 0; 00667 } 00668 #endif /* !HAVE_ARGZ_CREATE_SEP */ 00669 00670 00671 #if ! HAVE_ARGZ_INSERT 00672 # define argz_insert rpl_argz_insert 00673 00674 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, 00675 char *before, const char *entry)); 00676 00677 static error_t 00678 argz_insert (pargz, pargz_len, before, entry) 00679 char **pargz; 00680 size_t *pargz_len; 00681 char *before; 00682 const char *entry; 00683 { 00684 assert (pargz); 00685 assert (pargz_len); 00686 assert (entry && *entry); 00687 00688 /* No BEFORE address indicates ENTRY should be inserted after the 00689 current last element. */ 00690 if (!before) 00691 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); 00692 00693 /* This probably indicates a programmer error, but to preserve 00694 semantics, scan back to the start of an entry if BEFORE points 00695 into the middle of it. */ 00696 while ((before > *pargz) && (before[-1] != LT_EOS_CHAR)) 00697 --before; 00698 00699 { 00700 size_t entry_len = 1+ LT_STRLEN (entry); 00701 size_t argz_len = *pargz_len + entry_len; 00702 size_t offset = before - *pargz; 00703 char *argz = LT_DLREALLOC (char, *pargz, argz_len); 00704 00705 if (!argz) 00706 return ENOMEM; 00707 00708 /* Make BEFORE point to the equivalent offset in ARGZ that it 00709 used to have in *PARGZ incase realloc() moved the block. */ 00710 before = argz + offset; 00711 00712 /* Move the ARGZ entries starting at BEFORE up into the new 00713 space at the end -- making room to copy ENTRY into the 00714 resulting gap. */ 00715 memmove (before + entry_len, before, *pargz_len - offset); 00716 memcpy (before, entry, entry_len); 00717 00718 /* Assign new values. */ 00719 *pargz = argz; 00720 *pargz_len = argz_len; 00721 } 00722 00723 return 0; 00724 } 00725 #endif /* !HAVE_ARGZ_INSERT */ 00726 00727 00728 #if ! HAVE_ARGZ_NEXT 00729 # define argz_next rpl_argz_next 00730 00731 static char *argz_next LT_PARAMS((char *argz, size_t argz_len, 00732 const char *entry)); 00733 00734 static char * 00735 argz_next (argz, argz_len, entry) 00736 char *argz; 00737 size_t argz_len; 00738 const char *entry; 00739 { 00740 assert ((argz && argz_len) || (!argz && !argz_len)); 00741 00742 if (entry) 00743 { 00744 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address 00745 within the ARGZ vector. */ 00746 assert ((!argz && !argz_len) 00747 || ((argz <= entry) && (entry < (argz + argz_len)))); 00748 00749 /* Move to the char immediately after the terminating 00750 '\0' of ENTRY. */ 00751 entry = 1+ strchr (entry, LT_EOS_CHAR); 00752 00753 /* Return either the new ENTRY, or else NULL if ARGZ is 00754 exhausted. */ 00755 return (entry >= argz + argz_len) ? 0 : (char *) entry; 00756 } 00757 else 00758 { 00759 /* This should probably be flagged as a programmer error, 00760 since starting an argz_next loop with the iterator set 00761 to ARGZ is safer. To preserve semantics, handle the NULL 00762 case by returning the start of ARGZ (if any). */ 00763 if (argz_len > 0) 00764 return argz; 00765 else 00766 return 0; 00767 } 00768 } 00769 #endif /* !HAVE_ARGZ_NEXT */ 00770 00771 00772 00773 #if ! HAVE_ARGZ_STRINGIFY 00774 # define argz_stringify rpl_argz_stringify 00775 00776 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, 00777 int sep)); 00778 00779 static void 00780 argz_stringify (argz, argz_len, sep) 00781 char *argz; 00782 size_t argz_len; 00783 int sep; 00784 { 00785 assert ((argz && argz_len) || (!argz && !argz_len)); 00786 00787 if (sep) 00788 { 00789 --argz_len; /* don't stringify the terminating EOS */ 00790 while (--argz_len > 0) 00791 { 00792 if (argz[argz_len] == LT_EOS_CHAR) 00793 argz[argz_len] = sep; 00794 } 00795 } 00796 } 00797 #endif /* !HAVE_ARGZ_STRINGIFY */ 00798 00799 00800 00801 00802 /* --- TYPE DEFINITIONS -- */ 00803 00804 00805 /* This type is used for the array of caller data sets in each handler. */ 00806 typedef struct { 00807 lt_dlcaller_id key; 00808 lt_ptr data; 00809 } lt_caller_data; 00810 00811 00812 00813 00814 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ 00815 00816 00817 /* Extract the diagnostic strings from the error table macro in the same 00818 order as the enumerated indices in ltdl.h. */ 00819 00820 static const char *lt_dlerror_strings[] = 00821 { 00822 #define LT_ERROR(name, diagnostic) (diagnostic), 00823 lt_dlerror_table 00824 #undef LT_ERROR 00825 00826 0 00827 }; 00828 00829 /* This structure is used for the list of registered loaders. */ 00830 struct lt_dlloader { 00831 struct lt_dlloader *next; 00832 const char *loader_name; /* identifying name for each loader */ 00833 const char *sym_prefix; /* prefix for symbols */ 00834 lt_module_open *module_open; 00835 lt_module_close *module_close; 00836 lt_find_sym *find_sym; 00837 lt_dlloader_exit *dlloader_exit; 00838 lt_user_data dlloader_data; 00839 }; 00840 00841 struct lt_dlhandle_struct { 00842 struct lt_dlhandle_struct *next; 00843 lt_dlloader *loader; /* dlopening interface */ 00844 lt_dlinfo info; 00845 int depcount; /* number of dependencies */ 00846 lt_dlhandle *deplibs; /* dependencies */ 00847 lt_module module; /* system module handle */ 00848 lt_ptr system; /* system specific data */ 00849 lt_caller_data *caller_data; /* per caller associated data */ 00850 int flags; /* various boolean stats */ 00851 }; 00852 00853 /* Various boolean flags can be stored in the flags field of an 00854 lt_dlhandle_struct... */ 00855 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) 00856 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) 00857 00858 #define LT_DLRESIDENT_FLAG (0x01 << 0) 00859 /* ...add more flags here... */ 00860 00861 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) 00862 00863 00864 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] 00865 00866 static const char objdir[] = LTDL_OBJDIR; 00867 static const char archive_ext[] = LTDL_ARCHIVE_EXT; 00868 #ifdef LTDL_SHLIB_EXT 00869 static const char shlib_ext[] = LTDL_SHLIB_EXT; 00870 #endif 00871 #ifdef LTDL_SYSSEARCHPATH 00872 static const char sys_search_path[] = LTDL_SYSSEARCHPATH; 00873 #endif 00874 00875 00876 00877 00878 /* --- MUTEX LOCKING --- */ 00879 00880 00881 /* Macros to make it easier to run the lock functions only if they have 00882 been registered. The reason for the complicated lock macro is to 00883 ensure that the stored error message from the last error is not 00884 accidentally erased if the current function doesn't generate an 00885 error of its own. */ 00886 #define LT_DLMUTEX_LOCK() LT_STMT_START { \ 00887 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ 00888 } LT_STMT_END 00889 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ 00890 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ 00891 } LT_STMT_END 00892 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ 00893 if (lt_dlmutex_seterror_func) \ 00894 (*lt_dlmutex_seterror_func) (errormsg); \ 00895 else lt_dllast_error = (errormsg); } LT_STMT_END 00896 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ 00897 if (lt_dlmutex_seterror_func) \ 00898 (errormsg) = (*lt_dlmutex_geterror_func) (); \ 00899 else (errormsg) = lt_dllast_error; } LT_STMT_END 00900 00901 /* The mutex functions stored here are global, and are necessarily the 00902 same for all threads that wish to share access to libltdl. */ 00903 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; 00904 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; 00905 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; 00906 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; 00907 static const char *lt_dllast_error = 0; 00908 00909 00910 /* Either set or reset the mutex functions. Either all the arguments must 00911 be valid functions, or else all can be NULL to turn off locking entirely. 00912 The registered functions should be manipulating a static global lock 00913 from the lock() and unlock() callbacks, which needs to be reentrant. */ 00914 int 00915 lt_dlmutex_register (lock, unlock, seterror, geterror) 00916 lt_dlmutex_lock *lock; 00917 lt_dlmutex_unlock *unlock; 00918 lt_dlmutex_seterror *seterror; 00919 lt_dlmutex_geterror *geterror; 00920 { 00921 lt_dlmutex_unlock *old_unlock = unlock; 00922 int errors = 0; 00923 00924 /* Lock using the old lock() callback, if any. */ 00925 LT_DLMUTEX_LOCK (); 00926 00927 if ((lock && unlock && seterror && geterror) 00928 || !(lock || unlock || seterror || geterror)) 00929 { 00930 lt_dlmutex_lock_func = lock; 00931 lt_dlmutex_unlock_func = unlock; 00932 lt_dlmutex_geterror_func = geterror; 00933 } 00934 else 00935 { 00936 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); 00937 ++errors; 00938 } 00939 00940 /* Use the old unlock() callback we saved earlier, if any. Otherwise 00941 record any errors using internal storage. */ 00942 if (old_unlock) 00943 (*old_unlock) (); 00944 00945 /* Return the number of errors encountered during the execution of 00946 this function. */ 00947 return errors; 00948 } 00949 00950 00951 00952 00953 /* --- ERROR HANDLING --- */ 00954 00955 00956 static const char **user_error_strings = 0; 00957 static int errorcount = LT_ERROR_MAX; 00958 00959 int 00960 lt_dladderror (diagnostic) 00961 const char *diagnostic; 00962 { 00963 int errindex = 0; 00964 int result = -1; 00965 const char **temp = (const char **) 0; 00966 00967 assert (diagnostic); 00968 00969 LT_DLMUTEX_LOCK (); 00970 00971 errindex = errorcount - LT_ERROR_MAX; 00972 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); 00973 if (temp) 00974 { 00975 user_error_strings = temp; 00976 user_error_strings[errindex] = diagnostic; 00977 result = errorcount++; 00978 } 00979 00980 LT_DLMUTEX_UNLOCK (); 00981 00982 return result; 00983 } 00984 00985 int 00986 lt_dlseterror (errindex) 00987 int errindex; 00988 { 00989 int errors = 0; 00990 00991 LT_DLMUTEX_LOCK (); 00992 00993 if (errindex >= errorcount || errindex < 0) 00994 { 00995 /* Ack! Error setting the error message! */ 00996 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); 00997 ++errors; 00998 } 00999 else if (errindex < LT_ERROR_MAX) 01000 { 01001 /* No error setting the error message! */ 01002 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); 01003 } 01004 else 01005 { 01006 /* No error setting the error message! */ 01007 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); 01008 } 01009 01010 LT_DLMUTEX_UNLOCK (); 01011 01012 return errors; 01013 } 01014 01015 static lt_ptr 01016 lt_emalloc (size) 01017 size_t size; 01018 { 01019 lt_ptr mem = lt_dlmalloc (size); 01020 if (size && !mem) 01021 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 01022 return mem; 01023 } 01024 01025 static lt_ptr 01026 lt_erealloc (addr, size) 01027 lt_ptr addr; 01028 size_t size; 01029 { 01030 lt_ptr mem = lt_dlrealloc (addr, size); 01031 if (size && !mem) 01032 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 01033 return mem; 01034 } 01035 01036 static char * 01037 lt_estrdup (str) 01038 const char *str; 01039 { 01040 char *copy = strdup (str); 01041 if (LT_STRLEN (str) && !copy) 01042 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 01043 return copy; 01044 } 01045 01046 01047 01048 01049 /* --- DLOPEN() INTERFACE LOADER --- */ 01050 01051 01052 #if HAVE_LIBDL 01053 01054 /* dynamic linking with dlopen/dlsym */ 01055 01056 #if HAVE_DLFCN_H 01057 # include <dlfcn.h> 01058 #endif 01059 01060 #if HAVE_SYS_DL_H 01061 # include <sys/dl.h> 01062 #endif 01063 01064 #ifdef RTLD_GLOBAL 01065 # define LT_GLOBAL RTLD_GLOBAL 01066 #else 01067 # ifdef DL_GLOBAL 01068 # define LT_GLOBAL DL_GLOBAL 01069 # endif 01070 #endif /* !RTLD_GLOBAL */ 01071 #ifndef LT_GLOBAL 01072 # define LT_GLOBAL 0 01073 #endif /* !LT_GLOBAL */ 01074 01075 /* We may have to define LT_LAZY_OR_NOW in the command line if we 01076 find out it does not work in some platform. */ 01077 #ifndef LT_LAZY_OR_NOW 01078 # ifdef RTLD_LAZY 01079 # define LT_LAZY_OR_NOW RTLD_LAZY 01080 # else 01081 # ifdef DL_LAZY 01082 # define LT_LAZY_OR_NOW DL_LAZY 01083 # endif 01084 # endif /* !RTLD_LAZY */ 01085 #endif 01086 #ifndef LT_LAZY_OR_NOW 01087 # ifdef RTLD_NOW 01088 # define LT_LAZY_OR_NOW RTLD_NOW 01089 # else 01090 # ifdef DL_NOW 01091 # define LT_LAZY_OR_NOW DL_NOW 01092 # endif 01093 # endif /* !RTLD_NOW */ 01094 #endif 01095 #ifndef LT_LAZY_OR_NOW 01096 # define LT_LAZY_OR_NOW 0 01097 #endif /* !LT_LAZY_OR_NOW */ 01098 01099 #if HAVE_DLERROR 01100 # define DLERROR(arg) dlerror () 01101 #else 01102 # define DLERROR(arg) LT_DLSTRERROR (arg) 01103 #endif 01104 01105 static lt_module 01106 sys_dl_open (loader_data, filename) 01107 lt_user_data loader_data; 01108 const char *filename; 01109 { 01110 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW); 01111 01112 if (!module) 01113 { 01114 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); 01115 } 01116 01117 return module; 01118 } 01119 01120 static int 01121 sys_dl_close (loader_data, module) 01122 lt_user_data loader_data; 01123 lt_module module; 01124 { 01125 int errors = 0; 01126 01127 if (dlclose (module) != 0) 01128 { 01129 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); 01130 ++errors; 01131 } 01132 01133 return errors; 01134 } 01135 01136 static lt_ptr 01137 sys_dl_sym (loader_data, module, symbol) 01138 lt_user_data loader_data; 01139 lt_module module; 01140 const char *symbol; 01141 { 01142 lt_ptr address = dlsym (module, symbol); 01143 01144 if (!address) 01145 { 01146 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); 01147 } 01148 01149 return address; 01150 } 01151 01152 static struct lt_user_dlloader sys_dl = 01153 { 01154 # ifdef NEED_USCORE 01155 "_", 01156 # else 01157 0, 01158 # endif 01159 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; 01160 01161 01162 #endif /* HAVE_LIBDL */ 01163 01164 01165 01166 /* --- SHL_LOAD() INTERFACE LOADER --- */ 01167 01168 #if HAVE_SHL_LOAD && !defined(__llvm__) 01169 01170 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ 01171 01172 #ifdef HAVE_DL_H 01173 # include <dl.h> 01174 #endif 01175 01176 /* some flags are missing on some systems, so we provide 01177 * harmless defaults. 01178 * 01179 * Mandatory: 01180 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. 01181 * BIND_DEFERRED - Delay code symbol resolution until actual reference. 01182 * 01183 * Optionally: 01184 * BIND_FIRST - Place the library at the head of the symbol search 01185 * order. 01186 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all 01187 * unsatisfied symbols as fatal. This flag allows 01188 * binding of unsatisfied code symbols to be deferred 01189 * until use. 01190 * [Perl: For certain libraries, like DCE, deferred 01191 * binding often causes run time problems. Adding 01192 * BIND_NONFATAL to BIND_IMMEDIATE still allows 01193 * unresolved references in situations like this.] 01194 * BIND_NOSTART - Do not call the initializer for the shared library 01195 * when the library is loaded, nor on a future call to 01196 * shl_unload(). 01197 * BIND_VERBOSE - Print verbose messages concerning possible 01198 * unsatisfied symbols. 01199 * 01200 * hp9000s700/hp9000s800: 01201 * BIND_RESTRICTED - Restrict symbols visible by the library to those 01202 * present at library load time. 01203 * DYNAMIC_PATH - Allow the loader to dynamically search for the 01204 * library specified by the path argument. 01205 */ 01206 01207 #ifndef DYNAMIC_PATH 01208 # define DYNAMIC_PATH 0 01209 #endif 01210 #ifndef BIND_RESTRICTED 01211 # define BIND_RESTRICTED 0 01212 #endif 01213 01214 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) 01215 01216 static lt_module 01217 sys_shl_open (loader_data, filename) 01218 lt_user_data loader_data; 01219 const char *filename; 01220 { 01221 static shl_t self = (shl_t) 0; 01222 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); 01223 01224 /* Since searching for a symbol against a NULL module handle will also 01225 look in everything else that was already loaded and exported with 01226 the -E compiler flag, we always cache a handle saved before any 01227 modules are loaded. */ 01228 if (!self) 01229 { 01230 lt_ptr address; 01231 shl_findsym (&self, "main", TYPE_UNDEFINED, &address); 01232 } 01233 01234 if (!filename) 01235 { 01236 module = self; 01237 } 01238 else 01239 { 01240 module = shl_load (filename, LT_BIND_FLAGS, 0L); 01241 01242 if (!module) 01243 { 01244 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 01245 } 01246 } 01247 01248 return module; 01249 } 01250 01251 static int 01252 sys_shl_close (loader_data, module) 01253 lt_user_data loader_data; 01254 lt_module module; 01255 { 01256 int errors = 0; 01257 01258 if (module && (shl_unload ((shl_t) (module)) != 0)) 01259 { 01260 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 01261 ++errors; 01262 } 01263 01264 return errors; 01265 } 01266 01267 static lt_ptr 01268 sys_shl_sym (loader_data, module, symbol) 01269 lt_user_data loader_data; 01270 lt_module module; 01271 const char *symbol; 01272 { 01273 lt_ptr address = 0; 01274 01275 /* sys_shl_open should never return a NULL module handle */ 01276 if (module == (lt_module) 0) 01277 { 01278 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 01279 } 01280 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) 01281 { 01282 if (!address) 01283 { 01284 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 01285 } 01286 } 01287 01288 return address; 01289 } 01290 01291 static struct lt_user_dlloader sys_shl = { 01292 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 01293 }; 01294 01295 #endif /* HAVE_SHL_LOAD */ 01296 01297 01298 01299 01300 /* --- LOADLIBRARY() INTERFACE LOADER --- */ 01301 01302 #ifdef __WINDOWS__ 01303 01304 /* dynamic linking for Win32 */ 01305 01306 #include <windows.h> 01307 01308 /* Forward declaration; required to implement handle search below. */ 01309 static lt_dlhandle handles; 01310 01311 static lt_module 01312 sys_wll_open (loader_data, filename) 01313 lt_user_data loader_data; 01314 const char *filename; 01315 { 01316 lt_dlhandle cur; 01317 lt_module module = 0; 01318 const char *errormsg = 0; 01319 char *searchname = 0; 01320 char *ext; 01321 char self_name_buf[MAX_PATH]; 01322 01323 if (!filename) 01324 { 01325 /* Get the name of main module */ 01326 *self_name_buf = 0; 01327 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); 01328 filename = ext = self_name_buf; 01329 } 01330 else 01331 { 01332 ext = strrchr (filename, '.'); 01333 } 01334 01335 if (ext) 01336 { 01337 /* FILENAME already has an extension. */ 01338 searchname = lt_estrdup (filename); 01339 } 01340 else 01341 { 01342 /* Append a `.' to stop Windows from adding an 01343 implicit `.dll' extension. */ 01344 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); 01345 if (searchname) 01346 sprintf (searchname, "%s.", filename); 01347 } 01348 if (!searchname) 01349 return 0; 01350 01351 #if __CYGWIN__ 01352 { 01353 char wpath[MAX_PATH]; 01354 cygwin_conv_to_full_win32_path(searchname, wpath); 01355 module = LoadLibrary(wpath); 01356 } 01357 #else 01358 module = LoadLibrary (searchname); 01359 #endif 01360 LT_DLFREE (searchname); 01361 01362 /* libltdl expects this function to fail if it is unable 01363 to physically load the library. Sadly, LoadLibrary 01364 will search the loaded libraries for a match and return 01365 one of them if the path search load fails. 01366 01367 We check whether LoadLibrary is returning a handle to 01368 an already loaded module, and simulate failure if we 01369 find one. */ 01370 LT_DLMUTEX_LOCK (); 01371 cur = handles; 01372 while (cur) 01373 { 01374 if (!cur->module) 01375 { 01376 cur = 0; 01377 break; 01378 } 01379 01380 if (cur->module == module) 01381 { 01382 break; 01383 } 01384 01385 cur = cur->next; 01386 } 01387 LT_DLMUTEX_UNLOCK (); 01388 01389 if (cur || !module) 01390 { 01391 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 01392 module = 0; 01393 } 01394 01395 return module; 01396 } 01397 01398 static int 01399 sys_wll_close (loader_data, module) 01400 lt_user_data loader_data; 01401 lt_module module; 01402 { 01403 int errors = 0; 01404 01405 if (FreeLibrary(module) == 0) 01406 { 01407 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 01408 ++errors; 01409 } 01410 01411 return errors; 01412 } 01413 01414 static lt_ptr 01415 sys_wll_sym (loader_data, module, symbol) 01416 lt_user_data loader_data; 01417 lt_module module; 01418 const char *symbol; 01419 { 01420 lt_ptr address = GetProcAddress (module, symbol); 01421 01422 if (!address) 01423 { 01424 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 01425 } 01426 01427 return address; 01428 } 01429 01430 static struct lt_user_dlloader sys_wll = { 01431 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 01432 }; 01433 01434 #endif /* __WINDOWS__ */ 01435 01436 01437 01438 01439 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */ 01440 01441 01442 #ifdef __BEOS__ 01443 01444 /* dynamic linking for BeOS */ 01445 01446 #include <kernel/image.h> 01447 01448 static lt_module 01449 sys_bedl_open (loader_data, filename) 01450 lt_user_data loader_data; 01451 const char *filename; 01452 { 01453 image_id image = 0; 01454 01455 if (filename) 01456 { 01457 image = load_add_on (filename); 01458 } 01459 else 01460 { 01461 image_info info; 01462 int32 cookie = 0; 01463 if (get_next_image_info (0, &cookie, &info) == B_OK) 01464 image = load_add_on (info.name); 01465 } 01466 01467 if (image <= 0) 01468 { 01469 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 01470 image = 0; 01471 } 01472 01473 return (lt_module) image; 01474 } 01475 01476 static int 01477 sys_bedl_close (loader_data, module) 01478 lt_user_data loader_data; 01479 lt_module module; 01480 { 01481 int errors = 0; 01482 01483 if (unload_add_on ((image_id) module) != B_OK) 01484 { 01485 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 01486 ++errors; 01487 } 01488 01489 return errors; 01490 } 01491 01492 static lt_ptr 01493 sys_bedl_sym (loader_data, module, symbol) 01494 lt_user_data loader_data; 01495 lt_module module; 01496 const char *symbol; 01497 { 01498 lt_ptr address = 0; 01499 image_id image = (image_id) module; 01500 01501 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) 01502 { 01503 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 01504 address = 0; 01505 } 01506 01507 return address; 01508 } 01509 01510 static struct lt_user_dlloader sys_bedl = { 01511 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 01512 }; 01513 01514 #endif /* __BEOS__ */ 01515 01516 01517 01518 01519 /* --- DLD_LINK() INTERFACE LOADER --- */ 01520 01521 01522 #if HAVE_DLD 01523 01524 /* dynamic linking with dld */ 01525 01526 #if HAVE_DLD_H 01527 #include <dld.h> 01528 #endif 01529 01530 static lt_module 01531 sys_dld_open (loader_data, filename) 01532 lt_user_data loader_data; 01533 const char *filename; 01534 { 01535 lt_module module = strdup (filename); 01536 01537 if (dld_link (filename) != 0) 01538 { 01539 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 01540 LT_DLFREE (module); 01541 module = 0; 01542 } 01543 01544 return module; 01545 } 01546 01547 static int 01548 sys_dld_close (loader_data, module) 01549 lt_user_data loader_data; 01550 lt_module module; 01551 { 01552 int errors = 0; 01553 01554 if (dld_unlink_by_file ((char*)(module), 1) != 0) 01555 { 01556 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 01557 ++errors; 01558 } 01559 else 01560 { 01561 LT_DLFREE (module); 01562 } 01563 01564 return errors; 01565 } 01566 01567 static lt_ptr 01568 sys_dld_sym (loader_data, module, symbol) 01569 lt_user_data loader_data; 01570 lt_module module; 01571 const char *symbol; 01572 { 01573 lt_ptr address = dld_get_func (symbol); 01574 01575 if (!address) 01576 { 01577 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 01578 } 01579 01580 return address; 01581 } 01582 01583 static struct lt_user_dlloader sys_dld = { 01584 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 01585 }; 01586 01587 #endif /* HAVE_DLD */ 01588 01589 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */ 01590 #if HAVE_DYLD 01591 01592 01593 #if HAVE_MACH_O_DYLD_H 01594 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__) 01595 /* Is this correct? Does it still function properly? */ 01596 #define __private_extern__ extern 01597 #endif 01598 # include <mach-o/dyld.h> 01599 #endif 01600 #include <mach-o/getsect.h> 01601 01602 /* We have to put some stuff here that isn't in older dyld.h files */ 01603 #ifndef ENUM_DYLD_BOOL 01604 # define ENUM_DYLD_BOOL 01605 # undef FALSE 01606 # undef TRUE 01607 enum DYLD_BOOL { 01608 FALSE, 01609 TRUE 01610 }; 01611 #endif 01612 #ifndef LC_REQ_DYLD 01613 # define LC_REQ_DYLD 0x80000000 01614 #endif 01615 #ifndef LC_LOAD_WEAK_DYLIB 01616 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) 01617 #endif 01618 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0; 01619 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0; 01620 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0; 01621 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0; 01622 01623 #ifndef NSADDIMAGE_OPTION_NONE 01624 #define NSADDIMAGE_OPTION_NONE 0x0 01625 #endif 01626 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR 01627 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 01628 #endif 01629 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING 01630 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2 01631 #endif 01632 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 01633 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 01634 #endif 01635 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 01636 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 01637 #endif 01638 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 01639 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 01640 #endif 01641 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 01642 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1 01643 #endif 01644 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 01645 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2 01646 #endif 01647 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 01648 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 01649 #endif 01650 01651 01652 static const char * 01653 lt_int_dyld_error(othererror) 01654 char* othererror; 01655 { 01656 /* return the dyld error string, or the passed in error string if none */ 01657 NSLinkEditErrors ler; 01658 int lerno; 01659 const char *errstr; 01660 const char *file; 01661 NSLinkEditError(&ler,&lerno,&file,&errstr); 01662 if (!errstr || !strlen(errstr)) errstr = othererror; 01663 return errstr; 01664 } 01665 01666 static const struct mach_header * 01667 lt_int_dyld_get_mach_header_from_nsmodule(module) 01668 NSModule module; 01669 { 01670 /* There should probably be an apple dyld api for this */ 01671 int i=_dyld_image_count(); 01672 int j; 01673 const char *modname=NSNameOfModule(module); 01674 const struct mach_header *mh=NULL; 01675 if (!modname) return NULL; 01676 for (j = 0; j < i; j++) 01677 { 01678 if (!strcmp(_dyld_get_image_name(j),modname)) 01679 { 01680 mh=_dyld_get_image_header(j); 01681 break; 01682 } 01683 } 01684 return mh; 01685 } 01686 01687 static const char* lt_int_dyld_lib_install_name(mh) 01688 const struct mach_header *mh; 01689 { 01690 /* NSAddImage is also used to get the loaded image, but it only works if the lib 01691 is installed, for uninstalled libs we need to check the install_names against 01692 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a 01693 different lib was loaded as a result 01694 */ 01695 int j; 01696 struct load_command *lc; 01697 unsigned long offset = sizeof(struct mach_header); 01698 const char* retStr=NULL; 01699 for (j = 0; j < mh->ncmds; j++) 01700 { 01701 lc = (struct load_command*)(((unsigned long)mh) + offset); 01702 if (LC_ID_DYLIB == lc->cmd) 01703 { 01704 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset + 01705 (unsigned long)lc); 01706 } 01707 offset += lc->cmdsize; 01708 } 01709 return retStr; 01710 } 01711 01712 static const struct mach_header * 01713 lt_int_dyld_match_loaded_lib_by_install_name(const char *name) 01714 { 01715 int i=_dyld_image_count(); 01716 int j; 01717 const struct mach_header *mh=NULL; 01718 const char *id=NULL; 01719 for (j = 0; j < i; j++) 01720 { 01721 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j)); 01722 if ((id) && (!strcmp(id,name))) 01723 { 01724 mh=_dyld_get_image_header(j); 01725 break; 01726 } 01727 } 01728 return mh; 01729 } 01730 01731 static NSSymbol 01732 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh) 01733 const char *symbol; 01734 const struct mach_header *mh; 01735 { 01736 /* Safe to assume our mh is good */ 01737 int j; 01738 struct load_command *lc; 01739 unsigned long offset = sizeof(struct mach_header); 01740 NSSymbol retSym = 0; 01741 const struct mach_header *mh1; 01742 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) ) 01743 { 01744 for (j = 0; j < mh->ncmds; j++) 01745 { 01746 lc = (struct load_command*)(((unsigned long)mh) + offset); 01747 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) 01748 { 01749 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset + 01750 (unsigned long)lc)); 01751 if (!mh1) 01752 { 01753 /* Maybe NSAddImage can find it */ 01754 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset + 01755 (unsigned long)lc), 01756 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + 01757 NSADDIMAGE_OPTION_WITH_SEARCHING + 01758 NSADDIMAGE_OPTION_RETURN_ON_ERROR ); 01759 } 01760 if (mh1) 01761 { 01762 retSym = ltdl_NSLookupSymbolInImage(mh1, 01763 symbol, 01764 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 01765 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 01766 ); 01767 if (retSym) break; 01768 } 01769 } 01770 offset += lc->cmdsize; 01771 } 01772 } 01773 return retSym; 01774 } 01775 01776 static int 01777 sys_dyld_init() 01778 { 01779 int retCode = 0; 01780 int err = 0; 01781 if (!_dyld_present()) { 01782 retCode=1; 01783 } 01784 else { 01785 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage); 01786 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage); 01787 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage); 01788 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic); 01789 } 01790 return retCode; 01791 } 01792 01793 static lt_module 01794 sys_dyld_open (loader_data, filename) 01795 lt_user_data loader_data; 01796 const char *filename; 01797 { 01798 lt_module module = 0; 01799 NSObjectFileImage ofi = 0; 01800 NSObjectFileImageReturnCode ofirc; 01801 01802 if (!filename) 01803 return (lt_module)-1; 01804 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi); 01805 switch (ofirc) 01806 { 01807 case NSObjectFileImageSuccess: 01808 module = NSLinkModule(ofi, filename, 01809 NSLINKMODULE_OPTION_RETURN_ON_ERROR 01810 | NSLINKMODULE_OPTION_PRIVATE 01811 | NSLINKMODULE_OPTION_BINDNOW); 01812 NSDestroyObjectFileImage(ofi); 01813 if (module) 01814 ltdl_NSMakePrivateModulePublic(module); 01815 break; 01816 case NSObjectFileImageInappropriateFile: 01817 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) 01818 { 01819 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR); 01820 break; 01821 } 01822 default: 01823 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); 01824 return 0; 01825 } 01826 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); 01827 return module; 01828 } 01829 01830 static int 01831 sys_dyld_close (loader_data, module) 01832 lt_user_data loader_data; 01833 lt_module module; 01834 { 01835 int retCode = 0; 01836 int flags = 0; 01837 if (module == (lt_module)-1) return 0; 01838 #ifdef __BIG_ENDIAN__ 01839 if (((struct mach_header *)module)->magic == MH_MAGIC) 01840 #else 01841 if (((struct mach_header *)module)->magic == MH_CIGAM) 01842 #endif 01843 { 01844 LT_DLMUTEX_SETERROR("Can not close a dylib"); 01845 retCode = 1; 01846 } 01847 else 01848 { 01849 #if 1 01850 /* Currently, if a module contains c++ static destructors and it is unloaded, we 01851 get a segfault in atexit(), due to compiler and dynamic loader differences of 01852 opinion, this works around that. 01853 */ 01854 if ((const struct section *)NULL != 01855 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module), 01856 "__DATA","__mod_term_func")) 01857 { 01858 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; 01859 } 01860 #endif 01861 #ifdef __ppc__ 01862 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; 01863 #endif 01864 if (!NSUnLinkModule(module,flags)) 01865 { 01866 retCode=1; 01867 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE))); 01868 } 01869 } 01870 01871 return retCode; 01872 } 01873 01874 static lt_ptr 01875 sys_dyld_sym (loader_data, module, symbol) 01876 lt_user_data loader_data; 01877 lt_module module; 01878 const char *symbol; 01879 { 01880 lt_ptr address = 0; 01881 NSSymbol *nssym = 0; 01882 void *unused; 01883 const struct mach_header *mh=NULL; 01884 char saveError[256] = "Symbol not found"; 01885 if (module == (lt_module)-1) 01886 { 01887 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused); 01888 return address; 01889 } 01890 #ifdef __BIG_ENDIAN__ 01891 if (((struct mach_header *)module)->magic == MH_MAGIC) 01892 #else 01893 if (((struct mach_header *)module)->magic == MH_CIGAM) 01894 #endif 01895 { 01896 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) 01897 { 01898 mh=module; 01899 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol)) 01900 { 01901 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module, 01902 symbol, 01903 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 01904 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 01905 ); 01906 } 01907 } 01908 01909 } 01910 else { 01911 nssym = NSLookupSymbolInModule(module, symbol); 01912 } 01913 if (!nssym) 01914 { 01915 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255); 01916 saveError[255] = 0; 01917 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module); 01918 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh); 01919 } 01920 if (!nssym) 01921 { 01922 LT_DLMUTEX_SETERROR (saveError); 01923 return NULL; 01924 } 01925 return NSAddressOfSymbol(nssym); 01926 } 01927 01928 static struct lt_user_dlloader sys_dyld = 01929 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 }; 01930 01931 01932 #endif /* HAVE_DYLD */ 01933 01934 01935 /* --- DLPREOPEN() INTERFACE LOADER --- */ 01936 01937 01938 /* emulate dynamic linking using preloaded_symbols */ 01939 01940 typedef struct lt_dlsymlists_t 01941 { 01942 struct lt_dlsymlists_t *next; 01943 const lt_dlsymlist *syms; 01944 } lt_dlsymlists_t; 01945 01946 static const lt_dlsymlist *default_preloaded_symbols = 0; 01947 static lt_dlsymlists_t *preloaded_symbols = 0; 01948 01949 static int 01950 presym_init (loader_data) 01951 lt_user_data loader_data; 01952 { 01953 int errors = 0; 01954 01955 LT_DLMUTEX_LOCK (); 01956 01957 preloaded_symbols = 0; 01958 if (default_preloaded_symbols) 01959 { 01960 errors = lt_dlpreload (default_preloaded_symbols); 01961 } 01962 01963 LT_DLMUTEX_UNLOCK (); 01964 01965 return errors; 01966 } 01967 01968 static int 01969 presym_free_symlists () 01970 { 01971 lt_dlsymlists_t *lists; 01972 01973 LT_DLMUTEX_LOCK (); 01974 01975 lists = preloaded_symbols; 01976 while (lists) 01977 { 01978 lt_dlsymlists_t *tmp = lists; 01979 01980 lists = lists->next; 01981 LT_DLFREE (tmp); 01982 } 01983 preloaded_symbols = 0; 01984 01985 LT_DLMUTEX_UNLOCK (); 01986 01987 return 0; 01988 } 01989 01990 static int 01991 presym_exit (loader_data) 01992 lt_user_data loader_data; 01993 { 01994 presym_free_symlists (); 01995 return 0; 01996 } 01997 01998 static int 01999 presym_add_symlist (preloaded) 02000 const lt_dlsymlist *preloaded; 02001 { 02002 lt_dlsymlists_t *tmp; 02003 lt_dlsymlists_t *lists; 02004 int errors = 0; 02005 02006 LT_DLMUTEX_LOCK (); 02007 02008 lists = preloaded_symbols; 02009 while (lists) 02010 { 02011 if (lists->syms == preloaded) 02012 { 02013 goto done; 02014 } 02015 lists = lists->next; 02016 } 02017 02018 tmp = LT_EMALLOC (lt_dlsymlists_t, 1); 02019 if (tmp) 02020 { 02021 memset (tmp, 0, sizeof(lt_dlsymlists_t)); 02022 tmp->syms = preloaded; 02023 tmp->next = preloaded_symbols; 02024 preloaded_symbols = tmp; 02025 } 02026 else 02027 { 02028 ++errors; 02029 } 02030 02031 done: 02032 LT_DLMUTEX_UNLOCK (); 02033 return errors; 02034 } 02035 02036 static lt_module 02037 presym_open (loader_data, filename) 02038 lt_user_data loader_data; 02039 const char *filename; 02040 { 02041 lt_dlsymlists_t *lists; 02042 lt_module module = (lt_module) 0; 02043 02044 LT_DLMUTEX_LOCK (); 02045 lists = preloaded_symbols; 02046 02047 if (!lists) 02048 { 02049 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); 02050 goto done; 02051 } 02052 02053 /* Can't use NULL as the reflective symbol header, as NULL is 02054 used to mark the end of the entire symbol list. Self-dlpreopened 02055 symbols follow this magic number, chosen to be an unlikely 02056 clash with a real module name. */ 02057 if (!filename) 02058 { 02059 filename = "@PROGRAM@"; 02060 } 02061 02062 while (lists) 02063 { 02064 const lt_dlsymlist *syms = lists->syms; 02065 02066 while (syms->name) 02067 { 02068 if (!syms->address && strcmp(syms->name, filename) == 0) 02069 { 02070 module = (lt_module) syms; 02071 goto done; 02072 } 02073 ++syms; 02074 } 02075 02076 lists = lists->next; 02077 } 02078 02079 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 02080 02081 done: 02082 LT_DLMUTEX_UNLOCK (); 02083 return module; 02084 } 02085 02086 static int 02087 presym_close (loader_data, module) 02088 lt_user_data loader_data; 02089 lt_module module; 02090 { 02091 /* Just to silence gcc -Wall */ 02092 module = 0; 02093 return 0; 02094 } 02095 02096 static lt_ptr 02097 presym_sym (loader_data, module, symbol) 02098 lt_user_data loader_data; 02099 lt_module module; 02100 const char *symbol; 02101 { 02102 lt_dlsymlist *syms = (lt_dlsymlist*) module; 02103 02104 ++syms; 02105 while (syms->address) 02106 { 02107 if (strcmp(syms->name, symbol) == 0) 02108 { 02109 return syms->address; 02110 } 02111 02112 ++syms; 02113 } 02114 02115 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 02116 02117 return 0; 02118 } 02119 02120 static struct lt_user_dlloader presym = { 02121 0, presym_open, presym_close, presym_sym, presym_exit, 0 02122 }; 02123 02124 02125 02126 02127 02128 /* --- DYNAMIC MODULE LOADING --- */ 02129 02130 02131 /* The type of a function used at each iteration of foreach_dirinpath(). */ 02132 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, 02133 lt_ptr data2)); 02134 02135 static int foreach_dirinpath LT_PARAMS((const char *search_path, 02136 const char *base_name, 02137 foreach_callback_func *func, 02138 lt_ptr data1, lt_ptr data2)); 02139 02140 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, 02141 lt_ptr ignored)); 02142 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, 02143 lt_ptr ignored)); 02144 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, 02145 lt_ptr data2)); 02146 02147 02148 static int canonicalize_path LT_PARAMS((const char *path, 02149 char **pcanonical)); 02150 static int argzize_path LT_PARAMS((const char *path, 02151 char **pargz, 02152 size_t *pargz_len)); 02153 static FILE *find_file LT_PARAMS((const char *search_path, 02154 const char *base_name, 02155 char **pdir)); 02156 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, 02157 const char *base_name, 02158 lt_dlhandle *handle)); 02159 static int find_module LT_PARAMS((lt_dlhandle *handle, 02160 const char *dir, 02161 const char *libdir, 02162 const char *dlname, 02163 const char *old_name, 02164 int installed)); 02165 static int free_vars LT_PARAMS((char *dlname, char *oldname, 02166 char *libdir, char *deplibs)); 02167 static int load_deplibs LT_PARAMS((lt_dlhandle handle, 02168 char *deplibs)); 02169 static int trim LT_PARAMS((char **dest, 02170 const char *str)); 02171 static int try_dlopen LT_PARAMS((lt_dlhandle *handle, 02172 const char *filename)); 02173 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, 02174 const char *filename)); 02175 static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); 02176 static int lt_argz_insert LT_PARAMS((char **pargz, 02177 size_t *pargz_len, 02178 char *before, 02179 const char *entry)); 02180 static int lt_argz_insertinorder LT_PARAMS((char **pargz, 02181 size_t *pargz_len, 02182 const char *entry)); 02183 static int lt_argz_insertdir LT_PARAMS((char **pargz, 02184 size_t *pargz_len, 02185 const char *dirnam, 02186 struct dirent *dp)); 02187 static int lt_dlpath_insertdir LT_PARAMS((char **ppath, 02188 char *before, 02189 const char *dir)); 02190 static int list_files_by_dir LT_PARAMS((const char *dirnam, 02191 char **pargz, 02192 size_t *pargz_len)); 02193 static int file_not_found LT_PARAMS((void)); 02194 02195 static char *user_search_path= 0; 02196 static lt_dlloader *loaders = 0; 02197 static lt_dlhandle handles = 0; 02198 static int initialized = 0; 02199 02200 /* Initialize libltdl. */ 02201 int 02202 lt_dlinit () 02203 { 02204 int errors = 0; 02205 02206 LT_DLMUTEX_LOCK (); 02207 02208 /* Initialize only at first call. */ 02209 if (++initialized == 1) 02210 { 02211 handles = 0; 02212 user_search_path = 0; /* empty search path */ 02213 02214 #if HAVE_LIBDL 02215 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); 02216 #endif 02217 #if HAVE_SHL_LOAD && !defined(__llvm__) 02218 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); 02219 #endif 02220 #ifdef __WINDOWS__ 02221 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); 02222 #endif 02223 #ifdef __BEOS__ 02224 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); 02225 #endif 02226 #if HAVE_DLD 02227 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); 02228 #endif 02229 #if HAVE_DYLD 02230 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld"); 02231 errors += sys_dyld_init(); 02232 #endif 02233 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); 02234 02235 if (presym_init (presym.dlloader_data)) 02236 { 02237 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); 02238 ++errors; 02239 } 02240 else if (errors != 0) 02241 { 02242 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); 02243 ++errors; 02244 } 02245 } 02246 02247 LT_DLMUTEX_UNLOCK (); 02248 02249 return errors; 02250 } 02251 02252 int 02253 lt_dlpreload (preloaded) 02254 const lt_dlsymlist *preloaded; 02255 { 02256 int errors = 0; 02257 02258 if (preloaded) 02259 { 02260 errors = presym_add_symlist (preloaded); 02261 } 02262 else 02263 { 02264 presym_free_symlists(); 02265 02266 LT_DLMUTEX_LOCK (); 02267 if (default_preloaded_symbols) 02268 { 02269 errors = lt_dlpreload (default_preloaded_symbols); 02270 } 02271 LT_DLMUTEX_UNLOCK (); 02272 } 02273 02274 return errors; 02275 } 02276 02277 int 02278 lt_dlpreload_default (preloaded) 02279 const lt_dlsymlist *preloaded; 02280 { 02281 LT_DLMUTEX_LOCK (); 02282 default_preloaded_symbols = preloaded; 02283 LT_DLMUTEX_UNLOCK (); 02284 return 0; 02285 } 02286 02287 int 02288 lt_dlexit () 02289 { 02290 /* shut down libltdl */ 02291 lt_dlloader *loader; 02292 int errors = 0; 02293 02294 LT_DLMUTEX_LOCK (); 02295 loader = loaders; 02296 02297 if (!initialized) 02298 { 02299 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); 02300 ++errors; 02301 goto done; 02302 } 02303 02304 /* shut down only at last call. */ 02305 if (--initialized == 0) 02306 { 02307 int level; 02308 02309 while (handles && LT_DLIS_RESIDENT (handles)) 02310 { 02311 handles = handles->next; 02312 } 02313 02314 /* close all modules */ 02315 for (level = 1; handles; ++level) 02316 { 02317 lt_dlhandle cur = handles; 02318 int saw_nonresident = 0; 02319 02320 while (cur) 02321 { 02322 lt_dlhandle tmp = cur; 02323 cur = cur->next; 02324 if (!LT_DLIS_RESIDENT (tmp)) 02325 saw_nonresident = 1; 02326 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) 02327 { 02328 if (lt_dlclose (tmp)) 02329 { 02330 ++errors; 02331 } 02332 } 02333 } 02334 /* done if only resident modules are left */ 02335 if (!saw_nonresident) 02336 break; 02337 } 02338 02339 /* close all loaders */ 02340 while (loader) 02341 { 02342 lt_dlloader *next = loader->next; 02343 lt_user_data data = loader->dlloader_data; 02344 if (loader->dlloader_exit && loader->dlloader_exit (data)) 02345 { 02346 ++errors; 02347 } 02348 02349 LT_DLMEM_REASSIGN (loader, next); 02350 } 02351 loaders = 0; 02352 } 02353 02354 done: 02355 LT_DLMUTEX_UNLOCK (); 02356 return errors; 02357 } 02358 02359 static int 02360 tryall_dlopen (handle, filename) 02361 lt_dlhandle *handle; 02362 const char *filename; 02363 { 02364 lt_dlhandle cur; 02365 lt_dlloader *loader; 02366 const char *saved_error; 02367 int errors = 0; 02368 02369 LT_DLMUTEX_GETERROR (saved_error); 02370 LT_DLMUTEX_LOCK (); 02371 02372 cur = handles; 02373 loader = loaders; 02374 02375 /* check whether the module was already opened */ 02376 while (cur) 02377 { 02378 /* try to dlopen the program itself? */ 02379 if (!cur->info.filename && !filename) 02380 { 02381 break; 02382 } 02383 02384 if (cur->info.filename && filename 02385 && strcmp (cur->info.filename, filename) == 0) 02386 { 02387 break; 02388 } 02389 02390 cur = cur->next; 02391 } 02392 02393 if (cur) 02394 { 02395 ++cur->info.ref_count; 02396 *handle = cur; 02397 goto done; 02398 } 02399 02400 cur = *handle; 02401 if (filename) 02402 { 02403 /* Comment out the check of file permissions using access. 02404 This call seems to always return -1 with error EACCES. 02405 */ 02406 /* We need to catch missing file errors early so that 02407 file_not_found() can detect what happened. 02408 if (access (filename, R_OK) != 0) 02409 { 02410 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 02411 ++errors; 02412 goto done; 02413 } */ 02414 02415 cur->info.filename = lt_estrdup (filename); 02416 if (!cur->info.filename) 02417 { 02418 ++errors; 02419 goto done; 02420 } 02421 } 02422 else 02423 { 02424 cur->info.filename = 0; 02425 } 02426 02427 while (loader) 02428 { 02429 lt_user_data data = loader->dlloader_data; 02430 02431 cur->module = loader->module_open (data, filename); 02432 02433 if (cur->module != 0) 02434 { 02435 break; 02436 } 02437 loader = loader->next; 02438 } 02439 02440 if (!loader) 02441 { 02442 LT_DLFREE (cur->info.filename); 02443 ++errors; 02444 goto done; 02445 } 02446 02447 cur->loader = loader; 02448 LT_DLMUTEX_SETERROR (saved_error); 02449 02450 done: 02451 LT_DLMUTEX_UNLOCK (); 02452 02453 return errors; 02454 } 02455 02456 static int 02457 tryall_dlopen_module (handle, prefix, dirname, dlname) 02458 lt_dlhandle *handle; 02459 const char *prefix; 02460 const char *dirname; 02461 const char *dlname; 02462 { 02463 int error = 0; 02464 char *filename = 0; 02465 size_t filename_len = 0; 02466 size_t dirname_len = LT_STRLEN (dirname); 02467 02468 assert (handle); 02469 assert (dirname); 02470 assert (dlname); 02471 #ifdef LT_DIRSEP_CHAR 02472 /* Only canonicalized names (i.e. with DIRSEP chars already converted) 02473 should make it into this function: */ 02474 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); 02475 #endif 02476 02477 if (dirname_len > 0) 02478 if (dirname[dirname_len -1] == '/') 02479 --dirname_len; 02480 filename_len = dirname_len + 1 + LT_STRLEN (dlname); 02481 02482 /* Allocate memory, and combine DIRNAME and MODULENAME into it. 02483 The PREFIX (if any) is handled below. */ 02484 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); 02485 if (!filename) 02486 return 1; 02487 02488 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); 02489 02490 /* Now that we have combined DIRNAME and MODULENAME, if there is 02491 also a PREFIX to contend with, simply recurse with the arguments 02492 shuffled. Otherwise, attempt to open FILENAME as a module. */ 02493 if (prefix) 02494 { 02495 error += tryall_dlopen_module (handle, 02496 (const char *) 0, prefix, filename); 02497 } 02498 else if (tryall_dlopen (handle, filename) != 0) 02499 { 02500 ++error; 02501 } 02502 02503 LT_DLFREE (filename); 02504 return error; 02505 } 02506 02507 static int 02508 find_module (handle, dir, libdir, dlname, old_name, installed) 02509 lt_dlhandle *handle; 02510 const char *dir; 02511 const char *libdir; 02512 const char *dlname; 02513 const char *old_name; 02514 int installed; 02515 { 02516 /* Try to open the old library first; if it was dlpreopened, 02517 we want the preopened version of it, even if a dlopenable 02518 module is available. */ 02519 if (old_name && tryall_dlopen (handle, old_name) == 0) 02520 { 02521 return 0; 02522 } 02523 02524 /* Try to open the dynamic library. */ 02525 if (dlname) 02526 { 02527 /* try to open the installed module */ 02528 if (installed && libdir) 02529 { 02530 if (tryall_dlopen_module (handle, 02531 (const char *) 0, libdir, dlname) == 0) 02532 return 0; 02533 } 02534 02535 /* try to open the not-installed module */ 02536 if (!installed) 02537 { 02538 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) 02539 return 0; 02540 } 02541 02542 /* maybe it was moved to another directory */ 02543 { 02544 if (tryall_dlopen_module (handle, 02545 (const char *) 0, dir, dlname) == 0) 02546 return 0; 02547 } 02548 } 02549 02550 return 1; 02551 } 02552 02553 02554 static int 02555 canonicalize_path (path, pcanonical) 02556 const char *path; 02557 char **pcanonical; 02558 { 02559 char *canonical = 0; 02560 02561 assert (path && *path); 02562 assert (pcanonical); 02563 02564 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); 02565 if (!canonical) 02566 return 1; 02567 02568 { 02569 size_t dest = 0; 02570 size_t src; 02571 for (src = 0; path[src] != LT_EOS_CHAR; ++src) 02572 { 02573 /* Path separators are not copied to the beginning or end of 02574 the destination, or if another separator would follow 02575 immediately. */ 02576 if (path[src] == LT_PATHSEP_CHAR) 02577 { 02578 if ((dest == 0) 02579 || (path[1+ src] == LT_PATHSEP_CHAR) 02580 || (path[1+ src] == LT_EOS_CHAR)) 02581 continue; 02582 } 02583 02584 /* Anything other than a directory separator is copied verbatim. */ 02585 if ((path[src] != '/') 02586 #ifdef LT_DIRSEP_CHAR 02587 && (path[src] != LT_DIRSEP_CHAR) 02588 #endif 02589 ) 02590 { 02591 canonical[dest++] = path[src]; 02592 } 02593 /* Directory separators are converted and copied only if they are 02594 not at the end of a path -- i.e. before a path separator or 02595 NULL terminator. */ 02596 else if ((path[1+ src] != LT_PATHSEP_CHAR) 02597 && (path[1+ src] != LT_EOS_CHAR) 02598 #ifdef LT_DIRSEP_CHAR 02599 && (path[1+ src] != LT_DIRSEP_CHAR) 02600 #endif 02601 && (path[1+ src] != '/')) 02602 { 02603 canonical[dest++] = '/'; 02604 } 02605 } 02606 02607 /* Add an end-of-string marker at the end. */ 02608 canonical[dest] = LT_EOS_CHAR; 02609 } 02610 02611 /* Assign new value. */ 02612 *pcanonical = canonical; 02613 02614 return 0; 02615 } 02616 02617 static int 02618 argzize_path (path, pargz, pargz_len) 02619 const char *path; 02620 char **pargz; 02621 size_t *pargz_len; 02622 { 02623 error_t error; 02624 02625 assert (path); 02626 assert (pargz); 02627 assert (pargz_len); 02628 02629 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) 02630 { 02631 switch (error) 02632 { 02633 case ENOMEM: 02634 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 02635 break; 02636 default: 02637 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); 02638 break; 02639 } 02640 02641 return 1; 02642 } 02643 02644 return 0; 02645 } 02646 02647 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element 02648 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns 02649 non-zero or all elements are exhausted. If BASE_NAME is non-NULL, 02650 it is appended to each SEARCH_PATH element before FUNC is called. */ 02651 static int 02652 foreach_dirinpath (search_path, base_name, func, data1, data2) 02653 const char *search_path; 02654 const char *base_name; 02655 foreach_callback_func *func; 02656 lt_ptr data1; 02657 lt_ptr data2; 02658 { 02659 int result = 0; 02660 int filenamesize = 0; 02661 size_t lenbase = LT_STRLEN (base_name); 02662 size_t argz_len = 0; 02663 char *argz = 0; 02664 char *filename = 0; 02665 char *canonical = 0; 02666 02667 LT_DLMUTEX_LOCK (); 02668 02669 if (!search_path || !*search_path) 02670 { 02671 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 02672 goto cleanup; 02673 } 02674 02675 if (canonicalize_path (search_path, &canonical) != 0) 02676 goto cleanup; 02677 02678 if (argzize_path (canonical, &argz, &argz_len) != 0) 02679 goto cleanup; 02680 02681 { 02682 char *dir_name = 0; 02683 while ((dir_name = argz_next (argz, argz_len, dir_name))) 02684 { 02685 size_t lendir = LT_STRLEN (dir_name); 02686 02687 if (lendir +1 +lenbase >= (size_t)filenamesize) 02688 { 02689 LT_DLFREE (filename); 02690 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ 02691 filename = LT_EMALLOC (char, filenamesize); 02692 if (!filename) 02693 goto cleanup; 02694 } 02695 02696 assert ((size_t)filenamesize > lendir); 02697 strcpy (filename, dir_name); 02698 02699 if (base_name && *base_name) 02700 { 02701 if (filename[lendir -1] != '/') 02702 filename[lendir++] = '/'; 02703 strcpy (filename +lendir, base_name); 02704 } 02705 02706 if ((result = (*func) (filename, data1, data2))) 02707 { 02708 break; 02709 } 02710 } 02711 } 02712 02713 cleanup: 02714 LT_DLFREE (argz); 02715 LT_DLFREE (canonical); 02716 LT_DLFREE (filename); 02717 02718 LT_DLMUTEX_UNLOCK (); 02719 02720 return result; 02721 } 02722 02723 /* If FILEPATH can be opened, store the name of the directory component 02724 in DATA1, and the opened FILE* structure address in DATA2. Otherwise 02725 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ 02726 static int 02727 find_file_callback (filename, data1, data2) 02728 char *filename; 02729 lt_ptr data1; 02730 lt_ptr data2; 02731 { 02732 char **pdir = (char **) data1; 02733 FILE **pfile = (FILE **) data2; 02734 int is_done = 0; 02735 02736 assert (filename && *filename); 02737 assert (pdir); 02738 assert (pfile); 02739 02740 if ((*pfile = fopen (filename, LT_READTEXT_MODE))) 02741 { 02742 char *dirend = strrchr (filename, '/'); 02743 02744 if (dirend > filename) 02745 *dirend = LT_EOS_CHAR; 02746 02747 LT_DLFREE (*pdir); 02748 *pdir = lt_estrdup (filename); 02749 is_done = (*pdir == 0) ? -1 : 1; 02750 } 02751 02752 return is_done; 02753 } 02754 02755 static FILE * 02756 find_file (search_path, base_name, pdir) 02757 const char *search_path; 02758 const char *base_name; 02759 char **pdir; 02760 { 02761 FILE *file = 0; 02762 02763 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); 02764 02765 return file; 02766 } 02767 02768 static int 02769 find_handle_callback (filename, data, ignored) 02770 char *filename; 02771 lt_ptr data; 02772 lt_ptr ignored; 02773 { 02774 lt_dlhandle *handle = (lt_dlhandle *) data; 02775 int notfound = access (filename, R_OK); 02776 02777 /* Bail out if file cannot be read... */ 02778 if (notfound) 02779 return 0; 02780 02781 /* Try to dlopen the file, but do not continue searching in any 02782 case. */ 02783 if (tryall_dlopen (handle, filename) != 0) 02784 *handle = 0; 02785 02786 return 1; 02787 } 02788 02789 /* If HANDLE was found return it, otherwise return 0. If HANDLE was 02790 found but could not be opened, *HANDLE will be set to 0. */ 02791 static lt_dlhandle * 02792 find_handle (search_path, base_name, handle) 02793 const char *search_path; 02794 const char *base_name; 02795 lt_dlhandle *handle; 02796 { 02797 if (!search_path) 02798 return 0; 02799 02800 if (!foreach_dirinpath (search_path, base_name, find_handle_callback, 02801 handle, 0)) 02802 return 0; 02803 02804 return handle; 02805 } 02806 02807 static int 02808 load_deplibs (handle, deplibs) 02809 lt_dlhandle handle; 02810 char *deplibs; 02811 { 02812 #if LTDL_DLOPEN_DEPLIBS 02813 char *p, *save_search_path = 0; 02814 int depcount = 0; 02815 int i; 02816 char **names = 0; 02817 #endif 02818 int errors = 0; 02819 02820 handle->depcount = 0; 02821 02822 #if LTDL_DLOPEN_DEPLIBS 02823 if (!deplibs) 02824 { 02825 return errors; 02826 } 02827 ++errors; 02828 02829 LT_DLMUTEX_LOCK (); 02830 if (user_search_path) 02831 { 02832 save_search_path = lt_estrdup (user_search_path); 02833 if (!save_search_path) 02834 goto cleanup; 02835 } 02836 02837 /* extract search paths and count deplibs */ 02838 p = deplibs; 02839 while (*p) 02840 { 02841 if (!isspace ((int) *p)) 02842 { 02843 char *end = p+1; 02844 while (*end && !isspace((int) *end)) 02845 { 02846 ++end; 02847 } 02848 02849 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) 02850 { 02851 char save = *end; 02852 *end = 0; /* set a temporary string terminator */ 02853 if (lt_dladdsearchdir(p+2)) 02854 { 02855 goto cleanup; 02856 } 02857 *end = save; 02858 } 02859 else 02860 { 02861 ++depcount; 02862 } 02863 02864 p = end; 02865 } 02866 else 02867 { 02868 ++p; 02869 } 02870 } 02871 02872 /* restore the old search path */ 02873 LT_DLFREE (user_search_path); 02874 user_search_path = save_search_path; 02875 02876 LT_DLMUTEX_UNLOCK (); 02877 02878 if (!depcount) 02879 { 02880 errors = 0; 02881 goto cleanup; 02882 } 02883 02884 names = LT_EMALLOC (char *, depcount * sizeof (char*)); 02885 if (!names) 02886 goto cleanup; 02887 02888 /* now only extract the actual deplibs */ 02889 depcount = 0; 02890 p = deplibs; 02891 while (*p) 02892 { 02893 if (isspace ((int) *p)) 02894 { 02895 ++p; 02896 } 02897 else 02898 { 02899 char *end = p+1; 02900 while (*end && !isspace ((int) *end)) 02901 { 02902 ++end; 02903 } 02904 02905 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) 02906 { 02907 char *name; 02908 char save = *end; 02909 *end = 0; /* set a temporary string terminator */ 02910 if (strncmp(p, "-l", 2) == 0) 02911 { 02912 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); 02913 name = LT_EMALLOC (char, 1+ name_len); 02914 if (name) 02915 sprintf (name, "lib%s", p+2); 02916 } 02917 else 02918 name = lt_estrdup(p); 02919 02920 if (!name) 02921 goto cleanup_names; 02922 02923 names[depcount++] = name; 02924 *end = save; 02925 } 02926 p = end; 02927 } 02928 } 02929 02930 /* load the deplibs (in reverse order) 02931 At this stage, don't worry if the deplibs do not load correctly, 02932 they may already be statically linked into the loading application 02933 for instance. There will be a more enlightening error message 02934 later on if the loaded module cannot resolve all of its symbols. */ 02935 if (depcount) 02936 { 02937 int j = 0; 02938 02939 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); 02940 if (!handle->deplibs) 02941 goto cleanup; 02942 02943 for (i = 0; i < depcount; ++i) 02944 { 02945 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); 02946 if (handle->deplibs[j]) 02947 { 02948 ++j; 02949 } 02950 } 02951 02952 handle->depcount = j; /* Number of successfully loaded deplibs */ 02953 errors = 0; 02954 } 02955 02956 cleanup_names: 02957 for (i = 0; i < depcount; ++i) 02958 { 02959 LT_DLFREE (names[i]); 02960 } 02961 02962 cleanup: 02963 LT_DLFREE (names); 02964 #endif 02965 02966 return errors; 02967 } 02968 02969 static int 02970 unload_deplibs (handle) 02971 lt_dlhandle handle; 02972 { 02973 int i; 02974 int errors = 0; 02975 02976 if (handle->depcount) 02977 { 02978 for (i = 0; i < handle->depcount; ++i) 02979 { 02980 if (!LT_DLIS_RESIDENT (handle->deplibs[i])) 02981 { 02982 errors += lt_dlclose (handle->deplibs[i]); 02983 } 02984 } 02985 } 02986 02987 return errors; 02988 } 02989 02990 static int 02991 trim (dest, str) 02992 char **dest; 02993 const char *str; 02994 { 02995 /* remove the leading and trailing "'" from str 02996 and store the result in dest */ 02997 const char *end = strrchr (str, '\''); 02998 size_t len = LT_STRLEN (str); 02999 char *tmp; 03000 03001 LT_DLFREE (*dest); 03002 03003 if (len > 3 && str[0] == '\'') 03004 { 03005 tmp = LT_EMALLOC (char, end - str); 03006 if (!tmp) 03007 return 1; 03008 03009 strncpy(tmp, &str[1], (end - str) - 1); 03010 tmp[len-3] = LT_EOS_CHAR; 03011 *dest = tmp; 03012 } 03013 else 03014 { 03015 *dest = 0; 03016 } 03017 03018 return 0; 03019 } 03020 03021 static int 03022 free_vars (dlname, oldname, libdir, deplibs) 03023 char *dlname; 03024 char *oldname; 03025 char *libdir; 03026 char *deplibs; 03027 { 03028 LT_DLFREE (dlname); 03029 LT_DLFREE (oldname); 03030 LT_DLFREE (libdir); 03031 LT_DLFREE (deplibs); 03032 03033 return 0; 03034 } 03035 03036 static int 03037 try_dlopen (phandle, filename) 03038 lt_dlhandle *phandle; 03039 const char *filename; 03040 { 03041 const char * ext = 0; 03042 const char * saved_error = 0; 03043 char * canonical = 0; 03044 char * base_name = 0; 03045 char * dir = 0; 03046 char * name = 0; 03047 int errors = 0; 03048 lt_dlhandle newhandle; 03049 03050 assert (phandle); 03051 assert (*phandle == 0); 03052 03053 LT_DLMUTEX_GETERROR (saved_error); 03054 03055 /* dlopen self? */ 03056 if (!filename) 03057 { 03058 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 03059 if (*phandle == 0) 03060 return 1; 03061 03062 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); 03063 newhandle = *phandle; 03064 03065 /* lt_dlclose()ing yourself is very bad! Disallow it. */ 03066 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); 03067 03068 if (tryall_dlopen (&newhandle, 0) != 0) 03069 { 03070 LT_DLFREE (*phandle); 03071 return 1; 03072 } 03073 03074 goto register_handle; 03075 } 03076 03077 assert (filename && *filename); 03078 03079 /* Doing this immediately allows internal functions to safely 03080 assume only canonicalized paths are passed. */ 03081 if (canonicalize_path (filename, &canonical) != 0) 03082 { 03083 ++errors; 03084 goto cleanup; 03085 } 03086 03087 /* If the canonical module name is a path (relative or absolute) 03088 then split it into a directory part and a name part. */ 03089 base_name = strrchr (canonical, '/'); 03090 if (base_name) 03091 { 03092 size_t dirlen = (1+ base_name) - canonical; 03093 03094 dir = LT_EMALLOC (char, 1+ dirlen); 03095 if (!dir) 03096 { 03097 ++errors; 03098 goto cleanup; 03099 } 03100 03101 strncpy (dir, canonical, dirlen); 03102 dir[dirlen] = LT_EOS_CHAR; 03103 03104 ++base_name; 03105 } 03106 else 03107 LT_DLMEM_REASSIGN (base_name, canonical); 03108 03109 assert (base_name && *base_name); 03110 03111 /* Check whether we are opening a libtool module (.la extension). */ 03112 ext = strrchr (base_name, '.'); 03113 if (ext && strcmp (ext, archive_ext) == 0) 03114 { 03115 /* this seems to be a libtool module */ 03116 FILE * file = 0; 03117 char * dlname = 0; 03118 char * old_name = 0; 03119 char * libdir = 0; 03120 char * deplibs = 0; 03121 char * line = 0; 03122 size_t line_len; 03123 03124 /* if we can't find the installed flag, it is probably an 03125 installed libtool archive, produced with an old version 03126 of libtool */ 03127 int installed = 1; 03128 03129 /* extract the module name from the file name */ 03130 name = LT_EMALLOC (char, ext - base_name + 1); 03131 if (!name) 03132 { 03133 ++errors; 03134 goto cleanup; 03135 } 03136 03137 /* canonicalize the module name */ 03138 { 03139 size_t i; 03140 for (i = 0; i < (size_t)(ext - base_name); ++i) 03141 { 03142 if (isalnum ((int)(base_name[i]))) 03143 { 03144 name[i] = base_name[i]; 03145 } 03146 else 03147 { 03148 name[i] = '_'; 03149 } 03150 } 03151 name[ext - base_name] = LT_EOS_CHAR; 03152 } 03153 03154 /* Now try to open the .la file. If there is no directory name 03155 component, try to find it first in user_search_path and then other 03156 prescribed paths. Otherwise (or in any case if the module was not 03157 yet found) try opening just the module name as passed. */ 03158 if (!dir) 03159 { 03160 const char *search_path; 03161 03162 LT_DLMUTEX_LOCK (); 03163 search_path = user_search_path; 03164 if (search_path) 03165 file = find_file (user_search_path, base_name, &dir); 03166 LT_DLMUTEX_UNLOCK (); 03167 03168 if (!file) 03169 { 03170 search_path = getenv (LTDL_SEARCHPATH_VAR); 03171 if (search_path) 03172 file = find_file (search_path, base_name, &dir); 03173 } 03174 03175 #ifdef LTDL_SHLIBPATH_VAR 03176 if (!file) 03177 { 03178 search_path = getenv (LTDL_SHLIBPATH_VAR); 03179 if (search_path) 03180 file = find_file (search_path, base_name, &dir); 03181 } 03182 #endif 03183 #ifdef LTDL_SYSSEARCHPATH 03184 if (!file && sys_search_path) 03185 { 03186 file = find_file (sys_search_path, base_name, &dir); 03187 } 03188 #endif 03189 } 03190 if (!file) 03191 { 03192 file = fopen (filename, LT_READTEXT_MODE); 03193 } 03194 03195 /* If we didn't find the file by now, it really isn't there. Set 03196 the status flag, and bail out. */ 03197 if (!file) 03198 { 03199 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 03200 ++errors; 03201 goto cleanup; 03202 } 03203 03204 line_len = LT_FILENAME_MAX; 03205 line = LT_EMALLOC (char, line_len); 03206 if (!line) 03207 { 03208 fclose (file); 03209 ++errors; 03210 goto cleanup; 03211 } 03212 03213 /* read the .la file */ 03214 while (!feof (file)) 03215 { 03216 if (!fgets (line, (int) line_len, file)) 03217 { 03218 break; 03219 } 03220 03221 /* Handle the case where we occasionally need to read a line 03222 that is longer than the initial buffer size. */ 03223 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file))) 03224 { 03225 line = LT_DLREALLOC (char, line, line_len *2); 03226 if (!fgets (&line[line_len -1], (int) line_len +1, file)) 03227 { 03228 break; 03229 } 03230 line_len *= 2; 03231 } 03232 03233 if (line[0] == '\n' || line[0] == '#') 03234 { 03235 continue; 03236 } 03237 03238 #undef STR_DLNAME 03239 #define STR_DLNAME "dlname=" 03240 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) 03241 { 03242 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); 03243 } 03244 03245 #undef STR_OLD_LIBRARY 03246 #define STR_OLD_LIBRARY "old_library=" 03247 else if (strncmp (line, STR_OLD_LIBRARY, 03248 sizeof (STR_OLD_LIBRARY) - 1) == 0) 03249 { 03250 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); 03251 } 03252 #undef STR_LIBDIR 03253 #define STR_LIBDIR "libdir=" 03254 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) 03255 { 03256 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); 03257 } 03258 03259 #undef STR_DL_DEPLIBS 03260 #define STR_DL_DEPLIBS "dependency_libs=" 03261 else if (strncmp (line, STR_DL_DEPLIBS, 03262 sizeof (STR_DL_DEPLIBS) - 1) == 0) 03263 { 03264 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); 03265 } 03266 else if (strcmp (line, "installed=yes\n") == 0) 03267 { 03268 installed = 1; 03269 } 03270 else if (strcmp (line, "installed=no\n") == 0) 03271 { 03272 installed = 0; 03273 } 03274 03275 #undef STR_LIBRARY_NAMES 03276 #define STR_LIBRARY_NAMES "library_names=" 03277 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, 03278 sizeof (STR_LIBRARY_NAMES) - 1) == 0) 03279 { 03280 char *last_libname; 03281 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); 03282 if (!errors 03283 && dlname 03284 && (last_libname = strrchr (dlname, ' ')) != 0) 03285 { 03286 last_libname = lt_estrdup (last_libname + 1); 03287 if (!last_libname) 03288 { 03289 ++errors; 03290 goto cleanup; 03291 } 03292 LT_DLMEM_REASSIGN (dlname, last_libname); 03293 } 03294 } 03295 03296 if (errors) 03297 break; 03298 } 03299 03300 fclose (file); 03301 LT_DLFREE (line); 03302 03303 /* allocate the handle */ 03304 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 03305 if (*phandle == 0) 03306 ++errors; 03307 03308 if (errors) 03309 { 03310 free_vars (dlname, old_name, libdir, deplibs); 03311 LT_DLFREE (*phandle); 03312 goto cleanup; 03313 } 03314 03315 assert (*phandle); 03316 03317 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); 03318 if (load_deplibs (*phandle, deplibs) == 0) 03319 { 03320 newhandle = *phandle; 03321 /* find_module may replace newhandle */ 03322 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) 03323 { 03324 unload_deplibs (*phandle); 03325 ++errors; 03326 } 03327 } 03328 else 03329 { 03330 ++errors; 03331 } 03332 03333 free_vars (dlname, old_name, libdir, deplibs); 03334 if (errors) 03335 { 03336 LT_DLFREE (*phandle); 03337 goto cleanup; 03338 } 03339 03340 if (*phandle != newhandle) 03341 { 03342 unload_deplibs (*phandle); 03343 } 03344 } 03345 else 03346 { 03347 /* not a libtool module */ 03348 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 03349 if (*phandle == 0) 03350 { 03351 ++errors; 03352 goto cleanup; 03353 } 03354 03355 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); 03356 newhandle = *phandle; 03357 03358 /* If the module has no directory name component, try to find it 03359 first in user_search_path and then other prescribed paths. 03360 Otherwise (or in any case if the module was not yet found) try 03361 opening just the module name as passed. */ 03362 if ((dir || (!find_handle (user_search_path, base_name, &newhandle) 03363 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, 03364 &newhandle) 03365 #ifdef LTDL_SHLIBPATH_VAR 03366 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, 03367 &newhandle) 03368 #endif 03369 #ifdef LTDL_SYSSEARCHPATH 03370 && !find_handle (sys_search_path, base_name, &newhandle) 03371 #endif 03372 ))) 03373 { 03374 if (tryall_dlopen (&newhandle, filename) != 0) 03375 { 03376 newhandle = NULL; 03377 } 03378 } 03379 03380 if (!newhandle) 03381 { 03382 LT_DLFREE (*phandle); 03383 ++errors; 03384 goto cleanup; 03385 } 03386 } 03387 03388 register_handle: 03389 LT_DLMEM_REASSIGN (*phandle, newhandle); 03390 03391 if ((*phandle)->info.ref_count == 0) 03392 { 03393 (*phandle)->info.ref_count = 1; 03394 LT_DLMEM_REASSIGN ((*phandle)->info.name, name); 03395 03396 LT_DLMUTEX_LOCK (); 03397 (*phandle)->next = handles; 03398 handles = *phandle; 03399 LT_DLMUTEX_UNLOCK (); 03400 } 03401 03402 LT_DLMUTEX_SETERROR (saved_error); 03403 03404 cleanup: 03405 LT_DLFREE (dir); 03406 LT_DLFREE (name); 03407 LT_DLFREE (canonical); 03408 03409 return errors; 03410 } 03411 03412 lt_dlhandle 03413 lt_dlopen (filename) 03414 const char *filename; 03415 { 03416 lt_dlhandle handle = 0; 03417 03418 /* Just incase we missed a code path in try_dlopen() that reports 03419 an error, but forgets to reset handle... */ 03420 if (try_dlopen (&handle, filename) != 0) 03421 return 0; 03422 03423 return handle; 03424 } 03425 03426 /* If the last error messge store was `FILE_NOT_FOUND', then return 03427 non-zero. */ 03428 static int 03429 file_not_found () 03430 { 03431 const char *error = 0; 03432 03433 LT_DLMUTEX_GETERROR (error); 03434 if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) 03435 return 1; 03436 03437 return 0; 03438 } 03439 03440 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to 03441 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, 03442 and if a file is still not found try again with SHLIB_EXT appended 03443 instead. */ 03444 lt_dlhandle 03445 lt_dlopenext (filename) 03446 const char *filename; 03447 { 03448 lt_dlhandle handle = 0; 03449 char * tmp = 0; 03450 char * ext = 0; 03451 size_t len; 03452 int errors = 0; 03453 03454 if (!filename) 03455 { 03456 return lt_dlopen (filename); 03457 } 03458 03459 assert (filename); 03460 03461 len = LT_STRLEN (filename); 03462 ext = strrchr (filename, '.'); 03463 03464 /* If FILENAME already bears a suitable extension, there is no need 03465 to try appending additional extensions. */ 03466 if (ext && ((strcmp (ext, archive_ext) == 0) 03467 #ifdef LTDL_SHLIB_EXT 03468 || (strcmp (ext, shlib_ext) == 0) 03469 #endif 03470 )) 03471 { 03472 return lt_dlopen (filename); 03473 } 03474 03475 /* First try appending ARCHIVE_EXT. */ 03476 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); 03477 if (!tmp) 03478 return 0; 03479 03480 strcpy (tmp, filename); 03481 strcat (tmp, archive_ext); 03482 errors = try_dlopen (&handle, tmp); 03483 03484 /* If we found FILENAME, stop searching -- whether we were able to 03485 load the file as a module or not. If the file exists but loading 03486 failed, it is better to return an error message here than to 03487 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not 03488 in the module search path. */ 03489 if (handle || ((errors > 0) && !file_not_found ())) 03490 { 03491 LT_DLFREE (tmp); 03492 return handle; 03493 } 03494 03495 #ifdef LTDL_SHLIB_EXT 03496 /* Try appending SHLIB_EXT. */ 03497 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) 03498 { 03499 LT_DLFREE (tmp); 03500 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); 03501 if (!tmp) 03502 return 0; 03503 03504 strcpy (tmp, filename); 03505 } 03506 else 03507 { 03508 tmp[len] = LT_EOS_CHAR; 03509 } 03510 03511 strcat(tmp, shlib_ext); 03512 errors = try_dlopen (&handle, tmp); 03513 03514 /* As before, if the file was found but loading failed, return now 03515 with the current error message. */ 03516 if (handle || ((errors > 0) && !file_not_found ())) 03517 { 03518 LT_DLFREE (tmp); 03519 return handle; 03520 } 03521 #endif 03522 03523 /* Still here? Then we really did fail to locate any of the file 03524 names we tried. */ 03525 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 03526 LT_DLFREE (tmp); 03527 return 0; 03528 } 03529 03530 03531 static int 03532 lt_argz_insert (pargz, pargz_len, before, entry) 03533 char **pargz; 03534 size_t *pargz_len; 03535 char *before; 03536 const char *entry; 03537 { 03538 error_t error; 03539 03540 if ((error = argz_insert (pargz, pargz_len, before, entry))) 03541 { 03542 switch (error) 03543 { 03544 case ENOMEM: 03545 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 03546 break; 03547 default: 03548 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); 03549 break; 03550 } 03551 return 1; 03552 } 03553 03554 return 0; 03555 } 03556 03557 static int 03558 lt_argz_insertinorder (pargz, pargz_len, entry) 03559 char **pargz; 03560 size_t *pargz_len; 03561 const char *entry; 03562 { 03563 char *before = 0; 03564 03565 assert (pargz); 03566 assert (pargz_len); 03567 assert (entry && *entry); 03568 03569 if (*pargz) 03570 while ((before = argz_next (*pargz, *pargz_len, before))) 03571 { 03572 int cmp = strcmp (entry, before); 03573 03574 if (cmp < 0) break; 03575 if (cmp == 0) return 0; /* No duplicates! */ 03576 } 03577 03578 return lt_argz_insert (pargz, pargz_len, before, entry); 03579 } 03580 03581 static int 03582 lt_argz_insertdir (pargz, pargz_len, dirnam, dp) 03583 char **pargz; 03584 size_t *pargz_len; 03585 const char *dirnam; 03586 struct dirent *dp; 03587 { 03588 char *buf = 0; 03589 size_t buf_len = 0; 03590 char *end = 0; 03591 size_t end_offset = 0; 03592 size_t dir_len = 0; 03593 int errors = 0; 03594 03595 assert (pargz); 03596 assert (pargz_len); 03597 assert (dp); 03598 03599 dir_len = LT_STRLEN (dirnam); 03600 end = dp->d_name + LT_D_NAMLEN(dp); 03601 03602 /* Ignore version numbers. */ 03603 { 03604 char *p; 03605 for (p = end; p -1 > dp->d_name; --p) 03606 if (strchr (".0123456789", p[-1]) == 0) 03607 break; 03608 03609 if (*p == '.') 03610 end = p; 03611 } 03612 03613 /* Ignore filename extension. */ 03614 { 03615 char *p; 03616 for (p = end -1; p > dp->d_name; --p) 03617 if (*p == '.') 03618 { 03619 end = p; 03620 break; 03621 } 03622 } 03623 03624 /* Prepend the directory name. */ 03625 end_offset = end - dp->d_name; 03626 buf_len = dir_len + 1+ end_offset; 03627 buf = LT_EMALLOC (char, 1+ buf_len); 03628 if (!buf) 03629 return ++errors; 03630 03631 assert (buf); 03632 03633 strcpy (buf, dirnam); 03634 strcat (buf, "/"); 03635 strncat (buf, dp->d_name, end_offset); 03636 buf[buf_len] = LT_EOS_CHAR; 03637 03638 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ 03639 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) 03640 ++errors; 03641 03642 LT_DLFREE (buf); 03643 03644 return errors; 03645 } 03646 03647 static int 03648 list_files_by_dir (dirnam, pargz, pargz_len) 03649 const char *dirnam; 03650 char **pargz; 03651 size_t *pargz_len; 03652 { 03653 DIR *dirp = 0; 03654 int errors = 0; 03655 03656 assert (dirnam && *dirnam); 03657 assert (pargz); 03658 assert (pargz_len); 03659 assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); 03660 03661 dirp = opendir (dirnam); 03662 if (dirp) 03663 { 03664 struct dirent *dp = 0; 03665 03666 while ((dp = readdir (dirp))) 03667 if (dp->d_name[0] != '.') 03668 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) 03669 { 03670 ++errors; 03671 break; 03672 } 03673 03674 closedir (dirp); 03675 } 03676 else 03677 ++errors; 03678 03679 return errors; 03680 } 03681 03682 03683 /* If there are any files in DIRNAME, call the function passed in 03684 DATA1 (with the name of each file and DATA2 as arguments). */ 03685 static int 03686 foreachfile_callback (dirname, data1, data2) 03687 char *dirname; 03688 lt_ptr data1; 03689 lt_ptr data2; 03690 { 03691 int (*func) LT_PARAMS((const char *filename, lt_ptr data)) 03692 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; 03693 03694 int is_done = 0; 03695 char *argz = 0; 03696 size_t argz_len = 0; 03697 03698 if (list_files_by_dir (dirname, &argz, &argz_len) != 0) 03699 goto cleanup; 03700 if (!argz) 03701 goto cleanup; 03702 03703 { 03704 char *filename = 0; 03705 while ((filename = argz_next (argz, argz_len, filename))) 03706 if ((is_done = (*func) (filename, data2))) 03707 break; 03708 } 03709 03710 cleanup: 03711 LT_DLFREE (argz); 03712 03713 return is_done; 03714 } 03715 03716 03717 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along 03718 with DATA. The filenames passed to FUNC would be suitable for 03719 passing to lt_dlopenext. The extensions are stripped so that 03720 individual modules do not generate several entries (e.g. libfoo.la, 03721 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, 03722 then the same directories that lt_dlopen would search are examined. */ 03723 int 03724 lt_dlforeachfile (search_path, func, data) 03725 const char *search_path; 03726 int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); 03727 lt_ptr data; 03728 { 03729 int is_done = 0; 03730 03731 if (search_path) 03732 { 03733 /* If a specific path was passed, search only the directories 03734 listed in it. */ 03735 is_done = foreach_dirinpath (search_path, 0, 03736 foreachfile_callback, func, data); 03737 } 03738 else 03739 { 03740 /* Otherwise search the default paths. */ 03741 is_done = foreach_dirinpath (user_search_path, 0, 03742 foreachfile_callback, func, data); 03743 if (!is_done) 03744 { 03745 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, 03746 foreachfile_callback, func, data); 03747 } 03748 03749 #ifdef LTDL_SHLIBPATH_VAR 03750 if (!is_done) 03751 { 03752 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, 03753 foreachfile_callback, func, data); 03754 } 03755 #endif 03756 #ifdef LTDL_SYSSEARCHPATH 03757 if (!is_done) 03758 { 03759 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, 03760 foreachfile_callback, func, data); 03761 } 03762 #endif 03763 } 03764 03765 return is_done; 03766 } 03767 03768 int 03769 lt_dlclose (handle) 03770 lt_dlhandle handle; 03771 { 03772 lt_dlhandle cur, last; 03773 int errors = 0; 03774 03775 LT_DLMUTEX_LOCK (); 03776 03777 /* check whether the handle is valid */ 03778 last = cur = handles; 03779 while (cur && handle != cur) 03780 { 03781 last = cur; 03782 cur = cur->next; 03783 } 03784 03785 if (!cur) 03786 { 03787 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 03788 ++errors; 03789 goto done; 03790 } 03791 03792 handle->info.ref_count--; 03793 03794 /* Note that even with resident modules, we must track the ref_count 03795 correctly incase the user decides to reset the residency flag 03796 later (even though the API makes no provision for that at the 03797 moment). */ 03798 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) 03799 { 03800 lt_user_data data = handle->loader->dlloader_data; 03801 03802 if (handle != handles) 03803 { 03804 last->next = handle->next; 03805 } 03806 else 03807 { 03808 handles = handle->next; 03809 } 03810 03811 errors += handle->loader->module_close (data, handle->module); 03812 errors += unload_deplibs(handle); 03813 03814 /* It is up to the callers to free the data itself. */ 03815 LT_DLFREE (handle->caller_data); 03816 03817 LT_DLFREE (handle->info.filename); 03818 LT_DLFREE (handle->info.name); 03819 LT_DLFREE (handle); 03820 03821 goto done; 03822 } 03823 03824 if (LT_DLIS_RESIDENT (handle)) 03825 { 03826 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); 03827 ++errors; 03828 } 03829 03830 done: 03831 LT_DLMUTEX_UNLOCK (); 03832 03833 return errors; 03834 } 03835 03836 lt_ptr 03837 lt_dlsym (handle, symbol) 03838 lt_dlhandle handle; 03839 const char *symbol; 03840 { 03841 size_t lensym; 03842 char lsym[LT_SYMBOL_LENGTH]; 03843 char *sym; 03844 lt_ptr address; 03845 lt_user_data data; 03846 03847 if (!handle) 03848 { 03849 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 03850 return 0; 03851 } 03852 03853 if (!symbol) 03854 { 03855 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 03856 return 0; 03857 } 03858 03859 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) 03860 + LT_STRLEN (handle->info.name); 03861 03862 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) 03863 { 03864 sym = lsym; 03865 } 03866 else 03867 { 03868 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); 03869 if (!sym) 03870 { 03871 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); 03872 return 0; 03873 } 03874 } 03875 03876 data = handle->loader->dlloader_data; 03877 if (handle->info.name) 03878 { 03879 const char *saved_error; 03880 03881 LT_DLMUTEX_GETERROR (saved_error); 03882 03883 /* this is a libtool module */ 03884 if (handle->loader->sym_prefix) 03885 { 03886 strcpy(sym, handle->loader->sym_prefix); 03887 strcat(sym, handle->info.name); 03888 } 03889 else 03890 { 03891 strcpy(sym, handle->info.name); 03892 } 03893 03894 strcat(sym, "_LTX_"); 03895 strcat(sym, symbol); 03896 03897 /* try "modulename_LTX_symbol" */ 03898 address = handle->loader->find_sym (data, handle->module, sym); 03899 if (address) 03900 { 03901 if (sym != lsym) 03902 { 03903 LT_DLFREE (sym); 03904 } 03905 return address; 03906 } 03907 LT_DLMUTEX_SETERROR (saved_error); 03908 } 03909 03910 /* otherwise try "symbol" */ 03911 if (handle->loader->sym_prefix) 03912 { 03913 strcpy(sym, handle->loader->sym_prefix); 03914 strcat(sym, symbol); 03915 } 03916 else 03917 { 03918 strcpy(sym, symbol); 03919 } 03920 03921 address = handle->loader->find_sym (data, handle->module, sym); 03922 if (sym != lsym) 03923 { 03924 LT_DLFREE (sym); 03925 } 03926 03927 return address; 03928 } 03929 03930 const char * 03931 lt_dlerror () 03932 { 03933 const char *error; 03934 03935 LT_DLMUTEX_GETERROR (error); 03936 LT_DLMUTEX_SETERROR (0); 03937 03938 return error ? error : NULL; 03939 } 03940 03941 static int 03942 lt_dlpath_insertdir (ppath, before, dir) 03943 char **ppath; 03944 char *before; 03945 const char *dir; 03946 { 03947 int errors = 0; 03948 char *canonical = 0; 03949 char *argz = 0; 03950 size_t argz_len = 0; 03951 03952 assert (ppath); 03953 assert (dir && *dir); 03954 03955 if (canonicalize_path (dir, &canonical) != 0) 03956 { 03957 ++errors; 03958 goto cleanup; 03959 } 03960 03961 assert (canonical && *canonical); 03962 03963 /* If *PPATH is empty, set it to DIR. */ 03964 if (*ppath == 0) 03965 { 03966 assert (!before); /* BEFORE cannot be set without PPATH. */ 03967 assert (dir); /* Without DIR, don't call this function! */ 03968 03969 *ppath = lt_estrdup (dir); 03970 if (*ppath == 0) 03971 ++errors; 03972 03973 return errors; 03974 } 03975 03976 assert (ppath && *ppath); 03977 03978 if (argzize_path (*ppath, &argz, &argz_len) != 0) 03979 { 03980 ++errors; 03981 goto cleanup; 03982 } 03983 03984 /* Convert BEFORE into an equivalent offset into ARGZ. This only works 03985 if *PPATH is already canonicalized, and hence does not change length 03986 with respect to ARGZ. We canonicalize each entry as it is added to 03987 the search path, and don't call this function with (uncanonicalized) 03988 user paths, so this is a fair assumption. */ 03989 if (before) 03990 { 03991 assert (*ppath <= before); 03992 assert (before - *ppath <= (int)strlen (*ppath)); 03993 03994 before = before - *ppath + argz; 03995 } 03996 03997 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) 03998 { 03999 ++errors; 04000 goto cleanup; 04001 } 04002 04003 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); 04004 LT_DLMEM_REASSIGN (*ppath, argz); 04005 04006 cleanup: 04007 LT_DLFREE (canonical); 04008 LT_DLFREE (argz); 04009 04010 return errors; 04011 } 04012 04013 int 04014 lt_dladdsearchdir (search_dir) 04015 const char *search_dir; 04016 { 04017 int errors = 0; 04018 04019 if (search_dir && *search_dir) 04020 { 04021 LT_DLMUTEX_LOCK (); 04022 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) 04023 ++errors; 04024 LT_DLMUTEX_UNLOCK (); 04025 } 04026 04027 return errors; 04028 } 04029 04030 int 04031 lt_dlinsertsearchdir (before, search_dir) 04032 const char *before; 04033 const char *search_dir; 04034 { 04035 int errors = 0; 04036 04037 if (before) 04038 { 04039 LT_DLMUTEX_LOCK (); 04040 if ((before < user_search_path) 04041 || (before >= user_search_path + LT_STRLEN (user_search_path))) 04042 { 04043 LT_DLMUTEX_UNLOCK (); 04044 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); 04045 return 1; 04046 } 04047 LT_DLMUTEX_UNLOCK (); 04048 } 04049 04050 if (search_dir && *search_dir) 04051 { 04052 LT_DLMUTEX_LOCK (); 04053 if (lt_dlpath_insertdir (&user_search_path, 04054 (char *) before, search_dir) != 0) 04055 { 04056 ++errors; 04057 } 04058 LT_DLMUTEX_UNLOCK (); 04059 } 04060 04061 return errors; 04062 } 04063 04064 int 04065 lt_dlsetsearchpath (search_path) 04066 const char *search_path; 04067 { 04068 int errors = 0; 04069 04070 LT_DLMUTEX_LOCK (); 04071 LT_DLFREE (user_search_path); 04072 LT_DLMUTEX_UNLOCK (); 04073 04074 if (!search_path || !LT_STRLEN (search_path)) 04075 { 04076 return errors; 04077 } 04078 04079 LT_DLMUTEX_LOCK (); 04080 if (canonicalize_path (search_path, &user_search_path) != 0) 04081 ++errors; 04082 LT_DLMUTEX_UNLOCK (); 04083 04084 return errors; 04085 } 04086 04087 const char * 04088 lt_dlgetsearchpath () 04089 { 04090 const char *saved_path; 04091 04092 LT_DLMUTEX_LOCK (); 04093 saved_path = user_search_path; 04094 LT_DLMUTEX_UNLOCK (); 04095 04096 return saved_path; 04097 } 04098 04099 int 04100 lt_dlmakeresident (handle) 04101 lt_dlhandle handle; 04102 { 04103 int errors = 0; 04104 04105 if (!handle) 04106 { 04107 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 04108 ++errors; 04109 } 04110 else 04111 { 04112 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); 04113 } 04114 04115 return errors; 04116 } 04117 04118 int 04119 lt_dlisresident (handle) 04120 lt_dlhandle handle; 04121 { 04122 if (!handle) 04123 { 04124 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 04125 return -1; 04126 } 04127 04128 return LT_DLIS_RESIDENT (handle); 04129 } 04130 04131 04132 04133 04134 /* --- MODULE INFORMATION --- */ 04135 04136 const lt_dlinfo * 04137 lt_dlgetinfo (handle) 04138 lt_dlhandle handle; 04139 { 04140 if (!handle) 04141 { 04142 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 04143 return 0; 04144 } 04145 04146 return &(handle->info); 04147 } 04148 04149 lt_dlhandle 04150 lt_dlhandle_next (place) 04151 lt_dlhandle place; 04152 { 04153 return place ? place->next : handles; 04154 } 04155 04156 int 04157 lt_dlforeach (func, data) 04158 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); 04159 lt_ptr data; 04160 { 04161 int errors = 0; 04162 lt_dlhandle cur; 04163 04164 LT_DLMUTEX_LOCK (); 04165 04166 cur = handles; 04167 while (cur) 04168 { 04169 lt_dlhandle tmp = cur; 04170 04171 cur = cur->next; 04172 if ((*func) (tmp, data)) 04173 { 04174 ++errors; 04175 break; 04176 } 04177 } 04178 04179 LT_DLMUTEX_UNLOCK (); 04180 04181 return errors; 04182 } 04183 04184 lt_dlcaller_id 04185 lt_dlcaller_register () 04186 { 04187 static lt_dlcaller_id last_caller_id = 0; 04188 int result; 04189 04190 LT_DLMUTEX_LOCK (); 04191 result = ++last_caller_id; 04192 LT_DLMUTEX_UNLOCK (); 04193 04194 return result; 04195 } 04196 04197 lt_ptr 04198 lt_dlcaller_set_data (key, handle, data) 04199 lt_dlcaller_id key; 04200 lt_dlhandle handle; 04201 lt_ptr data; 04202 { 04203 int n_elements = 0; 04204 lt_ptr stale = (lt_ptr) 0; 04205 int i; 04206 04207 /* This needs to be locked so that the caller data can be updated 04208 simultaneously by different threads. */ 04209 LT_DLMUTEX_LOCK (); 04210 04211 if (handle->caller_data) 04212 while (handle->caller_data[n_elements].key) 04213 ++n_elements; 04214 04215 for (i = 0; i < n_elements; ++i) 04216 { 04217 if (handle->caller_data[i].key == key) 04218 { 04219 stale = handle->caller_data[i].data; 04220 break; 04221 } 04222 } 04223 04224 /* Ensure that there is enough room in this handle's caller_data 04225 array to accept a new element (and an empty end marker). */ 04226 if (i == n_elements) 04227 { 04228 lt_caller_data *temp 04229 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); 04230 04231 if (!temp) 04232 { 04233 stale = 0; 04234 goto done; 04235 } 04236 04237 handle->caller_data = temp; 04238 04239 /* We only need this if we needed to allocate a new caller_data. */ 04240 handle->caller_data[i].key = key; 04241 handle->caller_data[1+ i].key = 0; 04242 } 04243 04244 handle->caller_data[i].data = data; 04245 04246 done: 04247 LT_DLMUTEX_UNLOCK (); 04248 04249 return stale; 04250 } 04251 04252 lt_ptr 04253 lt_dlcaller_get_data (key, handle) 04254 lt_dlcaller_id key; 04255 lt_dlhandle handle; 04256 { 04257 lt_ptr result = (lt_ptr) 0; 04258 04259 /* This needs to be locked so that the caller data isn't updated by 04260 another thread part way through this function. */ 04261 LT_DLMUTEX_LOCK (); 04262 04263 /* Locate the index of the element with a matching KEY. */ 04264 { 04265 int i; 04266 for (i = 0; handle->caller_data[i].key; ++i) 04267 { 04268 if (handle->caller_data[i].key == key) 04269 { 04270 result = handle->caller_data[i].data; 04271 break; 04272 } 04273 } 04274 } 04275 04276 LT_DLMUTEX_UNLOCK (); 04277 04278 return result; 04279 } 04280 04281 04282 04283 /* --- USER MODULE LOADER API --- */ 04284 04285 04286 int 04287 lt_dlloader_add (place, dlloader, loader_name) 04288 lt_dlloader *place; 04289 const struct lt_user_dlloader *dlloader; 04290 const char *loader_name; 04291 { 04292 int errors = 0; 04293 lt_dlloader *node = 0, *ptr = 0; 04294 04295 if ((dlloader == 0) /* diagnose null parameters */ 04296 || (dlloader->module_open == 0) 04297 || (dlloader->module_close == 0) 04298 || (dlloader->find_sym == 0)) 04299 { 04300 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 04301 return 1; 04302 } 04303 04304 /* Create a new dlloader node with copies of the user callbacks. */ 04305 node = LT_EMALLOC (lt_dlloader, 1); 04306 if (!node) 04307 return 1; 04308 04309 node->next = 0; 04310 node->loader_name = loader_name; 04311 node->sym_prefix = dlloader->sym_prefix; 04312 node->dlloader_exit = dlloader->dlloader_exit; 04313 node->module_open = dlloader->module_open; 04314 node->module_close = dlloader->module_close; 04315 node->find_sym = dlloader->find_sym; 04316 node->dlloader_data = dlloader->dlloader_data; 04317 04318 LT_DLMUTEX_LOCK (); 04319 if (!loaders) 04320 { 04321 /* If there are no loaders, NODE becomes the list! */ 04322 loaders = node; 04323 } 04324 else if (!place) 04325 { 04326 /* If PLACE is not set, add NODE to the end of the 04327 LOADERS list. */ 04328 for (ptr = loaders; ptr->next; ptr = ptr->next) 04329 { 04330 /*NOWORK*/; 04331 } 04332 04333 ptr->next = node; 04334 } 04335 else if (loaders == place) 04336 { 04337 /* If PLACE is the first loader, NODE goes first. */ 04338 node->next = place; 04339 loaders = node; 04340 } 04341 else 04342 { 04343 /* Find the node immediately preceding PLACE. */ 04344 for (ptr = loaders; ptr->next != place; ptr = ptr->next) 04345 { 04346 /*NOWORK*/; 04347 } 04348 04349 if (ptr->next != place) 04350 { 04351 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 04352 ++errors; 04353 } 04354 else 04355 { 04356 /* Insert NODE between PTR and PLACE. */ 04357 node->next = place; 04358 ptr->next = node; 04359 } 04360 } 04361 04362 LT_DLMUTEX_UNLOCK (); 04363 04364 return errors; 04365 } 04366 04367 int 04368 lt_dlloader_remove (loader_name) 04369 const char *loader_name; 04370 { 04371 lt_dlloader *place = lt_dlloader_find (loader_name); 04372 lt_dlhandle handle; 04373 int errors = 0; 04374 04375 if (!place) 04376 { 04377 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 04378 return 1; 04379 } 04380 04381 LT_DLMUTEX_LOCK (); 04382 04383 /* Fail if there are any open modules which use this loader. */ 04384 for (handle = handles; handle; handle = handle->next) 04385 { 04386 if (handle->loader == place) 04387 { 04388 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); 04389 ++errors; 04390 goto done; 04391 } 04392 } 04393 04394 if (place == loaders) 04395 { 04396 /* PLACE is the first loader in the list. */ 04397 loaders = loaders->next; 04398 } 04399 else 04400 { 04401 /* Find the loader before the one being removed. */ 04402 lt_dlloader *prev; 04403 for (prev = loaders; prev->next; prev = prev->next) 04404 { 04405 if (!strcmp (prev->next->loader_name, loader_name)) 04406 { 04407 break; 04408 } 04409 } 04410 04411 place = prev->next; 04412 prev->next = prev->next->next; 04413 } 04414 04415 if (place->dlloader_exit) 04416 { 04417 errors = place->dlloader_exit (place->dlloader_data); 04418 } 04419 04420 LT_DLFREE (place); 04421 04422 done: 04423 LT_DLMUTEX_UNLOCK (); 04424 04425 return errors; 04426 } 04427 04428 lt_dlloader * 04429 lt_dlloader_next (place) 04430 lt_dlloader *place; 04431 { 04432 lt_dlloader *next; 04433 04434 LT_DLMUTEX_LOCK (); 04435 next = place ? place->next : loaders; 04436 LT_DLMUTEX_UNLOCK (); 04437 04438 return next; 04439 } 04440 04441 const char * 04442 lt_dlloader_name (place) 04443 lt_dlloader *place; 04444 { 04445 const char *name = 0; 04446 04447 if (place) 04448 { 04449 LT_DLMUTEX_LOCK (); 04450 name = place ? place->loader_name : 0; 04451 LT_DLMUTEX_UNLOCK (); 04452 } 04453 else 04454 { 04455 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 04456 } 04457 04458 return name; 04459 } 04460 04461 lt_user_data * 04462 lt_dlloader_data (place) 04463 lt_dlloader *place; 04464 { 04465 lt_user_data *data = 0; 04466 04467 if (place) 04468 { 04469 LT_DLMUTEX_LOCK (); 04470 data = place ? &(place->dlloader_data) : 0; 04471 LT_DLMUTEX_UNLOCK (); 04472 } 04473 else 04474 { 04475 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 04476 } 04477 04478 return data; 04479 } 04480 04481 lt_dlloader * 04482 lt_dlloader_find (loader_name) 04483 const char *loader_name; 04484 { 04485 lt_dlloader *place = 0; 04486 04487 LT_DLMUTEX_LOCK (); 04488 for (place = loaders; place; place = place->next) 04489 { 04490 if (strcmp (place->loader_name, loader_name) == 0) 04491 { 04492 break; 04493 } 04494 } 04495 LT_DLMUTEX_UNLOCK (); 04496 04497 return place; 04498 }