1/* ltdl.c -- system independent dlopen wrapper 2 Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. 3 Originally by Thomas Tanner <tanner@ffii.org> 4 This file is part of GNU Libtool. 5 6This library is free software; you can redistribute it and/or 7modify it under the terms of the GNU Lesser General Public 8License as published by the Free Software Foundation; either 9version 2 of the License, or (at your option) any later version. 10 11As a special exception to the GNU Lesser General Public License, 12if you distribute this file as part of a program or library that 13is built using GNU libtool, you may include it under the same 14distribution terms that you use for the rest of that program. 15 16This library is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19Lesser General Public License for more details. 20 21You should have received a copy of the GNU Lesser General Public 22License along with this library; if not, write to the Free Software 23Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2402110-1301 USA 25 26*/ 27 28#if HAVE_CONFIG_H 29# include <config.h> 30#endif 31 32#if HAVE_UNISTD_H 33# include <unistd.h> 34#endif 35 36#if HAVE_STDIO_H 37# include <stdio.h> 38#endif 39 40/* Include the header defining malloc. On K&R C compilers, 41 that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */ 42#if HAVE_STDLIB_H 43# include <stdlib.h> 44#else 45# if HAVE_MALLOC_H 46# include <malloc.h> 47# endif 48#endif 49 50#if HAVE_STRING_H 51# include <string.h> 52#else 53# if HAVE_STRINGS_H 54# include <strings.h> 55# endif 56#endif 57 58#if HAVE_CTYPE_H 59# include <ctype.h> 60#endif 61 62#if HAVE_MEMORY_H 63# include <memory.h> 64#endif 65 66#if HAVE_ERRNO_H 67# include <errno.h> 68#endif 69 70 71#ifndef __WINDOWS__ 72# ifdef __WIN32__ 73# define __WINDOWS__ 74# endif 75#endif 76 77 78#undef LT_USE_POSIX_DIRENT 79#ifdef HAVE_CLOSEDIR 80# ifdef HAVE_OPENDIR 81# ifdef HAVE_READDIR 82# ifdef HAVE_DIRENT_H 83# define LT_USE_POSIX_DIRENT 84# endif /* HAVE_DIRENT_H */ 85# endif /* HAVE_READDIR */ 86# endif /* HAVE_OPENDIR */ 87#endif /* HAVE_CLOSEDIR */ 88 89 90#undef LT_USE_WINDOWS_DIRENT_EMULATION 91#ifndef LT_USE_POSIX_DIRENT 92# ifdef __WINDOWS__ 93# define LT_USE_WINDOWS_DIRENT_EMULATION 94# endif /* __WINDOWS__ */ 95#endif /* LT_USE_POSIX_DIRENT */ 96 97 98#ifdef LT_USE_POSIX_DIRENT 99# include <dirent.h> 100# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) 101#else 102# ifdef LT_USE_WINDOWS_DIRENT_EMULATION 103# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) 104# else 105# define dirent direct 106# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) 107# if HAVE_SYS_NDIR_H 108# include <sys/ndir.h> 109# endif 110# if HAVE_SYS_DIR_H 111# include <sys/dir.h> 112# endif 113# if HAVE_NDIR_H 114# include <ndir.h> 115# endif 116# endif 117#endif 118 119#if HAVE_ARGZ_H 120# include <argz.h> 121#endif 122 123#if HAVE_ASSERT_H 124# include <assert.h> 125#else 126# define assert(arg) ((void) 0) 127#endif 128 129#include "ltdl.h" 130 131#if WITH_DMALLOC 132# include <dmalloc.h> 133#endif 134 135 136 137 138/* --- WINDOWS SUPPORT --- */ 139 140 141#ifdef DLL_EXPORT 142# define LT_GLOBAL_DATA __declspec(dllexport) 143#else 144# define LT_GLOBAL_DATA 145#endif 146 147/* fopen() mode flags for reading a text file */ 148#undef LT_READTEXT_MODE 149#ifdef __WINDOWS__ 150# define LT_READTEXT_MODE "rt" 151#else 152# define LT_READTEXT_MODE "r" 153#endif 154 155#ifdef LT_USE_WINDOWS_DIRENT_EMULATION 156 157#include <windows.h> 158 159#define dirent lt_dirent 160#define DIR lt_DIR 161 162struct dirent 163{ 164 char d_name[2048]; 165 int d_namlen; 166}; 167 168typedef struct _DIR 169{ 170 HANDLE hSearch; 171 WIN32_FIND_DATA Win32FindData; 172 BOOL firsttime; 173 struct dirent file_info; 174} DIR; 175 176#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ 177 178 179/* --- MANIFEST CONSTANTS --- */ 180 181 182/* Standard libltdl search path environment variable name */ 183#undef LTDL_SEARCHPATH_VAR 184#define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" 185 186/* Standard libtool archive file extension. */ 187#undef LTDL_ARCHIVE_EXT 188#define LTDL_ARCHIVE_EXT ".la" 189 190/* max. filename length */ 191#ifndef LT_FILENAME_MAX 192# define LT_FILENAME_MAX 1024 193#endif 194 195/* This is the maximum symbol size that won't require malloc/free */ 196#undef LT_SYMBOL_LENGTH 197#define LT_SYMBOL_LENGTH 128 198 199/* This accounts for the _LTX_ separator */ 200#undef LT_SYMBOL_OVERHEAD 201#define LT_SYMBOL_OVERHEAD 5 202 203 204 205 206/* --- MEMORY HANDLING --- */ 207 208 209/* These are the functions used internally. In addition to making 210 use of the associated function pointers above, they also perform 211 error handling. */ 212static char *lt_estrdup LT_PARAMS((const char *str)); 213static lt_ptr lt_emalloc LT_PARAMS((size_t size)); 214static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); 215 216/* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */ 217#define rpl_realloc realloc 218 219/* These are the pointers that can be changed by the caller: */ 220LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) 221 = (lt_ptr (*) LT_PARAMS((size_t))) malloc; 222LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) 223 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; 224LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) 225 = (void (*) LT_PARAMS((lt_ptr))) free; 226 227/* The following macros reduce the amount of typing needed to cast 228 assigned memory. */ 229#if WITH_DMALLOC 230 231#define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) 232#define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) 233#define LT_DLFREE(p) \ 234 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END 235 236#define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) 237#define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) 238 239#else 240 241#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) 242#define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp))) 243#define LT_DLFREE(p) \ 244 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END 245 246#define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) 247#define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) 248 249#endif 250 251#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ 252 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \ 253 } LT_STMT_END 254 255 256/* --- REPLACEMENT FUNCTIONS --- */ 257 258 259#undef strdup 260#define strdup rpl_strdup 261 262static char *strdup LT_PARAMS((const char *str)); 263 264static char * 265strdup(str) 266 const char *str; 267{ 268 char *tmp = 0; 269 270 if (str) 271 { 272 tmp = LT_DLMALLOC (char, 1+ strlen (str)); 273 if (tmp) 274 { 275 strcpy(tmp, str); 276 } 277 } 278 279 return tmp; 280} 281 282 283#if ! HAVE_STRCMP 284 285#undef strcmp 286#define strcmp rpl_strcmp 287 288static int strcmp LT_PARAMS((const char *str1, const char *str2)); 289 290static int 291strcmp (str1, str2) 292 const char *str1; 293 const char *str2; 294{ 295 if (str1 == str2) 296 return 0; 297 if (str1 == 0) 298 return -1; 299 if (str2 == 0) 300 return 1; 301 302 for (;*str1 && *str2; ++str1, ++str2) 303 { 304 if (*str1 != *str2) 305 break; 306 } 307 308 return (int)(*str1 - *str2); 309} 310#endif 311 312 313#if ! HAVE_STRCHR 314 315# if HAVE_INDEX 316# define strchr index 317# else 318# define strchr rpl_strchr 319 320static const char *strchr LT_PARAMS((const char *str, int ch)); 321 322static const char* 323strchr(str, ch) 324 const char *str; 325 int ch; 326{ 327 const char *p; 328 329 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) 330 /*NOWORK*/; 331 332 return (*p == (char)ch) ? p : 0; 333} 334 335# endif 336#endif /* !HAVE_STRCHR */ 337 338 339#if ! HAVE_STRRCHR 340 341# if HAVE_RINDEX 342# define strrchr rindex 343# else 344# define strrchr rpl_strrchr 345 346static const char *strrchr LT_PARAMS((const char *str, int ch)); 347 348static const char* 349strrchr(str, ch) 350 const char *str; 351 int ch; 352{ 353 const char *p, *q = 0; 354 355 for (p = str; *p != LT_EOS_CHAR; ++p) 356 { 357 if (*p == (char) ch) 358 { 359 q = p; 360 } 361 } 362 363 return q; 364} 365 366# endif 367#endif 368 369/* NOTE: Neither bcopy nor the memcpy implementation below can 370 reliably handle copying in overlapping areas of memory. Use 371 memmove (for which there is a fallback implmentation below) 372 if you need that behaviour. */ 373#if ! HAVE_MEMCPY 374 375# if HAVE_BCOPY 376# define memcpy(dest, src, size) bcopy (src, dest, size) 377# else 378# define memcpy rpl_memcpy 379 380static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); 381 382static lt_ptr 383memcpy (dest, src, size) 384 lt_ptr dest; 385 const lt_ptr src; 386 size_t size; 387{ 388 const char * s = src; 389 char * d = dest; 390 size_t i = 0; 391 392 for (i = 0; i < size; ++i) 393 { 394 d[i] = s[i]; 395 } 396 397 return dest; 398} 399 400# endif /* !HAVE_BCOPY */ 401#endif /* !HAVE_MEMCPY */ 402 403#if ! HAVE_MEMMOVE 404# define memmove rpl_memmove 405 406static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); 407 408static lt_ptr 409memmove (dest, src, size) 410 lt_ptr dest; 411 const lt_ptr src; 412 size_t size; 413{ 414 const char * s = src; 415 char * d = dest; 416 size_t i; 417 418 if (d < s) 419 for (i = 0; i < size; ++i) 420 { 421 d[i] = s[i]; 422 } 423 else if (d > s && size > 0) 424 for (i = size -1; ; --i) 425 { 426 d[i] = s[i]; 427 if (i == 0) 428 break; 429 } 430 431 return dest; 432} 433 434#endif /* !HAVE_MEMMOVE */ 435 436#ifdef LT_USE_WINDOWS_DIRENT_EMULATION 437 438static void closedir LT_PARAMS((DIR *entry)); 439 440static void 441closedir(entry) 442 DIR *entry; 443{ 444 assert(entry != (DIR *) NULL); 445 FindClose(entry->hSearch); 446 lt_dlfree((lt_ptr)entry); 447} 448 449 450static DIR * opendir LT_PARAMS((const char *path)); 451 452static DIR* 453opendir (path) 454 const char *path; 455{ 456 char file_specification[LT_FILENAME_MAX]; 457 DIR *entry; 458 459 assert(path != (char *) NULL); 460 /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */ 461 (void) strncpy (file_specification, path, LT_FILENAME_MAX-6); 462 file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR; 463 (void) strcat(file_specification,"\\"); 464 entry = LT_DLMALLOC (DIR,sizeof(DIR)); 465 if (entry != (DIR *) 0) 466 { 467 entry->firsttime = TRUE; 468 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); 469 } 470 if (entry->hSearch == INVALID_HANDLE_VALUE) 471 { 472 (void) strcat(file_specification,"\\*.*"); 473 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); 474 if (entry->hSearch == INVALID_HANDLE_VALUE) 475 { 476 LT_DLFREE (entry); 477 return (DIR *) 0; 478 } 479 } 480 return(entry); 481} 482 483 484static struct dirent *readdir LT_PARAMS((DIR *entry)); 485 486static struct dirent *readdir(entry) 487 DIR *entry; 488{ 489 int 490 status; 491 492 if (entry == (DIR *) 0) 493 return((struct dirent *) 0); 494 if (!entry->firsttime) 495 { 496 status = FindNextFile(entry->hSearch,&entry->Win32FindData); 497 if (status == 0) 498 return((struct dirent *) 0); 499 } 500 entry->firsttime = FALSE; 501 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName, 502 LT_FILENAME_MAX-1); 503 entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR; 504 entry->file_info.d_namlen = strlen(entry->file_info.d_name); 505 return(&entry->file_info); 506} 507 508#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ 509 510/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>, 511 ``realloc is not entirely portable'' 512 In any case we want to use the allocator supplied by the user without 513 burdening them with an lt_dlrealloc function pointer to maintain. 514 Instead implement our own version (with known boundary conditions) 515 using lt_dlmalloc and lt_dlfree. */ 516 517/* #undef realloc 518 #define realloc rpl_realloc 519*/ 520#if 0 521 /* You can't (re)define realloc unless you also (re)define malloc. 522 Right now, this code uses the size of the *destination* to decide 523 how much to copy. That's not right, but you can't know the size 524 of the source unless you know enough about, or wrote malloc. So 525 this code is disabled... */ 526 527static lt_ptr 528realloc (ptr, size) 529 lt_ptr ptr; 530 size_t size; 531{ 532 if (size == 0) 533 { 534 /* For zero or less bytes, free the original memory */ 535 if (ptr != 0) 536 { 537 lt_dlfree (ptr); 538 } 539 540 return (lt_ptr) 0; 541 } 542 else if (ptr == 0) 543 { 544 /* Allow reallocation of a NULL pointer. */ 545 return lt_dlmalloc (size); 546 } 547 else 548 { 549 /* Allocate a new block, copy and free the old block. */ 550 lt_ptr mem = lt_dlmalloc (size); 551 552 if (mem) 553 { 554 memcpy (mem, ptr, size); 555 lt_dlfree (ptr); 556 } 557 558 /* Note that the contents of PTR are not damaged if there is 559 insufficient memory to realloc. */ 560 return mem; 561 } 562} 563#endif 564 565 566#if ! HAVE_ARGZ_APPEND 567# define argz_append rpl_argz_append 568 569static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, 570 const char *buf, size_t buf_len)); 571 572static error_t 573argz_append (pargz, pargz_len, buf, buf_len) 574 char **pargz; 575 size_t *pargz_len; 576 const char *buf; 577 size_t buf_len; 578{ 579 size_t argz_len; 580 char *argz; 581 582 assert (pargz); 583 assert (pargz_len); 584 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); 585 586 /* If nothing needs to be appended, no more work is required. */ 587 if (buf_len == 0) 588 return 0; 589 590 /* Ensure there is enough room to append BUF_LEN. */ 591 argz_len = *pargz_len + buf_len; 592 argz = LT_DLREALLOC (char, *pargz, argz_len); 593 if (!argz) 594 return ENOMEM; 595 596 /* Copy characters from BUF after terminating '\0' in ARGZ. */ 597 memcpy (argz + *pargz_len, buf, buf_len); 598 599 /* Assign new values. */ 600 *pargz = argz; 601 *pargz_len = argz_len; 602 603 return 0; 604} 605#endif /* !HAVE_ARGZ_APPEND */ 606 607 608#if ! HAVE_ARGZ_CREATE_SEP 609# define argz_create_sep rpl_argz_create_sep 610 611static error_t argz_create_sep LT_PARAMS((const char *str, int delim, 612 char **pargz, size_t *pargz_len)); 613 614static error_t 615argz_create_sep (str, delim, pargz, pargz_len) 616 const char *str; 617 int delim; 618 char **pargz; 619 size_t *pargz_len; 620{ 621 size_t argz_len; 622 char *argz = 0; 623 624 assert (str); 625 assert (pargz); 626 assert (pargz_len); 627 628 /* Make a copy of STR, but replacing each occurrence of 629 DELIM with '\0'. */ 630 argz_len = 1+ LT_STRLEN (str); 631 if (argz_len) 632 { 633 const char *p; 634 char *q; 635 636 argz = LT_DLMALLOC (char, argz_len); 637 if (!argz) 638 return ENOMEM; 639 640 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) 641 { 642 if (*p == delim) 643 { 644 /* Ignore leading delimiters, and fold consecutive 645 delimiters in STR into a single '\0' in ARGZ. */ 646 if ((q > argz) && (q[-1] != LT_EOS_CHAR)) 647 *q++ = LT_EOS_CHAR; 648 else 649 --argz_len; 650 } 651 else 652 *q++ = *p; 653 } 654 /* Copy terminating LT_EOS_CHAR. */ 655 *q = *p; 656 } 657 658 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ 659 if (!argz_len) 660 LT_DLFREE (argz); 661 662 /* Assign new values. */ 663 *pargz = argz; 664 *pargz_len = argz_len; 665 666 return 0; 667} 668#endif /* !HAVE_ARGZ_CREATE_SEP */ 669 670 671#if ! HAVE_ARGZ_INSERT 672# define argz_insert rpl_argz_insert 673 674static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, 675 char *before, const char *entry)); 676 677static error_t 678argz_insert (pargz, pargz_len, before, entry) 679 char **pargz; 680 size_t *pargz_len; 681 char *before; 682 const char *entry; 683{ 684 assert (pargz); 685 assert (pargz_len); 686 assert (entry && *entry); 687 688 /* No BEFORE address indicates ENTRY should be inserted after the 689 current last element. */ 690 if (!before) 691 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); 692 693 /* This probably indicates a programmer error, but to preserve 694 semantics, scan back to the start of an entry if BEFORE points 695 into the middle of it. */ 696 while ((before > *pargz) && (before[-1] != LT_EOS_CHAR)) 697 --before; 698 699 { 700 size_t entry_len = 1+ LT_STRLEN (entry); 701 size_t argz_len = *pargz_len + entry_len; 702 size_t offset = before - *pargz; 703 char *argz = LT_DLREALLOC (char, *pargz, argz_len); 704 705 if (!argz) 706 return ENOMEM; 707 708 /* Make BEFORE point to the equivalent offset in ARGZ that it 709 used to have in *PARGZ incase realloc() moved the block. */ 710 before = argz + offset; 711 712 /* Move the ARGZ entries starting at BEFORE up into the new 713 space at the end -- making room to copy ENTRY into the 714 resulting gap. */ 715 memmove (before + entry_len, before, *pargz_len - offset); 716 memcpy (before, entry, entry_len); 717 718 /* Assign new values. */ 719 *pargz = argz; 720 *pargz_len = argz_len; 721 } 722 723 return 0; 724} 725#endif /* !HAVE_ARGZ_INSERT */ 726 727 728#if ! HAVE_ARGZ_NEXT 729# define argz_next rpl_argz_next 730 731static char *argz_next LT_PARAMS((char *argz, size_t argz_len, 732 const char *entry)); 733 734static char * 735argz_next (argz, argz_len, entry) 736 char *argz; 737 size_t argz_len; 738 const char *entry; 739{ 740 assert ((argz && argz_len) || (!argz && !argz_len)); 741 742 if (entry) 743 { 744 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address 745 within the ARGZ vector. */ 746 assert ((!argz && !argz_len) 747 || ((argz <= entry) && (entry < (argz + argz_len)))); 748 749 /* Move to the char immediately after the terminating 750 '\0' of ENTRY. */ 751 entry = 1+ strchr (entry, LT_EOS_CHAR); 752 753 /* Return either the new ENTRY, or else NULL if ARGZ is 754 exhausted. */ 755 return (entry >= argz + argz_len) ? 0 : (char *) entry; 756 } 757 else 758 { 759 /* This should probably be flagged as a programmer error, 760 since starting an argz_next loop with the iterator set 761 to ARGZ is safer. To preserve semantics, handle the NULL 762 case by returning the start of ARGZ (if any). */ 763 if (argz_len > 0) 764 return argz; 765 else 766 return 0; 767 } 768} 769#endif /* !HAVE_ARGZ_NEXT */ 770 771 772 773#if ! HAVE_ARGZ_STRINGIFY 774# define argz_stringify rpl_argz_stringify 775 776static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, 777 int sep)); 778 779static void 780argz_stringify (argz, argz_len, sep) 781 char *argz; 782 size_t argz_len; 783 int sep; 784{ 785 assert ((argz && argz_len) || (!argz && !argz_len)); 786 787 if (sep) 788 { 789 --argz_len; /* don't stringify the terminating EOS */ 790 while (--argz_len > 0) 791 { 792 if (argz[argz_len] == LT_EOS_CHAR) 793 argz[argz_len] = sep; 794 } 795 } 796} 797#endif /* !HAVE_ARGZ_STRINGIFY */ 798 799 800 801 802/* --- TYPE DEFINITIONS -- */ 803 804 805/* This type is used for the array of caller data sets in each handler. */ 806typedef struct { 807 lt_dlcaller_id key; 808 lt_ptr data; 809} lt_caller_data; 810 811 812 813 814/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ 815 816 817/* Extract the diagnostic strings from the error table macro in the same 818 order as the enumerated indices in ltdl.h. */ 819 820static const char *lt_dlerror_strings[] = 821 { 822#define LT_ERROR(name, diagnostic) (diagnostic), 823 lt_dlerror_table 824#undef LT_ERROR 825 826 0 827 }; 828 829/* This structure is used for the list of registered loaders. */ 830struct lt_dlloader { 831 struct lt_dlloader *next; 832 const char *loader_name; /* identifying name for each loader */ 833 const char *sym_prefix; /* prefix for symbols */ 834 lt_module_open *module_open; 835 lt_module_close *module_close; 836 lt_find_sym *find_sym; 837 lt_dlloader_exit *dlloader_exit; 838 lt_user_data dlloader_data; 839}; 840 841struct lt_dlhandle_struct { 842 struct lt_dlhandle_struct *next; 843 lt_dlloader *loader; /* dlopening interface */ 844 lt_dlinfo info; 845 int depcount; /* number of dependencies */ 846 lt_dlhandle *deplibs; /* dependencies */ 847 lt_module module; /* system module handle */ 848 lt_ptr system; /* system specific data */ 849 lt_caller_data *caller_data; /* per caller associated data */ 850 int flags; /* various boolean stats */ 851}; 852 853/* Various boolean flags can be stored in the flags field of an 854 lt_dlhandle_struct... */ 855#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) 856#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) 857 858#define LT_DLRESIDENT_FLAG (0x01 << 0) 859/* ...add more flags here... */ 860 861#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) 862 863 864#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] 865 866static const char objdir[] = LTDL_OBJDIR; 867static const char archive_ext[] = LTDL_ARCHIVE_EXT; 868#ifdef LTDL_SHLIB_EXT 869static const char shlib_ext[] = LTDL_SHLIB_EXT; 870#endif 871#ifdef LTDL_SYSSEARCHPATH 872static const char sys_search_path[] = LTDL_SYSSEARCHPATH; 873#endif 874 875 876 877 878/* --- MUTEX LOCKING --- */ 879 880 881/* Macros to make it easier to run the lock functions only if they have 882 been registered. The reason for the complicated lock macro is to 883 ensure that the stored error message from the last error is not 884 accidentally erased if the current function doesn't generate an 885 error of its own. */ 886#define LT_DLMUTEX_LOCK() LT_STMT_START { \ 887 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ 888 } LT_STMT_END 889#define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ 890 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ 891 } LT_STMT_END 892#define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ 893 if (lt_dlmutex_seterror_func) \ 894 (*lt_dlmutex_seterror_func) (errormsg); \ 895 else lt_dllast_error = (errormsg); } LT_STMT_END 896#define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ 897 if (lt_dlmutex_seterror_func) \ 898 (errormsg) = (*lt_dlmutex_geterror_func) (); \ 899 else (errormsg) = lt_dllast_error; } LT_STMT_END 900 901/* The mutex functions stored here are global, and are necessarily the 902 same for all threads that wish to share access to libltdl. */ 903static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; 904static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; 905static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; 906static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; 907static const char *lt_dllast_error = 0; 908 909 910/* Either set or reset the mutex functions. Either all the arguments must 911 be valid functions, or else all can be NULL to turn off locking entirely. 912 The registered functions should be manipulating a static global lock 913 from the lock() and unlock() callbacks, which needs to be reentrant. */ 914int 915lt_dlmutex_register (lock, unlock, seterror, geterror) 916 lt_dlmutex_lock *lock; 917 lt_dlmutex_unlock *unlock; 918 lt_dlmutex_seterror *seterror; 919 lt_dlmutex_geterror *geterror; 920{ 921 lt_dlmutex_unlock *old_unlock = unlock; 922 int errors = 0; 923 924 /* Lock using the old lock() callback, if any. */ 925 LT_DLMUTEX_LOCK (); 926 927 if ((lock && unlock && seterror && geterror) 928 || !(lock || unlock || seterror || geterror)) 929 { 930 lt_dlmutex_lock_func = lock; 931 lt_dlmutex_unlock_func = unlock; 932 lt_dlmutex_geterror_func = geterror; 933 } 934 else 935 { 936 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); 937 ++errors; 938 } 939 940 /* Use the old unlock() callback we saved earlier, if any. Otherwise 941 record any errors using internal storage. */ 942 if (old_unlock) 943 (*old_unlock) (); 944 945 /* Return the number of errors encountered during the execution of 946 this function. */ 947 return errors; 948} 949 950 951 952 953/* --- ERROR HANDLING --- */ 954 955 956static const char **user_error_strings = 0; 957static int errorcount = LT_ERROR_MAX; 958 959int 960lt_dladderror (diagnostic) 961 const char *diagnostic; 962{ 963 int errindex = 0; 964 int result = -1; 965 const char **temp = (const char **) 0; 966 967 assert (diagnostic); 968 969 LT_DLMUTEX_LOCK (); 970 971 errindex = errorcount - LT_ERROR_MAX; 972 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); 973 if (temp) 974 { 975 user_error_strings = temp; 976 user_error_strings[errindex] = diagnostic; 977 result = errorcount++; 978 } 979 980 LT_DLMUTEX_UNLOCK (); 981 982 return result; 983} 984 985int 986lt_dlseterror (errindex) 987 int errindex; 988{ 989 int errors = 0; 990 991 LT_DLMUTEX_LOCK (); 992 993 if (errindex >= errorcount || errindex < 0) 994 { 995 /* Ack! Error setting the error message! */ 996 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); 997 ++errors; 998 } 999 else if (errindex < LT_ERROR_MAX) 1000 { 1001 /* No error setting the error message! */ 1002 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); 1003 } 1004 else 1005 { 1006 /* No error setting the error message! */ 1007 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); 1008 } 1009 1010 LT_DLMUTEX_UNLOCK (); 1011 1012 return errors; 1013} 1014 1015static lt_ptr 1016lt_emalloc (size) 1017 size_t size; 1018{ 1019 lt_ptr mem = lt_dlmalloc (size); 1020 if (size && !mem) 1021 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 1022 return mem; 1023} 1024 1025static lt_ptr 1026lt_erealloc (addr, size) 1027 lt_ptr addr; 1028 size_t size; 1029{ 1030 lt_ptr mem = lt_dlrealloc (addr, size); 1031 if (size && !mem) 1032 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 1033 return mem; 1034} 1035 1036static char * 1037lt_estrdup (str) 1038 const char *str; 1039{ 1040 char *copy = strdup (str); 1041 if (LT_STRLEN (str) && !copy) 1042 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 1043 return copy; 1044} 1045 1046 1047 1048 1049/* --- DLOPEN() INTERFACE LOADER --- */ 1050 1051 1052#if HAVE_LIBDL 1053 1054/* dynamic linking with dlopen/dlsym */ 1055 1056#if HAVE_DLFCN_H 1057# include <dlfcn.h> 1058#endif 1059 1060#if HAVE_SYS_DL_H 1061# include <sys/dl.h> 1062#endif 1063 1064#ifdef RTLD_GLOBAL 1065# define LT_GLOBAL RTLD_GLOBAL 1066#else 1067# ifdef DL_GLOBAL 1068# define LT_GLOBAL DL_GLOBAL 1069# endif 1070#endif /* !RTLD_GLOBAL */ 1071#ifndef LT_GLOBAL 1072# define LT_GLOBAL 0 1073#endif /* !LT_GLOBAL */ 1074 1075/* We may have to define LT_LAZY_OR_NOW in the command line if we 1076 find out it does not work in some platform. */ 1077#ifndef LT_LAZY_OR_NOW 1078# ifdef RTLD_LAZY 1079# define LT_LAZY_OR_NOW RTLD_LAZY 1080# else 1081# ifdef DL_LAZY 1082# define LT_LAZY_OR_NOW DL_LAZY 1083# endif 1084# endif /* !RTLD_LAZY */ 1085#endif 1086#ifndef LT_LAZY_OR_NOW 1087# ifdef RTLD_NOW 1088# define LT_LAZY_OR_NOW RTLD_NOW 1089# else 1090# ifdef DL_NOW 1091# define LT_LAZY_OR_NOW DL_NOW 1092# endif 1093# endif /* !RTLD_NOW */ 1094#endif 1095#ifndef LT_LAZY_OR_NOW 1096# define LT_LAZY_OR_NOW 0 1097#endif /* !LT_LAZY_OR_NOW */ 1098 1099#if HAVE_DLERROR 1100# define DLERROR(arg) dlerror () 1101#else 1102# define DLERROR(arg) LT_DLSTRERROR (arg) 1103#endif 1104 1105static lt_module 1106sys_dl_open (loader_data, filename) 1107 lt_user_data loader_data; 1108 const char *filename; 1109{ 1110 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW); 1111 1112 if (!module) 1113 { 1114 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); 1115 } 1116 1117 return module; 1118} 1119 1120static int 1121sys_dl_close (loader_data, module) 1122 lt_user_data loader_data; 1123 lt_module module; 1124{ 1125 int errors = 0; 1126 1127 if (dlclose (module) != 0) 1128 { 1129 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); 1130 ++errors; 1131 } 1132 1133 return errors; 1134} 1135 1136static lt_ptr 1137sys_dl_sym (loader_data, module, symbol) 1138 lt_user_data loader_data; 1139 lt_module module; 1140 const char *symbol; 1141{ 1142 lt_ptr address = dlsym (module, symbol); 1143 1144 if (!address) 1145 { 1146 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); 1147 } 1148 1149 return address; 1150} 1151 1152static struct lt_user_dlloader sys_dl = 1153 { 1154# ifdef NEED_USCORE 1155 "_", 1156# else 1157 0, 1158# endif 1159 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; 1160 1161 1162#endif /* HAVE_LIBDL */ 1163 1164 1165 1166/* --- SHL_LOAD() INTERFACE LOADER --- */ 1167 1168#if HAVE_SHL_LOAD 1169 1170/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ 1171 1172#ifdef HAVE_DL_H 1173# include <dl.h> 1174#endif 1175 1176/* some flags are missing on some systems, so we provide 1177 * harmless defaults. 1178 * 1179 * Mandatory: 1180 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. 1181 * BIND_DEFERRED - Delay code symbol resolution until actual reference. 1182 * 1183 * Optionally: 1184 * BIND_FIRST - Place the library at the head of the symbol search 1185 * order. 1186 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all 1187 * unsatisfied symbols as fatal. This flag allows 1188 * binding of unsatisfied code symbols to be deferred 1189 * until use. 1190 * [Perl: For certain libraries, like DCE, deferred 1191 * binding often causes run time problems. Adding 1192 * BIND_NONFATAL to BIND_IMMEDIATE still allows 1193 * unresolved references in situations like this.] 1194 * BIND_NOSTART - Do not call the initializer for the shared library 1195 * when the library is loaded, nor on a future call to 1196 * shl_unload(). 1197 * BIND_VERBOSE - Print verbose messages concerning possible 1198 * unsatisfied symbols. 1199 * 1200 * hp9000s700/hp9000s800: 1201 * BIND_RESTRICTED - Restrict symbols visible by the library to those 1202 * present at library load time. 1203 * DYNAMIC_PATH - Allow the loader to dynamically search for the 1204 * library specified by the path argument. 1205 */ 1206 1207#ifndef DYNAMIC_PATH 1208# define DYNAMIC_PATH 0 1209#endif 1210#ifndef BIND_RESTRICTED 1211# define BIND_RESTRICTED 0 1212#endif 1213 1214#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) 1215 1216static lt_module 1217sys_shl_open (loader_data, filename) 1218 lt_user_data loader_data; 1219 const char *filename; 1220{ 1221 static shl_t self = (shl_t) 0; 1222 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); 1223 1224 /* Since searching for a symbol against a NULL module handle will also 1225 look in everything else that was already loaded and exported with 1226 the -E compiler flag, we always cache a handle saved before any 1227 modules are loaded. */ 1228 if (!self) 1229 { 1230 lt_ptr address; 1231 shl_findsym (&self, "main", TYPE_UNDEFINED, &address); 1232 } 1233 1234 if (!filename) 1235 { 1236 module = self; 1237 } 1238 else 1239 { 1240 module = shl_load (filename, LT_BIND_FLAGS, 0L); 1241 1242 if (!module) 1243 { 1244 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1245 } 1246 } 1247 1248 return module; 1249} 1250 1251static int 1252sys_shl_close (loader_data, module) 1253 lt_user_data loader_data; 1254 lt_module module; 1255{ 1256 int errors = 0; 1257 1258 if (module && (shl_unload ((shl_t) (module)) != 0)) 1259 { 1260 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1261 ++errors; 1262 } 1263 1264 return errors; 1265} 1266 1267static lt_ptr 1268sys_shl_sym (loader_data, module, symbol) 1269 lt_user_data loader_data; 1270 lt_module module; 1271 const char *symbol; 1272{ 1273 lt_ptr address = 0; 1274 1275 /* sys_shl_open should never return a NULL module handle */ 1276 if (module == (lt_module) 0) 1277 { 1278 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 1279 } 1280 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) 1281 { 1282 if (!address) 1283 { 1284 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1285 } 1286 } 1287 1288 return address; 1289} 1290 1291static struct lt_user_dlloader sys_shl = { 1292 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 1293}; 1294 1295#endif /* HAVE_SHL_LOAD */ 1296 1297 1298 1299 1300/* --- LOADLIBRARY() INTERFACE LOADER --- */ 1301 1302#ifdef __WINDOWS__ 1303 1304/* dynamic linking for Win32 */ 1305 1306#include <windows.h> 1307 1308/* Forward declaration; required to implement handle search below. */ 1309static lt_dlhandle handles; 1310 1311static lt_module 1312sys_wll_open (loader_data, filename) 1313 lt_user_data loader_data; 1314 const char *filename; 1315{ 1316 lt_dlhandle cur; 1317 lt_module module = 0; 1318 const char *errormsg = 0; 1319 char *searchname = 0; 1320 char *ext; 1321 char self_name_buf[MAX_PATH]; 1322 1323 if (!filename) 1324 { 1325 /* Get the name of main module */ 1326 *self_name_buf = 0; 1327 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); 1328 filename = ext = self_name_buf; 1329 } 1330 else 1331 { 1332 ext = strrchr (filename, '.'); 1333 } 1334 1335 if (ext) 1336 { 1337 /* FILENAME already has an extension. */ 1338 searchname = lt_estrdup (filename); 1339 } 1340 else 1341 { 1342 /* Append a `.' to stop Windows from adding an 1343 implicit `.dll' extension. */ 1344 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); 1345 if (searchname) 1346 sprintf (searchname, "%s.", filename); 1347 } 1348 if (!searchname) 1349 return 0; 1350 1351 { 1352 /* Silence dialog from LoadLibrary on some failures. 1353 No way to get the error mode, but to set it, 1354 so set it twice to preserve any previous flags. */ 1355 UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS); 1356 SetErrorMode(errormode | SEM_FAILCRITICALERRORS); 1357 1358#if defined(__CYGWIN__) 1359 { 1360 char wpath[MAX_PATH]; 1361 cygwin_conv_to_full_win32_path (searchname, wpath); 1362 module = LoadLibrary (wpath); 1363 } 1364#else 1365 module = LoadLibrary (searchname); 1366#endif 1367 1368 /* Restore the error mode. */ 1369 SetErrorMode(errormode); 1370 } 1371 1372 LT_DLFREE (searchname); 1373 1374 /* libltdl expects this function to fail if it is unable 1375 to physically load the library. Sadly, LoadLibrary 1376 will search the loaded libraries for a match and return 1377 one of them if the path search load fails. 1378 1379 We check whether LoadLibrary is returning a handle to 1380 an already loaded module, and simulate failure if we 1381 find one. */ 1382 LT_DLMUTEX_LOCK (); 1383 cur = handles; 1384 while (cur) 1385 { 1386 if (!cur->module) 1387 { 1388 cur = 0; 1389 break; 1390 } 1391 1392 if (cur->module == module) 1393 { 1394 break; 1395 } 1396 1397 cur = cur->next; 1398 } 1399 LT_DLMUTEX_UNLOCK (); 1400 1401 if (cur || !module) 1402 { 1403 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1404 module = 0; 1405 } 1406 1407 return module; 1408} 1409 1410static int 1411sys_wll_close (loader_data, module) 1412 lt_user_data loader_data; 1413 lt_module module; 1414{ 1415 int errors = 0; 1416 1417 if (FreeLibrary(module) == 0) 1418 { 1419 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1420 ++errors; 1421 } 1422 1423 return errors; 1424} 1425 1426static lt_ptr 1427sys_wll_sym (loader_data, module, symbol) 1428 lt_user_data loader_data; 1429 lt_module module; 1430 const char *symbol; 1431{ 1432 lt_ptr address = GetProcAddress (module, symbol); 1433 1434 if (!address) 1435 { 1436 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1437 } 1438 1439 return address; 1440} 1441 1442static struct lt_user_dlloader sys_wll = { 1443 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 1444}; 1445 1446#endif /* __WINDOWS__ */ 1447 1448 1449 1450 1451/* --- LOAD_ADD_ON() INTERFACE LOADER --- */ 1452 1453 1454#ifdef __BEOS__ 1455 1456/* dynamic linking for BeOS */ 1457 1458#include <kernel/image.h> 1459 1460static lt_module 1461sys_bedl_open (loader_data, filename) 1462 lt_user_data loader_data; 1463 const char *filename; 1464{ 1465 image_id image = 0; 1466 1467 if (filename) 1468 { 1469 image = load_add_on (filename); 1470 } 1471 else 1472 { 1473 image_info info; 1474 int32 cookie = 0; 1475 if (get_next_image_info (0, &cookie, &info) == B_OK) 1476 image = load_add_on (info.name); 1477 } 1478 1479 if (image <= 0) 1480 { 1481 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1482 image = 0; 1483 } 1484 1485 return (lt_module) image; 1486} 1487 1488static int 1489sys_bedl_close (loader_data, module) 1490 lt_user_data loader_data; 1491 lt_module module; 1492{ 1493 int errors = 0; 1494 1495 if (unload_add_on ((image_id) module) != B_OK) 1496 { 1497 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1498 ++errors; 1499 } 1500 1501 return errors; 1502} 1503 1504static lt_ptr 1505sys_bedl_sym (loader_data, module, symbol) 1506 lt_user_data loader_data; 1507 lt_module module; 1508 const char *symbol; 1509{ 1510 lt_ptr address = 0; 1511 image_id image = (image_id) module; 1512 1513 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) 1514 { 1515 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1516 address = 0; 1517 } 1518 1519 return address; 1520} 1521 1522static struct lt_user_dlloader sys_bedl = { 1523 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 1524}; 1525 1526#endif /* __BEOS__ */ 1527 1528 1529 1530 1531/* --- DLD_LINK() INTERFACE LOADER --- */ 1532 1533 1534#if HAVE_DLD 1535 1536/* dynamic linking with dld */ 1537 1538#if HAVE_DLD_H 1539#include <dld.h> 1540#endif 1541 1542static lt_module 1543sys_dld_open (loader_data, filename) 1544 lt_user_data loader_data; 1545 const char *filename; 1546{ 1547 lt_module module = strdup (filename); 1548 1549 if (dld_link (filename) != 0) 1550 { 1551 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); 1552 LT_DLFREE (module); 1553 module = 0; 1554 } 1555 1556 return module; 1557} 1558 1559static int 1560sys_dld_close (loader_data, module) 1561 lt_user_data loader_data; 1562 lt_module module; 1563{ 1564 int errors = 0; 1565 1566 if (dld_unlink_by_file ((char*)(module), 1) != 0) 1567 { 1568 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); 1569 ++errors; 1570 } 1571 else 1572 { 1573 LT_DLFREE (module); 1574 } 1575 1576 return errors; 1577} 1578 1579static lt_ptr 1580sys_dld_sym (loader_data, module, symbol) 1581 lt_user_data loader_data; 1582 lt_module module; 1583 const char *symbol; 1584{ 1585 lt_ptr address = dld_get_func (symbol); 1586 1587 if (!address) 1588 { 1589 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 1590 } 1591 1592 return address; 1593} 1594 1595static struct lt_user_dlloader sys_dld = { 1596 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 1597}; 1598 1599#endif /* HAVE_DLD */ 1600 1601/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */ 1602#if HAVE_DYLD 1603 1604 1605#if HAVE_MACH_O_DYLD_H 1606#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__) 1607/* Is this correct? Does it still function properly? */ 1608#define __private_extern__ extern 1609#endif 1610# include <mach-o/dyld.h> 1611#endif 1612#include <mach-o/getsect.h> 1613 1614/* We have to put some stuff here that isn't in older dyld.h files */ 1615#ifndef ENUM_DYLD_BOOL 1616# define ENUM_DYLD_BOOL 1617# undef FALSE 1618# undef TRUE 1619 enum DYLD_BOOL { 1620 FALSE, 1621 TRUE 1622 }; 1623#endif 1624#ifndef LC_REQ_DYLD 1625# define LC_REQ_DYLD 0x80000000 1626#endif 1627#ifndef LC_LOAD_WEAK_DYLIB 1628# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) 1629#endif 1630static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0; 1631static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0; 1632static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0; 1633static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0; 1634 1635#ifndef NSADDIMAGE_OPTION_NONE 1636#define NSADDIMAGE_OPTION_NONE 0x0 1637#endif 1638#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR 1639#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 1640#endif 1641#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING 1642#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2 1643#endif 1644#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 1645#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 1646#endif 1647#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 1648#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 1649#endif 1650#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 1651#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 1652#endif 1653#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 1654#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1 1655#endif 1656#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 1657#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2 1658#endif 1659#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 1660#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 1661#endif 1662 1663 1664static const char * 1665lt_int_dyld_error(othererror) 1666 char* othererror; 1667{ 1668/* return the dyld error string, or the passed in error string if none */ 1669 NSLinkEditErrors ler; 1670 int lerno; 1671 const char *errstr; 1672 const char *file; 1673 NSLinkEditError(&ler,&lerno,&file,&errstr); 1674 if (!errstr || !strlen(errstr)) errstr = othererror; 1675 return errstr; 1676} 1677 1678static const struct mach_header * 1679lt_int_dyld_get_mach_header_from_nsmodule(module) 1680 NSModule module; 1681{ 1682/* There should probably be an apple dyld api for this */ 1683 int i=_dyld_image_count(); 1684 int j; 1685 const char *modname=NSNameOfModule(module); 1686 const struct mach_header *mh=NULL; 1687 if (!modname) return NULL; 1688 for (j = 0; j < i; j++) 1689 { 1690 if (!strcmp(_dyld_get_image_name(j),modname)) 1691 { 1692 mh=_dyld_get_image_header(j); 1693 break; 1694 } 1695 } 1696 return mh; 1697} 1698 1699static const char* lt_int_dyld_lib_install_name(mh) 1700 const struct mach_header *mh; 1701{ 1702/* NSAddImage is also used to get the loaded image, but it only works if the lib 1703 is installed, for uninstalled libs we need to check the install_names against 1704 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a 1705 different lib was loaded as a result 1706*/ 1707 int j; 1708 struct load_command *lc; 1709 unsigned long offset = sizeof(struct mach_header); 1710 const char* retStr=NULL; 1711 for (j = 0; j < mh->ncmds; j++) 1712 { 1713 lc = (struct load_command*)(((unsigned long)mh) + offset); 1714 if (LC_ID_DYLIB == lc->cmd) 1715 { 1716 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset + 1717 (unsigned long)lc); 1718 } 1719 offset += lc->cmdsize; 1720 } 1721 return retStr; 1722} 1723 1724static const struct mach_header * 1725lt_int_dyld_match_loaded_lib_by_install_name(const char *name) 1726{ 1727 int i=_dyld_image_count(); 1728 int j; 1729 const struct mach_header *mh=NULL; 1730 const char *id=NULL; 1731 for (j = 0; j < i; j++) 1732 { 1733 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j)); 1734 if ((id) && (!strcmp(id,name))) 1735 { 1736 mh=_dyld_get_image_header(j); 1737 break; 1738 } 1739 } 1740 return mh; 1741} 1742 1743static NSSymbol 1744lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh) 1745 const char *symbol; 1746 const struct mach_header *mh; 1747{ 1748 /* Safe to assume our mh is good */ 1749 int j; 1750 struct load_command *lc; 1751 unsigned long offset = sizeof(struct mach_header); 1752 NSSymbol retSym = 0; 1753 const struct mach_header *mh1; 1754 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) ) 1755 { 1756 for (j = 0; j < mh->ncmds; j++) 1757 { 1758 lc = (struct load_command*)(((unsigned long)mh) + offset); 1759 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) 1760 { 1761 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset + 1762 (unsigned long)lc)); 1763 if (!mh1) 1764 { 1765 /* Maybe NSAddImage can find it */ 1766 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset + 1767 (unsigned long)lc), 1768 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + 1769 NSADDIMAGE_OPTION_WITH_SEARCHING + 1770 NSADDIMAGE_OPTION_RETURN_ON_ERROR ); 1771 } 1772 if (mh1) 1773 { 1774 retSym = ltdl_NSLookupSymbolInImage(mh1, 1775 symbol, 1776 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 1777 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 1778 ); 1779 if (retSym) break; 1780 } 1781 } 1782 offset += lc->cmdsize; 1783 } 1784 } 1785 return retSym; 1786} 1787 1788static int 1789sys_dyld_init() 1790{ 1791 int retCode = 0; 1792 int err = 0; 1793 if (!_dyld_present()) { 1794 retCode=1; 1795 } 1796 else { 1797 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage); 1798 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage); 1799 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage); 1800 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic); 1801 } 1802 return retCode; 1803} 1804 1805static lt_module 1806sys_dyld_open (loader_data, filename) 1807 lt_user_data loader_data; 1808 const char *filename; 1809{ 1810 lt_module module = 0; 1811 NSObjectFileImage ofi = 0; 1812 NSObjectFileImageReturnCode ofirc; 1813 1814 if (!filename) 1815 return (lt_module)-1; 1816 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi); 1817 switch (ofirc) 1818 { 1819 case NSObjectFileImageSuccess: 1820 module = NSLinkModule(ofi, filename, 1821 NSLINKMODULE_OPTION_RETURN_ON_ERROR 1822 | NSLINKMODULE_OPTION_PRIVATE 1823 | NSLINKMODULE_OPTION_BINDNOW); 1824 NSDestroyObjectFileImage(ofi); 1825 if (module) 1826 ltdl_NSMakePrivateModulePublic(module); 1827 break; 1828 case NSObjectFileImageInappropriateFile: 1829 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) 1830 { 1831 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR); 1832 break; 1833 } 1834 default: 1835 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); 1836 return 0; 1837 } 1838 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); 1839 return module; 1840} 1841 1842static int 1843sys_dyld_close (loader_data, module) 1844 lt_user_data loader_data; 1845 lt_module module; 1846{ 1847 int retCode = 0; 1848 int flags = 0; 1849 if (module == (lt_module)-1) return 0; 1850#ifdef __BIG_ENDIAN__ 1851 if (((struct mach_header *)module)->magic == MH_MAGIC) 1852#else 1853 if (((struct mach_header *)module)->magic == MH_CIGAM) 1854#endif 1855 { 1856 LT_DLMUTEX_SETERROR("Can not close a dylib"); 1857 retCode = 1; 1858 } 1859 else 1860 { 1861#if 1 1862/* Currently, if a module contains c++ static destructors and it is unloaded, we 1863 get a segfault in atexit(), due to compiler and dynamic loader differences of 1864 opinion, this works around that. 1865*/ 1866 if ((const struct section *)NULL != 1867 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module), 1868 "__DATA","__mod_term_func")) 1869 { 1870 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; 1871 } 1872#endif 1873#ifdef __ppc__ 1874 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; 1875#endif 1876 if (!NSUnLinkModule(module,flags)) 1877 { 1878 retCode=1; 1879 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE))); 1880 } 1881 } 1882 1883 return retCode; 1884} 1885 1886static lt_ptr 1887sys_dyld_sym (loader_data, module, symbol) 1888 lt_user_data loader_data; 1889 lt_module module; 1890 const char *symbol; 1891{ 1892 lt_ptr address = 0; 1893 NSSymbol *nssym = 0; 1894 void *unused; 1895 const struct mach_header *mh=NULL; 1896 char saveError[256] = "Symbol not found"; 1897 if (module == (lt_module)-1) 1898 { 1899 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused); 1900 return address; 1901 } 1902#ifdef __BIG_ENDIAN__ 1903 if (((struct mach_header *)module)->magic == MH_MAGIC) 1904#else 1905 if (((struct mach_header *)module)->magic == MH_CIGAM) 1906#endif 1907 { 1908 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) 1909 { 1910 mh=module; 1911 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol)) 1912 { 1913 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module, 1914 symbol, 1915 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 1916 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 1917 ); 1918 } 1919 } 1920 1921 } 1922 else { 1923 nssym = NSLookupSymbolInModule(module, symbol); 1924 } 1925 if (!nssym) 1926 { 1927 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255); 1928 saveError[255] = 0; 1929 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module); 1930 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh); 1931 } 1932 if (!nssym) 1933 { 1934 LT_DLMUTEX_SETERROR (saveError); 1935 return NULL; 1936 } 1937 return NSAddressOfSymbol(nssym); 1938} 1939 1940static struct lt_user_dlloader sys_dyld = 1941 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 }; 1942 1943 1944#endif /* HAVE_DYLD */ 1945 1946 1947/* --- DLPREOPEN() INTERFACE LOADER --- */ 1948 1949 1950/* emulate dynamic linking using preloaded_symbols */ 1951 1952typedef struct lt_dlsymlists_t 1953{ 1954 struct lt_dlsymlists_t *next; 1955 const lt_dlsymlist *syms; 1956} lt_dlsymlists_t; 1957 1958static const lt_dlsymlist *default_preloaded_symbols = 0; 1959static lt_dlsymlists_t *preloaded_symbols = 0; 1960 1961static int 1962presym_init (loader_data) 1963 lt_user_data loader_data; 1964{ 1965 int errors = 0; 1966 1967 LT_DLMUTEX_LOCK (); 1968 1969 preloaded_symbols = 0; 1970 if (default_preloaded_symbols) 1971 { 1972 errors = lt_dlpreload (default_preloaded_symbols); 1973 } 1974 1975 LT_DLMUTEX_UNLOCK (); 1976 1977 return errors; 1978} 1979 1980static int 1981presym_free_symlists () 1982{ 1983 lt_dlsymlists_t *lists; 1984 1985 LT_DLMUTEX_LOCK (); 1986 1987 lists = preloaded_symbols; 1988 while (lists) 1989 { 1990 lt_dlsymlists_t *tmp = lists; 1991 1992 lists = lists->next; 1993 LT_DLFREE (tmp); 1994 } 1995 preloaded_symbols = 0; 1996 1997 LT_DLMUTEX_UNLOCK (); 1998 1999 return 0; 2000} 2001 2002static int 2003presym_exit (loader_data) 2004 lt_user_data loader_data; 2005{ 2006 presym_free_symlists (); 2007 return 0; 2008} 2009 2010static int 2011presym_add_symlist (preloaded) 2012 const lt_dlsymlist *preloaded; 2013{ 2014 lt_dlsymlists_t *tmp; 2015 lt_dlsymlists_t *lists; 2016 int errors = 0; 2017 2018 LT_DLMUTEX_LOCK (); 2019 2020 lists = preloaded_symbols; 2021 while (lists) 2022 { 2023 if (lists->syms == preloaded) 2024 { 2025 goto done; 2026 } 2027 lists = lists->next; 2028 } 2029 2030 tmp = LT_EMALLOC (lt_dlsymlists_t, 1); 2031 if (tmp) 2032 { 2033 memset (tmp, 0, sizeof(lt_dlsymlists_t)); 2034 tmp->syms = preloaded; 2035 tmp->next = preloaded_symbols; 2036 preloaded_symbols = tmp; 2037 } 2038 else 2039 { 2040 ++errors; 2041 } 2042 2043 done: 2044 LT_DLMUTEX_UNLOCK (); 2045 return errors; 2046} 2047 2048static lt_module 2049presym_open (loader_data, filename) 2050 lt_user_data loader_data; 2051 const char *filename; 2052{ 2053 lt_dlsymlists_t *lists; 2054 lt_module module = (lt_module) 0; 2055 2056 LT_DLMUTEX_LOCK (); 2057 lists = preloaded_symbols; 2058 2059 if (!lists) 2060 { 2061 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); 2062 goto done; 2063 } 2064 2065 /* Can't use NULL as the reflective symbol header, as NULL is 2066 used to mark the end of the entire symbol list. Self-dlpreopened 2067 symbols follow this magic number, chosen to be an unlikely 2068 clash with a real module name. */ 2069 if (!filename) 2070 { 2071 filename = "@PROGRAM@"; 2072 } 2073 2074 while (lists) 2075 { 2076 const lt_dlsymlist *syms = lists->syms; 2077 2078 while (syms->name) 2079 { 2080 if (!syms->address && strcmp(syms->name, filename) == 0) 2081 { 2082 module = (lt_module) syms; 2083 goto done; 2084 } 2085 ++syms; 2086 } 2087 2088 lists = lists->next; 2089 } 2090 2091 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 2092 2093 done: 2094 LT_DLMUTEX_UNLOCK (); 2095 return module; 2096} 2097 2098static int 2099presym_close (loader_data, module) 2100 lt_user_data loader_data; 2101 lt_module module; 2102{ 2103 /* Just to silence gcc -Wall */ 2104 module = 0; 2105 return 0; 2106} 2107 2108static lt_ptr 2109presym_sym (loader_data, module, symbol) 2110 lt_user_data loader_data; 2111 lt_module module; 2112 const char *symbol; 2113{ 2114 lt_dlsymlist *syms = (lt_dlsymlist*) module; 2115 2116 ++syms; 2117 while (syms->address) 2118 { 2119 if (strcmp(syms->name, symbol) == 0) 2120 { 2121 return syms->address; 2122 } 2123 2124 ++syms; 2125 } 2126 2127 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 2128 2129 return 0; 2130} 2131 2132static struct lt_user_dlloader presym = { 2133 0, presym_open, presym_close, presym_sym, presym_exit, 0 2134}; 2135 2136 2137 2138 2139 2140/* --- DYNAMIC MODULE LOADING --- */ 2141 2142 2143/* The type of a function used at each iteration of foreach_dirinpath(). */ 2144typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, 2145 lt_ptr data2)); 2146 2147static int foreach_dirinpath LT_PARAMS((const char *search_path, 2148 const char *base_name, 2149 foreach_callback_func *func, 2150 lt_ptr data1, lt_ptr data2)); 2151 2152static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, 2153 lt_ptr ignored)); 2154static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, 2155 lt_ptr ignored)); 2156static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, 2157 lt_ptr data2)); 2158 2159 2160static int canonicalize_path LT_PARAMS((const char *path, 2161 char **pcanonical)); 2162static int argzize_path LT_PARAMS((const char *path, 2163 char **pargz, 2164 size_t *pargz_len)); 2165static FILE *find_file LT_PARAMS((const char *search_path, 2166 const char *base_name, 2167 char **pdir)); 2168static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, 2169 const char *base_name, 2170 lt_dlhandle *handle)); 2171static int find_module LT_PARAMS((lt_dlhandle *handle, 2172 const char *dir, 2173 const char *libdir, 2174 const char *dlname, 2175 const char *old_name, 2176 int installed)); 2177static int free_vars LT_PARAMS((char *dlname, char *oldname, 2178 char *libdir, char *deplibs)); 2179static int load_deplibs LT_PARAMS((lt_dlhandle handle, 2180 char *deplibs)); 2181static int trim LT_PARAMS((char **dest, 2182 const char *str)); 2183static int try_dlopen LT_PARAMS((lt_dlhandle *handle, 2184 const char *filename)); 2185static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, 2186 const char *filename)); 2187static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); 2188static int lt_argz_insert LT_PARAMS((char **pargz, 2189 size_t *pargz_len, 2190 char *before, 2191 const char *entry)); 2192static int lt_argz_insertinorder LT_PARAMS((char **pargz, 2193 size_t *pargz_len, 2194 const char *entry)); 2195static int lt_argz_insertdir LT_PARAMS((char **pargz, 2196 size_t *pargz_len, 2197 const char *dirnam, 2198 struct dirent *dp)); 2199static int lt_dlpath_insertdir LT_PARAMS((char **ppath, 2200 char *before, 2201 const char *dir)); 2202static int list_files_by_dir LT_PARAMS((const char *dirnam, 2203 char **pargz, 2204 size_t *pargz_len)); 2205static int file_not_found LT_PARAMS((void)); 2206 2207static char *user_search_path= 0; 2208static lt_dlloader *loaders = 0; 2209static lt_dlhandle handles = 0; 2210static int initialized = 0; 2211 2212/* Initialize libltdl. */ 2213int 2214lt_dlinit () 2215{ 2216 int errors = 0; 2217 2218 LT_DLMUTEX_LOCK (); 2219 2220 /* Initialize only at first call. */ 2221 if (++initialized == 1) 2222 { 2223 handles = 0; 2224 user_search_path = 0; /* empty search path */ 2225 2226#if HAVE_LIBDL 2227 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); 2228#endif 2229#if HAVE_SHL_LOAD 2230 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); 2231#endif 2232#ifdef __WINDOWS__ 2233 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); 2234#endif 2235#ifdef __BEOS__ 2236 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); 2237#endif 2238#if HAVE_DLD 2239 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); 2240#endif 2241#if HAVE_DYLD 2242 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld"); 2243 errors += sys_dyld_init(); 2244#endif 2245 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); 2246 2247 if (presym_init (presym.dlloader_data)) 2248 { 2249 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); 2250 ++errors; 2251 } 2252 else if (errors != 0) 2253 { 2254 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); 2255 ++errors; 2256 } 2257 } 2258 2259 LT_DLMUTEX_UNLOCK (); 2260 2261 return errors; 2262} 2263 2264int 2265lt_dlpreload (preloaded) 2266 const lt_dlsymlist *preloaded; 2267{ 2268 int errors = 0; 2269 2270 if (preloaded) 2271 { 2272 errors = presym_add_symlist (preloaded); 2273 } 2274 else 2275 { 2276 presym_free_symlists(); 2277 2278 LT_DLMUTEX_LOCK (); 2279 if (default_preloaded_symbols) 2280 { 2281 errors = lt_dlpreload (default_preloaded_symbols); 2282 } 2283 LT_DLMUTEX_UNLOCK (); 2284 } 2285 2286 return errors; 2287} 2288 2289int 2290lt_dlpreload_default (preloaded) 2291 const lt_dlsymlist *preloaded; 2292{ 2293 LT_DLMUTEX_LOCK (); 2294 default_preloaded_symbols = preloaded; 2295 LT_DLMUTEX_UNLOCK (); 2296 return 0; 2297} 2298 2299int 2300lt_dlexit () 2301{ 2302 /* shut down libltdl */ 2303 lt_dlloader *loader; 2304 int errors = 0; 2305 2306 LT_DLMUTEX_LOCK (); 2307 loader = loaders; 2308 2309 if (!initialized) 2310 { 2311 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); 2312 ++errors; 2313 goto done; 2314 } 2315 2316 /* shut down only at last call. */ 2317 if (--initialized == 0) 2318 { 2319 int level; 2320 2321 while (handles && LT_DLIS_RESIDENT (handles)) 2322 { 2323 handles = handles->next; 2324 } 2325 2326 /* close all modules */ 2327 for (level = 1; handles; ++level) 2328 { 2329 lt_dlhandle cur = handles; 2330 int saw_nonresident = 0; 2331 2332 while (cur) 2333 { 2334 lt_dlhandle tmp = cur; 2335 cur = cur->next; 2336 if (!LT_DLIS_RESIDENT (tmp)) 2337 saw_nonresident = 1; 2338 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) 2339 { 2340 if (lt_dlclose (tmp)) 2341 { 2342 ++errors; 2343 } 2344 } 2345 } 2346 /* done if only resident modules are left */ 2347 if (!saw_nonresident) 2348 break; 2349 } 2350 2351 /* close all loaders */ 2352 while (loader) 2353 { 2354 lt_dlloader *next = loader->next; 2355 lt_user_data data = loader->dlloader_data; 2356 if (loader->dlloader_exit && loader->dlloader_exit (data)) 2357 { 2358 ++errors; 2359 } 2360 2361 LT_DLMEM_REASSIGN (loader, next); 2362 } 2363 loaders = 0; 2364 } 2365 2366 done: 2367 LT_DLMUTEX_UNLOCK (); 2368 return errors; 2369} 2370 2371static int 2372tryall_dlopen (handle, filename) 2373 lt_dlhandle *handle; 2374 const char *filename; 2375{ 2376 lt_dlhandle cur; 2377 lt_dlloader *loader; 2378 const char *saved_error; 2379 int errors = 0; 2380 2381 LT_DLMUTEX_GETERROR (saved_error); 2382 LT_DLMUTEX_LOCK (); 2383 2384 cur = handles; 2385 loader = loaders; 2386 2387 /* check whether the module was already opened */ 2388 while (cur) 2389 { 2390 /* try to dlopen the program itself? */ 2391 if (!cur->info.filename && !filename) 2392 { 2393 break; 2394 } 2395 2396 if (cur->info.filename && filename 2397 && strcmp (cur->info.filename, filename) == 0) 2398 { 2399 break; 2400 } 2401 2402 cur = cur->next; 2403 } 2404 2405 if (cur) 2406 { 2407 ++cur->info.ref_count; 2408 *handle = cur; 2409 goto done; 2410 } 2411 2412 cur = *handle; 2413 if (filename) 2414 { 2415 /* Comment out the check of file permissions using access. 2416 This call seems to always return -1 with error EACCES. 2417 */ 2418 /* We need to catch missing file errors early so that 2419 file_not_found() can detect what happened. 2420 if (access (filename, R_OK) != 0) 2421 { 2422 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 2423 ++errors; 2424 goto done; 2425 } */ 2426 2427 cur->info.filename = lt_estrdup (filename); 2428 if (!cur->info.filename) 2429 { 2430 ++errors; 2431 goto done; 2432 } 2433 } 2434 else 2435 { 2436 cur->info.filename = 0; 2437 } 2438 2439 while (loader) 2440 { 2441 lt_user_data data = loader->dlloader_data; 2442 2443 cur->module = loader->module_open (data, filename); 2444 2445 if (cur->module != 0) 2446 { 2447 break; 2448 } 2449 loader = loader->next; 2450 } 2451 2452 if (!loader) 2453 { 2454 LT_DLFREE (cur->info.filename); 2455 ++errors; 2456 goto done; 2457 } 2458 2459 cur->loader = loader; 2460 LT_DLMUTEX_SETERROR (saved_error); 2461 2462 done: 2463 LT_DLMUTEX_UNLOCK (); 2464 2465 return errors; 2466} 2467 2468static int 2469tryall_dlopen_module (handle, prefix, dirname, dlname) 2470 lt_dlhandle *handle; 2471 const char *prefix; 2472 const char *dirname; 2473 const char *dlname; 2474{ 2475 int error = 0; 2476 char *filename = 0; 2477 size_t filename_len = 0; 2478 size_t dirname_len = LT_STRLEN (dirname); 2479 2480 assert (handle); 2481 assert (dirname); 2482 assert (dlname); 2483#ifdef LT_DIRSEP_CHAR 2484 /* Only canonicalized names (i.e. with DIRSEP chars already converted) 2485 should make it into this function: */ 2486 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); 2487#endif 2488 2489 if (dirname_len > 0) 2490 if (dirname[dirname_len -1] == '/') 2491 --dirname_len; 2492 filename_len = dirname_len + 1 + LT_STRLEN (dlname); 2493 2494 /* Allocate memory, and combine DIRNAME and MODULENAME into it. 2495 The PREFIX (if any) is handled below. */ 2496 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); 2497 if (!filename) 2498 return 1; 2499 2500 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); 2501 2502 /* Now that we have combined DIRNAME and MODULENAME, if there is 2503 also a PREFIX to contend with, simply recurse with the arguments 2504 shuffled. Otherwise, attempt to open FILENAME as a module. */ 2505 if (prefix) 2506 { 2507 error += tryall_dlopen_module (handle, 2508 (const char *) 0, prefix, filename); 2509 } 2510 else if (tryall_dlopen (handle, filename) != 0) 2511 { 2512 ++error; 2513 } 2514 2515 LT_DLFREE (filename); 2516 return error; 2517} 2518 2519static int 2520find_module (handle, dir, libdir, dlname, old_name, installed) 2521 lt_dlhandle *handle; 2522 const char *dir; 2523 const char *libdir; 2524 const char *dlname; 2525 const char *old_name; 2526 int installed; 2527{ 2528 /* Try to open the old library first; if it was dlpreopened, 2529 we want the preopened version of it, even if a dlopenable 2530 module is available. */ 2531 if (old_name && tryall_dlopen (handle, old_name) == 0) 2532 { 2533 return 0; 2534 } 2535 2536 /* Try to open the dynamic library. */ 2537 if (dlname) 2538 { 2539 /* try to open the installed module */ 2540 if (installed && libdir) 2541 { 2542 if (tryall_dlopen_module (handle, 2543 (const char *) 0, libdir, dlname) == 0) 2544 return 0; 2545 } 2546 2547 /* try to open the not-installed module */ 2548 if (!installed) 2549 { 2550 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) 2551 return 0; 2552 } 2553 2554 /* maybe it was moved to another directory */ 2555 { 2556 if (tryall_dlopen_module (handle, 2557 (const char *) 0, dir, dlname) == 0) 2558 return 0; 2559 } 2560 } 2561 2562 return 1; 2563} 2564 2565 2566static int 2567canonicalize_path (path, pcanonical) 2568 const char *path; 2569 char **pcanonical; 2570{ 2571 char *canonical = 0; 2572 2573 assert (path && *path); 2574 assert (pcanonical); 2575 2576 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); 2577 if (!canonical) 2578 return 1; 2579 2580 { 2581 size_t dest = 0; 2582 size_t src; 2583 for (src = 0; path[src] != LT_EOS_CHAR; ++src) 2584 { 2585 /* Path separators are not copied to the beginning or end of 2586 the destination, or if another separator would follow 2587 immediately. */ 2588 if (path[src] == LT_PATHSEP_CHAR) 2589 { 2590 if ((dest == 0) 2591 || (path[1+ src] == LT_PATHSEP_CHAR) 2592 || (path[1+ src] == LT_EOS_CHAR)) 2593 continue; 2594 } 2595 2596 /* Anything other than a directory separator is copied verbatim. */ 2597 if ((path[src] != '/') 2598#ifdef LT_DIRSEP_CHAR 2599 && (path[src] != LT_DIRSEP_CHAR) 2600#endif 2601 ) 2602 { 2603 canonical[dest++] = path[src]; 2604 } 2605 /* Directory separators are converted and copied only if they are 2606 not at the end of a path -- i.e. before a path separator or 2607 NULL terminator. */ 2608 else if ((path[1+ src] != LT_PATHSEP_CHAR) 2609 && (path[1+ src] != LT_EOS_CHAR) 2610#ifdef LT_DIRSEP_CHAR 2611 && (path[1+ src] != LT_DIRSEP_CHAR) 2612#endif 2613 && (path[1+ src] != '/')) 2614 { 2615 canonical[dest++] = '/'; 2616 } 2617 } 2618 2619 /* Add an end-of-string marker at the end. */ 2620 canonical[dest] = LT_EOS_CHAR; 2621 } 2622 2623 /* Assign new value. */ 2624 *pcanonical = canonical; 2625 2626 return 0; 2627} 2628 2629static int 2630argzize_path (path, pargz, pargz_len) 2631 const char *path; 2632 char **pargz; 2633 size_t *pargz_len; 2634{ 2635 error_t error; 2636 2637 assert (path); 2638 assert (pargz); 2639 assert (pargz_len); 2640 2641 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) 2642 { 2643 switch (error) 2644 { 2645 case ENOMEM: 2646 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 2647 break; 2648 default: 2649 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); 2650 break; 2651 } 2652 2653 return 1; 2654 } 2655 2656 return 0; 2657} 2658 2659/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element 2660 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns 2661 non-zero or all elements are exhausted. If BASE_NAME is non-NULL, 2662 it is appended to each SEARCH_PATH element before FUNC is called. */ 2663static int 2664foreach_dirinpath (search_path, base_name, func, data1, data2) 2665 const char *search_path; 2666 const char *base_name; 2667 foreach_callback_func *func; 2668 lt_ptr data1; 2669 lt_ptr data2; 2670{ 2671 int result = 0; 2672 int filenamesize = 0; 2673 size_t lenbase = LT_STRLEN (base_name); 2674 size_t argz_len = 0; 2675 char *argz = 0; 2676 char *filename = 0; 2677 char *canonical = 0; 2678 2679 LT_DLMUTEX_LOCK (); 2680 2681 if (!search_path || !*search_path) 2682 { 2683 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 2684 goto cleanup; 2685 } 2686 2687 if (canonicalize_path (search_path, &canonical) != 0) 2688 goto cleanup; 2689 2690 if (argzize_path (canonical, &argz, &argz_len) != 0) 2691 goto cleanup; 2692 2693 { 2694 char *dir_name = 0; 2695 while ((dir_name = argz_next (argz, argz_len, dir_name))) 2696 { 2697 size_t lendir = LT_STRLEN (dir_name); 2698 2699 if (lendir +1 +lenbase >= filenamesize) 2700 { 2701 LT_DLFREE (filename); 2702 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ 2703 filename = LT_EMALLOC (char, filenamesize); 2704 if (!filename) 2705 goto cleanup; 2706 } 2707 2708 assert (filenamesize > lendir); 2709 strcpy (filename, dir_name); 2710 2711 if (base_name && *base_name) 2712 { 2713 if (filename[lendir -1] != '/') 2714 filename[lendir++] = '/'; 2715 strcpy (filename +lendir, base_name); 2716 } 2717 2718 if ((result = (*func) (filename, data1, data2))) 2719 { 2720 break; 2721 } 2722 } 2723 } 2724 2725 cleanup: 2726 LT_DLFREE (argz); 2727 LT_DLFREE (canonical); 2728 LT_DLFREE (filename); 2729 2730 LT_DLMUTEX_UNLOCK (); 2731 2732 return result; 2733} 2734 2735/* If FILEPATH can be opened, store the name of the directory component 2736 in DATA1, and the opened FILE* structure address in DATA2. Otherwise 2737 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ 2738static int 2739find_file_callback (filename, data1, data2) 2740 char *filename; 2741 lt_ptr data1; 2742 lt_ptr data2; 2743{ 2744 char **pdir = (char **) data1; 2745 FILE **pfile = (FILE **) data2; 2746 int is_done = 0; 2747 2748 assert (filename && *filename); 2749 assert (pdir); 2750 assert (pfile); 2751 2752 if ((*pfile = fopen (filename, LT_READTEXT_MODE))) 2753 { 2754 char *dirend = strrchr (filename, '/'); 2755 2756 if (dirend > filename) 2757 *dirend = LT_EOS_CHAR; 2758 2759 LT_DLFREE (*pdir); 2760 *pdir = lt_estrdup (filename); 2761 is_done = (*pdir == 0) ? -1 : 1; 2762 } 2763 2764 return is_done; 2765} 2766 2767static FILE * 2768find_file (search_path, base_name, pdir) 2769 const char *search_path; 2770 const char *base_name; 2771 char **pdir; 2772{ 2773 FILE *file = 0; 2774 2775 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); 2776 2777 return file; 2778} 2779 2780static int 2781find_handle_callback (filename, data, ignored) 2782 char *filename; 2783 lt_ptr data; 2784 lt_ptr ignored; 2785{ 2786 lt_dlhandle *handle = (lt_dlhandle *) data; 2787 int notfound = access (filename, R_OK); 2788 2789 /* Bail out if file cannot be read... */ 2790 if (notfound) 2791 return 0; 2792 2793 /* Try to dlopen the file, but do not continue searching in any 2794 case. */ 2795 if (tryall_dlopen (handle, filename) != 0) 2796 *handle = 0; 2797 2798 return 1; 2799} 2800 2801/* If HANDLE was found return it, otherwise return 0. If HANDLE was 2802 found but could not be opened, *HANDLE will be set to 0. */ 2803static lt_dlhandle * 2804find_handle (search_path, base_name, handle) 2805 const char *search_path; 2806 const char *base_name; 2807 lt_dlhandle *handle; 2808{ 2809 if (!search_path) 2810 return 0; 2811 2812 if (!foreach_dirinpath (search_path, base_name, find_handle_callback, 2813 handle, 0)) 2814 return 0; 2815 2816 return handle; 2817} 2818 2819static int 2820load_deplibs (handle, deplibs) 2821 lt_dlhandle handle; 2822 char *deplibs; 2823{ 2824#if LTDL_DLOPEN_DEPLIBS 2825 char *p, *save_search_path = 0; 2826 int depcount = 0; 2827 int i; 2828 char **names = 0; 2829#endif 2830 int errors = 0; 2831 2832 handle->depcount = 0; 2833 2834#if LTDL_DLOPEN_DEPLIBS 2835 if (!deplibs) 2836 { 2837 return errors; 2838 } 2839 ++errors; 2840 2841 LT_DLMUTEX_LOCK (); 2842 if (user_search_path) 2843 { 2844 save_search_path = lt_estrdup (user_search_path); 2845 if (!save_search_path) 2846 goto cleanup; 2847 } 2848 2849 /* extract search paths and count deplibs */ 2850 p = deplibs; 2851 while (*p) 2852 { 2853 if (!isspace ((int) *p)) 2854 { 2855 char *end = p+1; 2856 while (*end && !isspace((int) *end)) 2857 { 2858 ++end; 2859 } 2860 2861 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) 2862 { 2863 char save = *end; 2864 *end = 0; /* set a temporary string terminator */ 2865 if (lt_dladdsearchdir(p+2)) 2866 { 2867 goto cleanup; 2868 } 2869 *end = save; 2870 } 2871 else 2872 { 2873 ++depcount; 2874 } 2875 2876 p = end; 2877 } 2878 else 2879 { 2880 ++p; 2881 } 2882 } 2883 2884 /* restore the old search path */ 2885 LT_DLFREE (user_search_path); 2886 user_search_path = save_search_path; 2887 2888 LT_DLMUTEX_UNLOCK (); 2889 2890 if (!depcount) 2891 { 2892 errors = 0; 2893 goto cleanup; 2894 } 2895 2896 names = LT_EMALLOC (char *, depcount * sizeof (char*)); 2897 if (!names) 2898 goto cleanup; 2899 2900 /* now only extract the actual deplibs */ 2901 depcount = 0; 2902 p = deplibs; 2903 while (*p) 2904 { 2905 if (isspace ((int) *p)) 2906 { 2907 ++p; 2908 } 2909 else 2910 { 2911 char *end = p+1; 2912 while (*end && !isspace ((int) *end)) 2913 { 2914 ++end; 2915 } 2916 2917 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) 2918 { 2919 char *name; 2920 char save = *end; 2921 *end = 0; /* set a temporary string terminator */ 2922 if (strncmp(p, "-l", 2) == 0) 2923 { 2924 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); 2925 name = LT_EMALLOC (char, 1+ name_len); 2926 if (name) 2927 sprintf (name, "lib%s", p+2); 2928 } 2929 else 2930 name = lt_estrdup(p); 2931 2932 if (!name) 2933 goto cleanup_names; 2934 2935 names[depcount++] = name; 2936 *end = save; 2937 } 2938 p = end; 2939 } 2940 } 2941 2942 /* load the deplibs (in reverse order) 2943 At this stage, don't worry if the deplibs do not load correctly, 2944 they may already be statically linked into the loading application 2945 for instance. There will be a more enlightening error message 2946 later on if the loaded module cannot resolve all of its symbols. */ 2947 if (depcount) 2948 { 2949 int j = 0; 2950 2951 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); 2952 if (!handle->deplibs) 2953 goto cleanup; 2954 2955 for (i = 0; i < depcount; ++i) 2956 { 2957 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); 2958 if (handle->deplibs[j]) 2959 { 2960 ++j; 2961 } 2962 } 2963 2964 handle->depcount = j; /* Number of successfully loaded deplibs */ 2965 errors = 0; 2966 } 2967 2968 cleanup_names: 2969 for (i = 0; i < depcount; ++i) 2970 { 2971 LT_DLFREE (names[i]); 2972 } 2973 2974 cleanup: 2975 LT_DLFREE (names); 2976#endif 2977 2978 return errors; 2979} 2980 2981static int 2982unload_deplibs (handle) 2983 lt_dlhandle handle; 2984{ 2985 int i; 2986 int errors = 0; 2987 2988 if (handle->depcount) 2989 { 2990 for (i = 0; i < handle->depcount; ++i) 2991 { 2992 if (!LT_DLIS_RESIDENT (handle->deplibs[i])) 2993 { 2994 errors += lt_dlclose (handle->deplibs[i]); 2995 } 2996 } 2997 } 2998 2999 return errors; 3000} 3001 3002static int 3003trim (dest, str) 3004 char **dest; 3005 const char *str; 3006{ 3007 /* remove the leading and trailing "'" from str 3008 and store the result in dest */ 3009 const char *end = strrchr (str, '\''); 3010 size_t len = LT_STRLEN (str); 3011 char *tmp; 3012 3013 LT_DLFREE (*dest); 3014 3015 if (!end) 3016 return 1; 3017 3018 if (len > 3 && str[0] == '\'') 3019 { 3020 tmp = LT_EMALLOC (char, end - str); 3021 if (!tmp) 3022 return 1; 3023 3024 strncpy(tmp, &str[1], (end - str) - 1); 3025 tmp[len-3] = LT_EOS_CHAR; 3026 *dest = tmp; 3027 } 3028 else 3029 { 3030 *dest = 0; 3031 } 3032 3033 return 0; 3034} 3035 3036static int 3037free_vars (dlname, oldname, libdir, deplibs) 3038 char *dlname; 3039 char *oldname; 3040 char *libdir; 3041 char *deplibs; 3042{ 3043 LT_DLFREE (dlname); 3044 LT_DLFREE (oldname); 3045 LT_DLFREE (libdir); 3046 LT_DLFREE (deplibs); 3047 3048 return 0; 3049} 3050 3051static int 3052try_dlopen (phandle, filename) 3053 lt_dlhandle *phandle; 3054 const char *filename; 3055{ 3056 const char * ext = 0; 3057 const char * saved_error = 0; 3058 char * canonical = 0; 3059 char * base_name = 0; 3060 char * dir = 0; 3061 char * name = 0; 3062 int errors = 0; 3063 lt_dlhandle newhandle; 3064 3065 assert (phandle); 3066 assert (*phandle == 0); 3067 3068 LT_DLMUTEX_GETERROR (saved_error); 3069 3070 /* dlopen self? */ 3071 if (!filename) 3072 { 3073 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 3074 if (*phandle == 0) 3075 return 1; 3076 3077 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); 3078 newhandle = *phandle; 3079 3080 /* lt_dlclose()ing yourself is very bad! Disallow it. */ 3081 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); 3082 3083 if (tryall_dlopen (&newhandle, 0) != 0) 3084 { 3085 LT_DLFREE (*phandle); 3086 return 1; 3087 } 3088 3089 goto register_handle; 3090 } 3091 3092 assert (filename && *filename); 3093 3094 /* Doing this immediately allows internal functions to safely 3095 assume only canonicalized paths are passed. */ 3096 if (canonicalize_path (filename, &canonical) != 0) 3097 { 3098 ++errors; 3099 goto cleanup; 3100 } 3101 3102 /* If the canonical module name is a path (relative or absolute) 3103 then split it into a directory part and a name part. */ 3104 base_name = strrchr (canonical, '/'); 3105 if (base_name) 3106 { 3107 size_t dirlen = (1+ base_name) - canonical; 3108 3109 dir = LT_EMALLOC (char, 1+ dirlen); 3110 if (!dir) 3111 { 3112 ++errors; 3113 goto cleanup; 3114 } 3115 3116 strncpy (dir, canonical, dirlen); 3117 dir[dirlen] = LT_EOS_CHAR; 3118 3119 ++base_name; 3120 } 3121 else 3122 base_name = canonical; 3123 3124 assert (base_name && *base_name); 3125 3126 /* Check whether we are opening a libtool module (.la extension). */ 3127 ext = strrchr (base_name, '.'); 3128 if (ext && strcmp (ext, archive_ext) == 0) 3129 { 3130 /* this seems to be a libtool module */ 3131 FILE * file = 0; 3132 char * dlname = 0; 3133 char * old_name = 0; 3134 char * libdir = 0; 3135 char * deplibs = 0; 3136 char * line = 0; 3137 size_t line_len; 3138 3139 /* if we can't find the installed flag, it is probably an 3140 installed libtool archive, produced with an old version 3141 of libtool */ 3142 int installed = 1; 3143 3144 /* extract the module name from the file name */ 3145 name = LT_EMALLOC (char, ext - base_name + 1); 3146 if (!name) 3147 { 3148 ++errors; 3149 goto cleanup; 3150 } 3151 3152 /* canonicalize the module name */ 3153 { 3154 size_t i; 3155 for (i = 0; i < ext - base_name; ++i) 3156 { 3157 if (isalnum ((int)(base_name[i]))) 3158 { 3159 name[i] = base_name[i]; 3160 } 3161 else 3162 { 3163 name[i] = '_'; 3164 } 3165 } 3166 name[ext - base_name] = LT_EOS_CHAR; 3167 } 3168 3169 /* Now try to open the .la file. If there is no directory name 3170 component, try to find it first in user_search_path and then other 3171 prescribed paths. Otherwise (or in any case if the module was not 3172 yet found) try opening just the module name as passed. */ 3173 if (!dir) 3174 { 3175 const char *search_path; 3176 3177 LT_DLMUTEX_LOCK (); 3178 search_path = user_search_path; 3179 if (search_path) 3180 file = find_file (user_search_path, base_name, &dir); 3181 LT_DLMUTEX_UNLOCK (); 3182 3183 if (!file) 3184 { 3185 search_path = getenv (LTDL_SEARCHPATH_VAR); 3186 if (search_path) 3187 file = find_file (search_path, base_name, &dir); 3188 } 3189 3190#ifdef LTDL_SHLIBPATH_VAR 3191 if (!file) 3192 { 3193 search_path = getenv (LTDL_SHLIBPATH_VAR); 3194 if (search_path) 3195 file = find_file (search_path, base_name, &dir); 3196 } 3197#endif 3198#ifdef LTDL_SYSSEARCHPATH 3199 if (!file && sys_search_path) 3200 { 3201 file = find_file (sys_search_path, base_name, &dir); 3202 } 3203#endif 3204 } 3205 if (!file) 3206 { 3207 file = fopen (filename, LT_READTEXT_MODE); 3208 } 3209 3210 /* If we didn't find the file by now, it really isn't there. Set 3211 the status flag, and bail out. */ 3212 if (!file) 3213 { 3214 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 3215 ++errors; 3216 goto cleanup; 3217 } 3218 3219 line_len = LT_FILENAME_MAX; 3220 line = LT_EMALLOC (char, line_len); 3221 if (!line) 3222 { 3223 fclose (file); 3224 ++errors; 3225 goto cleanup; 3226 } 3227 3228 /* read the .la file */ 3229 while (!feof (file)) 3230 { 3231 if (!fgets (line, (int) line_len, file)) 3232 { 3233 break; 3234 } 3235 3236 /* Handle the case where we occasionally need to read a line 3237 that is longer than the initial buffer size. */ 3238 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file))) 3239 { 3240 line = LT_DLREALLOC (char, line, line_len *2); 3241 if (!fgets (&line[line_len -1], (int) line_len +1, file)) 3242 { 3243 break; 3244 } 3245 line_len *= 2; 3246 } 3247 3248 if (line[0] == '\n' || line[0] == '#') 3249 { 3250 continue; 3251 } 3252 3253#undef STR_DLNAME 3254#define STR_DLNAME "dlname=" 3255 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) 3256 { 3257 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); 3258 } 3259 3260#undef STR_OLD_LIBRARY 3261#define STR_OLD_LIBRARY "old_library=" 3262 else if (strncmp (line, STR_OLD_LIBRARY, 3263 sizeof (STR_OLD_LIBRARY) - 1) == 0) 3264 { 3265 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); 3266 } 3267#undef STR_LIBDIR 3268#define STR_LIBDIR "libdir=" 3269 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) 3270 { 3271 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); 3272 } 3273 3274#undef STR_DL_DEPLIBS 3275#define STR_DL_DEPLIBS "dependency_libs=" 3276 else if (strncmp (line, STR_DL_DEPLIBS, 3277 sizeof (STR_DL_DEPLIBS) - 1) == 0) 3278 { 3279 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); 3280 } 3281 else if (strcmp (line, "installed=yes\n") == 0) 3282 { 3283 installed = 1; 3284 } 3285 else if (strcmp (line, "installed=no\n") == 0) 3286 { 3287 installed = 0; 3288 } 3289 3290#undef STR_LIBRARY_NAMES 3291#define STR_LIBRARY_NAMES "library_names=" 3292 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, 3293 sizeof (STR_LIBRARY_NAMES) - 1) == 0) 3294 { 3295 char *last_libname; 3296 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); 3297 if (!errors 3298 && dlname 3299 && (last_libname = strrchr (dlname, ' ')) != 0) 3300 { 3301 last_libname = lt_estrdup (last_libname + 1); 3302 if (!last_libname) 3303 { 3304 ++errors; 3305 goto cleanup; 3306 } 3307 LT_DLMEM_REASSIGN (dlname, last_libname); 3308 } 3309 } 3310 3311 if (errors) 3312 break; 3313 } 3314 3315 fclose (file); 3316 LT_DLFREE (line); 3317 3318 /* allocate the handle */ 3319 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 3320 if (*phandle == 0) 3321 ++errors; 3322 3323 if (errors) 3324 { 3325 free_vars (dlname, old_name, libdir, deplibs); 3326 LT_DLFREE (*phandle); 3327 goto cleanup; 3328 } 3329 3330 assert (*phandle); 3331 3332 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); 3333 if (load_deplibs (*phandle, deplibs) == 0) 3334 { 3335 newhandle = *phandle; 3336 /* find_module may replace newhandle */ 3337 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) 3338 { 3339 unload_deplibs (*phandle); 3340 ++errors; 3341 } 3342 } 3343 else 3344 { 3345 ++errors; 3346 } 3347 3348 free_vars (dlname, old_name, libdir, deplibs); 3349 if (errors) 3350 { 3351 LT_DLFREE (*phandle); 3352 goto cleanup; 3353 } 3354 3355 if (*phandle != newhandle) 3356 { 3357 unload_deplibs (*phandle); 3358 } 3359 } 3360 else 3361 { 3362 /* not a libtool module */ 3363 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); 3364 if (*phandle == 0) 3365 { 3366 ++errors; 3367 goto cleanup; 3368 } 3369 3370 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); 3371 newhandle = *phandle; 3372 3373 /* If the module has no directory name component, try to find it 3374 first in user_search_path and then other prescribed paths. 3375 Otherwise (or in any case if the module was not yet found) try 3376 opening just the module name as passed. */ 3377 if ((dir || (!find_handle (user_search_path, base_name, &newhandle) 3378 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, 3379 &newhandle) 3380#ifdef LTDL_SHLIBPATH_VAR 3381 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, 3382 &newhandle) 3383#endif 3384#ifdef LTDL_SYSSEARCHPATH 3385 && !find_handle (sys_search_path, base_name, &newhandle) 3386#endif 3387 ))) 3388 { 3389 if (tryall_dlopen (&newhandle, filename) != 0) 3390 { 3391 newhandle = NULL; 3392 } 3393 } 3394 3395 if (!newhandle) 3396 { 3397 LT_DLFREE (*phandle); 3398 ++errors; 3399 goto cleanup; 3400 } 3401 } 3402 3403 register_handle: 3404 LT_DLMEM_REASSIGN (*phandle, newhandle); 3405 3406 if ((*phandle)->info.ref_count == 0) 3407 { 3408 (*phandle)->info.ref_count = 1; 3409 LT_DLMEM_REASSIGN ((*phandle)->info.name, name); 3410 3411 LT_DLMUTEX_LOCK (); 3412 (*phandle)->next = handles; 3413 handles = *phandle; 3414 LT_DLMUTEX_UNLOCK (); 3415 } 3416 3417 LT_DLMUTEX_SETERROR (saved_error); 3418 3419 cleanup: 3420 LT_DLFREE (dir); 3421 LT_DLFREE (name); 3422 LT_DLFREE (canonical); 3423 3424 return errors; 3425} 3426 3427lt_dlhandle 3428lt_dlopen (filename) 3429 const char *filename; 3430{ 3431 lt_dlhandle handle = 0; 3432 3433 /* Just incase we missed a code path in try_dlopen() that reports 3434 an error, but forgets to reset handle... */ 3435 if (try_dlopen (&handle, filename) != 0) 3436 return 0; 3437 3438 return handle; 3439} 3440 3441/* If the last error messge store was `FILE_NOT_FOUND', then return 3442 non-zero. */ 3443static int 3444file_not_found () 3445{ 3446 const char *error = 0; 3447 3448 LT_DLMUTEX_GETERROR (error); 3449 if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) 3450 return 1; 3451 3452 return 0; 3453} 3454 3455/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to 3456 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, 3457 and if a file is still not found try again with SHLIB_EXT appended 3458 instead. */ 3459lt_dlhandle 3460lt_dlopenext (filename) 3461 const char *filename; 3462{ 3463 lt_dlhandle handle = 0; 3464 char * tmp = 0; 3465 char * ext = 0; 3466 size_t len; 3467 int errors = 0; 3468 3469 if (!filename) 3470 { 3471 return lt_dlopen (filename); 3472 } 3473 3474 assert (filename); 3475 3476 len = LT_STRLEN (filename); 3477 ext = strrchr (filename, '.'); 3478 3479 /* If FILENAME already bears a suitable extension, there is no need 3480 to try appending additional extensions. */ 3481 if (ext && ((strcmp (ext, archive_ext) == 0) 3482#ifdef LTDL_SHLIB_EXT 3483 || (strcmp (ext, shlib_ext) == 0) 3484#endif 3485 )) 3486 { 3487 return lt_dlopen (filename); 3488 } 3489 3490 /* First try appending ARCHIVE_EXT. */ 3491 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); 3492 if (!tmp) 3493 return 0; 3494 3495 strcpy (tmp, filename); 3496 strcat (tmp, archive_ext); 3497 errors = try_dlopen (&handle, tmp); 3498 3499 /* If we found FILENAME, stop searching -- whether we were able to 3500 load the file as a module or not. If the file exists but loading 3501 failed, it is better to return an error message here than to 3502 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not 3503 in the module search path. */ 3504 if (handle || ((errors > 0) && !file_not_found ())) 3505 { 3506 LT_DLFREE (tmp); 3507 return handle; 3508 } 3509 3510#ifdef LTDL_SHLIB_EXT 3511 /* Try appending SHLIB_EXT. */ 3512 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) 3513 { 3514 LT_DLFREE (tmp); 3515 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); 3516 if (!tmp) 3517 return 0; 3518 3519 strcpy (tmp, filename); 3520 } 3521 else 3522 { 3523 tmp[len] = LT_EOS_CHAR; 3524 } 3525 3526 strcat(tmp, shlib_ext); 3527 errors = try_dlopen (&handle, tmp); 3528 3529 /* As before, if the file was found but loading failed, return now 3530 with the current error message. */ 3531 if (handle || ((errors > 0) && !file_not_found ())) 3532 { 3533 LT_DLFREE (tmp); 3534 return handle; 3535 } 3536#endif 3537 3538 /* Still here? Then we really did fail to locate any of the file 3539 names we tried. */ 3540 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); 3541 LT_DLFREE (tmp); 3542 return 0; 3543} 3544 3545 3546static int 3547lt_argz_insert (pargz, pargz_len, before, entry) 3548 char **pargz; 3549 size_t *pargz_len; 3550 char *before; 3551 const char *entry; 3552{ 3553 error_t error; 3554 3555 if ((error = argz_insert (pargz, pargz_len, before, entry))) 3556 { 3557 switch (error) 3558 { 3559 case ENOMEM: 3560 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); 3561 break; 3562 default: 3563 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); 3564 break; 3565 } 3566 return 1; 3567 } 3568 3569 return 0; 3570} 3571 3572static int 3573lt_argz_insertinorder (pargz, pargz_len, entry) 3574 char **pargz; 3575 size_t *pargz_len; 3576 const char *entry; 3577{ 3578 char *before = 0; 3579 3580 assert (pargz); 3581 assert (pargz_len); 3582 assert (entry && *entry); 3583 3584 if (*pargz) 3585 while ((before = argz_next (*pargz, *pargz_len, before))) 3586 { 3587 int cmp = strcmp (entry, before); 3588 3589 if (cmp < 0) break; 3590 if (cmp == 0) return 0; /* No duplicates! */ 3591 } 3592 3593 return lt_argz_insert (pargz, pargz_len, before, entry); 3594} 3595 3596static int 3597lt_argz_insertdir (pargz, pargz_len, dirnam, dp) 3598 char **pargz; 3599 size_t *pargz_len; 3600 const char *dirnam; 3601 struct dirent *dp; 3602{ 3603 char *buf = 0; 3604 size_t buf_len = 0; 3605 char *end = 0; 3606 size_t end_offset = 0; 3607 size_t dir_len = 0; 3608 int errors = 0; 3609 3610 assert (pargz); 3611 assert (pargz_len); 3612 assert (dp); 3613 3614 dir_len = LT_STRLEN (dirnam); 3615 end = dp->d_name + LT_D_NAMLEN(dp); 3616 3617 /* Ignore version numbers. */ 3618 { 3619 char *p; 3620 for (p = end; p -1 > dp->d_name; --p) 3621 if (strchr (".0123456789", p[-1]) == 0) 3622 break; 3623 3624 if (*p == '.') 3625 end = p; 3626 } 3627 3628 /* Ignore filename extension. */ 3629 { 3630 char *p; 3631 for (p = end -1; p > dp->d_name; --p) 3632 if (*p == '.') 3633 { 3634 end = p; 3635 break; 3636 } 3637 } 3638 3639 /* Prepend the directory name. */ 3640 end_offset = end - dp->d_name; 3641 buf_len = dir_len + 1+ end_offset; 3642 buf = LT_EMALLOC (char, 1+ buf_len); 3643 if (!buf) 3644 return ++errors; 3645 3646 assert (buf); 3647 3648 strcpy (buf, dirnam); 3649 strcat (buf, "/"); 3650 strncat (buf, dp->d_name, end_offset); 3651 buf[buf_len] = LT_EOS_CHAR; 3652 3653 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ 3654 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) 3655 ++errors; 3656 3657 LT_DLFREE (buf); 3658 3659 return errors; 3660} 3661 3662static int 3663list_files_by_dir (dirnam, pargz, pargz_len) 3664 const char *dirnam; 3665 char **pargz; 3666 size_t *pargz_len; 3667{ 3668 DIR *dirp = 0; 3669 int errors = 0; 3670 3671 assert (dirnam && *dirnam); 3672 assert (pargz); 3673 assert (pargz_len); 3674 assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); 3675 3676 dirp = opendir (dirnam); 3677 if (dirp) 3678 { 3679 struct dirent *dp = 0; 3680 3681 while ((dp = readdir (dirp))) 3682 if (dp->d_name[0] != '.') 3683 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) 3684 { 3685 ++errors; 3686 break; 3687 } 3688 3689 closedir (dirp); 3690 } 3691 else 3692 ++errors; 3693 3694 return errors; 3695} 3696 3697 3698/* If there are any files in DIRNAME, call the function passed in 3699 DATA1 (with the name of each file and DATA2 as arguments). */ 3700static int 3701foreachfile_callback (dirname, data1, data2) 3702 char *dirname; 3703 lt_ptr data1; 3704 lt_ptr data2; 3705{ 3706 int (*func) LT_PARAMS((const char *filename, lt_ptr data)) 3707 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; 3708 3709 int is_done = 0; 3710 char *argz = 0; 3711 size_t argz_len = 0; 3712 3713 if (list_files_by_dir (dirname, &argz, &argz_len) != 0) 3714 goto cleanup; 3715 if (!argz) 3716 goto cleanup; 3717 3718 { 3719 char *filename = 0; 3720 while ((filename = argz_next (argz, argz_len, filename))) 3721 if ((is_done = (*func) (filename, data2))) 3722 break; 3723 } 3724 3725 cleanup: 3726 LT_DLFREE (argz); 3727 3728 return is_done; 3729} 3730 3731 3732/* Call FUNC for each unique extensionless file in SEARCH_PATH, along 3733 with DATA. The filenames passed to FUNC would be suitable for 3734 passing to lt_dlopenext. The extensions are stripped so that 3735 individual modules do not generate several entries (e.g. libfoo.la, 3736 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, 3737 then the same directories that lt_dlopen would search are examined. */ 3738int 3739lt_dlforeachfile (search_path, func, data) 3740 const char *search_path; 3741 int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); 3742 lt_ptr data; 3743{ 3744 int is_done = 0; 3745 3746 if (search_path) 3747 { 3748 /* If a specific path was passed, search only the directories 3749 listed in it. */ 3750 is_done = foreach_dirinpath (search_path, 0, 3751 foreachfile_callback, func, data); 3752 } 3753 else 3754 { 3755 /* Otherwise search the default paths. */ 3756 is_done = foreach_dirinpath (user_search_path, 0, 3757 foreachfile_callback, func, data); 3758 if (!is_done) 3759 { 3760 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, 3761 foreachfile_callback, func, data); 3762 } 3763 3764#ifdef LTDL_SHLIBPATH_VAR 3765 if (!is_done) 3766 { 3767 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, 3768 foreachfile_callback, func, data); 3769 } 3770#endif 3771#ifdef LTDL_SYSSEARCHPATH 3772 if (!is_done) 3773 { 3774 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, 3775 foreachfile_callback, func, data); 3776 } 3777#endif 3778 } 3779 3780 return is_done; 3781} 3782 3783int 3784lt_dlclose (handle) 3785 lt_dlhandle handle; 3786{ 3787 lt_dlhandle cur, last; 3788 int errors = 0; 3789 3790 LT_DLMUTEX_LOCK (); 3791 3792 /* check whether the handle is valid */ 3793 last = cur = handles; 3794 while (cur && handle != cur) 3795 { 3796 last = cur; 3797 cur = cur->next; 3798 } 3799 3800 if (!cur) 3801 { 3802 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3803 ++errors; 3804 goto done; 3805 } 3806 3807 handle->info.ref_count--; 3808 3809 /* Note that even with resident modules, we must track the ref_count 3810 correctly incase the user decides to reset the residency flag 3811 later (even though the API makes no provision for that at the 3812 moment). */ 3813 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) 3814 { 3815 lt_user_data data = handle->loader->dlloader_data; 3816 3817 if (handle != handles) 3818 { 3819 last->next = handle->next; 3820 } 3821 else 3822 { 3823 handles = handle->next; 3824 } 3825 3826 errors += handle->loader->module_close (data, handle->module); 3827 errors += unload_deplibs(handle); 3828 3829 /* It is up to the callers to free the data itself. */ 3830 LT_DLFREE (handle->caller_data); 3831 3832 LT_DLFREE (handle->info.filename); 3833 LT_DLFREE (handle->info.name); 3834 LT_DLFREE (handle); 3835 3836 goto done; 3837 } 3838 3839 if (LT_DLIS_RESIDENT (handle)) 3840 { 3841 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); 3842 ++errors; 3843 } 3844 3845 done: 3846 LT_DLMUTEX_UNLOCK (); 3847 3848 return errors; 3849} 3850 3851lt_ptr 3852lt_dlsym (handle, symbol) 3853 lt_dlhandle handle; 3854 const char *symbol; 3855{ 3856 size_t lensym; 3857 char lsym[LT_SYMBOL_LENGTH]; 3858 char *sym; 3859 lt_ptr address; 3860 lt_user_data data; 3861 3862 if (!handle) 3863 { 3864 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 3865 return 0; 3866 } 3867 3868 if (!symbol) 3869 { 3870 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); 3871 return 0; 3872 } 3873 3874 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) 3875 + LT_STRLEN (handle->info.name); 3876 3877 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) 3878 { 3879 sym = lsym; 3880 } 3881 else 3882 { 3883 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); 3884 if (!sym) 3885 { 3886 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); 3887 return 0; 3888 } 3889 } 3890 3891 data = handle->loader->dlloader_data; 3892 if (handle->info.name) 3893 { 3894 const char *saved_error; 3895 3896 LT_DLMUTEX_GETERROR (saved_error); 3897 3898 /* this is a libtool module */ 3899 if (handle->loader->sym_prefix) 3900 { 3901 strcpy(sym, handle->loader->sym_prefix); 3902 strcat(sym, handle->info.name); 3903 } 3904 else 3905 { 3906 strcpy(sym, handle->info.name); 3907 } 3908 3909 strcat(sym, "_LTX_"); 3910 strcat(sym, symbol); 3911 3912 /* try "modulename_LTX_symbol" */ 3913 address = handle->loader->find_sym (data, handle->module, sym); 3914 if (address) 3915 { 3916 if (sym != lsym) 3917 { 3918 LT_DLFREE (sym); 3919 } 3920 return address; 3921 } 3922 LT_DLMUTEX_SETERROR (saved_error); 3923 } 3924 3925 /* otherwise try "symbol" */ 3926 if (handle->loader->sym_prefix) 3927 { 3928 strcpy(sym, handle->loader->sym_prefix); 3929 strcat(sym, symbol); 3930 } 3931 else 3932 { 3933 strcpy(sym, symbol); 3934 } 3935 3936 address = handle->loader->find_sym (data, handle->module, sym); 3937 if (sym != lsym) 3938 { 3939 LT_DLFREE (sym); 3940 } 3941 3942 return address; 3943} 3944 3945const char * 3946lt_dlerror () 3947{ 3948 const char *error; 3949 3950 LT_DLMUTEX_GETERROR (error); 3951 LT_DLMUTEX_SETERROR (0); 3952 3953 return error ? error : NULL; 3954} 3955 3956static int 3957lt_dlpath_insertdir (ppath, before, dir) 3958 char **ppath; 3959 char *before; 3960 const char *dir; 3961{ 3962 int errors = 0; 3963 char *canonical = 0; 3964 char *argz = 0; 3965 size_t argz_len = 0; 3966 3967 assert (ppath); 3968 assert (dir && *dir); 3969 3970 if (canonicalize_path (dir, &canonical) != 0) 3971 { 3972 ++errors; 3973 goto cleanup; 3974 } 3975 3976 assert (canonical && *canonical); 3977 3978 /* If *PPATH is empty, set it to DIR. */ 3979 if (*ppath == 0) 3980 { 3981 assert (!before); /* BEFORE cannot be set without PPATH. */ 3982 assert (dir); /* Without DIR, don't call this function! */ 3983 3984 *ppath = lt_estrdup (dir); 3985 if (*ppath == 0) 3986 ++errors; 3987 3988 return errors; 3989 } 3990 3991 assert (ppath && *ppath); 3992 3993 if (argzize_path (*ppath, &argz, &argz_len) != 0) 3994 { 3995 ++errors; 3996 goto cleanup; 3997 } 3998 3999 /* Convert BEFORE into an equivalent offset into ARGZ. This only works 4000 if *PPATH is already canonicalized, and hence does not change length 4001 with respect to ARGZ. We canonicalize each entry as it is added to 4002 the search path, and don't call this function with (uncanonicalized) 4003 user paths, so this is a fair assumption. */ 4004 if (before) 4005 { 4006 assert (*ppath <= before); 4007 assert (before - *ppath <= strlen (*ppath)); 4008 4009 before = before - *ppath + argz; 4010 } 4011 4012 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) 4013 { 4014 ++errors; 4015 goto cleanup; 4016 } 4017 4018 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); 4019 LT_DLMEM_REASSIGN (*ppath, argz); 4020 4021 cleanup: 4022 LT_DLFREE (canonical); 4023 LT_DLFREE (argz); 4024 4025 return errors; 4026} 4027 4028int 4029lt_dladdsearchdir (search_dir) 4030 const char *search_dir; 4031{ 4032 int errors = 0; 4033 4034 if (search_dir && *search_dir) 4035 { 4036 LT_DLMUTEX_LOCK (); 4037 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) 4038 ++errors; 4039 LT_DLMUTEX_UNLOCK (); 4040 } 4041 4042 return errors; 4043} 4044 4045int 4046lt_dlinsertsearchdir (before, search_dir) 4047 const char *before; 4048 const char *search_dir; 4049{ 4050 int errors = 0; 4051 4052 if (before) 4053 { 4054 LT_DLMUTEX_LOCK (); 4055 if ((before < user_search_path) 4056 || (before >= user_search_path + LT_STRLEN (user_search_path))) 4057 { 4058 LT_DLMUTEX_UNLOCK (); 4059 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); 4060 return 1; 4061 } 4062 LT_DLMUTEX_UNLOCK (); 4063 } 4064 4065 if (search_dir && *search_dir) 4066 { 4067 LT_DLMUTEX_LOCK (); 4068 if (lt_dlpath_insertdir (&user_search_path, 4069 (char *) before, search_dir) != 0) 4070 { 4071 ++errors; 4072 } 4073 LT_DLMUTEX_UNLOCK (); 4074 } 4075 4076 return errors; 4077} 4078 4079int 4080lt_dlsetsearchpath (search_path) 4081 const char *search_path; 4082{ 4083 int errors = 0; 4084 4085 LT_DLMUTEX_LOCK (); 4086 LT_DLFREE (user_search_path); 4087 LT_DLMUTEX_UNLOCK (); 4088 4089 if (!search_path || !LT_STRLEN (search_path)) 4090 { 4091 return errors; 4092 } 4093 4094 LT_DLMUTEX_LOCK (); 4095 if (canonicalize_path (search_path, &user_search_path) != 0) 4096 ++errors; 4097 LT_DLMUTEX_UNLOCK (); 4098 4099 return errors; 4100} 4101 4102const char * 4103lt_dlgetsearchpath () 4104{ 4105 const char *saved_path; 4106 4107 LT_DLMUTEX_LOCK (); 4108 saved_path = user_search_path; 4109 LT_DLMUTEX_UNLOCK (); 4110 4111 return saved_path; 4112} 4113 4114int 4115lt_dlmakeresident (handle) 4116 lt_dlhandle handle; 4117{ 4118 int errors = 0; 4119 4120 if (!handle) 4121 { 4122 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 4123 ++errors; 4124 } 4125 else 4126 { 4127 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); 4128 } 4129 4130 return errors; 4131} 4132 4133int 4134lt_dlisresident (handle) 4135 lt_dlhandle handle; 4136{ 4137 if (!handle) 4138 { 4139 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 4140 return -1; 4141 } 4142 4143 return LT_DLIS_RESIDENT (handle); 4144} 4145 4146 4147 4148 4149/* --- MODULE INFORMATION --- */ 4150 4151const lt_dlinfo * 4152lt_dlgetinfo (handle) 4153 lt_dlhandle handle; 4154{ 4155 if (!handle) 4156 { 4157 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); 4158 return 0; 4159 } 4160 4161 return &(handle->info); 4162} 4163 4164lt_dlhandle 4165lt_dlhandle_next (place) 4166 lt_dlhandle place; 4167{ 4168 return place ? place->next : handles; 4169} 4170 4171int 4172lt_dlforeach (func, data) 4173 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); 4174 lt_ptr data; 4175{ 4176 int errors = 0; 4177 lt_dlhandle cur; 4178 4179 LT_DLMUTEX_LOCK (); 4180 4181 cur = handles; 4182 while (cur) 4183 { 4184 lt_dlhandle tmp = cur; 4185 4186 cur = cur->next; 4187 if ((*func) (tmp, data)) 4188 { 4189 ++errors; 4190 break; 4191 } 4192 } 4193 4194 LT_DLMUTEX_UNLOCK (); 4195 4196 return errors; 4197} 4198 4199lt_dlcaller_id 4200lt_dlcaller_register () 4201{ 4202 static lt_dlcaller_id last_caller_id = 0; 4203 int result; 4204 4205 LT_DLMUTEX_LOCK (); 4206 result = ++last_caller_id; 4207 LT_DLMUTEX_UNLOCK (); 4208 4209 return result; 4210} 4211 4212lt_ptr 4213lt_dlcaller_set_data (key, handle, data) 4214 lt_dlcaller_id key; 4215 lt_dlhandle handle; 4216 lt_ptr data; 4217{ 4218 int n_elements = 0; 4219 lt_ptr stale = (lt_ptr) 0; 4220 int i; 4221 4222 /* This needs to be locked so that the caller data can be updated 4223 simultaneously by different threads. */ 4224 LT_DLMUTEX_LOCK (); 4225 4226 if (handle->caller_data) 4227 while (handle->caller_data[n_elements].key) 4228 ++n_elements; 4229 4230 for (i = 0; i < n_elements; ++i) 4231 { 4232 if (handle->caller_data[i].key == key) 4233 { 4234 stale = handle->caller_data[i].data; 4235 break; 4236 } 4237 } 4238 4239 /* Ensure that there is enough room in this handle's caller_data 4240 array to accept a new element (and an empty end marker). */ 4241 if (i == n_elements) 4242 { 4243 lt_caller_data *temp 4244 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); 4245 4246 if (!temp) 4247 { 4248 stale = 0; 4249 goto done; 4250 } 4251 4252 handle->caller_data = temp; 4253 4254 /* We only need this if we needed to allocate a new caller_data. */ 4255 handle->caller_data[i].key = key; 4256 handle->caller_data[1+ i].key = 0; 4257 } 4258 4259 handle->caller_data[i].data = data; 4260 4261 done: 4262 LT_DLMUTEX_UNLOCK (); 4263 4264 return stale; 4265} 4266 4267lt_ptr 4268lt_dlcaller_get_data (key, handle) 4269 lt_dlcaller_id key; 4270 lt_dlhandle handle; 4271{ 4272 lt_ptr result = (lt_ptr) 0; 4273 4274 /* This needs to be locked so that the caller data isn't updated by 4275 another thread part way through this function. */ 4276 LT_DLMUTEX_LOCK (); 4277 4278 /* Locate the index of the element with a matching KEY. */ 4279 { 4280 int i; 4281 for (i = 0; handle->caller_data[i].key; ++i) 4282 { 4283 if (handle->caller_data[i].key == key) 4284 { 4285 result = handle->caller_data[i].data; 4286 break; 4287 } 4288 } 4289 } 4290 4291 LT_DLMUTEX_UNLOCK (); 4292 4293 return result; 4294} 4295 4296 4297 4298/* --- USER MODULE LOADER API --- */ 4299 4300 4301int 4302lt_dlloader_add (place, dlloader, loader_name) 4303 lt_dlloader *place; 4304 const struct lt_user_dlloader *dlloader; 4305 const char *loader_name; 4306{ 4307 int errors = 0; 4308 lt_dlloader *node = 0, *ptr = 0; 4309 4310 if ((dlloader == 0) /* diagnose null parameters */ 4311 || (dlloader->module_open == 0) 4312 || (dlloader->module_close == 0) 4313 || (dlloader->find_sym == 0)) 4314 { 4315 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4316 return 1; 4317 } 4318 4319 /* Create a new dlloader node with copies of the user callbacks. */ 4320 node = LT_EMALLOC (lt_dlloader, 1); 4321 if (!node) 4322 return 1; 4323 4324 node->next = 0; 4325 node->loader_name = loader_name; 4326 node->sym_prefix = dlloader->sym_prefix; 4327 node->dlloader_exit = dlloader->dlloader_exit; 4328 node->module_open = dlloader->module_open; 4329 node->module_close = dlloader->module_close; 4330 node->find_sym = dlloader->find_sym; 4331 node->dlloader_data = dlloader->dlloader_data; 4332 4333 LT_DLMUTEX_LOCK (); 4334 if (!loaders) 4335 { 4336 /* If there are no loaders, NODE becomes the list! */ 4337 loaders = node; 4338 } 4339 else if (!place) 4340 { 4341 /* If PLACE is not set, add NODE to the end of the 4342 LOADERS list. */ 4343 for (ptr = loaders; ptr->next; ptr = ptr->next) 4344 { 4345 /*NOWORK*/; 4346 } 4347 4348 ptr->next = node; 4349 } 4350 else if (loaders == place) 4351 { 4352 /* If PLACE is the first loader, NODE goes first. */ 4353 node->next = place; 4354 loaders = node; 4355 } 4356 else 4357 { 4358 /* Find the node immediately preceding PLACE. */ 4359 for (ptr = loaders; ptr->next != place; ptr = ptr->next) 4360 { 4361 /*NOWORK*/; 4362 } 4363 4364 if (ptr->next != place) 4365 { 4366 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4367 ++errors; 4368 } 4369 else 4370 { 4371 /* Insert NODE between PTR and PLACE. */ 4372 node->next = place; 4373 ptr->next = node; 4374 } 4375 } 4376 4377 LT_DLMUTEX_UNLOCK (); 4378 4379 return errors; 4380} 4381 4382int 4383lt_dlloader_remove (loader_name) 4384 const char *loader_name; 4385{ 4386 lt_dlloader *place = lt_dlloader_find (loader_name); 4387 lt_dlhandle handle; 4388 int errors = 0; 4389 4390 if (!place) 4391 { 4392 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4393 return 1; 4394 } 4395 4396 LT_DLMUTEX_LOCK (); 4397 4398 /* Fail if there are any open modules which use this loader. */ 4399 for (handle = handles; handle; handle = handle->next) 4400 { 4401 if (handle->loader == place) 4402 { 4403 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); 4404 ++errors; 4405 goto done; 4406 } 4407 } 4408 4409 if (place == loaders) 4410 { 4411 /* PLACE is the first loader in the list. */ 4412 loaders = loaders->next; 4413 } 4414 else 4415 { 4416 /* Find the loader before the one being removed. */ 4417 lt_dlloader *prev; 4418 for (prev = loaders; prev->next; prev = prev->next) 4419 { 4420 if (!strcmp (prev->next->loader_name, loader_name)) 4421 { 4422 break; 4423 } 4424 } 4425 4426 place = prev->next; 4427 prev->next = prev->next->next; 4428 } 4429 4430 if (place->dlloader_exit) 4431 { 4432 errors = place->dlloader_exit (place->dlloader_data); 4433 } 4434 4435 LT_DLFREE (place); 4436 4437 done: 4438 LT_DLMUTEX_UNLOCK (); 4439 4440 return errors; 4441} 4442 4443lt_dlloader * 4444lt_dlloader_next (place) 4445 lt_dlloader *place; 4446{ 4447 lt_dlloader *next; 4448 4449 LT_DLMUTEX_LOCK (); 4450 next = place ? place->next : loaders; 4451 LT_DLMUTEX_UNLOCK (); 4452 4453 return next; 4454} 4455 4456const char * 4457lt_dlloader_name (place) 4458 lt_dlloader *place; 4459{ 4460 const char *name = 0; 4461 4462 if (place) 4463 { 4464 LT_DLMUTEX_LOCK (); 4465 name = place ? place->loader_name : 0; 4466 LT_DLMUTEX_UNLOCK (); 4467 } 4468 else 4469 { 4470 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4471 } 4472 4473 return name; 4474} 4475 4476lt_user_data * 4477lt_dlloader_data (place) 4478 lt_dlloader *place; 4479{ 4480 lt_user_data *data = 0; 4481 4482 if (place) 4483 { 4484 LT_DLMUTEX_LOCK (); 4485 data = place ? &(place->dlloader_data) : 0; 4486 LT_DLMUTEX_UNLOCK (); 4487 } 4488 else 4489 { 4490 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); 4491 } 4492 4493 return data; 4494} 4495 4496lt_dlloader * 4497lt_dlloader_find (loader_name) 4498 const char *loader_name; 4499{ 4500 lt_dlloader *place = 0; 4501 4502 LT_DLMUTEX_LOCK (); 4503 for (place = loaders; place; place = place->next) 4504 { 4505 if (strcmp (place->loader_name, loader_name) == 0) 4506 { 4507 break; 4508 } 4509 } 4510 LT_DLMUTEX_UNLOCK (); 4511 4512 return place; 4513} 4514