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