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