OSDN Git Service

* alias.c: Fix comment formatting.
[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-profile-arcs -fno-test-coverage -fno-branch-probabilities
888      -fno-exceptions -w */
889   num_c_args += 5;
890
891   c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
892
893   if (argc < 2)
894     fatal ("no arguments");
895
896 #ifdef SIGQUIT
897   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
898     signal (SIGQUIT, handler);
899 #endif
900   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
901     signal (SIGINT, handler);
902 #ifdef SIGALRM
903   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
904     signal (SIGALRM, handler);
905 #endif
906 #ifdef SIGHUP
907   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
908     signal (SIGHUP, handler);
909 #endif
910   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
911     signal (SIGSEGV, handler);
912 #ifdef SIGBUS
913   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
914     signal (SIGBUS, handler);
915 #endif
916
917   /* Extract COMPILER_PATH and PATH into our prefix list.  */
918   prefix_from_env ("COMPILER_PATH", &cpath);
919   prefix_from_env ("PATH", &path);
920
921   /* Try to discover a valid linker/nm/strip to use.  */
922
923   /* Maybe we know the right file to use (if not cross).  */
924   ld_file_name = 0;
925 #ifdef DEFAULT_LINKER
926   if (access (DEFAULT_LINKER, X_OK) == 0)
927     ld_file_name = DEFAULT_LINKER;
928   if (ld_file_name == 0)
929 #endif
930 #ifdef REAL_LD_FILE_NAME
931   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
932   if (ld_file_name == 0)
933 #endif
934   /* Search the (target-specific) compiler dirs for ld'.  */
935   ld_file_name = find_a_file (&cpath, real_ld_suffix);
936   /* Likewise for `collect-ld'.  */
937   if (ld_file_name == 0)
938     ld_file_name = find_a_file (&cpath, collect_ld_suffix);
939   /* Search the compiler directories for `ld'.  We have protection against
940      recursive calls in find_a_file.  */
941   if (ld_file_name == 0)
942     ld_file_name = find_a_file (&cpath, ld_suffix);
943   /* Search the ordinary system bin directories
944      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
945   if (ld_file_name == 0)
946     ld_file_name = find_a_file (&path, full_ld_suffix);
947
948 #ifdef REAL_NM_FILE_NAME
949   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
950   if (nm_file_name == 0)
951 #endif
952   nm_file_name = find_a_file (&cpath, gnm_suffix);
953   if (nm_file_name == 0)
954     nm_file_name = find_a_file (&path, full_gnm_suffix);
955   if (nm_file_name == 0)
956     nm_file_name = find_a_file (&cpath, nm_suffix);
957   if (nm_file_name == 0)
958     nm_file_name = find_a_file (&path, full_nm_suffix);
959
960 #ifdef LDD_SUFFIX
961   ldd_file_name = find_a_file (&cpath, ldd_suffix);
962   if (ldd_file_name == 0)
963     ldd_file_name = find_a_file (&path, full_ldd_suffix);
964 #endif
965
966 #ifdef REAL_STRIP_FILE_NAME
967   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
968   if (strip_file_name == 0)
969 #endif
970   strip_file_name = find_a_file (&cpath, gstrip_suffix);
971   if (strip_file_name == 0)
972     strip_file_name = find_a_file (&path, full_gstrip_suffix);
973   if (strip_file_name == 0)
974     strip_file_name = find_a_file (&cpath, strip_suffix);
975   if (strip_file_name == 0)
976     strip_file_name = find_a_file (&path, full_strip_suffix);
977
978   /* Determine the full path name of the C compiler to use.  */
979   c_file_name = getenv ("COLLECT_GCC");
980   if (c_file_name == 0)
981     {
982 #ifdef CROSS_COMPILE
983       c_file_name = concat (target_machine, "-gcc", NULL);
984 #else
985       c_file_name = "gcc";
986 #endif
987     }
988
989   p = find_a_file (&cpath, c_file_name);
990
991   /* Here it should be safe to use the system search path since we should have
992      already qualified the name of the compiler when it is needed.  */
993   if (p == 0)
994     p = find_a_file (&path, c_file_name);
995
996   if (p)
997     c_file_name = p;
998
999   *ld1++ = *ld2++ = ld_file_name;
1000
1001   /* Make temp file names.  */
1002   c_file = make_temp_file (".c");
1003   o_file = make_temp_file (".o");
1004 #ifdef COLLECT_EXPORT_LIST
1005   export_file = make_temp_file (".x");
1006 #endif
1007   ldout = make_temp_file (".ld");
1008   *c_ptr++ = c_file_name;
1009   *c_ptr++ = "-x";
1010   *c_ptr++ = "c";
1011   *c_ptr++ = "-c";
1012   *c_ptr++ = "-o";
1013   *c_ptr++ = o_file;
1014
1015 #ifdef COLLECT_EXPORT_LIST
1016   /* Generate a list of directories from LIBPATH.  */
1017   prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1018   /* Add to this list also two standard directories where
1019      AIX loader always searches for libraries.  */
1020   add_prefix (&libpath_lib_dirs, "/lib");
1021   add_prefix (&libpath_lib_dirs, "/usr/lib");
1022 #endif
1023
1024   /* Get any options that the upper GCC wants to pass to the sub-GCC.
1025
1026      AIX support needs to know if -shared has been specified before
1027      parsing commandline arguments.  */
1028
1029   p = getenv ("COLLECT_GCC_OPTIONS");
1030   while (p && *p)
1031     {
1032       const char *q = extract_string (&p);
1033       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1034         *c_ptr++ = xstrdup (q);
1035       if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1036         *c_ptr++ = xstrdup (q);
1037       if (strcmp (q, "-shared") == 0)
1038         shared_obj = 1;
1039       if (*q == '-' && q[1] == 'B')
1040         {
1041           *c_ptr++ = xstrdup (q);
1042           if (q[2] == 0)
1043             {
1044               q = extract_string (&p);
1045               *c_ptr++ = xstrdup (q);
1046             }
1047         }
1048     }
1049   obstack_free (&temporary_obstack, temporary_firstobj);
1050   *c_ptr++ = "-fno-profile-arcs";
1051   *c_ptr++ = "-fno-test-coverage";
1052   *c_ptr++ = "-fno-branch-probabilities";
1053   *c_ptr++ = "-fno-exceptions";
1054   *c_ptr++ = "-w";
1055
1056   /* !!! When GCC calls collect2,
1057      it does not know whether it is calling collect2 or ld.
1058      So collect2 cannot meaningfully understand any options
1059      except those ld understands.
1060      If you propose to make GCC pass some other option,
1061      just imagine what will happen if ld is really ld!!!  */
1062
1063   /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
1064   /* After the first file, put in the c++ rt0.  */
1065
1066   first_file = 1;
1067   while ((arg = *++argv) != (char *) 0)
1068     {
1069       *ld1++ = *ld2++ = arg;
1070
1071       if (arg[0] == '-')
1072         {
1073           switch (arg[1])
1074             {
1075 #ifdef COLLECT_EXPORT_LIST
1076             /* We want to disable automatic exports on AIX when user
1077                explicitly puts an export list in command line */
1078             case 'b':
1079               if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1080                 export_flag = 1;
1081               else if (arg[2] == '6' && arg[3] == '4')
1082                 aix64_flag = 1;
1083               break;
1084 #endif
1085
1086             case 'd':
1087               if (!strcmp (arg, "-debug"))
1088                 {
1089                   /* Already parsed.  */
1090                   ld1--;
1091                   ld2--;
1092                 }
1093               break;
1094
1095             case 'l':
1096               if (first_file)
1097                 {
1098                   /* place o_file BEFORE this argument! */
1099                   first_file = 0;
1100                   ld2--;
1101                   *ld2++ = o_file;
1102                   *ld2++ = arg;
1103                 }
1104 #ifdef COLLECT_EXPORT_LIST
1105               {
1106                 /* Resolving full library name.  */
1107                 const char *s = resolve_lib_name (arg+2);
1108
1109                 /* Saving a full library name.  */
1110                 add_to_list (&libs, s);
1111               }
1112 #endif
1113               break;
1114
1115 #ifdef COLLECT_EXPORT_LIST
1116             /* Saving directories where to search for libraries.  */
1117             case 'L':
1118               add_prefix (&cmdline_lib_dirs, arg+2);
1119               break;
1120 #else
1121 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1122             case 'L':
1123               if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
1124                 --ld1;
1125               break;
1126 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1127 #endif
1128
1129             case 'o':
1130               if (arg[2] == '\0')
1131                 output_file = *ld1++ = *ld2++ = *++argv;
1132               else if (1
1133 #ifdef SWITCHES_NEED_SPACES
1134                        && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1135 #endif
1136                        )
1137
1138                 output_file = &arg[2];
1139               break;
1140
1141             case 'r':
1142               if (arg[2] == '\0')
1143                 rflag = 1;
1144               break;
1145
1146             case 's':
1147               if (arg[2] == '\0' && do_collecting)
1148                 {
1149                   /* We must strip after the nm run, otherwise C++ linking
1150                      will not work.  Thus we strip in the second ld run, or
1151                      else with strip if there is no second ld run.  */
1152                   strip_flag = 1;
1153                   ld1--;
1154                 }
1155               break;
1156
1157             case 'v':
1158               if (arg[2] == '\0')
1159                 vflag = 1;
1160               break;
1161             }
1162         }
1163       else if ((p = strrchr (arg, '.')) != (char *) 0
1164                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1165                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
1166                    || strcmp (p, ".obj") == 0))
1167         {
1168           if (first_file)
1169             {
1170               first_file = 0;
1171               if (p[1] == 'o')
1172                 *ld2++ = o_file;
1173               else
1174                 {
1175                   /* place o_file BEFORE this argument! */
1176                   ld2--;
1177                   *ld2++ = o_file;
1178                   *ld2++ = arg;
1179                 }
1180             }
1181           if (p[1] == 'o' || p[1] == 'l')
1182             *object++ = arg;
1183 #ifdef COLLECT_EXPORT_LIST
1184           /* libraries can be specified directly, i.e. without -l flag.  */
1185           else
1186             {
1187               /* Saving a full library name.  */
1188               add_to_list (&libs, arg);
1189             }
1190 #endif
1191         }
1192     }
1193
1194 #ifdef COLLECT_EXPORT_LIST
1195   /* This is added only for debugging purposes.  */
1196   if (debug)
1197     {
1198       fprintf (stderr, "List of libraries:\n");
1199       dump_list (stderr, "\t", libs.first);
1200     }
1201
1202   /* The AIX linker will discard static constructors in object files if
1203      nothing else in the file is referenced, so look at them first.  */
1204   {
1205       const char **export_object_lst = (const char **)object_lst;
1206
1207       while (export_object_lst < object)
1208         scan_prog_file (*export_object_lst++, PASS_OBJ);
1209   }
1210   {
1211     struct id *list = libs.first;
1212
1213     for (; list; list = list->next)
1214       scan_prog_file (list->name, PASS_FIRST);
1215   }
1216
1217   if (exports.first)
1218     {
1219       char *buf = concat ("-bE:", export_file, NULL);
1220
1221       *ld1++ = buf;
1222       *ld2++ = buf;
1223
1224       exportf = fopen (export_file, "w");
1225       if (exportf == (FILE *) 0)
1226         fatal_perror ("fopen %s", export_file);
1227       write_aix_file (exportf, exports.first);
1228       if (fclose (exportf))
1229         fatal_perror ("fclose %s", export_file);
1230     }
1231 #endif
1232
1233   *c_ptr++ = c_file;
1234   *c_ptr = *ld1 = *object = (char *) 0;
1235
1236   if (vflag)
1237     {
1238       notice ("collect2 version %s", version_string);
1239 #ifdef TARGET_VERSION
1240       TARGET_VERSION;
1241 #endif
1242       fprintf (stderr, "\n");
1243     }
1244
1245   if (debug)
1246     {
1247       const char *ptr;
1248       fprintf (stderr, "ld_file_name        = %s\n",
1249                (ld_file_name ? ld_file_name : "not found"));
1250       fprintf (stderr, "c_file_name         = %s\n",
1251                (c_file_name ? c_file_name : "not found"));
1252       fprintf (stderr, "nm_file_name        = %s\n",
1253                (nm_file_name ? nm_file_name : "not found"));
1254 #ifdef LDD_SUFFIX
1255       fprintf (stderr, "ldd_file_name       = %s\n",
1256                (ldd_file_name ? ldd_file_name : "not found"));
1257 #endif
1258       fprintf (stderr, "strip_file_name     = %s\n",
1259                (strip_file_name ? strip_file_name : "not found"));
1260       fprintf (stderr, "c_file              = %s\n",
1261                (c_file ? c_file : "not found"));
1262       fprintf (stderr, "o_file              = %s\n",
1263                (o_file ? o_file : "not found"));
1264
1265       ptr = getenv ("COLLECT_GCC_OPTIONS");
1266       if (ptr)
1267         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1268
1269       ptr = getenv ("COLLECT_GCC");
1270       if (ptr)
1271         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1272
1273       ptr = getenv ("COMPILER_PATH");
1274       if (ptr)
1275         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1276
1277       ptr = getenv (LIBRARY_PATH_ENV);
1278       if (ptr)
1279         fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
1280
1281       fprintf (stderr, "\n");
1282     }
1283
1284   /* Load the program, searching all libraries and attempting to provide
1285      undefined symbols from repository information.  */
1286
1287   /* On AIX we do this later.  */
1288 #ifndef COLLECT_EXPORT_LIST
1289   do_tlink (ld1_argv, object_lst);
1290 #endif
1291
1292   /* If -r or they will be run via some other method, do not build the
1293      constructor or destructor list, just return now.  */
1294   if (rflag
1295 #ifndef COLLECT_EXPORT_LIST
1296       || ! do_collecting
1297 #endif
1298       )
1299     {
1300 #ifdef COLLECT_EXPORT_LIST
1301       /* Do the link we avoided above if we are exiting.  */
1302       do_tlink (ld1_argv, object_lst);
1303
1304       /* But make sure we delete the export file we may have created.  */
1305       if (export_file != 0 && export_file[0])
1306         maybe_unlink (export_file);
1307 #endif
1308       maybe_unlink (c_file);
1309       maybe_unlink (o_file);
1310       return 0;
1311     }
1312
1313   /* Examine the namelist with nm and search it for static constructors
1314      and destructors to call.
1315      Write the constructor and destructor tables to a .s file and reload.  */
1316
1317   /* On AIX we already scanned for global constructors/destructors.  */
1318 #ifndef COLLECT_EXPORT_LIST
1319   scan_prog_file (output_file, PASS_FIRST);
1320 #endif
1321
1322 #ifdef SCAN_LIBRARIES
1323   scan_libraries (output_file);
1324 #endif
1325
1326   if (debug)
1327     {
1328       notice ("%d constructor(s) found\n", constructors.number);
1329       notice ("%d destructor(s)  found\n", destructors.number);
1330       notice ("%d frame table(s) found\n", frame_tables.number);
1331     }
1332
1333   if (constructors.number == 0 && destructors.number == 0
1334       && frame_tables.number == 0
1335 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1336       /* If we will be running these functions ourselves, we want to emit
1337          stubs into the shared library so that we do not have to relink
1338          dependent programs when we add static objects.  */
1339       && ! shared_obj
1340 #endif
1341       )
1342     {
1343 #ifdef COLLECT_EXPORT_LIST
1344       /* Do tlink without additional code generation.  */
1345       do_tlink (ld1_argv, object_lst);
1346 #endif
1347       /* Strip now if it was requested on the command line.  */
1348       if (strip_flag)
1349         {
1350           char **real_strip_argv = xcalloc (sizeof (char *), 3);
1351           const char ** strip_argv = (const char **) real_strip_argv;
1352
1353           strip_argv[0] = strip_file_name;
1354           strip_argv[1] = output_file;
1355           strip_argv[2] = (char *) 0;
1356           fork_execute ("strip", real_strip_argv);
1357         }
1358
1359 #ifdef COLLECT_EXPORT_LIST
1360       maybe_unlink (export_file);
1361 #endif
1362       maybe_unlink (c_file);
1363       maybe_unlink (o_file);
1364       return 0;
1365     }
1366
1367   /* Sort ctor and dtor lists by priority.  */
1368   sort_ids (&constructors);
1369   sort_ids (&destructors);
1370
1371   maybe_unlink(output_file);
1372   outf = fopen (c_file, "w");
1373   if (outf == (FILE *) 0)
1374     fatal_perror ("fopen %s", c_file);
1375
1376   write_c_file (outf, c_file);
1377
1378   if (fclose (outf))
1379     fatal_perror ("fclose %s", c_file);
1380
1381   /* Tell the linker that we have initializer and finalizer functions.  */
1382 #ifdef LD_INIT_SWITCH
1383 #ifdef COLLECT_EXPORT_LIST
1384   *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
1385 #else
1386   *ld2++ = LD_INIT_SWITCH;
1387   *ld2++ = initname;
1388   *ld2++ = LD_FINI_SWITCH;
1389   *ld2++ = fininame;
1390 #endif
1391 #endif
1392
1393 #ifdef COLLECT_EXPORT_LIST
1394   if (shared_obj)
1395     {
1396       /* If we did not add export flag to link arguments before, add it to
1397          second link phase now.  No new exports should have been added.  */
1398       if (! exports.first)
1399         *ld2++ = concat ("-bE:", export_file, NULL);
1400
1401       add_to_list (&exports, initname);
1402       add_to_list (&exports, fininame);
1403       add_to_list (&exports, "_GLOBAL__DI");
1404       add_to_list (&exports, "_GLOBAL__DD");
1405       exportf = fopen (export_file, "w");
1406       if (exportf == (FILE *) 0)
1407         fatal_perror ("fopen %s", export_file);
1408       write_aix_file (exportf, exports.first);
1409       if (fclose (exportf))
1410         fatal_perror ("fclose %s", export_file);
1411     }
1412 #endif
1413
1414   /* End of arguments to second link phase.  */
1415   *ld2 = (char*) 0;
1416
1417   if (debug)
1418     {
1419       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1420                output_file, c_file);
1421       write_c_file (stderr, "stderr");
1422       fprintf (stderr, "========== end of c_file\n\n");
1423 #ifdef COLLECT_EXPORT_LIST
1424       fprintf (stderr, "\n========== export_file = %s\n", export_file);
1425       write_aix_file (stderr, exports.first);
1426       fprintf (stderr, "========== end of export_file\n\n");
1427 #endif
1428     }
1429
1430   /* Assemble the constructor and destructor tables.
1431      Link the tables in with the rest of the program.  */
1432
1433   fork_execute ("gcc",  c_argv);
1434 #ifdef COLLECT_EXPORT_LIST
1435   /* On AIX we must call tlink because of possible templates resolution.  */
1436   do_tlink (ld2_argv, object_lst);
1437 #else
1438   /* Otherwise, simply call ld because tlink is already done.  */
1439   fork_execute ("ld", ld2_argv);
1440
1441   /* Let scan_prog_file do any final mods (OSF/rose needs this for
1442      constructors/destructors in shared libraries.  */
1443   scan_prog_file (output_file, PASS_SECOND);
1444 #endif
1445
1446   maybe_unlink (c_file);
1447   maybe_unlink (o_file);
1448
1449 #ifdef COLLECT_EXPORT_LIST
1450   maybe_unlink (export_file);
1451 #endif
1452
1453   return 0;
1454 }
1455
1456 \f
1457 /* Wait for a process to finish, and exit if a nonzero status is found.  */
1458
1459 int
1460 collect_wait (const char *prog)
1461 {
1462   int status;
1463
1464   pwait (pid, &status, 0);
1465   if (status)
1466     {
1467       if (WIFSIGNALED (status))
1468         {
1469           int sig = WTERMSIG (status);
1470           error ("%s terminated with signal %d [%s]%s",
1471                  prog, sig, strsignal(sig),
1472                  WCOREDUMP(status) ? ", core dumped" : "");
1473           collect_exit (FATAL_EXIT_CODE);
1474         }
1475
1476       if (WIFEXITED (status))
1477         return WEXITSTATUS (status);
1478     }
1479   return 0;
1480 }
1481
1482 static void
1483 do_wait (const char *prog)
1484 {
1485   int ret = collect_wait (prog);
1486   if (ret != 0)
1487     {
1488       error ("%s returned %d exit status", prog, ret);
1489       collect_exit (ret);
1490     }
1491 }
1492
1493 \f
1494 /* Execute a program, and wait for the reply.  */
1495
1496 void
1497 collect_execute (const char *prog, char **argv, const char *redir)
1498 {
1499   char *errmsg_fmt;
1500   char *errmsg_arg;
1501   int redir_handle = -1;
1502   int stdout_save = -1;
1503   int stderr_save = -1;
1504
1505   if (vflag || debug)
1506     {
1507       char **p_argv;
1508       const char *str;
1509
1510       if (argv[0])
1511         fprintf (stderr, "%s", argv[0]);
1512       else
1513         notice ("[cannot find %s]", prog);
1514
1515       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1516         fprintf (stderr, " %s", str);
1517
1518       fprintf (stderr, "\n");
1519     }
1520
1521   fflush (stdout);
1522   fflush (stderr);
1523
1524   /* If we cannot find a program we need, complain error.  Do this here
1525      since we might not end up needing something that we could not find.  */
1526
1527   if (argv[0] == 0)
1528     fatal ("cannot find `%s'", prog);
1529
1530   if (redir)
1531     {
1532       /* Open response file.  */
1533       redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1534
1535       /* Duplicate the stdout and stderr file handles
1536          so they can be restored later.  */
1537       stdout_save = dup (STDOUT_FILENO);
1538       if (stdout_save == -1)
1539         fatal_perror ("redirecting stdout: %s", redir);
1540       stderr_save = dup (STDERR_FILENO);
1541       if (stderr_save == -1)
1542         fatal_perror ("redirecting stdout: %s", redir);
1543
1544       /* Redirect stdout & stderr to our response file.  */
1545       dup2 (redir_handle, STDOUT_FILENO);
1546       dup2 (redir_handle, STDERR_FILENO);
1547     }
1548
1549   pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
1550                   (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1551
1552   if (redir)
1553     {
1554       /* Restore stdout and stderr to their previous settings.  */
1555       dup2 (stdout_save, STDOUT_FILENO);
1556       dup2 (stderr_save, STDERR_FILENO);
1557
1558       /* Close response file.  */
1559       close (redir_handle);
1560     }
1561
1562  if (pid == -1)
1563    fatal_perror (errmsg_fmt, errmsg_arg);
1564 }
1565
1566 static void
1567 fork_execute (const char *prog, char **argv)
1568 {
1569   collect_execute (prog, argv, NULL);
1570   do_wait (prog);
1571 }
1572 \f
1573 /* Unlink a file unless we are debugging.  */
1574
1575 static void
1576 maybe_unlink (const char *file)
1577 {
1578   if (!debug)
1579     unlink (file);
1580   else
1581     notice ("[Leaving %s]\n", file);
1582 }
1583
1584 \f
1585 static long sequence_number = 0;
1586
1587 /* Add a name to a linked list.  */
1588
1589 static void
1590 add_to_list (struct head *head_ptr, const char *name)
1591 {
1592   struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1);
1593   struct id *p;
1594   strcpy (newid->name, name);
1595
1596   if (head_ptr->first)
1597     head_ptr->last->next = newid;
1598   else
1599     head_ptr->first = newid;
1600
1601   /* Check for duplicate symbols.  */
1602   for (p = head_ptr->first;
1603        strcmp (name, p->name) != 0;
1604        p = p->next)
1605     ;
1606   if (p != newid)
1607     {
1608       head_ptr->last->next = 0;
1609       free (newid);
1610       return;
1611     }
1612
1613   newid->sequence = ++sequence_number;
1614   head_ptr->last = newid;
1615   head_ptr->number++;
1616 }
1617
1618 /* Grab the init priority number from an init function name that
1619    looks like "_GLOBAL_.I.12345.foo".  */
1620
1621 static int
1622 extract_init_priority (const char *name)
1623 {
1624   int pos = 0, pri;
1625
1626   while (name[pos] == '_')
1627     ++pos;
1628   pos += 10; /* strlen ("GLOBAL__X_") */
1629
1630   /* Extract init_p number from ctor/dtor name.  */
1631   pri = atoi (name + pos);
1632   return pri ? pri : DEFAULT_INIT_PRIORITY;
1633 }
1634
1635 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1636    ctors will be run from right to left, dtors from left to right.  */
1637
1638 static void
1639 sort_ids (struct head *head_ptr)
1640 {
1641   /* id holds the current element to insert.  id_next holds the next
1642      element to insert.  id_ptr iterates through the already sorted elements
1643      looking for the place to insert id.  */
1644   struct id *id, *id_next, **id_ptr;
1645
1646   id = head_ptr->first;
1647
1648   /* We don't have any sorted elements yet.  */
1649   head_ptr->first = NULL;
1650
1651   for (; id; id = id_next)
1652     {
1653       id_next = id->next;
1654       id->sequence = extract_init_priority (id->name);
1655
1656       for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1657         if (*id_ptr == NULL
1658             /* If the sequence numbers are the same, we put the id from the
1659                file later on the command line later in the list.  */
1660             || id->sequence > (*id_ptr)->sequence
1661             /* Hack: do lexical compare, too.
1662             || (id->sequence == (*id_ptr)->sequence
1663                 && strcmp (id->name, (*id_ptr)->name) > 0) */
1664             )
1665           {
1666             id->next = *id_ptr;
1667             *id_ptr = id;
1668             break;
1669           }
1670     }
1671
1672   /* Now set the sequence numbers properly so write_c_file works.  */
1673   for (id = head_ptr->first; id; id = id->next)
1674     id->sequence = ++sequence_number;
1675 }
1676
1677 /* Write: `prefix', the names on list LIST, `suffix'.  */
1678
1679 static void
1680 write_list (FILE *stream, const char *prefix, struct id *list)
1681 {
1682   while (list)
1683     {
1684       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1685       list = list->next;
1686     }
1687 }
1688
1689 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1690 /* Given a STRING, return nonzero if it occurs in the list in range
1691    [ARGS_BEGIN,ARGS_END).  */
1692
1693 static int
1694 is_in_args (const char *string, const char **args_begin,
1695             const char **args_end)
1696 {
1697   const char **args_pointer;
1698   for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
1699     if (strcmp (string, *args_pointer) == 0)
1700       return 1;
1701   return 0;
1702 }
1703 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1704
1705 #ifdef COLLECT_EXPORT_LIST
1706 /* This function is really used only on AIX, but may be useful.  */
1707 #if 0
1708 static int
1709 is_in_list (const char *prefix, struct id *list)
1710 {
1711   while (list)
1712     {
1713       if (!strcmp (prefix, list->name)) return 1;
1714       list = list->next;
1715     }
1716     return 0;
1717 }
1718 #endif
1719 #endif /* COLLECT_EXPORT_LIST */
1720
1721 /* Added for debugging purpose.  */
1722 #ifdef COLLECT_EXPORT_LIST
1723 static void
1724 dump_list (FILE *stream, const char *prefix, struct id *list)
1725 {
1726   while (list)
1727     {
1728       fprintf (stream, "%s%s,\n", prefix, list->name);
1729       list = list->next;
1730     }
1731 }
1732 #endif
1733
1734 #if 0
1735 static void
1736 dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
1737 {
1738   while (list)
1739     {
1740       fprintf (stream, "%s%s,\n", prefix, list->prefix);
1741       list = list->next;
1742     }
1743 }
1744 #endif
1745
1746 static void
1747 write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
1748 {
1749   while (list)
1750     {
1751       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1752                prefix, list->sequence, list->name);
1753       list = list->next;
1754     }
1755 }
1756
1757 /* Write out the constructor and destructor tables statically (for a shared
1758    object), along with the functions to execute them.  */
1759
1760 static void
1761 write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
1762 {
1763   const char *p, *q;
1764   char *prefix, *r;
1765   int frames = (frame_tables.number > 0);
1766
1767   /* Figure out name of output_file, stripping off .so version.  */
1768   p = strrchr (output_file, '/');
1769   if (p == 0)
1770     p = output_file;
1771   else
1772     p++;
1773   q = p;
1774   while (q)
1775     {
1776       q = strchr (q,'.');
1777       if (q == 0)
1778         {
1779           q = p + strlen (p);
1780           break;
1781         }
1782       else
1783         {
1784           if (strncmp (q, ".so", 3) == 0)
1785             {
1786               q += 3;
1787               break;
1788             }
1789           else
1790             q++;
1791         }
1792     }
1793   /* q points to null at end of the string (or . of the .so version) */
1794   prefix = xmalloc (q - p + 1);
1795   strncpy (prefix, p, q - p);
1796   prefix[q - p] = 0;
1797   for (r = prefix; *r; r++)
1798     if (!ISALNUM ((unsigned char)*r))
1799       *r = '_';
1800   if (debug)
1801     notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
1802             output_file, prefix);
1803
1804   initname = concat ("_GLOBAL__FI_", prefix, NULL);
1805   fininame = concat ("_GLOBAL__FD_", prefix, NULL);
1806
1807   free (prefix);
1808
1809   /* Write the tables as C code.  */
1810
1811   fprintf (stream, "static int count;\n");
1812   fprintf (stream, "typedef void entry_pt();\n");
1813   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1814
1815   if (frames)
1816     {
1817       write_list_with_asm (stream, "extern void *", frame_tables.first);
1818
1819       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1820       write_list (stream, "\t\t&", frame_tables.first);
1821       fprintf (stream, "\t0\n};\n");
1822
1823       /* This must match what's in frame.h.  */
1824       fprintf (stream, "struct object {\n");
1825       fprintf (stream, "  void *pc_begin;\n");
1826       fprintf (stream, "  void *pc_end;\n");
1827       fprintf (stream, "  void *fde_begin;\n");
1828       fprintf (stream, "  void *fde_array;\n");
1829       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1830       fprintf (stream, "  struct object *next;\n");
1831       fprintf (stream, "};\n");
1832
1833       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1834       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1835
1836       fprintf (stream, "static void reg_frame () {\n");
1837       fprintf (stream, "\tstatic struct object ob;\n");
1838       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1839       fprintf (stream, "\t}\n");
1840
1841       fprintf (stream, "static void dereg_frame () {\n");
1842       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1843       fprintf (stream, "\t}\n");
1844     }
1845
1846   fprintf (stream, "void %s() {\n", initname);
1847   if (constructors.number > 0 || frames)
1848     {
1849       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1850       write_list (stream, "\t\t", constructors.first);
1851       if (frames)
1852         fprintf (stream, "\treg_frame,\n");
1853       fprintf (stream, "\t};\n");
1854       fprintf (stream, "\tentry_pt **p;\n");
1855       fprintf (stream, "\tif (count++ != 0) return;\n");
1856       fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
1857       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1858     }
1859   else
1860     fprintf (stream, "\t++count;\n");
1861   fprintf (stream, "}\n");
1862   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1863   fprintf (stream, "void %s() {\n", fininame);
1864   if (destructors.number > 0 || frames)
1865     {
1866       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1867       write_list (stream, "\t\t", destructors.first);
1868       if (frames)
1869         fprintf (stream, "\tdereg_frame,\n");
1870       fprintf (stream, "\t};\n");
1871       fprintf (stream, "\tentry_pt **p;\n");
1872       fprintf (stream, "\tif (--count != 0) return;\n");
1873       fprintf (stream, "\tp = dtors;\n");
1874       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1875                destructors.number + frames);
1876     }
1877   fprintf (stream, "}\n");
1878
1879   if (shared_obj)
1880     {
1881       COLLECT_SHARED_INIT_FUNC(stream, initname);
1882       COLLECT_SHARED_FINI_FUNC(stream, fininame);
1883     }
1884 }
1885
1886 /* Write the constructor/destructor tables.  */
1887
1888 #ifndef LD_INIT_SWITCH
1889 static void
1890 write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
1891 {
1892   /* Write the tables as C code.  */
1893
1894   int frames = (frame_tables.number > 0);
1895
1896   fprintf (stream, "typedef void entry_pt();\n\n");
1897
1898   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1899
1900   if (frames)
1901     {
1902       write_list_with_asm (stream, "extern void *", frame_tables.first);
1903
1904       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1905       write_list (stream, "\t\t&", frame_tables.first);
1906       fprintf (stream, "\t0\n};\n");
1907
1908       /* This must match what's in frame.h.  */
1909       fprintf (stream, "struct object {\n");
1910       fprintf (stream, "  void *pc_begin;\n");
1911       fprintf (stream, "  void *pc_end;\n");
1912       fprintf (stream, "  void *fde_begin;\n");
1913       fprintf (stream, "  void *fde_array;\n");
1914       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1915       fprintf (stream, "  struct object *next;\n");
1916       fprintf (stream, "};\n");
1917
1918       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1919       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1920
1921       fprintf (stream, "static void reg_frame () {\n");
1922       fprintf (stream, "\tstatic struct object ob;\n");
1923       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1924       fprintf (stream, "\t}\n");
1925
1926       fprintf (stream, "static void dereg_frame () {\n");
1927       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1928       fprintf (stream, "\t}\n");
1929     }
1930
1931   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1932   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
1933   write_list (stream, "\t", constructors.first);
1934   if (frames)
1935     fprintf (stream, "\treg_frame,\n");
1936   fprintf (stream, "\t0\n};\n\n");
1937
1938   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1939
1940   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1941   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
1942   write_list (stream, "\t", destructors.first);
1943   if (frames)
1944     fprintf (stream, "\tdereg_frame,\n");
1945   fprintf (stream, "\t0\n};\n\n");
1946
1947   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1948   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
1949 }
1950 #endif /* ! LD_INIT_SWITCH */
1951
1952 static void
1953 write_c_file (FILE *stream, const char *name)
1954 {
1955   fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
1956 #ifndef LD_INIT_SWITCH
1957   if (! shared_obj)
1958     write_c_file_glob (stream, name);
1959   else
1960 #endif
1961     write_c_file_stat (stream, name);
1962   fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
1963 }
1964
1965 #ifdef COLLECT_EXPORT_LIST
1966 static void
1967 write_aix_file (FILE *stream, struct id *list)
1968 {
1969   for (; list; list = list->next)
1970     {
1971       fputs (list->name, stream);
1972       putc ('\n', stream);
1973     }
1974 }
1975 #endif
1976 \f
1977 #ifdef OBJECT_FORMAT_NONE
1978
1979 /* Generic version to scan the name list of the loaded program for
1980    the symbols g++ uses for static constructors and destructors.
1981
1982    The constructor table begins at __CTOR_LIST__ and contains a count
1983    of the number of pointers (or -1 if the constructors are built in a
1984    separate section by the linker), followed by the pointers to the
1985    constructor functions, terminated with a null pointer.  The
1986    destructor table has the same format, and begins at __DTOR_LIST__.  */
1987
1988 static void
1989 scan_prog_file (const char *prog_name, enum pass which_pass)
1990 {
1991   void (*int_handler) (int);
1992   void (*quit_handler) (int);
1993   char *real_nm_argv[4];
1994   const char **nm_argv = (const char **) real_nm_argv;
1995   int argc = 0;
1996   int pipe_fd[2];
1997   char *p, buf[1024];
1998   FILE *inf;
1999
2000   if (which_pass == PASS_SECOND)
2001     return;
2002
2003   /* If we do not have an `nm', complain.  */
2004   if (nm_file_name == 0)
2005     fatal ("cannot find `nm'");
2006
2007   nm_argv[argc++] = nm_file_name;
2008   if (NM_FLAGS[0] != '\0')
2009     nm_argv[argc++] = NM_FLAGS;
2010
2011   nm_argv[argc++] = prog_name;
2012   nm_argv[argc++] = (char *) 0;
2013
2014   if (pipe (pipe_fd) < 0)
2015     fatal_perror ("pipe");
2016
2017   inf = fdopen (pipe_fd[0], "r");
2018   if (inf == (FILE *) 0)
2019     fatal_perror ("fdopen");
2020
2021   /* Trace if needed.  */
2022   if (vflag)
2023     {
2024       const char **p_argv;
2025       const char *str;
2026
2027       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2028         fprintf (stderr, " %s", str);
2029
2030       fprintf (stderr, "\n");
2031     }
2032
2033   fflush (stdout);
2034   fflush (stderr);
2035
2036   /* Spawn child nm on pipe.  */
2037   pid = vfork ();
2038   if (pid == -1)
2039     fatal_perror (VFORK_STRING);
2040
2041   if (pid == 0)                 /* child context */
2042     {
2043       /* setup stdout */
2044       if (dup2 (pipe_fd[1], 1) < 0)
2045         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2046
2047       if (close (pipe_fd[0]) < 0)
2048         fatal_perror ("close %d", pipe_fd[0]);
2049
2050       if (close (pipe_fd[1]) < 0)
2051         fatal_perror ("close %d", pipe_fd[1]);
2052
2053       execv (nm_file_name, real_nm_argv);
2054       fatal_perror ("execv %s", nm_file_name);
2055     }
2056
2057   /* Parent context from here on.  */
2058   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
2059 #ifdef SIGQUIT
2060   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
2061 #endif
2062
2063   if (close (pipe_fd[1]) < 0)
2064     fatal_perror ("close %d", pipe_fd[1]);
2065
2066   if (debug)
2067     fprintf (stderr, "\nnm output with constructors/destructors.\n");
2068
2069   /* Read each line of nm output.  */
2070   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2071     {
2072       int ch, ch2;
2073       char *name, *end;
2074
2075       /* If it contains a constructor or destructor name, add the name
2076          to the appropriate list.  */
2077
2078       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2079         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2080           break;
2081
2082       if (ch != '_')
2083         continue;
2084
2085       name = p;
2086       /* Find the end of the symbol name.
2087          Do not include `|', because Encore nm can tack that on the end.  */
2088       for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2089            end++)
2090         continue;
2091
2092
2093       *end = '\0';
2094       switch (is_ctor_dtor (name))
2095         {
2096         case 1:
2097           if (which_pass != PASS_LIB)
2098             add_to_list (&constructors, name);
2099           break;
2100
2101         case 2:
2102           if (which_pass != PASS_LIB)
2103             add_to_list (&destructors, name);
2104           break;
2105
2106         case 3:
2107           if (which_pass != PASS_LIB)
2108             fatal ("init function found in object %s", prog_name);
2109 #ifndef LD_INIT_SWITCH
2110           add_to_list (&constructors, name);
2111 #endif
2112           break;
2113
2114         case 4:
2115           if (which_pass != PASS_LIB)
2116             fatal ("fini function found in object %s", prog_name);
2117 #ifndef LD_FINI_SWITCH
2118           add_to_list (&destructors, name);
2119 #endif
2120           break;
2121
2122         case 5:
2123           if (which_pass != PASS_LIB)
2124             add_to_list (&frame_tables, name);
2125           break;
2126
2127         default:                /* not a constructor or destructor */
2128           continue;
2129         }
2130
2131       if (debug)
2132         fprintf (stderr, "\t%s\n", buf);
2133     }
2134
2135   if (debug)
2136     fprintf (stderr, "\n");
2137
2138   if (fclose (inf) != 0)
2139     fatal_perror ("fclose");
2140
2141   do_wait (nm_file_name);
2142
2143   signal (SIGINT,  int_handler);
2144 #ifdef SIGQUIT
2145   signal (SIGQUIT, quit_handler);
2146 #endif
2147 }
2148
2149 #if SUNOS4_SHARED_LIBRARIES
2150
2151 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2152    that the output file depends upon and their initialization/finalization
2153    routines, if any.  */
2154
2155 #include <a.out.h>
2156 #include <fcntl.h>
2157 #include <link.h>
2158 #include <sys/mman.h>
2159 #include <sys/param.h>
2160 #include <unistd.h>
2161 #include <sys/dir.h>
2162
2163 /* pointers to the object file */
2164 unsigned object;        /* address of memory mapped file */
2165 unsigned objsize;       /* size of memory mapped to file */
2166 char * code;            /* pointer to code segment */
2167 char * data;            /* pointer to data segment */
2168 struct nlist *symtab;   /* pointer to symbol table */
2169 struct link_dynamic *ld;
2170 struct link_dynamic_2 *ld_2;
2171 struct head libraries;
2172
2173 /* Map the file indicated by NAME into memory and store its address.  */
2174
2175 static void
2176 mapfile (const char *name)
2177 {
2178   int fp;
2179   struct stat s;
2180   if ((fp = open (name, O_RDONLY)) == -1)
2181     fatal ("unable to open file '%s'", name);
2182   if (fstat (fp, &s) == -1)
2183     fatal ("unable to stat file '%s'", name);
2184
2185   objsize = s.st_size;
2186   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2187                             fp, 0);
2188   if (object == (unsigned)-1)
2189     fatal ("unable to mmap file '%s'", name);
2190
2191   close (fp);
2192 }
2193
2194 /* Helpers for locatelib.  */
2195
2196 static const char *libname;
2197
2198 static int
2199 libselect (struct direct *d)
2200 {
2201   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2202 }
2203
2204 /* If one file has an additional numeric extension past LIBNAME, then put
2205    that one first in the sort.  If both files have additional numeric
2206    extensions, then put the one with the higher number first in the sort.
2207
2208    We must verify that the extension is numeric, because Sun saves the
2209    original versions of patched libraries with a .FCS extension.  Files with
2210    invalid extensions must go last in the sort, so that they will not be used.  */
2211
2212 static int
2213 libcompare (struct direct **d1, struct direct **d2)
2214 {
2215   int i1, i2 = strlen (libname);
2216   char *e1 = (*d1)->d_name + i2;
2217   char *e2 = (*d2)->d_name + i2;
2218
2219   while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2220          && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2221     {
2222       ++e1;
2223       ++e2;
2224       i1 = strtol (e1, &e1, 10);
2225       i2 = strtol (e2, &e2, 10);
2226       if (i1 != i2)
2227         return i1 - i2;
2228     }
2229
2230   if (*e1)
2231     {
2232       /* It has a valid numeric extension, prefer this one.  */
2233       if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2234         return 1;
2235       /* It has an invalid numeric extension, must prefer the other one.  */
2236       else
2237         return -1;
2238     }
2239   else if (*e2)
2240     {
2241       /* It has a valid numeric extension, prefer this one.  */
2242       if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2243         return -1;
2244       /* It has an invalid numeric extension, must prefer the other one.  */
2245       else
2246         return 1;
2247     }
2248   else
2249     return 0;
2250 }
2251
2252 /* Given the name NAME of a dynamic dependency, find its pathname and add
2253    it to the list of libraries.  */
2254
2255 static void
2256 locatelib (const char *name)
2257 {
2258   static const char **l;
2259   static int cnt;
2260   char buf[MAXPATHLEN];
2261   char *p, *q;
2262   const char **pp;
2263
2264   if (l == 0)
2265     {
2266       char *ld_rules;
2267       char *ldr = 0;
2268       /* counting elements in array, need 1 extra for null */
2269       cnt = 1;
2270       ld_rules = (char *) (ld_2->ld_rules + code);
2271       if (ld_rules)
2272         {
2273           cnt++;
2274           for (; *ld_rules != 0; ld_rules++)
2275             if (*ld_rules == ':')
2276               cnt++;
2277           ld_rules = (char *) (ld_2->ld_rules + code);
2278           ldr = xstrdup (ld_rules);
2279         }
2280       p = getenv ("LD_LIBRARY_PATH");
2281       q = 0;
2282       if (p)
2283         {
2284           cnt++;
2285           for (q = p ; *q != 0; q++)
2286             if (*q == ':')
2287               cnt++;
2288           q = xstrdup (p);
2289         }
2290       l = xmalloc ((cnt + 3) * sizeof (char *));
2291       pp = l;
2292       if (ldr)
2293         {
2294           *pp++ = ldr;
2295           for (; *ldr != 0; ldr++)
2296             if (*ldr == ':')
2297               {
2298                 *ldr++ = 0;
2299                 *pp++ = ldr;
2300               }
2301         }
2302       if (q)
2303         {
2304           *pp++ = q;
2305           for (; *q != 0; q++)
2306             if (*q == ':')
2307               {
2308                 *q++ = 0;
2309                 *pp++ = q;
2310               }
2311         }
2312       /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2313       *pp++ = "/lib";
2314       *pp++ = "/usr/lib";
2315       *pp++ = "/usr/local/lib";
2316       *pp = 0;
2317     }
2318   libname = name;
2319   for (pp = l; *pp != 0 ; pp++)
2320     {
2321       struct direct **namelist;
2322       int entries;
2323       if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2324         {
2325           sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2326           add_to_list (&libraries, buf);
2327           if (debug)
2328             fprintf (stderr, "%s\n", buf);
2329           break;
2330         }
2331     }
2332   if (*pp == 0)
2333     {
2334       if (debug)
2335         notice ("not found\n");
2336       else
2337         fatal ("dynamic dependency %s not found", name);
2338     }
2339 }
2340
2341 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2342    that it depends upon and any constructors or destructors they contain.  */
2343
2344 static void
2345 scan_libraries (const char *prog_name)
2346 {
2347   struct exec *header;
2348   char *base;
2349   struct link_object *lo;
2350   char buff[MAXPATHLEN];
2351   struct id *list;
2352
2353   mapfile (prog_name);
2354   header = (struct exec *)object;
2355   if (N_BADMAG (*header))
2356     fatal ("bad magic number in file '%s'", prog_name);
2357   if (header->a_dynamic == 0)
2358     return;
2359
2360   code = (char *) (N_TXTOFF (*header) + (long) header);
2361   data = (char *) (N_DATOFF (*header) + (long) header);
2362   symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2363
2364   if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2365     {
2366       /* shared object */
2367       ld = (struct link_dynamic *) (symtab->n_value + code);
2368       base = code;
2369     }
2370   else
2371     {
2372       /* executable */
2373       ld = (struct link_dynamic *) data;
2374       base = code-PAGSIZ;
2375     }
2376
2377   if (debug)
2378     notice ("dynamic dependencies.\n");
2379
2380   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2381   for (lo = (struct link_object *) ld_2->ld_need; lo;
2382        lo = (struct link_object *) lo->lo_next)
2383     {
2384       char *name;
2385       lo = (struct link_object *) ((long) lo + code);
2386       name = (char *) (code + lo->lo_name);
2387       if (lo->lo_library)
2388         {
2389           if (debug)
2390             fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2391           sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2392           locatelib (buff);
2393         }
2394       else
2395         {
2396           if (debug)
2397             fprintf (stderr, "\t%s\n", name);
2398           add_to_list (&libraries, name);
2399         }
2400     }
2401
2402   if (debug)
2403     fprintf (stderr, "\n");
2404
2405   /* now iterate through the library list adding their symbols to
2406      the list.  */
2407   for (list = libraries.first; list; list = list->next)
2408     scan_prog_file (list->name, PASS_LIB);
2409 }
2410
2411 #else  /* SUNOS4_SHARED_LIBRARIES */
2412 #ifdef LDD_SUFFIX
2413
2414 /* Use the List Dynamic Dependencies program to find shared libraries that
2415    the output file depends upon and their initialization/finalization
2416    routines, if any.  */
2417
2418 static void
2419 scan_libraries (const char *prog_name)
2420 {
2421   static struct head libraries;         /* list of shared libraries found */
2422   struct id *list;
2423   void (*int_handler) (int);
2424   void (*quit_handler) (int);
2425   char *real_ldd_argv[4];
2426   const char **ldd_argv = (const char **) real_ldd_argv;
2427   int argc = 0;
2428   int pipe_fd[2];
2429   char buf[1024];
2430   FILE *inf;
2431
2432   /* If we do not have an `ldd', complain.  */
2433   if (ldd_file_name == 0)
2434     {
2435       error ("cannot find `ldd'");
2436       return;
2437     }
2438
2439   ldd_argv[argc++] = ldd_file_name;
2440   ldd_argv[argc++] = prog_name;
2441   ldd_argv[argc++] = (char *) 0;
2442
2443   if (pipe (pipe_fd) < 0)
2444     fatal_perror ("pipe");
2445
2446   inf = fdopen (pipe_fd[0], "r");
2447   if (inf == (FILE *) 0)
2448     fatal_perror ("fdopen");
2449
2450   /* Trace if needed.  */
2451   if (vflag)
2452     {
2453       const char **p_argv;
2454       const char *str;
2455
2456       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2457         fprintf (stderr, " %s", str);
2458
2459       fprintf (stderr, "\n");
2460     }
2461
2462   fflush (stdout);
2463   fflush (stderr);
2464
2465   /* Spawn child ldd on pipe.  */
2466   pid = vfork ();
2467   if (pid == -1)
2468     fatal_perror (VFORK_STRING);
2469
2470   if (pid == 0)                 /* child context */
2471     {
2472       /* setup stdout */
2473       if (dup2 (pipe_fd[1], 1) < 0)
2474         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2475
2476       if (close (pipe_fd[0]) < 0)
2477         fatal_perror ("close %d", pipe_fd[0]);
2478
2479       if (close (pipe_fd[1]) < 0)
2480         fatal_perror ("close %d", pipe_fd[1]);
2481
2482       execv (ldd_file_name, real_ldd_argv);
2483       fatal_perror ("execv %s", ldd_file_name);
2484     }
2485
2486   /* Parent context from here on.  */
2487   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
2488 #ifdef SIGQUIT
2489   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
2490 #endif
2491
2492   if (close (pipe_fd[1]) < 0)
2493     fatal_perror ("close %d", pipe_fd[1]);
2494
2495   if (debug)
2496     notice ("\nldd output with constructors/destructors.\n");
2497
2498   /* Read each line of ldd output.  */
2499   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2500     {
2501       int ch2;
2502       char *name, *end, *p = buf;
2503
2504       /* Extract names of libraries and add to list.  */
2505       PARSE_LDD_OUTPUT (p);
2506       if (p == 0)
2507         continue;
2508
2509       name = p;
2510       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2511         fatal ("dynamic dependency %s not found", buf);
2512
2513       /* Find the end of the symbol name.  */
2514       for (end = p;
2515            (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2516            end++)
2517         continue;
2518       *end = '\0';
2519
2520       if (access (name, R_OK) == 0)
2521         add_to_list (&libraries, name);
2522       else
2523         fatal ("unable to open dynamic dependency '%s'", buf);
2524
2525       if (debug)
2526         fprintf (stderr, "\t%s\n", buf);
2527     }
2528   if (debug)
2529     fprintf (stderr, "\n");
2530
2531   if (fclose (inf) != 0)
2532     fatal_perror ("fclose");
2533
2534   do_wait (ldd_file_name);
2535
2536   signal (SIGINT,  int_handler);
2537 #ifdef SIGQUIT
2538   signal (SIGQUIT, quit_handler);
2539 #endif
2540
2541   /* now iterate through the library list adding their symbols to
2542      the list.  */
2543   for (list = libraries.first; list; list = list->next)
2544     scan_prog_file (list->name, PASS_LIB);
2545 }
2546
2547 #endif /* LDD_SUFFIX */
2548 #endif /* SUNOS4_SHARED_LIBRARIES */
2549
2550 #endif /* OBJECT_FORMAT_NONE */
2551
2552 \f
2553 /*
2554  * COFF specific stuff.
2555  */
2556
2557 #ifdef OBJECT_FORMAT_COFF
2558
2559 #if defined (EXTENDED_COFF)
2560
2561 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2562 #   define GCC_SYMENT           SYMR
2563 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc || (X).st == stGlobal)
2564 #   define GCC_SYMINC(X)        (1)
2565 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
2566 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
2567
2568 #else
2569
2570 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
2571 #   define GCC_SYMENT           SYMENT
2572 #   if defined (C_WEAKEXT)
2573 #     define GCC_OK_SYMBOL(X) \
2574        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
2575         ((X).n_scnum > N_UNDEF) && \
2576         (aix64_flag \
2577          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2578              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2579 #     define GCC_UNDEF_SYMBOL(X) \
2580        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
2581         ((X).n_scnum == N_UNDEF))
2582 #   else
2583 #     define GCC_OK_SYMBOL(X) \
2584        (((X).n_sclass == C_EXT) && \
2585         ((X).n_scnum > N_UNDEF) && \
2586         (aix64_flag \
2587          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2588              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2589 #     define GCC_UNDEF_SYMBOL(X) \
2590        (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2591 #   endif
2592 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
2593 #   define GCC_SYMZERO(X)       0
2594
2595 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
2596 #ifdef _AIX51
2597 #   define GCC_CHECK_HDR(X) \
2598      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2599       || (HEADER (X).f_magic == 0767 && aix64_flag))
2600 #else
2601 #   define GCC_CHECK_HDR(X) \
2602      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2603       || (HEADER (X).f_magic == 0757 && aix64_flag))
2604 #endif
2605
2606 #endif
2607
2608 #ifdef COLLECT_EXPORT_LIST
2609 /* Array of standard AIX libraries which should not
2610    be scanned for ctors/dtors.  */
2611 static const char *const aix_std_libs[] = {
2612   "/unix",
2613   "/lib/libc.a",
2614   "/lib/libm.a",
2615   "/lib/libc_r.a",
2616   "/lib/libm_r.a",
2617   "/usr/lib/libc.a",
2618   "/usr/lib/libm.a",
2619   "/usr/lib/libc_r.a",
2620   "/usr/lib/libm_r.a",
2621   "/usr/lib/threads/libc.a",
2622   "/usr/ccs/lib/libc.a",
2623   "/usr/ccs/lib/libm.a",
2624   "/usr/ccs/lib/libc_r.a",
2625   "/usr/ccs/lib/libm_r.a",
2626   NULL
2627 };
2628
2629 /* This function checks the filename and returns 1
2630    if this name matches the location of a standard AIX library.  */
2631 static int ignore_library (const char *);
2632 static int
2633 ignore_library (const char *name)
2634 {
2635   const char *const *p = &aix_std_libs[0];
2636   while (*p++ != NULL)
2637     if (! strcmp (name, *p)) return 1;
2638   return 0;
2639 }
2640 #endif /* COLLECT_EXPORT_LIST */
2641
2642 #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
2643 extern char *ldgetname (LDFILE *, GCC_SYMENT *);
2644 #endif
2645
2646 /* COFF version to scan the name list of the loaded program for
2647    the symbols g++ uses for static constructors and destructors.
2648
2649    The constructor table begins at __CTOR_LIST__ and contains a count
2650    of the number of pointers (or -1 if the constructors are built in a
2651    separate section by the linker), followed by the pointers to the
2652    constructor functions, terminated with a null pointer.  The
2653    destructor table has the same format, and begins at __DTOR_LIST__.  */
2654
2655 static void
2656 scan_prog_file (const char *prog_name, enum pass which_pass)
2657 {
2658   LDFILE *ldptr = NULL;
2659   int sym_index, sym_count;
2660   int is_shared = 0;
2661
2662   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2663     return;
2664
2665 #ifdef COLLECT_EXPORT_LIST
2666   /* We do not need scanning for some standard C libraries.  */
2667   if (which_pass == PASS_FIRST && ignore_library (prog_name))
2668     return;
2669
2670   /* On AIX we have a loop, because there is not much difference
2671      between an object and an archive. This trick allows us to
2672      eliminate scan_libraries() function.  */
2673   do
2674     {
2675 #endif
2676       /* Some platforms (e.g. OSF4) declare ldopen as taking a
2677          non-const char * filename parameter, even though it will not
2678          modify that string.  So we must cast away const-ness here,
2679          which will cause -Wcast-qual to burp.  */
2680       if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2681         {
2682           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2683             fatal ("%s: not a COFF file", prog_name);
2684
2685           if (GCC_CHECK_HDR (ldptr))
2686             {
2687               sym_count = GCC_SYMBOLS (ldptr);
2688               sym_index = GCC_SYMZERO (ldptr);
2689
2690 #ifdef COLLECT_EXPORT_LIST
2691               /* Is current archive member a shared object?  */
2692               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2693 #endif
2694
2695               while (sym_index < sym_count)
2696                 {
2697                   GCC_SYMENT symbol;
2698
2699                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2700                     break;
2701                   sym_index += GCC_SYMINC (symbol);
2702
2703                   if (GCC_OK_SYMBOL (symbol))
2704                     {
2705                       char *name;
2706
2707                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
2708                         continue;               /* should never happen */
2709
2710 #ifdef XCOFF_DEBUGGING_INFO
2711                       /* All AIX function names have a duplicate entry
2712                          beginning with a dot.  */
2713                       if (*name == '.')
2714                         ++name;
2715 #endif
2716
2717                       switch (is_ctor_dtor (name))
2718                         {
2719                         case 1:
2720                           if (! is_shared)
2721                             add_to_list (&constructors, name);
2722 #ifdef COLLECT_EXPORT_LIST
2723                           if (which_pass == PASS_OBJ)
2724                             add_to_list (&exports, name);
2725 #endif
2726                           break;
2727
2728                         case 2:
2729                           if (! is_shared)
2730                             add_to_list (&destructors, name);
2731 #ifdef COLLECT_EXPORT_LIST
2732                           if (which_pass == PASS_OBJ)
2733                             add_to_list (&exports, name);
2734 #endif
2735                           break;
2736
2737 #ifdef COLLECT_EXPORT_LIST
2738                         case 3:
2739 #ifndef LD_INIT_SWITCH
2740                           if (is_shared)
2741                             add_to_list (&constructors, name);
2742 #endif
2743                           break;
2744
2745                         case 4:
2746 #ifndef LD_INIT_SWITCH
2747                           if (is_shared)
2748                             add_to_list (&destructors, name);
2749 #endif
2750                           break;
2751 #endif
2752
2753                         case 5:
2754                           if (! is_shared)
2755                             add_to_list (&frame_tables, name);
2756 #ifdef COLLECT_EXPORT_LIST
2757                           if (which_pass == PASS_OBJ)
2758                             add_to_list (&exports, name);
2759 #endif
2760                           break;
2761
2762                         default:        /* not a constructor or destructor */
2763 #ifdef COLLECT_EXPORT_LIST
2764                           /* If we are building a shared object on AIX we need
2765                              to explicitly export all global symbols.  */
2766                           if (shared_obj)
2767                             {
2768                               if (which_pass == PASS_OBJ && (! export_flag))
2769                                 add_to_list (&exports, name);
2770                             }
2771 #endif
2772                           continue;
2773                         }
2774
2775                       if (debug)
2776 #if !defined(EXTENDED_COFF)
2777                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2778                                  symbol.n_scnum, symbol.n_sclass,
2779                                  (symbol.n_type ? "0" : ""), symbol.n_type,
2780                                  name);
2781 #else
2782                         fprintf (stderr,
2783                                  "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2784                                  symbol.iss, (long) symbol.value, symbol.index, name);
2785 #endif
2786                     }
2787                 }
2788             }
2789 #ifdef COLLECT_EXPORT_LIST
2790           else
2791             {
2792               /* If archive contains both 32-bit and 64-bit objects,
2793                  we want to skip objects in other mode so mismatch normal.  */
2794               if (debug)
2795                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2796                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
2797             }
2798 #endif
2799         }
2800       else
2801         {
2802           fatal ("%s: cannot open as COFF file", prog_name);
2803         }
2804 #ifdef COLLECT_EXPORT_LIST
2805       /* On AIX loop continues while there are more members in archive.  */
2806     }
2807   while (ldclose (ldptr) == FAILURE);
2808 #else
2809   /* Otherwise we simply close ldptr.  */
2810   (void) ldclose(ldptr);
2811 #endif
2812 }
2813 #endif /* OBJECT_FORMAT_COFF */
2814
2815 #ifdef COLLECT_EXPORT_LIST
2816 /* Given a library name without "lib" prefix, this function
2817    returns a full library name including a path.  */
2818 static char *
2819 resolve_lib_name (const char *name)
2820 {
2821   char *lib_buf;
2822   int i, j, l = 0;
2823
2824   for (i = 0; libpaths[i]; i++)
2825     if (libpaths[i]->max_len > l)
2826       l = libpaths[i]->max_len;
2827
2828   lib_buf = xmalloc (l + strlen(name) + 10);
2829
2830   for (i = 0; libpaths[i]; i++)
2831     {
2832       struct prefix_list *list = libpaths[i]->plist;
2833       for (; list; list = list->next)
2834         {
2835           /* The following lines are needed because path_prefix list
2836              may contain directories both with trailing '/' and
2837              without it.  */
2838           const char *p = "";
2839           if (list->prefix[strlen(list->prefix)-1] != '/')
2840             p = "/";
2841           for (j = 0; libexts[j]; j++)
2842             {
2843               sprintf (lib_buf, "%s%slib%s.%s",
2844                        list->prefix, p, name, libexts[j]);
2845 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2846               if (file_exists (lib_buf))
2847                 {
2848 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2849                   return (lib_buf);
2850                 }
2851             }
2852         }
2853     }
2854   if (debug)
2855     fprintf (stderr, "not found\n");
2856   else
2857     fatal ("library lib%s not found", name);
2858   return (NULL);
2859 }
2860 #endif /* COLLECT_EXPORT_LIST */