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