OSDN Git Service

PR c/12553
[pf3gnuchains/gcc-fork.git] / gcc / collect2.c
1 /* Collect static initialization info into data structures that can be
2    traversed by C++ initialization and finalization routines.
3    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4    1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
5    Contributed by Chris Smith (csmith@convex.com).
6    Heavily modified by Michael Meissner (meissner@cygnus.com),
7    Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
8
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
15
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19 for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING.  If not, write to the Free
23 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 02111-1307, USA.  */
25
26
27 /* Build tables of static constructors and destructors and run ld.  */
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include <signal.h>
34 #if ! defined( SIGCHLD ) && defined( SIGCLD )
35 #  define SIGCHLD SIGCLD
36 #endif
37
38 #ifdef vfork /* Autoconf may define this to fork for us.  */
39 # define VFORK_STRING "fork"
40 #else
41 # define VFORK_STRING "vfork"
42 #endif
43 #ifdef HAVE_VFORK_H
44 #include <vfork.h>
45 #endif
46 #ifdef VMS
47 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
48                lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
49 #endif /* VMS */
50
51 #ifndef LIBRARY_PATH_ENV
52 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
53 #endif
54
55 #define COLLECT
56
57 #include "collect2.h"
58 #include "demangle.h"
59 #include "obstack.h"
60 #include "intl.h"
61 #include "version.h"
62 \f
63 /* On certain systems, we have code that works by scanning the object file
64    directly.  But this code uses system-specific header files and library
65    functions, so turn it off in a cross-compiler.  Likewise, the names of
66    the utilities are not correct for a cross-compiler; we have to hope that
67    cross-versions are in the proper directories.  */
68
69 #ifdef CROSS_COMPILE
70 #undef SUNOS4_SHARED_LIBRARIES
71 #undef OBJECT_FORMAT_COFF
72 #undef MD_EXEC_PREFIX
73 #undef REAL_LD_FILE_NAME
74 #undef REAL_NM_FILE_NAME
75 #undef REAL_STRIP_FILE_NAME
76 #endif
77
78 /* If we cannot use a special method, use the ordinary one:
79    run nm to find what symbols are present.
80    In a cross-compiler, this means you need a cross nm,
81    but that is not quite as unpleasant as special headers.  */
82
83 #if !defined (OBJECT_FORMAT_COFF)
84 #define OBJECT_FORMAT_NONE
85 #endif
86
87 #ifdef OBJECT_FORMAT_COFF
88
89 #include <a.out.h>
90 #include <ar.h>
91
92 #ifdef UMAX
93 #include <sgs.h>
94 #endif
95
96 /* Many versions of ldfcn.h define these.  */
97 #ifdef FREAD
98 #undef FREAD
99 #undef FWRITE
100 #endif
101
102 #include <ldfcn.h>
103
104 /* Some systems have an ISCOFF macro, but others do not.  In some cases
105    the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
106    that either do not have an ISCOFF macro in /usr/include or for those
107    where it is wrong.  */
108
109 #ifndef MY_ISCOFF
110 #define MY_ISCOFF(X) ISCOFF (X)
111 #endif
112
113 #endif /* OBJECT_FORMAT_COFF */
114
115 #ifdef OBJECT_FORMAT_NONE
116
117 /* Default flags to pass to nm.  */
118 #ifndef NM_FLAGS
119 #define NM_FLAGS "-n"
120 #endif
121
122 #endif /* OBJECT_FORMAT_NONE */
123
124 /* Some systems use __main in a way incompatible with its use in gcc, in these
125    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
126    give the same symbol without quotes for an alternative entry point.  */
127 #ifndef NAME__MAIN
128 #define NAME__MAIN "__main"
129 #endif
130
131 /* This must match tree.h.  */
132 #define DEFAULT_INIT_PRIORITY 65535
133
134 #ifndef COLLECT_SHARED_INIT_FUNC
135 #define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
136   fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
137 #endif
138 #ifndef COLLECT_SHARED_FINI_FUNC
139 #define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
140   fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
141 #endif
142
143 #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
144 #define SCAN_LIBRARIES
145 #endif
146
147 #ifdef USE_COLLECT2
148 int do_collecting = 1;
149 #else
150 int do_collecting = 0;
151 #endif
152
153 #ifndef COLLECT_PARSE_FLAG
154 #define COLLECT_PARSE_FLAG(FLAG)
155 #endif
156
157 /* Nonzero if we should suppress the automatic demangling of identifiers
158    in linker error messages.  Set from COLLECT_NO_DEMANGLE.  */
159 int no_demangle;
160 \f
161 /* Linked lists of constructor and destructor names.  */
162
163 struct id
164 {
165   struct id *next;
166   int sequence;
167   char name[1];
168 };
169
170 struct head
171 {
172   struct id *first;
173   struct id *last;
174   int number;
175 };
176
177 /* Enumeration giving which pass this is for scanning the program file.  */
178
179 enum pass {
180   PASS_FIRST,                           /* without constructors */
181   PASS_OBJ,                             /* individual objects */
182   PASS_LIB,                             /* looking for shared libraries */
183   PASS_SECOND                           /* with constructors linked in */
184 };
185
186 int vflag;                              /* true if -v */
187 static int rflag;                       /* true if -r */
188 static int strip_flag;                  /* true if -s */
189 #ifdef COLLECT_EXPORT_LIST
190 static int export_flag;                 /* true if -bE */
191 static int aix64_flag;                  /* true if -b64 */
192 #endif
193
194 int debug;                              /* true if -debug */
195
196 static int shared_obj;                  /* true if -shared */
197
198 static const char *c_file;              /* <xxx>.c for constructor/destructor list.  */
199 static const char *o_file;              /* <xxx>.o for constructor/destructor list.  */
200 #ifdef COLLECT_EXPORT_LIST
201 static const char *export_file;         /* <xxx>.x for AIX export list.  */
202 #endif
203 const char *ldout;                      /* File for ld errors.  */
204 static const char *output_file;         /* Output file for ld.  */
205 static const char *nm_file_name;        /* pathname of nm */
206 #ifdef LDD_SUFFIX
207 static const char *ldd_file_name;       /* pathname of ldd (or equivalent) */
208 #endif
209 static const char *strip_file_name;             /* pathname of strip */
210 const char *c_file_name;                /* pathname of gcc */
211 static char *initname, *fininame;       /* names of init and fini funcs */
212
213 static struct head constructors;        /* list of constructors found */
214 static struct head destructors;         /* list of destructors found */
215 #ifdef COLLECT_EXPORT_LIST
216 static struct head exports;             /* list of exported symbols */
217 #endif
218 static struct head frame_tables;        /* list of frame unwind info tables */
219
220 struct obstack temporary_obstack;
221 char * temporary_firstobj;
222
223 /* Holds the return value of pexecute and fork.  */
224 int pid;
225
226 /* Structure to hold all the directories in which to search for files to
227    execute.  */
228
229 struct prefix_list
230 {
231   const char *prefix;         /* String to prepend to the path.  */
232   struct prefix_list *next;   /* Next in linked list.  */
233 };
234
235 struct path_prefix
236 {
237   struct prefix_list *plist;  /* List of prefixes to try */
238   int max_len;                /* Max length of a prefix in PLIST */
239   const char *name;           /* Name of this list (used in config stuff) */
240 };
241
242 #ifdef COLLECT_EXPORT_LIST
243 /* Lists to keep libraries to be scanned for global constructors/destructors.  */
244 static struct head libs;                    /* list of libraries */
245 static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
246 static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
247 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
248                                           &libpath_lib_dirs, NULL};
249 static const char *const libexts[3] = {"a", "so", NULL};  /* possible library extensions */
250 #endif
251
252 static void handler (int);
253 static int is_ctor_dtor (const char *);
254 static char *find_a_file (struct path_prefix *, const char *);
255 static void add_prefix (struct path_prefix *, const char *);
256 static void prefix_from_env (const char *, struct path_prefix *);
257 static void prefix_from_string (const char *, struct path_prefix *);
258 static void do_wait (const char *);
259 static void fork_execute (const char *, char **);
260 static void maybe_unlink (const char *);
261 static void add_to_list (struct head *, const char *);
262 static int extract_init_priority (const char *);
263 static void sort_ids (struct head *);
264 static void write_list (FILE *, const char *, struct id *);
265 #ifdef COLLECT_EXPORT_LIST
266 static void dump_list (FILE *, const char *, struct id *);
267 #endif
268 #if 0
269 static void dump_prefix_list (FILE *, const char *, struct prefix_list *);
270 #endif
271 static void write_list_with_asm (FILE *, const char *, struct id *);
272 static void write_c_file (FILE *, const char *);
273 static void write_c_file_stat (FILE *, const char *);
274 #ifndef LD_INIT_SWITCH
275 static void write_c_file_glob (FILE *, const char *);
276 #endif
277 static void scan_prog_file (const char *, enum pass);
278 #ifdef SCAN_LIBRARIES
279 static void scan_libraries (const char *);
280 #endif
281 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
282 static int is_in_args (const char *, const char **, const char **);
283 #endif
284 #ifdef COLLECT_EXPORT_LIST
285 #if 0
286 static int is_in_list (const char *, struct id *);
287 #endif
288 static void write_aix_file (FILE *, struct id *);
289 static char *resolve_lib_name (const char *);
290 #endif
291 static char *extract_string (const char **);
292 \f
293 #ifndef HAVE_DUP2
294 static int
295 dup2 (int oldfd, int newfd)
296 {
297   int fdtmp[256];
298   int fdx = 0;
299   int fd;
300
301   if (oldfd == newfd)
302     return oldfd;
303   close (newfd);
304   while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
305     fdtmp[fdx++] = fd;
306   while (fdx > 0)
307     close (fdtmp[--fdx]);
308
309   return fd;
310 }
311 #endif /* ! HAVE_DUP2 */
312 \f
313 /* Delete tempfiles and exit function.  */
314
315 void
316 collect_exit (int status)
317 {
318   if (c_file != 0 && c_file[0])
319     maybe_unlink (c_file);
320
321   if (o_file != 0 && o_file[0])
322     maybe_unlink (o_file);
323
324 #ifdef COLLECT_EXPORT_LIST
325   if (export_file != 0 && export_file[0])
326     maybe_unlink (export_file);
327 #endif
328
329   if (ldout != 0 && ldout[0])
330     {
331       dump_file (ldout);
332       maybe_unlink (ldout);
333     }
334
335   if (status != 0 && output_file != 0 && output_file[0])
336     maybe_unlink (output_file);
337
338   exit (status);
339 }
340
341 \f
342 /* Notify user of a non-error.  */
343 void
344 notice (const char *msgid, ...)
345 {
346   va_list ap;
347
348   va_start (ap, msgid);
349   vfprintf (stderr, _(msgid), ap);
350   va_end (ap);
351 }
352
353 /* Die when sys call fails.  */
354
355 void
356 fatal_perror (const char * msgid, ...)
357 {
358   int e = errno;
359   va_list ap;
360
361   va_start (ap, msgid);
362   fprintf (stderr, "collect2: ");
363   vfprintf (stderr, _(msgid), ap);
364   fprintf (stderr, ": %s\n", xstrerror (e));
365   va_end (ap);
366
367   collect_exit (FATAL_EXIT_CODE);
368 }
369
370 /* Just die.  */
371
372 void
373 fatal (const char * msgid, ...)
374 {
375   va_list ap;
376
377   va_start (ap, msgid);
378   fprintf (stderr, "collect2: ");
379   vfprintf (stderr, _(msgid), ap);
380   fprintf (stderr, "\n");
381   va_end (ap);
382
383   collect_exit (FATAL_EXIT_CODE);
384 }
385
386 /* Write error message.  */
387
388 void
389 error (const char * msgid, ...)
390 {
391   va_list ap;
392
393   va_start (ap, msgid);
394   fprintf (stderr, "collect2: ");
395   vfprintf (stderr, _(msgid), ap);
396   fprintf (stderr, "\n");
397   va_end(ap);
398 }
399
400 /* In case obstack is linked in, and abort is defined to fancy_abort,
401    provide a default entry.  */
402
403 void
404 fancy_abort (void)
405 {
406   fatal ("internal error");
407 }
408 \f
409 static void
410 handler (int signo)
411 {
412   if (c_file != 0 && c_file[0])
413     maybe_unlink (c_file);
414
415   if (o_file != 0 && o_file[0])
416     maybe_unlink (o_file);
417
418   if (ldout != 0 && ldout[0])
419     maybe_unlink (ldout);
420
421 #ifdef COLLECT_EXPORT_LIST
422   if (export_file != 0 && export_file[0])
423     maybe_unlink (export_file);
424 #endif
425
426   signal (signo, SIG_DFL);
427   kill (getpid (), signo);
428 }
429
430 \f
431 int
432 file_exists (const char *name)
433 {
434   return access (name, R_OK) == 0;
435 }
436
437 /* Parse a reasonable subset of shell quoting syntax.  */
438
439 static char *
440 extract_string (const char **pp)
441 {
442   const char *p = *pp;
443   int backquote = 0;
444   int inside = 0;
445
446   for (;;)
447     {
448       char c = *p;
449       if (c == '\0')
450         break;
451       ++p;
452       if (backquote)
453         obstack_1grow (&temporary_obstack, c);
454       else if (! inside && c == ' ')
455         break;
456       else if (! inside && c == '\\')
457         backquote = 1;
458       else if (c == '\'')
459         inside = !inside;
460       else
461         obstack_1grow (&temporary_obstack, c);
462     }
463
464   obstack_1grow (&temporary_obstack, '\0');
465   *pp = p;
466   return obstack_finish (&temporary_obstack);
467 }
468 \f
469 void
470 dump_file (const char *name)
471 {
472   FILE *stream = fopen (name, "r");
473
474   if (stream == 0)
475     return;
476   while (1)
477     {
478       int c;
479       while (c = getc (stream),
480              c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
481         obstack_1grow (&temporary_obstack, c);
482       if (obstack_object_size (&temporary_obstack) > 0)
483         {
484           const char *word, *p;
485           char *result;
486           obstack_1grow (&temporary_obstack, '\0');
487           word = obstack_finish (&temporary_obstack);
488
489           if (*word == '.')
490             ++word, putc ('.', stderr);
491           p = word;
492           if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
493             p += strlen (USER_LABEL_PREFIX);
494
495           if (no_demangle)
496             result = 0;
497           else
498             result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
499
500           if (result)
501             {
502               int diff;
503               fputs (result, stderr);
504
505               diff = strlen (word) - strlen (result);
506               while (diff > 0 && c == ' ')
507                 --diff, putc (' ', stderr);
508               while (diff < 0 && c == ' ')
509                 ++diff, c = getc (stream);
510
511               free (result);
512             }
513           else
514             fputs (word, stderr);
515
516           fflush (stderr);
517           obstack_free (&temporary_obstack, temporary_firstobj);
518         }
519       if (c == EOF)
520         break;
521       putc (c, stderr);
522     }
523   fclose (stream);
524 }
525 \f
526 /* Decide whether the given symbol is: a constructor (1), a destructor
527    (2), a routine in a shared object that calls all the constructors
528    (3) or destructors (4), a DWARF exception-handling table (5), or
529    nothing special (0).  */
530
531 static int
532 is_ctor_dtor (const char *s)
533 {
534   struct names { const char *const name; const int len; const int ret;
535     const int two_underscores; };
536
537   const struct names *p;
538   int ch;
539   const char *orig_s = s;
540
541   static const struct names special[] = {
542 #ifndef NO_DOLLAR_IN_LABEL
543     { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 },
544     { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 },
545 #else
546 #ifndef NO_DOT_IN_LABEL
547     { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 },
548     { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 },
549 #endif /* NO_DOT_IN_LABEL */
550 #endif /* NO_DOLLAR_IN_LABEL */
551     { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
552     { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
553     { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
554     { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
555     { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
556     { NULL, 0, 0, 0 }
557   };
558
559   while ((ch = *s) == '_')
560     ++s;
561
562   if (s == orig_s)
563     return 0;
564
565   for (p = &special[0]; p->len > 0; p++)
566     {
567       if (ch == p->name[0]
568           && (!p->two_underscores || ((s - orig_s) >= 2))
569           && strncmp(s, p->name, p->len) == 0)
570         {
571           return p->ret;
572         }
573     }
574   return 0;
575 }
576 \f
577 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
578    and one from the PATH variable.  */
579
580 static struct path_prefix cpath, path;
581
582 #ifdef CROSS_COMPILE
583 /* This is the name of the target machine.  We use it to form the name
584    of the files to execute.  */
585
586 static const char *const target_machine = TARGET_MACHINE;
587 #endif
588
589 /* Search for NAME using prefix list PPREFIX.  We only look for executable
590    files.
591
592    Return 0 if not found, otherwise return its name, allocated with malloc.  */
593
594 static char *
595 find_a_file (struct path_prefix *pprefix, const char *name)
596 {
597   char *temp;
598   struct prefix_list *pl;
599   int len = pprefix->max_len + strlen (name) + 1;
600
601   if (debug)
602     fprintf (stderr, "Looking for '%s'\n", name);
603
604 #ifdef HOST_EXECUTABLE_SUFFIX
605   len += strlen (HOST_EXECUTABLE_SUFFIX);
606 #endif
607
608   temp = xmalloc (len);
609
610   /* Determine the filename to execute (special case for absolute paths).  */
611
612   if (*name == '/'
613 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
614       || (*name && name[1] == ':')
615 #endif
616       )
617     {
618       if (access (name, X_OK) == 0)
619         {
620           strcpy (temp, name);
621
622           if (debug)
623             fprintf (stderr, "  - found: absolute path\n");
624
625           return temp;
626         }
627
628 #ifdef HOST_EXECUTABLE_SUFFIX
629         /* Some systems have a suffix for executable files.
630            So try appending that.  */
631       strcpy (temp, name);
632         strcat (temp, HOST_EXECUTABLE_SUFFIX);
633
634         if (access (temp, X_OK) == 0)
635           return temp;
636 #endif
637
638       if (debug)
639         fprintf (stderr, "  - failed to locate using absolute path\n");
640     }
641   else
642     for (pl = pprefix->plist; pl; pl = pl->next)
643       {
644         struct stat st;
645
646         strcpy (temp, pl->prefix);
647         strcat (temp, name);
648
649         if (stat (temp, &st) >= 0
650             && ! S_ISDIR (st.st_mode)
651             && access (temp, X_OK) == 0)
652           return temp;
653
654 #ifdef HOST_EXECUTABLE_SUFFIX
655         /* Some systems have a suffix for executable files.
656            So try appending that.  */
657         strcat (temp, HOST_EXECUTABLE_SUFFIX);
658
659         if (stat (temp, &st) >= 0
660             && ! S_ISDIR (st.st_mode)
661             && access (temp, X_OK) == 0)
662           return temp;
663 #endif
664       }
665
666   if (debug && pprefix->plist == NULL)
667     fprintf (stderr, "  - failed: no entries in prefix list\n");
668
669   free (temp);
670   return 0;
671 }
672
673 /* Add an entry for PREFIX to prefix list PPREFIX.  */
674
675 static void
676 add_prefix (struct path_prefix *pprefix, const char *prefix)
677 {
678   struct prefix_list *pl, **prev;
679   int len;
680
681   if (pprefix->plist)
682     {
683       for (pl = pprefix->plist; pl->next; pl = pl->next)
684         ;
685       prev = &pl->next;
686     }
687   else
688     prev = &pprefix->plist;
689
690   /* Keep track of the longest prefix.  */
691
692   len = strlen (prefix);
693   if (len > pprefix->max_len)
694     pprefix->max_len = len;
695
696   pl = xmalloc (sizeof (struct prefix_list));
697   pl->prefix = xstrdup (prefix);
698
699   if (*prev)
700     pl->next = *prev;
701   else
702     pl->next = (struct prefix_list *) 0;
703   *prev = pl;
704 }
705 \f
706 /* Take the value of the environment variable ENV, break it into a path, and
707    add of the entries to PPREFIX.  */
708
709 static void
710 prefix_from_env (const char *env, struct path_prefix *pprefix)
711 {
712   const char *p;
713   GET_ENVIRONMENT (p, env);
714
715   if (p)
716     prefix_from_string (p, pprefix);
717 }
718
719 static void
720 prefix_from_string (const char *p, struct path_prefix *pprefix)
721 {
722   const char *startp, *endp;
723   char *nstore = xmalloc (strlen (p) + 3);
724
725   if (debug)
726     fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
727
728   startp = endp = p;
729   while (1)
730     {
731       if (*endp == PATH_SEPARATOR || *endp == 0)
732         {
733           strncpy (nstore, startp, endp-startp);
734           if (endp == startp)
735             {
736               strcpy (nstore, "./");
737             }
738           else if (! IS_DIR_SEPARATOR (endp[-1]))
739             {
740               nstore[endp-startp] = DIR_SEPARATOR;
741               nstore[endp-startp+1] = 0;
742             }
743           else
744             nstore[endp-startp] = 0;
745
746           if (debug)
747             fprintf (stderr, "  - add prefix: %s\n", nstore);
748
749           add_prefix (pprefix, nstore);
750           if (*endp == 0)
751             break;
752           endp = startp = endp + 1;
753         }
754       else
755         endp++;
756     }
757 }
758 \f
759 /* Main program.  */
760
761 int
762 main (int argc, char **argv)
763 {
764   static const char *const ld_suffix    = "ld";
765   static const char *const real_ld_suffix = "real-ld";
766   static const char *const collect_ld_suffix = "collect-ld";
767   static const char *const nm_suffix    = "nm";
768   static const char *const gnm_suffix   = "gnm";
769 #ifdef LDD_SUFFIX
770   static const char *const ldd_suffix   = LDD_SUFFIX;
771 #endif
772   static const char *const strip_suffix = "strip";
773   static const char *const gstrip_suffix = "gstrip";
774
775 #ifdef CROSS_COMPILE
776   /* If we look for a program in the compiler directories, we just use
777      the short name, since these directories are already system-specific.
778      But it we look for a program in the system directories, we need to
779      qualify the program name with the target machine.  */
780
781   const char *const full_ld_suffix =
782     concat(target_machine, "-", ld_suffix, NULL);
783   const char *const full_nm_suffix =
784     concat (target_machine, "-", nm_suffix, NULL);
785   const char *const full_gnm_suffix =
786     concat (target_machine, "-", gnm_suffix, NULL);
787 #ifdef LDD_SUFFIX
788   const char *const full_ldd_suffix =
789     concat (target_machine, "-", ldd_suffix, NULL);
790 #endif
791   const char *const full_strip_suffix =
792     concat (target_machine, "-", strip_suffix, NULL);
793   const char *const full_gstrip_suffix =
794     concat (target_machine, "-", gstrip_suffix, NULL);
795 #else
796   const char *const full_ld_suffix      = ld_suffix;
797   const char *const full_nm_suffix      = nm_suffix;
798   const char *const full_gnm_suffix     = gnm_suffix;
799 #ifdef LDD_SUFFIX
800   const char *const full_ldd_suffix     = ldd_suffix;
801 #endif
802   const char *const full_strip_suffix   = strip_suffix;
803   const char *const full_gstrip_suffix  = gstrip_suffix;
804 #endif /* CROSS_COMPILE */
805
806   const char *arg;
807   FILE *outf;
808 #ifdef COLLECT_EXPORT_LIST
809   FILE *exportf;
810 #endif
811   const char *ld_file_name;
812   const char *p;
813   char **c_argv;
814   const char **c_ptr;
815   char **ld1_argv;
816   const char **ld1;
817   char **ld2_argv;
818   const char **ld2;
819   char **object_lst;
820   const char **object;
821   int first_file;
822   int num_c_args        = argc+9;
823
824   no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
825
826   /* Suppress demangling by the real linker, which may be broken.  */
827   putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
828
829 #if defined (COLLECT2_HOST_INITIALIZATION)
830   /* Perform system dependent initialization, if necessary.  */
831   COLLECT2_HOST_INITIALIZATION;
832 #endif
833
834 #ifdef SIGCHLD
835   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
836      receive the signal.  A different setting is inheritable */
837   signal (SIGCHLD, SIG_DFL);
838 #endif
839
840   gcc_init_libintl ();
841
842   /* Do not invoke xcalloc before this point, since locale needs to be
843      set first, in case a diagnostic is issued.  */
844
845   ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+3));
846   ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+10));
847   object = (const char **)(object_lst = xcalloc(sizeof (char *), argc));
848
849 #ifdef DEBUG
850   debug = 1;
851 #endif
852
853   /* Parse command line early for instances of -debug.  This allows
854      the debug flag to be set before functions like find_a_file()
855      are called.  */
856   {
857     int i;
858
859     for (i = 1; argv[i] != NULL; i ++)
860       {
861         if (! strcmp (argv[i], "-debug"))
862           debug = 1;
863         COLLECT_PARSE_FLAG (argv[i]);
864       }
865     vflag = debug;
866   }
867
868 #ifndef DEFAULT_A_OUT_NAME
869   output_file = "a.out";
870 #else
871   output_file = DEFAULT_A_OUT_NAME;
872 #endif
873
874   obstack_begin (&temporary_obstack, 0);
875   temporary_firstobj = obstack_alloc (&temporary_obstack, 0);
876
877   current_demangling_style = auto_demangling;
878   p = getenv ("COLLECT_GCC_OPTIONS");
879   while (p && *p)
880     {
881       const char *q = extract_string (&p);
882       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
883         num_c_args++;
884     }
885   obstack_free (&temporary_obstack, temporary_firstobj);
886
887   /* -fno-exceptions -w */
888   num_c_args += 2;
889
890   c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
891
892   if (argc < 2)
893     fatal ("no arguments");
894
895 #ifdef SIGQUIT
896   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
897     signal (SIGQUIT, handler);
898 #endif
899   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
900     signal (SIGINT, handler);
901 #ifdef SIGALRM
902   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
903     signal (SIGALRM, handler);
904 #endif
905 #ifdef SIGHUP
906   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
907     signal (SIGHUP, handler);
908 #endif
909   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
910     signal (SIGSEGV, handler);
911 #ifdef SIGBUS
912   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
913     signal (SIGBUS, handler);
914 #endif
915
916   /* Extract COMPILER_PATH and PATH into our prefix list.  */
917   prefix_from_env ("COMPILER_PATH", &cpath);
918   prefix_from_env ("PATH", &path);
919
920   /* Try to discover a valid linker/nm/strip to use.  */
921
922   /* Maybe we know the right file to use (if not cross).  */
923   ld_file_name = 0;
924 #ifdef DEFAULT_LINKER
925   if (access (DEFAULT_LINKER, X_OK) == 0)
926     ld_file_name = DEFAULT_LINKER;
927   if (ld_file_name == 0)
928 #endif
929 #ifdef REAL_LD_FILE_NAME
930   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
931   if (ld_file_name == 0)
932 #endif
933   /* Search the (target-specific) compiler dirs for ld'.  */
934   ld_file_name = find_a_file (&cpath, real_ld_suffix);
935   /* Likewise for `collect-ld'.  */
936   if (ld_file_name == 0)
937     ld_file_name = find_a_file (&cpath, collect_ld_suffix);
938   /* Search the compiler directories for `ld'.  We have protection against
939      recursive calls in find_a_file.  */
940   if (ld_file_name == 0)
941     ld_file_name = find_a_file (&cpath, ld_suffix);
942   /* Search the ordinary system bin directories
943      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
944   if (ld_file_name == 0)
945     ld_file_name = find_a_file (&path, full_ld_suffix);
946
947 #ifdef REAL_NM_FILE_NAME
948   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
949   if (nm_file_name == 0)
950 #endif
951   nm_file_name = find_a_file (&cpath, gnm_suffix);
952   if (nm_file_name == 0)
953     nm_file_name = find_a_file (&path, full_gnm_suffix);
954   if (nm_file_name == 0)
955     nm_file_name = find_a_file (&cpath, nm_suffix);
956   if (nm_file_name == 0)
957     nm_file_name = find_a_file (&path, full_nm_suffix);
958
959 #ifdef LDD_SUFFIX
960   ldd_file_name = find_a_file (&cpath, ldd_suffix);
961   if (ldd_file_name == 0)
962     ldd_file_name = find_a_file (&path, full_ldd_suffix);
963 #endif
964
965 #ifdef REAL_STRIP_FILE_NAME
966   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
967   if (strip_file_name == 0)
968 #endif
969   strip_file_name = find_a_file (&cpath, gstrip_suffix);
970   if (strip_file_name == 0)
971     strip_file_name = find_a_file (&path, full_gstrip_suffix);
972   if (strip_file_name == 0)
973     strip_file_name = find_a_file (&cpath, strip_suffix);
974   if (strip_file_name == 0)
975     strip_file_name = find_a_file (&path, full_strip_suffix);
976
977   /* Determine the full path name of the C compiler to use.  */
978   c_file_name = getenv ("COLLECT_GCC");
979   if (c_file_name == 0)
980     {
981 #ifdef CROSS_COMPILE
982       c_file_name = concat (target_machine, "-gcc", NULL);
983 #else
984       c_file_name = "gcc";
985 #endif
986     }
987
988   p = find_a_file (&cpath, c_file_name);
989
990   /* Here it should be safe to use the system search path since we should have
991      already qualified the name of the compiler when it is needed.  */
992   if (p == 0)
993     p = find_a_file (&path, c_file_name);
994
995   if (p)
996     c_file_name = p;
997
998   *ld1++ = *ld2++ = ld_file_name;
999
1000   /* Make temp file names.  */
1001   c_file = make_temp_file (".c");
1002   o_file = make_temp_file (".o");
1003 #ifdef COLLECT_EXPORT_LIST
1004   export_file = make_temp_file (".x");
1005 #endif
1006   ldout = make_temp_file (".ld");
1007   *c_ptr++ = c_file_name;
1008   *c_ptr++ = "-x";
1009   *c_ptr++ = "c";
1010   *c_ptr++ = "-c";
1011   *c_ptr++ = "-o";
1012   *c_ptr++ = o_file;
1013
1014 #ifdef COLLECT_EXPORT_LIST
1015   /* Generate a list of directories from LIBPATH.  */
1016   prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1017   /* Add to this list also two standard directories where
1018      AIX loader always searches for libraries.  */
1019   add_prefix (&libpath_lib_dirs, "/lib");
1020   add_prefix (&libpath_lib_dirs, "/usr/lib");
1021 #endif
1022
1023   /* Get any options that the upper GCC wants to pass to the sub-GCC.
1024
1025      AIX support needs to know if -shared has been specified before
1026      parsing commandline arguments.  */
1027
1028   p = getenv ("COLLECT_GCC_OPTIONS");
1029   while (p && *p)
1030     {
1031       const char *q = extract_string (&p);
1032       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1033         *c_ptr++ = xstrdup (q);
1034       if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1035         *c_ptr++ = xstrdup (q);
1036       if (strcmp (q, "-shared") == 0)
1037         shared_obj = 1;
1038       if (*q == '-' && q[1] == 'B')
1039         {
1040           *c_ptr++ = xstrdup (q);
1041           if (q[2] == 0)
1042             {
1043               q = extract_string (&p);
1044               *c_ptr++ = xstrdup (q);
1045             }
1046         }
1047     }
1048   obstack_free (&temporary_obstack, temporary_firstobj);
1049   *c_ptr++ = "-fno-exceptions";
1050   *c_ptr++ = "-w";
1051
1052   /* !!! When GCC calls collect2,
1053      it does not know whether it is calling collect2 or ld.
1054      So collect2 cannot meaningfully understand any options
1055      except those ld understands.
1056      If you propose to make GCC pass some other option,
1057      just imagine what will happen if ld is really ld!!!  */
1058
1059   /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
1060   /* After the first file, put in the c++ rt0.  */
1061
1062   first_file = 1;
1063   while ((arg = *++argv) != (char *) 0)
1064     {
1065       *ld1++ = *ld2++ = arg;
1066
1067       if (arg[0] == '-')
1068         {
1069           switch (arg[1])
1070             {
1071 #ifdef COLLECT_EXPORT_LIST
1072             /* We want to disable automatic exports on AIX when user
1073                explicitly puts an export list in command line */
1074             case 'b':
1075               if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1076                 export_flag = 1;
1077               else if (arg[2] == '6' && arg[3] == '4')
1078                 aix64_flag = 1;
1079               break;
1080 #endif
1081
1082             case 'd':
1083               if (!strcmp (arg, "-debug"))
1084                 {
1085                   /* Already parsed.  */
1086                   ld1--;
1087                   ld2--;
1088                 }
1089               break;
1090
1091             case 'l':
1092               if (first_file)
1093                 {
1094                   /* place o_file BEFORE this argument! */
1095                   first_file = 0;
1096                   ld2--;
1097                   *ld2++ = o_file;
1098                   *ld2++ = arg;
1099                 }
1100 #ifdef COLLECT_EXPORT_LIST
1101               {
1102                 /* Resolving full library name.  */
1103                 const char *s = resolve_lib_name (arg+2);
1104
1105                 /* Saving a full library name.  */
1106                 add_to_list (&libs, s);
1107               }
1108 #endif
1109               break;
1110
1111 #ifdef COLLECT_EXPORT_LIST
1112             /* Saving directories where to search for libraries.  */
1113             case 'L':
1114               add_prefix (&cmdline_lib_dirs, arg+2);
1115               break;
1116 #else
1117 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1118             case 'L':
1119               if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
1120                 --ld1;
1121               break;
1122 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1123 #endif
1124
1125             case 'o':
1126               if (arg[2] == '\0')
1127                 output_file = *ld1++ = *ld2++ = *++argv;
1128               else if (1
1129 #ifdef SWITCHES_NEED_SPACES
1130                        && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1131 #endif
1132                        )
1133
1134                 output_file = &arg[2];
1135               break;
1136
1137             case 'r':
1138               if (arg[2] == '\0')
1139                 rflag = 1;
1140               break;
1141
1142             case 's':
1143               if (arg[2] == '\0' && do_collecting)
1144                 {
1145                   /* We must strip after the nm run, otherwise C++ linking
1146                      will not work.  Thus we strip in the second ld run, or
1147                      else with strip if there is no second ld run.  */
1148                   strip_flag = 1;
1149                   ld1--;
1150                 }
1151               break;
1152
1153             case 'v':
1154               if (arg[2] == '\0')
1155                 vflag = 1;
1156               break;
1157             }
1158         }
1159       else if ((p = strrchr (arg, '.')) != (char *) 0
1160                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1161                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
1162                    || strcmp (p, ".obj") == 0))
1163         {
1164           if (first_file)
1165             {
1166               first_file = 0;
1167               if (p[1] == 'o')
1168                 *ld2++ = o_file;
1169               else
1170                 {
1171                   /* place o_file BEFORE this argument! */
1172                   ld2--;
1173                   *ld2++ = o_file;
1174                   *ld2++ = arg;
1175                 }
1176             }
1177           if (p[1] == 'o' || p[1] == 'l')
1178             *object++ = arg;
1179 #ifdef COLLECT_EXPORT_LIST
1180           /* libraries can be specified directly, i.e. without -l flag.  */
1181           else
1182             {
1183               /* Saving a full library name.  */
1184               add_to_list (&libs, arg);
1185             }
1186 #endif
1187         }
1188     }
1189
1190 #ifdef COLLECT_EXPORT_LIST
1191   /* This is added only for debugging purposes.  */
1192   if (debug)
1193     {
1194       fprintf (stderr, "List of libraries:\n");
1195       dump_list (stderr, "\t", libs.first);
1196     }
1197
1198   /* The AIX linker will discard static constructors in object files if
1199      nothing else in the file is referenced, so look at them first.  */
1200   {
1201       const char **export_object_lst = (const char **)object_lst;
1202
1203       while (export_object_lst < object)
1204         scan_prog_file (*export_object_lst++, PASS_OBJ);
1205   }
1206   {
1207     struct id *list = libs.first;
1208
1209     for (; list; list = list->next)
1210       scan_prog_file (list->name, PASS_FIRST);
1211   }
1212
1213   if (exports.first)
1214     {
1215       char *buf = concat ("-bE:", export_file, NULL);
1216
1217       *ld1++ = buf;
1218       *ld2++ = buf;
1219
1220       exportf = fopen (export_file, "w");
1221       if (exportf == (FILE *) 0)
1222         fatal_perror ("fopen %s", export_file);
1223       write_aix_file (exportf, exports.first);
1224       if (fclose (exportf))
1225         fatal_perror ("fclose %s", export_file);
1226     }
1227 #endif
1228
1229   *c_ptr++ = c_file;
1230   *c_ptr = *ld1 = *object = (char *) 0;
1231
1232   if (vflag)
1233     {
1234       notice ("collect2 version %s", version_string);
1235 #ifdef TARGET_VERSION
1236       TARGET_VERSION;
1237 #endif
1238       fprintf (stderr, "\n");
1239     }
1240
1241   if (debug)
1242     {
1243       const char *ptr;
1244       fprintf (stderr, "ld_file_name        = %s\n",
1245                (ld_file_name ? ld_file_name : "not found"));
1246       fprintf (stderr, "c_file_name         = %s\n",
1247                (c_file_name ? c_file_name : "not found"));
1248       fprintf (stderr, "nm_file_name        = %s\n",
1249                (nm_file_name ? nm_file_name : "not found"));
1250 #ifdef LDD_SUFFIX
1251       fprintf (stderr, "ldd_file_name       = %s\n",
1252                (ldd_file_name ? ldd_file_name : "not found"));
1253 #endif
1254       fprintf (stderr, "strip_file_name     = %s\n",
1255                (strip_file_name ? strip_file_name : "not found"));
1256       fprintf (stderr, "c_file              = %s\n",
1257                (c_file ? c_file : "not found"));
1258       fprintf (stderr, "o_file              = %s\n",
1259                (o_file ? o_file : "not found"));
1260
1261       ptr = getenv ("COLLECT_GCC_OPTIONS");
1262       if (ptr)
1263         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1264
1265       ptr = getenv ("COLLECT_GCC");
1266       if (ptr)
1267         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1268
1269       ptr = getenv ("COMPILER_PATH");
1270       if (ptr)
1271         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1272
1273       ptr = getenv (LIBRARY_PATH_ENV);
1274       if (ptr)
1275         fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
1276
1277       fprintf (stderr, "\n");
1278     }
1279
1280   /* Load the program, searching all libraries and attempting to provide
1281      undefined symbols from repository information.  */
1282
1283   /* On AIX we do this later.  */
1284 #ifndef COLLECT_EXPORT_LIST
1285   do_tlink (ld1_argv, object_lst);
1286 #endif
1287
1288   /* If -r or they will be run via some other method, do not build the
1289      constructor or destructor list, just return now.  */
1290   if (rflag
1291 #ifndef COLLECT_EXPORT_LIST
1292       || ! do_collecting
1293 #endif
1294       )
1295     {
1296 #ifdef COLLECT_EXPORT_LIST
1297       /* Do the link we avoided above if we are exiting.  */
1298       do_tlink (ld1_argv, object_lst);
1299
1300       /* But make sure we delete the export file we may have created.  */
1301       if (export_file != 0 && export_file[0])
1302         maybe_unlink (export_file);
1303 #endif
1304       maybe_unlink (c_file);
1305       maybe_unlink (o_file);
1306       return 0;
1307     }
1308
1309   /* Examine the namelist with nm and search it for static constructors
1310      and destructors to call.
1311      Write the constructor and destructor tables to a .s file and reload.  */
1312
1313   /* On AIX we already scanned for global constructors/destructors.  */
1314 #ifndef COLLECT_EXPORT_LIST
1315   scan_prog_file (output_file, PASS_FIRST);
1316 #endif
1317
1318 #ifdef SCAN_LIBRARIES
1319   scan_libraries (output_file);
1320 #endif
1321
1322   if (debug)
1323     {
1324       notice ("%d constructor(s) found\n", constructors.number);
1325       notice ("%d destructor(s)  found\n", destructors.number);
1326       notice ("%d frame table(s) found\n", frame_tables.number);
1327     }
1328
1329   if (constructors.number == 0 && destructors.number == 0
1330       && frame_tables.number == 0
1331 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1332       /* If we will be running these functions ourselves, we want to emit
1333          stubs into the shared library so that we do not have to relink
1334          dependent programs when we add static objects.  */
1335       && ! shared_obj
1336 #endif
1337       )
1338     {
1339 #ifdef COLLECT_EXPORT_LIST
1340       /* Do tlink without additional code generation.  */
1341       do_tlink (ld1_argv, object_lst);
1342 #endif
1343       /* Strip now if it was requested on the command line.  */
1344       if (strip_flag)
1345         {
1346           char **real_strip_argv = xcalloc (sizeof (char *), 3);
1347           const char ** strip_argv = (const char **) real_strip_argv;
1348
1349           strip_argv[0] = strip_file_name;
1350           strip_argv[1] = output_file;
1351           strip_argv[2] = (char *) 0;
1352           fork_execute ("strip", real_strip_argv);
1353         }
1354
1355 #ifdef COLLECT_EXPORT_LIST
1356       maybe_unlink (export_file);
1357 #endif
1358       maybe_unlink (c_file);
1359       maybe_unlink (o_file);
1360       return 0;
1361     }
1362
1363   /* Sort ctor and dtor lists by priority.  */
1364   sort_ids (&constructors);
1365   sort_ids (&destructors);
1366
1367   maybe_unlink(output_file);
1368   outf = fopen (c_file, "w");
1369   if (outf == (FILE *) 0)
1370     fatal_perror ("fopen %s", c_file);
1371
1372   write_c_file (outf, c_file);
1373
1374   if (fclose (outf))
1375     fatal_perror ("fclose %s", c_file);
1376
1377   /* Tell the linker that we have initializer and finalizer functions.  */
1378 #ifdef LD_INIT_SWITCH
1379 #ifdef COLLECT_EXPORT_LIST
1380   *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
1381 #else
1382   *ld2++ = LD_INIT_SWITCH;
1383   *ld2++ = initname;
1384   *ld2++ = LD_FINI_SWITCH;
1385   *ld2++ = fininame;
1386 #endif
1387 #endif
1388
1389 #ifdef COLLECT_EXPORT_LIST
1390   if (shared_obj)
1391     {
1392       /* If we did not add export flag to link arguments before, add it to
1393          second link phase now.  No new exports should have been added.  */
1394       if (! exports.first)
1395         *ld2++ = concat ("-bE:", export_file, NULL);
1396
1397       add_to_list (&exports, initname);
1398       add_to_list (&exports, fininame);
1399       add_to_list (&exports, "_GLOBAL__DI");
1400       add_to_list (&exports, "_GLOBAL__DD");
1401       exportf = fopen (export_file, "w");
1402       if (exportf == (FILE *) 0)
1403         fatal_perror ("fopen %s", export_file);
1404       write_aix_file (exportf, exports.first);
1405       if (fclose (exportf))
1406         fatal_perror ("fclose %s", export_file);
1407     }
1408 #endif
1409
1410   /* End of arguments to second link phase.  */
1411   *ld2 = (char*) 0;
1412
1413   if (debug)
1414     {
1415       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1416                output_file, c_file);
1417       write_c_file (stderr, "stderr");
1418       fprintf (stderr, "========== end of c_file\n\n");
1419 #ifdef COLLECT_EXPORT_LIST
1420       fprintf (stderr, "\n========== export_file = %s\n", export_file);
1421       write_aix_file (stderr, exports.first);
1422       fprintf (stderr, "========== end of export_file\n\n");
1423 #endif
1424     }
1425
1426   /* Assemble the constructor and destructor tables.
1427      Link the tables in with the rest of the program.  */
1428
1429   fork_execute ("gcc",  c_argv);
1430 #ifdef COLLECT_EXPORT_LIST
1431   /* On AIX we must call tlink because of possible templates resolution */
1432   do_tlink (ld2_argv, object_lst);
1433 #else
1434   /* Otherwise, simply call ld because tlink is already done */
1435   fork_execute ("ld", ld2_argv);
1436
1437   /* Let scan_prog_file do any final mods (OSF/rose needs this for
1438      constructors/destructors in shared libraries.  */
1439   scan_prog_file (output_file, PASS_SECOND);
1440 #endif
1441
1442   maybe_unlink (c_file);
1443   maybe_unlink (o_file);
1444
1445 #ifdef COLLECT_EXPORT_LIST
1446   maybe_unlink (export_file);
1447 #endif
1448
1449   return 0;
1450 }
1451
1452 \f
1453 /* Wait for a process to finish, and exit if a nonzero status is found.  */
1454
1455 int
1456 collect_wait (const char *prog)
1457 {
1458   int status;
1459
1460   pwait (pid, &status, 0);
1461   if (status)
1462     {
1463       if (WIFSIGNALED (status))
1464         {
1465           int sig = WTERMSIG (status);
1466           error ("%s terminated with signal %d [%s]%s",
1467                  prog, sig, strsignal(sig),
1468                  WCOREDUMP(status) ? ", core dumped" : "");
1469           collect_exit (FATAL_EXIT_CODE);
1470         }
1471
1472       if (WIFEXITED (status))
1473         return WEXITSTATUS (status);
1474     }
1475   return 0;
1476 }
1477
1478 static void
1479 do_wait (const char *prog)
1480 {
1481   int ret = collect_wait (prog);
1482   if (ret != 0)
1483     {
1484       error ("%s returned %d exit status", prog, ret);
1485       collect_exit (ret);
1486     }
1487 }
1488
1489 \f
1490 /* Execute a program, and wait for the reply.  */
1491
1492 void
1493 collect_execute (const char *prog, char **argv, const char *redir)
1494 {
1495   char *errmsg_fmt;
1496   char *errmsg_arg;
1497   int redir_handle = -1;
1498   int stdout_save = -1;
1499   int stderr_save = -1;
1500
1501   if (vflag || debug)
1502     {
1503       char **p_argv;
1504       const char *str;
1505
1506       if (argv[0])
1507         fprintf (stderr, "%s", argv[0]);
1508       else
1509         notice ("[cannot find %s]", prog);
1510
1511       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1512         fprintf (stderr, " %s", str);
1513
1514       fprintf (stderr, "\n");
1515     }
1516
1517   fflush (stdout);
1518   fflush (stderr);
1519
1520   /* If we cannot find a program we need, complain error.  Do this here
1521      since we might not end up needing something that we could not find.  */
1522
1523   if (argv[0] == 0)
1524     fatal ("cannot find `%s'", prog);
1525
1526   if (redir)
1527     {
1528       /* Open response file.  */
1529       redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1530
1531       /* Duplicate the stdout and stderr file handles
1532          so they can be restored later.  */
1533       stdout_save = dup (STDOUT_FILENO);
1534       if (stdout_save == -1)
1535         fatal_perror ("redirecting stdout: %s", redir);
1536       stderr_save = dup (STDERR_FILENO);
1537       if (stderr_save == -1)
1538         fatal_perror ("redirecting stdout: %s", redir);
1539
1540       /* Redirect stdout & stderr to our response file.  */
1541       dup2 (redir_handle, STDOUT_FILENO);
1542       dup2 (redir_handle, STDERR_FILENO);
1543     }
1544
1545   pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
1546                   (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1547
1548   if (redir)
1549     {
1550       /* Restore stdout and stderr to their previous settings.  */
1551       dup2 (stdout_save, STDOUT_FILENO);
1552       dup2 (stderr_save, STDERR_FILENO);
1553
1554       /* Close response file.  */
1555       close (redir_handle);
1556     }
1557
1558  if (pid == -1)
1559    fatal_perror (errmsg_fmt, errmsg_arg);
1560 }
1561
1562 static void
1563 fork_execute (const char *prog, char **argv)
1564 {
1565   collect_execute (prog, argv, NULL);
1566   do_wait (prog);
1567 }
1568 \f
1569 /* Unlink a file unless we are debugging.  */
1570
1571 static void
1572 maybe_unlink (const char *file)
1573 {
1574   if (!debug)
1575     unlink (file);
1576   else
1577     notice ("[Leaving %s]\n", file);
1578 }
1579
1580 \f
1581 static long sequence_number = 0;
1582
1583 /* Add a name to a linked list.  */
1584
1585 static void
1586 add_to_list (struct head *head_ptr, const char *name)
1587 {
1588   struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1);
1589   struct id *p;
1590   strcpy (newid->name, name);
1591
1592   if (head_ptr->first)
1593     head_ptr->last->next = newid;
1594   else
1595     head_ptr->first = newid;
1596
1597   /* Check for duplicate symbols.  */
1598   for (p = head_ptr->first;
1599        strcmp (name, p->name) != 0;
1600        p = p->next)
1601     ;
1602   if (p != newid)
1603     {
1604       head_ptr->last->next = 0;
1605       free (newid);
1606       return;
1607     }
1608
1609   newid->sequence = ++sequence_number;
1610   head_ptr->last = newid;
1611   head_ptr->number++;
1612 }
1613
1614 /* Grab the init priority number from an init function name that
1615    looks like "_GLOBAL_.I.12345.foo".  */
1616
1617 static int
1618 extract_init_priority (const char *name)
1619 {
1620   int pos = 0, pri;
1621
1622   while (name[pos] == '_')
1623     ++pos;
1624   pos += 10; /* strlen ("GLOBAL__X_") */
1625
1626   /* Extract init_p number from ctor/dtor name.  */
1627   pri = atoi (name + pos);
1628   return pri ? pri : DEFAULT_INIT_PRIORITY;
1629 }
1630
1631 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1632    ctors will be run from right to left, dtors from left to right.  */
1633
1634 static void
1635 sort_ids (struct head *head_ptr)
1636 {
1637   /* id holds the current element to insert.  id_next holds the next
1638      element to insert.  id_ptr iterates through the already sorted elements
1639      looking for the place to insert id.  */
1640   struct id *id, *id_next, **id_ptr;
1641
1642   id = head_ptr->first;
1643
1644   /* We don't have any sorted elements yet.  */
1645   head_ptr->first = NULL;
1646
1647   for (; id; id = id_next)
1648     {
1649       id_next = id->next;
1650       id->sequence = extract_init_priority (id->name);
1651
1652       for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1653         if (*id_ptr == NULL
1654             /* If the sequence numbers are the same, we put the id from the
1655                file later on the command line later in the list.  */
1656             || id->sequence > (*id_ptr)->sequence
1657             /* Hack: do lexical compare, too.
1658             || (id->sequence == (*id_ptr)->sequence
1659                 && strcmp (id->name, (*id_ptr)->name) > 0) */
1660             )
1661           {
1662             id->next = *id_ptr;
1663             *id_ptr = id;
1664             break;
1665           }
1666     }
1667
1668   /* Now set the sequence numbers properly so write_c_file works.  */
1669   for (id = head_ptr->first; id; id = id->next)
1670     id->sequence = ++sequence_number;
1671 }
1672
1673 /* Write: `prefix', the names on list LIST, `suffix'.  */
1674
1675 static void
1676 write_list (FILE *stream, const char *prefix, struct id *list)
1677 {
1678   while (list)
1679     {
1680       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1681       list = list->next;
1682     }
1683 }
1684
1685 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1686 /* Given a STRING, return nonzero if it occurs in the list in range
1687    [ARGS_BEGIN,ARGS_END).  */
1688
1689 static int
1690 is_in_args (const char *string, const char **args_begin,
1691             const char **args_end)
1692 {
1693   const char **args_pointer;
1694   for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
1695     if (strcmp (string, *args_pointer) == 0)
1696       return 1;
1697   return 0;
1698 }
1699 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1700
1701 #ifdef COLLECT_EXPORT_LIST
1702 /* This function is really used only on AIX, but may be useful.  */
1703 #if 0
1704 static int
1705 is_in_list (const char *prefix, struct id *list)
1706 {
1707   while (list)
1708     {
1709       if (!strcmp (prefix, list->name)) return 1;
1710       list = list->next;
1711     }
1712     return 0;
1713 }
1714 #endif
1715 #endif /* COLLECT_EXPORT_LIST */
1716
1717 /* Added for debugging purpose.  */
1718 #ifdef COLLECT_EXPORT_LIST
1719 static void
1720 dump_list (FILE *stream, const char *prefix, struct id *list)
1721 {
1722   while (list)
1723     {
1724       fprintf (stream, "%s%s,\n", prefix, list->name);
1725       list = list->next;
1726     }
1727 }
1728 #endif
1729
1730 #if 0
1731 static void
1732 dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
1733 {
1734   while (list)
1735     {
1736       fprintf (stream, "%s%s,\n", prefix, list->prefix);
1737       list = list->next;
1738     }
1739 }
1740 #endif
1741
1742 static void
1743 write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
1744 {
1745   while (list)
1746     {
1747       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1748                prefix, list->sequence, list->name);
1749       list = list->next;
1750     }
1751 }
1752
1753 /* Write out the constructor and destructor tables statically (for a shared
1754    object), along with the functions to execute them.  */
1755
1756 static void
1757 write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
1758 {
1759   const char *p, *q;
1760   char *prefix, *r;
1761   int frames = (frame_tables.number > 0);
1762
1763   /* Figure out name of output_file, stripping off .so version.  */
1764   p = strrchr (output_file, '/');
1765   if (p == 0)
1766     p = output_file;
1767   else
1768     p++;
1769   q = p;
1770   while (q)
1771     {
1772       q = strchr (q,'.');
1773       if (q == 0)
1774         {
1775           q = p + strlen (p);
1776           break;
1777         }
1778       else
1779         {
1780           if (strncmp (q, ".so", 3) == 0)
1781             {
1782               q += 3;
1783               break;
1784             }
1785           else
1786             q++;
1787         }
1788     }
1789   /* q points to null at end of the string (or . of the .so version) */
1790   prefix = xmalloc (q - p + 1);
1791   strncpy (prefix, p, q - p);
1792   prefix[q - p] = 0;
1793   for (r = prefix; *r; r++)
1794     if (!ISALNUM ((unsigned char)*r))
1795       *r = '_';
1796   if (debug)
1797     notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
1798             output_file, prefix);
1799
1800   initname = concat ("_GLOBAL__FI_", prefix, NULL);
1801   fininame = concat ("_GLOBAL__FD_", prefix, NULL);
1802
1803   free (prefix);
1804
1805   /* Write the tables as C code.  */
1806
1807   fprintf (stream, "static int count;\n");
1808   fprintf (stream, "typedef void entry_pt();\n");
1809   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1810
1811   if (frames)
1812     {
1813       write_list_with_asm (stream, "extern void *", frame_tables.first);
1814
1815       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1816       write_list (stream, "\t\t&", frame_tables.first);
1817       fprintf (stream, "\t0\n};\n");
1818
1819       /* This must match what's in frame.h.  */
1820       fprintf (stream, "struct object {\n");
1821       fprintf (stream, "  void *pc_begin;\n");
1822       fprintf (stream, "  void *pc_end;\n");
1823       fprintf (stream, "  void *fde_begin;\n");
1824       fprintf (stream, "  void *fde_array;\n");
1825       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1826       fprintf (stream, "  struct object *next;\n");
1827       fprintf (stream, "};\n");
1828
1829       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1830       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1831
1832       fprintf (stream, "static void reg_frame () {\n");
1833       fprintf (stream, "\tstatic struct object ob;\n");
1834       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1835       fprintf (stream, "\t}\n");
1836
1837       fprintf (stream, "static void dereg_frame () {\n");
1838       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1839       fprintf (stream, "\t}\n");
1840     }
1841
1842   fprintf (stream, "void %s() {\n", initname);
1843   if (constructors.number > 0 || frames)
1844     {
1845       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1846       write_list (stream, "\t\t", constructors.first);
1847       if (frames)
1848         fprintf (stream, "\treg_frame,\n");
1849       fprintf (stream, "\t};\n");
1850       fprintf (stream, "\tentry_pt **p;\n");
1851       fprintf (stream, "\tif (count++ != 0) return;\n");
1852       fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
1853       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1854     }
1855   else
1856     fprintf (stream, "\t++count;\n");
1857   fprintf (stream, "}\n");
1858   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1859   fprintf (stream, "void %s() {\n", fininame);
1860   if (destructors.number > 0 || frames)
1861     {
1862       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1863       write_list (stream, "\t\t", destructors.first);
1864       if (frames)
1865         fprintf (stream, "\tdereg_frame,\n");
1866       fprintf (stream, "\t};\n");
1867       fprintf (stream, "\tentry_pt **p;\n");
1868       fprintf (stream, "\tif (--count != 0) return;\n");
1869       fprintf (stream, "\tp = dtors;\n");
1870       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1871                destructors.number + frames);
1872     }
1873   fprintf (stream, "}\n");
1874
1875   if (shared_obj)
1876     {
1877       COLLECT_SHARED_INIT_FUNC(stream, initname);
1878       COLLECT_SHARED_FINI_FUNC(stream, fininame);
1879     }
1880 }
1881
1882 /* Write the constructor/destructor tables.  */
1883
1884 #ifndef LD_INIT_SWITCH
1885 static void
1886 write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
1887 {
1888   /* Write the tables as C code.  */
1889
1890   int frames = (frame_tables.number > 0);
1891
1892   fprintf (stream, "typedef void entry_pt();\n\n");
1893
1894   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1895
1896   if (frames)
1897     {
1898       write_list_with_asm (stream, "extern void *", frame_tables.first);
1899
1900       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1901       write_list (stream, "\t\t&", frame_tables.first);
1902       fprintf (stream, "\t0\n};\n");
1903
1904       /* This must match what's in frame.h.  */
1905       fprintf (stream, "struct object {\n");
1906       fprintf (stream, "  void *pc_begin;\n");
1907       fprintf (stream, "  void *pc_end;\n");
1908       fprintf (stream, "  void *fde_begin;\n");
1909       fprintf (stream, "  void *fde_array;\n");
1910       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1911       fprintf (stream, "  struct object *next;\n");
1912       fprintf (stream, "};\n");
1913
1914       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1915       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1916
1917       fprintf (stream, "static void reg_frame () {\n");
1918       fprintf (stream, "\tstatic struct object ob;\n");
1919       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1920       fprintf (stream, "\t}\n");
1921
1922       fprintf (stream, "static void dereg_frame () {\n");
1923       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1924       fprintf (stream, "\t}\n");
1925     }
1926
1927   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1928   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
1929   write_list (stream, "\t", constructors.first);
1930   if (frames)
1931     fprintf (stream, "\treg_frame,\n");
1932   fprintf (stream, "\t0\n};\n\n");
1933
1934   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1935
1936   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1937   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
1938   write_list (stream, "\t", destructors.first);
1939   if (frames)
1940     fprintf (stream, "\tdereg_frame,\n");
1941   fprintf (stream, "\t0\n};\n\n");
1942
1943   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1944   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
1945 }
1946 #endif /* ! LD_INIT_SWITCH */
1947
1948 static void
1949 write_c_file (FILE *stream, const char *name)
1950 {
1951   fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
1952 #ifndef LD_INIT_SWITCH
1953   if (! shared_obj)
1954     write_c_file_glob (stream, name);
1955   else
1956 #endif
1957     write_c_file_stat (stream, name);
1958   fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
1959 }
1960
1961 #ifdef COLLECT_EXPORT_LIST
1962 static void
1963 write_aix_file (FILE *stream, struct id *list)
1964 {
1965   for (; list; list = list->next)
1966     {
1967       fputs (list->name, stream);
1968       putc ('\n', stream);
1969     }
1970 }
1971 #endif
1972 \f
1973 #ifdef OBJECT_FORMAT_NONE
1974
1975 /* Generic version to scan the name list of the loaded program for
1976    the symbols g++ uses for static constructors and destructors.
1977
1978    The constructor table begins at __CTOR_LIST__ and contains a count
1979    of the number of pointers (or -1 if the constructors are built in a
1980    separate section by the linker), followed by the pointers to the
1981    constructor functions, terminated with a null pointer.  The
1982    destructor table has the same format, and begins at __DTOR_LIST__.  */
1983
1984 static void
1985 scan_prog_file (const char *prog_name, enum pass which_pass)
1986 {
1987   void (*int_handler) (int);
1988   void (*quit_handler) (int);
1989   char *real_nm_argv[4];
1990   const char **nm_argv = (const char **) real_nm_argv;
1991   int argc = 0;
1992   int pipe_fd[2];
1993   char *p, buf[1024];
1994   FILE *inf;
1995
1996   if (which_pass == PASS_SECOND)
1997     return;
1998
1999   /* If we do not have an `nm', complain.  */
2000   if (nm_file_name == 0)
2001     fatal ("cannot find `nm'");
2002
2003   nm_argv[argc++] = nm_file_name;
2004   if (NM_FLAGS[0] != '\0')
2005     nm_argv[argc++] = NM_FLAGS;
2006
2007   nm_argv[argc++] = prog_name;
2008   nm_argv[argc++] = (char *) 0;
2009
2010   if (pipe (pipe_fd) < 0)
2011     fatal_perror ("pipe");
2012
2013   inf = fdopen (pipe_fd[0], "r");
2014   if (inf == (FILE *) 0)
2015     fatal_perror ("fdopen");
2016
2017   /* Trace if needed.  */
2018   if (vflag)
2019     {
2020       const char **p_argv;
2021       const char *str;
2022
2023       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2024         fprintf (stderr, " %s", str);
2025
2026       fprintf (stderr, "\n");
2027     }
2028
2029   fflush (stdout);
2030   fflush (stderr);
2031
2032   /* Spawn child nm on pipe.  */
2033   pid = vfork ();
2034   if (pid == -1)
2035     fatal_perror (VFORK_STRING);
2036
2037   if (pid == 0)                 /* child context */
2038     {
2039       /* setup stdout */
2040       if (dup2 (pipe_fd[1], 1) < 0)
2041         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2042
2043       if (close (pipe_fd[0]) < 0)
2044         fatal_perror ("close %d", pipe_fd[0]);
2045
2046       if (close (pipe_fd[1]) < 0)
2047         fatal_perror ("close %d", pipe_fd[1]);
2048
2049       execv (nm_file_name, real_nm_argv);
2050       fatal_perror ("execv %s", nm_file_name);
2051     }
2052
2053   /* Parent context from here on.  */
2054   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
2055 #ifdef SIGQUIT
2056   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
2057 #endif
2058
2059   if (close (pipe_fd[1]) < 0)
2060     fatal_perror ("close %d", pipe_fd[1]);
2061
2062   if (debug)
2063     fprintf (stderr, "\nnm output with constructors/destructors.\n");
2064
2065   /* Read each line of nm output.  */
2066   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2067     {
2068       int ch, ch2;
2069       char *name, *end;
2070
2071       /* If it contains a constructor or destructor name, add the name
2072          to the appropriate list.  */
2073
2074       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2075         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2076           break;
2077
2078       if (ch != '_')
2079         continue;
2080
2081       name = p;
2082       /* Find the end of the symbol name.
2083          Do not include `|', because Encore nm can tack that on the end.  */
2084       for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2085            end++)
2086         continue;
2087
2088
2089       *end = '\0';
2090       switch (is_ctor_dtor (name))
2091         {
2092         case 1:
2093           if (which_pass != PASS_LIB)
2094             add_to_list (&constructors, name);
2095           break;
2096
2097         case 2:
2098           if (which_pass != PASS_LIB)
2099             add_to_list (&destructors, name);
2100           break;
2101
2102         case 3:
2103           if (which_pass != PASS_LIB)
2104             fatal ("init function found in object %s", prog_name);
2105 #ifndef LD_INIT_SWITCH
2106           add_to_list (&constructors, name);
2107 #endif
2108           break;
2109
2110         case 4:
2111           if (which_pass != PASS_LIB)
2112             fatal ("fini function found in object %s", prog_name);
2113 #ifndef LD_FINI_SWITCH
2114           add_to_list (&destructors, name);
2115 #endif
2116           break;
2117
2118         case 5:
2119           if (which_pass != PASS_LIB)
2120             add_to_list (&frame_tables, name);
2121           break;
2122
2123         default:                /* not a constructor or destructor */
2124           continue;
2125         }
2126
2127       if (debug)
2128         fprintf (stderr, "\t%s\n", buf);
2129     }
2130
2131   if (debug)
2132     fprintf (stderr, "\n");
2133
2134   if (fclose (inf) != 0)
2135     fatal_perror ("fclose");
2136
2137   do_wait (nm_file_name);
2138
2139   signal (SIGINT,  int_handler);
2140 #ifdef SIGQUIT
2141   signal (SIGQUIT, quit_handler);
2142 #endif
2143 }
2144
2145 #if SUNOS4_SHARED_LIBRARIES
2146
2147 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2148    that the output file depends upon and their initialization/finalization
2149    routines, if any.  */
2150
2151 #include <a.out.h>
2152 #include <fcntl.h>
2153 #include <link.h>
2154 #include <sys/mman.h>
2155 #include <sys/param.h>
2156 #include <unistd.h>
2157 #include <sys/dir.h>
2158
2159 /* pointers to the object file */
2160 unsigned object;        /* address of memory mapped file */
2161 unsigned objsize;       /* size of memory mapped to file */
2162 char * code;            /* pointer to code segment */
2163 char * data;            /* pointer to data segment */
2164 struct nlist *symtab;   /* pointer to symbol table */
2165 struct link_dynamic *ld;
2166 struct link_dynamic_2 *ld_2;
2167 struct head libraries;
2168
2169 /* Map the file indicated by NAME into memory and store its address.  */
2170
2171 static void
2172 mapfile (const char *name)
2173 {
2174   int fp;
2175   struct stat s;
2176   if ((fp = open (name, O_RDONLY)) == -1)
2177     fatal ("unable to open file '%s'", name);
2178   if (fstat (fp, &s) == -1)
2179     fatal ("unable to stat file '%s'", name);
2180
2181   objsize = s.st_size;
2182   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2183                             fp, 0);
2184   if (object == (unsigned)-1)
2185     fatal ("unable to mmap file '%s'", name);
2186
2187   close (fp);
2188 }
2189
2190 /* Helpers for locatelib.  */
2191
2192 static const char *libname;
2193
2194 static int
2195 libselect (struct direct *d)
2196 {
2197   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2198 }
2199
2200 /* If one file has an additional numeric extension past LIBNAME, then put
2201    that one first in the sort.  If both files have additional numeric
2202    extensions, then put the one with the higher number first in the sort.
2203
2204    We must verify that the extension is numeric, because Sun saves the
2205    original versions of patched libraries with a .FCS extension.  Files with
2206    invalid extensions must go last in the sort, so that they will not be used.  */
2207
2208 static int
2209 libcompare (struct direct **d1, struct direct **d2)
2210 {
2211   int i1, i2 = strlen (libname);
2212   char *e1 = (*d1)->d_name + i2;
2213   char *e2 = (*d2)->d_name + i2;
2214
2215   while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2216          && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2217     {
2218       ++e1;
2219       ++e2;
2220       i1 = strtol (e1, &e1, 10);
2221       i2 = strtol (e2, &e2, 10);
2222       if (i1 != i2)
2223         return i1 - i2;
2224     }
2225
2226   if (*e1)
2227     {
2228       /* It has a valid numeric extension, prefer this one.  */
2229       if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2230         return 1;
2231       /* It has an invalid numeric extension, must prefer the other one.  */
2232       else
2233         return -1;
2234     }
2235   else if (*e2)
2236     {
2237       /* It has a valid numeric extension, prefer this one.  */
2238       if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2239         return -1;
2240       /* It has an invalid numeric extension, must prefer the other one.  */
2241       else
2242         return 1;
2243     }
2244   else
2245     return 0;
2246 }
2247
2248 /* Given the name NAME of a dynamic dependency, find its pathname and add
2249    it to the list of libraries.  */
2250
2251 static void
2252 locatelib (const char *name)
2253 {
2254   static const char **l;
2255   static int cnt;
2256   char buf[MAXPATHLEN];
2257   char *p, *q;
2258   const char **pp;
2259
2260   if (l == 0)
2261     {
2262       char *ld_rules;
2263       char *ldr = 0;
2264       /* counting elements in array, need 1 extra for null */
2265       cnt = 1;
2266       ld_rules = (char *) (ld_2->ld_rules + code);
2267       if (ld_rules)
2268         {
2269           cnt++;
2270           for (; *ld_rules != 0; ld_rules++)
2271             if (*ld_rules == ':')
2272               cnt++;
2273           ld_rules = (char *) (ld_2->ld_rules + code);
2274           ldr = xstrdup (ld_rules);
2275         }
2276       p = getenv ("LD_LIBRARY_PATH");
2277       q = 0;
2278       if (p)
2279         {
2280           cnt++;
2281           for (q = p ; *q != 0; q++)
2282             if (*q == ':')
2283               cnt++;
2284           q = xstrdup (p);
2285         }
2286       l = xmalloc ((cnt + 3) * sizeof (char *));
2287       pp = l;
2288       if (ldr)
2289         {
2290           *pp++ = ldr;
2291           for (; *ldr != 0; ldr++)
2292             if (*ldr == ':')
2293               {
2294                 *ldr++ = 0;
2295                 *pp++ = ldr;
2296               }
2297         }
2298       if (q)
2299         {
2300           *pp++ = q;
2301           for (; *q != 0; q++)
2302             if (*q == ':')
2303               {
2304                 *q++ = 0;
2305                 *pp++ = q;
2306               }
2307         }
2308       /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2309       *pp++ = "/lib";
2310       *pp++ = "/usr/lib";
2311       *pp++ = "/usr/local/lib";
2312       *pp = 0;
2313     }
2314   libname = name;
2315   for (pp = l; *pp != 0 ; pp++)
2316     {
2317       struct direct **namelist;
2318       int entries;
2319       if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2320         {
2321           sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2322           add_to_list (&libraries, buf);
2323           if (debug)
2324             fprintf (stderr, "%s\n", buf);
2325           break;
2326         }
2327     }
2328   if (*pp == 0)
2329     {
2330       if (debug)
2331         notice ("not found\n");
2332       else
2333         fatal ("dynamic dependency %s not found", name);
2334     }
2335 }
2336
2337 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2338    that it depends upon and any constructors or destructors they contain.  */
2339
2340 static void
2341 scan_libraries (const char *prog_name)
2342 {
2343   struct exec *header;
2344   char *base;
2345   struct link_object *lo;
2346   char buff[MAXPATHLEN];
2347   struct id *list;
2348
2349   mapfile (prog_name);
2350   header = (struct exec *)object;
2351   if (N_BADMAG (*header))
2352     fatal ("bad magic number in file '%s'", prog_name);
2353   if (header->a_dynamic == 0)
2354     return;
2355
2356   code = (char *) (N_TXTOFF (*header) + (long) header);
2357   data = (char *) (N_DATOFF (*header) + (long) header);
2358   symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2359
2360   if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2361     {
2362       /* shared object */
2363       ld = (struct link_dynamic *) (symtab->n_value + code);
2364       base = code;
2365     }
2366   else
2367     {
2368       /* executable */
2369       ld = (struct link_dynamic *) data;
2370       base = code-PAGSIZ;
2371     }
2372
2373   if (debug)
2374     notice ("dynamic dependencies.\n");
2375
2376   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2377   for (lo = (struct link_object *) ld_2->ld_need; lo;
2378        lo = (struct link_object *) lo->lo_next)
2379     {
2380       char *name;
2381       lo = (struct link_object *) ((long) lo + code);
2382       name = (char *) (code + lo->lo_name);
2383       if (lo->lo_library)
2384         {
2385           if (debug)
2386             fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2387           sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2388           locatelib (buff);
2389         }
2390       else
2391         {
2392           if (debug)
2393             fprintf (stderr, "\t%s\n", name);
2394           add_to_list (&libraries, name);
2395         }
2396     }
2397
2398   if (debug)
2399     fprintf (stderr, "\n");
2400
2401   /* now iterate through the library list adding their symbols to
2402      the list.  */
2403   for (list = libraries.first; list; list = list->next)
2404     scan_prog_file (list->name, PASS_LIB);
2405 }
2406
2407 #else  /* SUNOS4_SHARED_LIBRARIES */
2408 #ifdef LDD_SUFFIX
2409
2410 /* Use the List Dynamic Dependencies program to find shared libraries that
2411    the output file depends upon and their initialization/finalization
2412    routines, if any.  */
2413
2414 static void
2415 scan_libraries (const char *prog_name)
2416 {
2417   static struct head libraries;         /* list of shared libraries found */
2418   struct id *list;
2419   void (*int_handler) (int);
2420   void (*quit_handler) (int);
2421   char *real_ldd_argv[4];
2422   const char **ldd_argv = (const char **) real_ldd_argv;
2423   int argc = 0;
2424   int pipe_fd[2];
2425   char buf[1024];
2426   FILE *inf;
2427
2428   /* If we do not have an `ldd', complain.  */
2429   if (ldd_file_name == 0)
2430     {
2431       error ("cannot find `ldd'");
2432       return;
2433     }
2434
2435   ldd_argv[argc++] = ldd_file_name;
2436   ldd_argv[argc++] = prog_name;
2437   ldd_argv[argc++] = (char *) 0;
2438
2439   if (pipe (pipe_fd) < 0)
2440     fatal_perror ("pipe");
2441
2442   inf = fdopen (pipe_fd[0], "r");
2443   if (inf == (FILE *) 0)
2444     fatal_perror ("fdopen");
2445
2446   /* Trace if needed.  */
2447   if (vflag)
2448     {
2449       const char **p_argv;
2450       const char *str;
2451
2452       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2453         fprintf (stderr, " %s", str);
2454
2455       fprintf (stderr, "\n");
2456     }
2457
2458   fflush (stdout);
2459   fflush (stderr);
2460
2461   /* Spawn child ldd on pipe.  */
2462   pid = vfork ();
2463   if (pid == -1)
2464     fatal_perror (VFORK_STRING);
2465
2466   if (pid == 0)                 /* child context */
2467     {
2468       /* setup stdout */
2469       if (dup2 (pipe_fd[1], 1) < 0)
2470         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2471
2472       if (close (pipe_fd[0]) < 0)
2473         fatal_perror ("close %d", pipe_fd[0]);
2474
2475       if (close (pipe_fd[1]) < 0)
2476         fatal_perror ("close %d", pipe_fd[1]);
2477
2478       execv (ldd_file_name, real_ldd_argv);
2479       fatal_perror ("execv %s", ldd_file_name);
2480     }
2481
2482   /* Parent context from here on.  */
2483   int_handler  = (void (*) (int))) signal (SIGINT,  SIG_IGN;
2484 #ifdef SIGQUIT
2485   quit_handler = (void (*) (int))) signal (SIGQUIT, SIG_IGN;
2486 #endif
2487
2488   if (close (pipe_fd[1]) < 0)
2489     fatal_perror ("close %d", pipe_fd[1]);
2490
2491   if (debug)
2492     notice ("\nldd output with constructors/destructors.\n");
2493
2494   /* Read each line of ldd output.  */
2495   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2496     {
2497       int ch2;
2498       char *name, *end, *p = buf;
2499
2500       /* Extract names of libraries and add to list.  */
2501       PARSE_LDD_OUTPUT (p);
2502       if (p == 0)
2503         continue;
2504
2505       name = p;
2506       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2507         fatal ("dynamic dependency %s not found", buf);
2508
2509       /* Find the end of the symbol name.  */
2510       for (end = p;
2511            (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2512            end++)
2513         continue;
2514       *end = '\0';
2515
2516       if (access (name, R_OK) == 0)
2517         add_to_list (&libraries, name);
2518       else
2519         fatal ("unable to open dynamic dependency '%s'", buf);
2520
2521       if (debug)
2522         fprintf (stderr, "\t%s\n", buf);
2523     }
2524   if (debug)
2525     fprintf (stderr, "\n");
2526
2527   if (fclose (inf) != 0)
2528     fatal_perror ("fclose");
2529
2530   do_wait (ldd_file_name);
2531
2532   signal (SIGINT,  int_handler);
2533 #ifdef SIGQUIT
2534   signal (SIGQUIT, quit_handler);
2535 #endif
2536
2537   /* now iterate through the library list adding their symbols to
2538      the list.  */
2539   for (list = libraries.first; list; list = list->next)
2540     scan_prog_file (list->name, PASS_LIB);
2541 }
2542
2543 #endif /* LDD_SUFFIX */
2544 #endif /* SUNOS4_SHARED_LIBRARIES */
2545
2546 #endif /* OBJECT_FORMAT_NONE */
2547
2548 \f
2549 /*
2550  * COFF specific stuff.
2551  */
2552
2553 #ifdef OBJECT_FORMAT_COFF
2554
2555 #if defined(EXTENDED_COFF)
2556
2557 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2558 #   define GCC_SYMENT           SYMR
2559 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc || (X).st == stGlobal)
2560 #   define GCC_SYMINC(X)        (1)
2561 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
2562 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
2563
2564 #else
2565
2566 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
2567 #   define GCC_SYMENT           SYMENT
2568 #   define GCC_OK_SYMBOL(X) \
2569      (((X).n_sclass == C_EXT) && \
2570       ((X).n_scnum > N_UNDEF) && \
2571       (aix64_flag \
2572        || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2573            || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2574 #   define GCC_UNDEF_SYMBOL(X) \
2575      (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2576 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
2577 #   define GCC_SYMZERO(X)       0
2578
2579 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
2580 #ifdef _AIX51
2581 #   define GCC_CHECK_HDR(X) \
2582      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2583       || (HEADER (X).f_magic == 0767 && aix64_flag))
2584 #else
2585 #   define GCC_CHECK_HDR(X) \
2586      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2587       || (HEADER (X).f_magic == 0757 && aix64_flag))
2588 #endif
2589
2590 #endif
2591
2592 #ifdef COLLECT_EXPORT_LIST
2593 /* Array of standard AIX libraries which should not
2594    be scanned for ctors/dtors.  */
2595 static const char *const aix_std_libs[] = {
2596   "/unix",
2597   "/lib/libc.a",
2598   "/lib/libm.a",
2599   "/lib/libc_r.a",
2600   "/lib/libm_r.a",
2601   "/usr/lib/libc.a",
2602   "/usr/lib/libm.a",
2603   "/usr/lib/libc_r.a",
2604   "/usr/lib/libm_r.a",
2605   "/usr/lib/threads/libc.a",
2606   "/usr/ccs/lib/libc.a",
2607   "/usr/ccs/lib/libm.a",
2608   "/usr/ccs/lib/libc_r.a",
2609   "/usr/ccs/lib/libm_r.a",
2610   NULL
2611 };
2612
2613 /* This function checks the filename and returns 1
2614    if this name matches the location of a standard AIX library.  */
2615 static int ignore_library (const char *);
2616 static int
2617 ignore_library (const char *name)
2618 {
2619   const char *const *p = &aix_std_libs[0];
2620   while (*p++ != NULL)
2621     if (! strcmp (name, *p)) return 1;
2622   return 0;
2623 }
2624 #endif /* COLLECT_EXPORT_LIST */
2625
2626 #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
2627 extern char *ldgetname (LDFILE *, GCC_SYMENT *);
2628 #endif
2629
2630 /* COFF version to scan the name list of the loaded program for
2631    the symbols g++ uses for static constructors and destructors.
2632
2633    The constructor table begins at __CTOR_LIST__ and contains a count
2634    of the number of pointers (or -1 if the constructors are built in a
2635    separate section by the linker), followed by the pointers to the
2636    constructor functions, terminated with a null pointer.  The
2637    destructor table has the same format, and begins at __DTOR_LIST__.  */
2638
2639 static void
2640 scan_prog_file (const char *prog_name, enum pass which_pass)
2641 {
2642   LDFILE *ldptr = NULL;
2643   int sym_index, sym_count;
2644   int is_shared = 0;
2645
2646   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2647     return;
2648
2649 #ifdef COLLECT_EXPORT_LIST
2650   /* We do not need scanning for some standard C libraries.  */
2651   if (which_pass == PASS_FIRST && ignore_library (prog_name))
2652     return;
2653
2654   /* On AIX we have a loop, because there is not much difference
2655      between an object and an archive. This trick allows us to
2656      eliminate scan_libraries() function.  */
2657   do
2658     {
2659 #endif
2660       /* Some platforms (e.g. OSF4) declare ldopen as taking a
2661          non-const char * filename parameter, even though it will not
2662          modify that string.  So we must cast away const-ness here,
2663          which will cause -Wcast-qual to burp.  */
2664       if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2665         {
2666           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2667             fatal ("%s: not a COFF file", prog_name);
2668
2669           if (GCC_CHECK_HDR (ldptr))
2670             {
2671               sym_count = GCC_SYMBOLS (ldptr);
2672               sym_index = GCC_SYMZERO (ldptr);
2673
2674 #ifdef COLLECT_EXPORT_LIST
2675               /* Is current archive member a shared object?  */
2676               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2677 #endif
2678
2679               while (sym_index < sym_count)
2680                 {
2681                   GCC_SYMENT symbol;
2682
2683                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2684                     break;
2685                   sym_index += GCC_SYMINC (symbol);
2686
2687                   if (GCC_OK_SYMBOL (symbol))
2688                     {
2689                       char *name;
2690
2691                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
2692                         continue;               /* should never happen */
2693
2694 #ifdef XCOFF_DEBUGGING_INFO
2695                       /* All AIX function names have a duplicate entry
2696                          beginning with a dot.  */
2697                       if (*name == '.')
2698                         ++name;
2699 #endif
2700
2701                       switch (is_ctor_dtor (name))
2702                         {
2703                         case 1:
2704                           if (! is_shared)
2705                             add_to_list (&constructors, name);
2706 #ifdef COLLECT_EXPORT_LIST
2707                           if (which_pass == PASS_OBJ)
2708                             add_to_list (&exports, name);
2709 #endif
2710                           break;
2711
2712                         case 2:
2713                           if (! is_shared)
2714                             add_to_list (&destructors, name);
2715 #ifdef COLLECT_EXPORT_LIST
2716                           if (which_pass == PASS_OBJ)
2717                             add_to_list (&exports, name);
2718 #endif
2719                           break;
2720
2721 #ifdef COLLECT_EXPORT_LIST
2722                         case 3:
2723 #ifndef LD_INIT_SWITCH
2724                           if (is_shared)
2725                             add_to_list (&constructors, name);
2726 #endif
2727                           break;
2728
2729                         case 4:
2730 #ifndef LD_INIT_SWITCH
2731                           if (is_shared)
2732                             add_to_list (&destructors, name);
2733 #endif
2734                           break;
2735 #endif
2736
2737                         case 5:
2738                           if (! is_shared)
2739                             add_to_list (&frame_tables, name);
2740 #ifdef COLLECT_EXPORT_LIST
2741                           if (which_pass == PASS_OBJ)
2742                             add_to_list (&exports, name);
2743 #endif
2744                           break;
2745
2746                         default:        /* not a constructor or destructor */
2747 #ifdef COLLECT_EXPORT_LIST
2748                           /* If we are building a shared object on AIX we need
2749                              to explicitly export all global symbols.  */
2750                           if (shared_obj)
2751                             {
2752                               if (which_pass == PASS_OBJ && (! export_flag))
2753                                 add_to_list (&exports, name);
2754                             }
2755 #endif
2756                           continue;
2757                         }
2758
2759                       if (debug)
2760 #if !defined(EXTENDED_COFF)
2761                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2762                                  symbol.n_scnum, symbol.n_sclass,
2763                                  (symbol.n_type ? "0" : ""), symbol.n_type,
2764                                  name);
2765 #else
2766                         fprintf (stderr,
2767                                  "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2768                                  symbol.iss, (long) symbol.value, symbol.index, name);
2769 #endif
2770                     }
2771                 }
2772             }
2773 #ifdef COLLECT_EXPORT_LIST
2774           else
2775             {
2776               /* If archive contains both 32-bit and 64-bit objects,
2777                  we want to skip objects in other mode so mismatch normal.  */
2778               if (debug)
2779                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2780                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
2781             }
2782 #endif
2783         }
2784       else
2785         {
2786           fatal ("%s: cannot open as COFF file", prog_name);
2787         }
2788 #ifdef COLLECT_EXPORT_LIST
2789       /* On AIX loop continues while there are more members in archive.  */
2790     }
2791   while (ldclose (ldptr) == FAILURE);
2792 #else
2793   /* Otherwise we simply close ldptr.  */
2794   (void) ldclose(ldptr);
2795 #endif
2796 }
2797 #endif /* OBJECT_FORMAT_COFF */
2798
2799 #ifdef COLLECT_EXPORT_LIST
2800 /* Given a library name without "lib" prefix, this function
2801    returns a full library name including a path.  */
2802 static char *
2803 resolve_lib_name (const char *name)
2804 {
2805   char *lib_buf;
2806   int i, j, l = 0;
2807
2808   for (i = 0; libpaths[i]; i++)
2809     if (libpaths[i]->max_len > l)
2810       l = libpaths[i]->max_len;
2811
2812   lib_buf = xmalloc (l + strlen(name) + 10);
2813
2814   for (i = 0; libpaths[i]; i++)
2815     {
2816       struct prefix_list *list = libpaths[i]->plist;
2817       for (; list; list = list->next)
2818         {
2819           /* The following lines are needed because path_prefix list
2820              may contain directories both with trailing '/' and
2821              without it.  */
2822           const char *p = "";
2823           if (list->prefix[strlen(list->prefix)-1] != '/')
2824             p = "/";
2825           for (j = 0; libexts[j]; j++)
2826             {
2827               sprintf (lib_buf, "%s%slib%s.%s",
2828                        list->prefix, p, name, libexts[j]);
2829 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2830               if (file_exists (lib_buf))
2831                 {
2832 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2833                   return (lib_buf);
2834                 }
2835             }
2836         }
2837     }
2838   if (debug)
2839     fprintf (stderr, "not found\n");
2840   else
2841     fatal ("library lib%s not found", name);
2842   return (NULL);
2843 }
2844 #endif /* COLLECT_EXPORT_LIST */