collect2.c revision 146895
1260684Skaiw/* Collect static initialization info into data structures that can be
2260684Skaiw   traversed by C++ initialization and finalization routines.
3260684Skaiw   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4260684Skaiw   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5260684Skaiw   Contributed by Chris Smith (csmith@convex.com).
6260684Skaiw   Heavily modified by Michael Meissner (meissner@cygnus.com),
7260684Skaiw   Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
8260684Skaiw
9260684SkaiwThis file is part of GCC.
10260684Skaiw
11260684SkaiwGCC is free software; you can redistribute it and/or modify it under
12260684Skaiwthe terms of the GNU General Public License as published by the Free
13260684SkaiwSoftware Foundation; either version 2, or (at your option) any later
14260684Skaiwversion.
15260684Skaiw
16260684SkaiwGCC is distributed in the hope that it will be useful, but WITHOUT ANY
17260684SkaiwWARRANTY; without even the implied warranty of MERCHANTABILITY or
18260684SkaiwFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19260684Skaiwfor more details.
20260684Skaiw
21260684SkaiwYou should have received a copy of the GNU General Public License
22260684Skaiwalong with GCC; see the file COPYING.  If not, write to the Free
23260684SkaiwSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
24260684Skaiw02111-1307, USA.  */
25260684Skaiw
26260684Skaiw
27260684Skaiw/* Build tables of static constructors and destructors and run ld.  */
28260684Skaiw
29260684Skaiw#include "config.h"
30260684Skaiw#include "system.h"
31260684Skaiw#include "coretypes.h"
32260684Skaiw#include "tm.h"
33260684Skaiw#include <signal.h>
34260684Skaiw#if ! defined( SIGCHLD ) && defined( SIGCLD )
35260684Skaiw#  define SIGCHLD SIGCLD
36367466Sdim#endif
37260684Skaiw
38260684Skaiw#ifdef vfork /* Autoconf may define this to fork for us.  */
39260684Skaiw# define VFORK_STRING "fork"
40260684Skaiw#else
41260684Skaiw# define VFORK_STRING "vfork"
42260684Skaiw#endif
43260684Skaiw#ifdef HAVE_VFORK_H
44260684Skaiw#include <vfork.h>
45260684Skaiw#endif
46260684Skaiw#ifdef VMS
47260684Skaiw#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
48260684Skaiw               lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
49260684Skaiw#endif /* VMS */
50260684Skaiw
51260684Skaiw#ifndef LIBRARY_PATH_ENV
52260684Skaiw#define LIBRARY_PATH_ENV "LIBRARY_PATH"
53260684Skaiw#endif
54260684Skaiw
55260684Skaiw#define COLLECT
56260684Skaiw
57260684Skaiw#include "collect2.h"
58260684Skaiw#include "demangle.h"
59260684Skaiw#include "obstack.h"
60260684Skaiw#include "intl.h"
61260684Skaiw#include "version.h"
62260684Skaiw
63260684Skaiw/* On certain systems, we have code that works by scanning the object file
64260684Skaiw   directly.  But this code uses system-specific header files and library
65260684Skaiw   functions, so turn it off in a cross-compiler.  Likewise, the names of
66260684Skaiw   the utilities are not correct for a cross-compiler; we have to hope that
67300311Semaste   cross-versions are in the proper directories.  */
68260684Skaiw
69260684Skaiw#ifdef CROSS_COMPILE
70260684Skaiw#undef SUNOS4_SHARED_LIBRARIES
71260684Skaiw#undef OBJECT_FORMAT_COFF
72260684Skaiw#undef MD_EXEC_PREFIX
73260684Skaiw#undef REAL_LD_FILE_NAME
74260684Skaiw#undef REAL_NM_FILE_NAME
75260684Skaiw#undef REAL_STRIP_FILE_NAME
76260684Skaiw#endif
77260684Skaiw
78260684Skaiw/* If we cannot use a special method, use the ordinary one:
79260684Skaiw   run nm to find what symbols are present.
80260684Skaiw   In a cross-compiler, this means you need a cross nm,
81260684Skaiw   but that is not quite as unpleasant as special headers.  */
82260684Skaiw
83260684Skaiw#if !defined (OBJECT_FORMAT_COFF)
84260684Skaiw#define OBJECT_FORMAT_NONE
85260684Skaiw#endif
86260684Skaiw
87260684Skaiw#ifdef OBJECT_FORMAT_COFF
88260684Skaiw
89260684Skaiw#include <a.out.h>
90260684Skaiw#include <ar.h>
91260684Skaiw
92260684Skaiw#ifdef UMAX
93260684Skaiw#include <sgs.h>
94260684Skaiw#endif
95260684Skaiw
96260684Skaiw/* Many versions of ldfcn.h define these.  */
97260684Skaiw#ifdef FREAD
98260684Skaiw#undef FREAD
99260684Skaiw#undef FWRITE
100260684Skaiw#endif
101260684Skaiw
102260684Skaiw#include <ldfcn.h>
103260684Skaiw
104260684Skaiw/* Some systems have an ISCOFF macro, but others do not.  In some cases
105260684Skaiw   the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
106260684Skaiw   that either do not have an ISCOFF macro in /usr/include or for those
107260684Skaiw   where it is wrong.  */
108260684Skaiw
109260684Skaiw#ifndef MY_ISCOFF
110260684Skaiw#define MY_ISCOFF(X) ISCOFF (X)
111276371Semaste#endif
112260684Skaiw
113260684Skaiw#endif /* OBJECT_FORMAT_COFF */
114260684Skaiw
115260684Skaiw#ifdef OBJECT_FORMAT_NONE
116260684Skaiw
117260684Skaiw/* Default flags to pass to nm.  */
118260684Skaiw#ifndef NM_FLAGS
119260684Skaiw#define NM_FLAGS "-n"
120260684Skaiw#endif
121260684Skaiw
122260684Skaiw#endif /* OBJECT_FORMAT_NONE */
123260684Skaiw
124260684Skaiw/* Some systems use __main in a way incompatible with its use in gcc, in these
125260684Skaiw   cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
126260684Skaiw   give the same symbol without quotes for an alternative entry point.  */
127367466Sdim#ifndef NAME__MAIN
128367466Sdim#define NAME__MAIN "__main"
129367466Sdim#endif
130367466Sdim
131367466Sdim/* This must match tree.h.  */
132367466Sdim#define DEFAULT_INIT_PRIORITY 65535
133367466Sdim
134367466Sdim#ifndef COLLECT_SHARED_INIT_FUNC
135367466Sdim#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
136367466Sdim  fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
137260684Skaiw#endif
138260684Skaiw#ifndef COLLECT_SHARED_FINI_FUNC
139260684Skaiw#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
140260684Skaiw  fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
141260684Skaiw#endif
142260684Skaiw
143260684Skaiw#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
144260684Skaiw#define SCAN_LIBRARIES
145260684Skaiw#endif
146260684Skaiw
147260684Skaiw#ifdef USE_COLLECT2
148260684Skaiwint do_collecting = 1;
149260684Skaiw#else
150260684Skaiwint do_collecting = 0;
151260684Skaiw#endif
152260684Skaiw
153260684Skaiw#ifndef COLLECT_PARSE_FLAG
154260684Skaiw#define COLLECT_PARSE_FLAG(FLAG)
155260684Skaiw#endif
156260684Skaiw
157260684Skaiw/* Nonzero if we should suppress the automatic demangling of identifiers
158260684Skaiw   in linker error messages.  Set from COLLECT_NO_DEMANGLE.  */
159260684Skaiwint no_demangle;
160260684Skaiw
161260684Skaiw/* Linked lists of constructor and destructor names.  */
162260684Skaiw
163260684Skaiwstruct id
164260684Skaiw{
165260684Skaiw  struct id *next;
166260684Skaiw  int sequence;
167260684Skaiw  char name[1];
168260684Skaiw};
169260684Skaiw
170260684Skaiwstruct head
171260684Skaiw{
172260684Skaiw  struct id *first;
173260684Skaiw  struct id *last;
174260684Skaiw  int number;
175260684Skaiw};
176260684Skaiw
177260684Skaiw/* Enumeration giving which pass this is for scanning the program file.  */
178260684Skaiw
179260684Skaiwenum pass {
180260684Skaiw  PASS_FIRST,				/* without constructors */
181260684Skaiw  PASS_OBJ,				/* individual objects */
182260684Skaiw  PASS_LIB,			        /* looking for shared libraries */
183260684Skaiw  PASS_SECOND				/* with constructors linked in */
184260684Skaiw};
185260684Skaiw
186260684Skaiwint vflag;				/* true if -v */
187260684Skaiwstatic int rflag;			/* true if -r */
188260684Skaiwstatic int strip_flag;			/* true if -s */
189260684Skaiw#ifdef COLLECT_EXPORT_LIST
190260684Skaiwstatic int export_flag;                 /* true if -bE */
191260684Skaiwstatic int aix64_flag;			/* true if -b64 */
192260684Skaiwstatic int aixrtl_flag;			/* true if -brtl */
193260684Skaiw#endif
194260684Skaiw
195260684Skaiwint debug;				/* true if -debug */
196260684Skaiw
197260684Skaiwstatic int shared_obj;		        /* true if -shared */
198260684Skaiw
199260684Skaiwstatic const char *c_file;		/* <xxx>.c for constructor/destructor list.  */
200260684Skaiwstatic const char *o_file;		/* <xxx>.o for constructor/destructor list.  */
201276371Semaste#ifdef COLLECT_EXPORT_LIST
202260684Skaiwstatic const char *export_file;	        /* <xxx>.x for AIX export list.  */
203260684Skaiw#endif
204260684Skaiwconst char *ldout;			/* File for ld errors.  */
205260684Skaiwstatic const char *output_file;		/* Output file for ld.  */
206260684Skaiwstatic const char *nm_file_name;	/* pathname of nm */
207260684Skaiw#ifdef LDD_SUFFIX
208260684Skaiwstatic const char *ldd_file_name;	/* pathname of ldd (or equivalent) */
209260684Skaiw#endif
210260684Skaiwstatic const char *strip_file_name;		/* pathname of strip */
211367466Sdimconst char *c_file_name;	        /* pathname of gcc */
212260684Skaiwstatic char *initname, *fininame;	/* names of init and fini funcs */
213276371Semaste
214260684Skaiwstatic struct head constructors;	/* list of constructors found */
215260684Skaiwstatic struct head destructors;		/* list of destructors found */
216260684Skaiw#ifdef COLLECT_EXPORT_LIST
217260684Skaiwstatic struct head exports;		/* list of exported symbols */
218260684Skaiw#endif
219260684Skaiwstatic struct head frame_tables;	/* list of frame unwind info tables */
220260684Skaiw
221260684Skaiwstruct obstack temporary_obstack;
222260684Skaiwchar * temporary_firstobj;
223260684Skaiw
224260684Skaiw/* Holds the return value of pexecute and fork.  */
225260684Skaiwint pid;
226260684Skaiw
227260684Skaiw/* Structure to hold all the directories in which to search for files to
228367466Sdim   execute.  */
229367466Sdim
230367466Sdimstruct prefix_list
231367466Sdim{
232367466Sdim  const char *prefix;         /* String to prepend to the path.  */
233367466Sdim  struct prefix_list *next;   /* Next in linked list.  */
234367466Sdim};
235367466Sdim
236367466Sdimstruct path_prefix
237367466Sdim{
238367466Sdim  struct prefix_list *plist;  /* List of prefixes to try */
239260684Skaiw  int max_len;                /* Max length of a prefix in PLIST */
240260684Skaiw  const char *name;           /* Name of this list (used in config stuff) */
241260684Skaiw};
242260684Skaiw
243260684Skaiw#ifdef COLLECT_EXPORT_LIST
244260684Skaiw/* Lists to keep libraries to be scanned for global constructors/destructors.  */
245260684Skaiwstatic struct head libs;                    /* list of libraries */
246260684Skaiwstatic struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
247260684Skaiwstatic struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
248260684Skaiwstatic struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
249260684Skaiw					  &libpath_lib_dirs, NULL};
250260684Skaiw#endif
251367466Sdim
252367466Sdimstatic void handler (int);
253367466Sdimstatic int is_ctor_dtor (const char *);
254367466Sdimstatic char *find_a_file (struct path_prefix *, const char *);
255367466Sdimstatic void add_prefix (struct path_prefix *, const char *);
256367466Sdimstatic void prefix_from_env (const char *, struct path_prefix *);
257367466Sdimstatic void prefix_from_string (const char *, struct path_prefix *);
258367466Sdimstatic void do_wait (const char *);
259367466Sdimstatic void fork_execute (const char *, char **);
260367466Sdimstatic void maybe_unlink (const char *);
261367466Sdimstatic void add_to_list (struct head *, const char *);
262260684Skaiwstatic int extract_init_priority (const char *);
263260684Skaiwstatic void sort_ids (struct head *);
264260684Skaiwstatic void write_list (FILE *, const char *, struct id *);
265260684Skaiw#ifdef COLLECT_EXPORT_LIST
266260684Skaiwstatic void dump_list (FILE *, const char *, struct id *);
267260684Skaiw#endif
268260684Skaiw#if 0
269260684Skaiwstatic void dump_prefix_list (FILE *, const char *, struct prefix_list *);
270260684Skaiw#endif
271260684Skaiwstatic void write_list_with_asm (FILE *, const char *, struct id *);
272260684Skaiwstatic void write_c_file (FILE *, const char *);
273260684Skaiwstatic void write_c_file_stat (FILE *, const char *);
274260684Skaiw#ifndef LD_INIT_SWITCH
275260684Skaiwstatic void write_c_file_glob (FILE *, const char *);
276260684Skaiw#endif
277260684Skaiwstatic void scan_prog_file (const char *, enum pass);
278260684Skaiw#ifdef SCAN_LIBRARIES
279260684Skaiwstatic void scan_libraries (const char *);
280276371Semaste#endif
281260684Skaiw#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
282260684Skaiwstatic int is_in_args (const char *, const char **, const char **);
283260684Skaiw#endif
284260684Skaiw#ifdef COLLECT_EXPORT_LIST
285276371Semaste#if 0
286260684Skaiwstatic int is_in_list (const char *, struct id *);
287260684Skaiw#endif
288260684Skaiwstatic void write_aix_file (FILE *, struct id *);
289260684Skaiwstatic char *resolve_lib_name (const char *);
290260684Skaiw#endif
291260684Skaiwstatic char *extract_string (const char **);
292260684Skaiw
293260684Skaiw#ifndef HAVE_DUP2
294260684Skaiwstatic int
295260684Skaiwdup2 (int oldfd, int newfd)
296260684Skaiw{
297260684Skaiw  int fdtmp[256];
298260684Skaiw  int fdx = 0;
299260684Skaiw  int fd;
300260684Skaiw
301260684Skaiw  if (oldfd == newfd)
302260684Skaiw    return oldfd;
303260684Skaiw  close (newfd);
304260684Skaiw  while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
305276371Semaste    fdtmp[fdx++] = fd;
306276371Semaste  while (fdx > 0)
307276371Semaste    close (fdtmp[--fdx]);
308276371Semaste
309260684Skaiw  return fd;
310260684Skaiw}
311260684Skaiw#endif /* ! HAVE_DUP2 */
312260684Skaiw
313260684Skaiw/* Delete tempfiles and exit function.  */
314260684Skaiw
315260684Skaiwvoid
316260684Skaiwcollect_exit (int status)
317260684Skaiw{
318260684Skaiw  if (c_file != 0 && c_file[0])
319367466Sdim    maybe_unlink (c_file);
320367466Sdim
321260684Skaiw  if (o_file != 0 && o_file[0])
322276371Semaste    maybe_unlink (o_file);
323276371Semaste
324260684Skaiw#ifdef COLLECT_EXPORT_LIST
325260684Skaiw  if (export_file != 0 && export_file[0])
326260684Skaiw    maybe_unlink (export_file);
327260684Skaiw#endif
328260684Skaiw
329260684Skaiw  if (ldout != 0 && ldout[0])
330260684Skaiw    {
331260684Skaiw      dump_file (ldout);
332260684Skaiw      maybe_unlink (ldout);
333260684Skaiw    }
334260684Skaiw
335260684Skaiw  if (status != 0 && output_file != 0 && output_file[0])
336260684Skaiw    maybe_unlink (output_file);
337260684Skaiw
338260684Skaiw  exit (status);
339260684Skaiw}
340260684Skaiw
341260684Skaiw
342260684Skaiw/* Notify user of a non-error.  */
343260684Skaiwvoid
344260684Skaiwnotice (const char *msgid, ...)
345260684Skaiw{
346260684Skaiw  va_list ap;
347276371Semaste
348276371Semaste  va_start (ap, msgid);
349260684Skaiw  vfprintf (stderr, _(msgid), ap);
350260684Skaiw  va_end (ap);
351260684Skaiw}
352260684Skaiw
353260684Skaiw/* Die when sys call fails.  */
354260684Skaiw
355260684Skaiwvoid
356260684Skaiwfatal_perror (const char * msgid, ...)
357260684Skaiw{
358276371Semaste  int e = errno;
359260684Skaiw  va_list ap;
360260684Skaiw
361276371Semaste  va_start (ap, msgid);
362260684Skaiw  fprintf (stderr, "collect2: ");
363260684Skaiw  vfprintf (stderr, _(msgid), ap);
364260684Skaiw  fprintf (stderr, ": %s\n", xstrerror (e));
365260684Skaiw  va_end (ap);
366260684Skaiw
367260684Skaiw  collect_exit (FATAL_EXIT_CODE);
368260684Skaiw}
369260684Skaiw
370260684Skaiw/* Just die.  */
371260684Skaiw
372260684Skaiwvoid
373260684Skaiwfatal (const char * msgid, ...)
374260684Skaiw{
375260684Skaiw  va_list ap;
376276371Semaste
377367466Sdim  va_start (ap, msgid);
378276371Semaste  fprintf (stderr, "collect2: ");
379276371Semaste  vfprintf (stderr, _(msgid), ap);
380260684Skaiw  fprintf (stderr, "\n");
381260684Skaiw  va_end (ap);
382260684Skaiw
383260684Skaiw  collect_exit (FATAL_EXIT_CODE);
384260684Skaiw}
385276371Semaste
386260684Skaiw/* Write error message.  */
387260684Skaiw
388260684Skaiwvoid
389260684Skaiwerror (const char * msgid, ...)
390260684Skaiw{
391260684Skaiw  va_list ap;
392260684Skaiw
393260684Skaiw  va_start (ap, msgid);
394260684Skaiw  fprintf (stderr, "collect2: ");
395260684Skaiw  vfprintf (stderr, _(msgid), ap);
396260684Skaiw  fprintf (stderr, "\n");
397260684Skaiw  va_end(ap);
398260684Skaiw}
399260684Skaiw
400260684Skaiw/* In case obstack is linked in, and abort is defined to fancy_abort,
401260684Skaiw   provide a default entry.  */
402260684Skaiw
403260684Skaiwvoid
404260684Skaiwfancy_abort (void)
405260684Skaiw{
406260684Skaiw  fatal ("internal error");
407260684Skaiw}
408260684Skaiw
409260684Skaiwstatic void
410260684Skaiwhandler (int signo)
411260684Skaiw{
412260684Skaiw  if (c_file != 0 && c_file[0])
413260684Skaiw    maybe_unlink (c_file);
414260684Skaiw
415260684Skaiw  if (o_file != 0 && o_file[0])
416260684Skaiw    maybe_unlink (o_file);
417260684Skaiw
418260684Skaiw  if (ldout != 0 && ldout[0])
419260684Skaiw    maybe_unlink (ldout);
420260684Skaiw
421260684Skaiw#ifdef COLLECT_EXPORT_LIST
422260684Skaiw  if (export_file != 0 && export_file[0])
423260684Skaiw    maybe_unlink (export_file);
424260684Skaiw#endif
425260684Skaiw
426260684Skaiw  signal (signo, SIG_DFL);
427260684Skaiw  kill (getpid (), signo);
428260684Skaiw}
429260684Skaiw
430260684Skaiw
431260684Skaiwint
432276371Semastefile_exists (const char *name)
433276371Semaste{
434260684Skaiw  return access (name, R_OK) == 0;
435260684Skaiw}
436260684Skaiw
437260684Skaiw/* Parse a reasonable subset of shell quoting syntax.  */
438260684Skaiw
439260684Skaiwstatic char *
440260684Skaiwextract_string (const char **pp)
441260684Skaiw{
442260684Skaiw  const char *p = *pp;
443260684Skaiw  int backquote = 0;
444260684Skaiw  int inside = 0;
445260684Skaiw
446260684Skaiw  for (;;)
447260684Skaiw    {
448260684Skaiw      char c = *p;
449260684Skaiw      if (c == '\0')
450260684Skaiw	break;
451260684Skaiw      ++p;
452260684Skaiw      if (backquote)
453260684Skaiw	obstack_1grow (&temporary_obstack, c);
454260684Skaiw      else if (! inside && c == ' ')
455260684Skaiw	break;
456260684Skaiw      else if (! inside && c == '\\')
457260684Skaiw	backquote = 1;
458260684Skaiw      else if (c == '\'')
459260684Skaiw	inside = !inside;
460260684Skaiw      else
461260684Skaiw	obstack_1grow (&temporary_obstack, c);
462260684Skaiw    }
463260684Skaiw
464260684Skaiw  obstack_1grow (&temporary_obstack, '\0');
465260684Skaiw  *pp = p;
466260684Skaiw  return obstack_finish (&temporary_obstack);
467260684Skaiw}
468276371Semaste
469276371Semastevoid
470260684Skaiwdump_file (const char *name)
471276371Semaste{
472260684Skaiw  FILE *stream = fopen (name, "r");
473260684Skaiw
474260684Skaiw  if (stream == 0)
475260684Skaiw    return;
476260684Skaiw  while (1)
477260684Skaiw    {
478260684Skaiw      int c;
479260684Skaiw      while (c = getc (stream),
480260684Skaiw	     c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
481260684Skaiw	obstack_1grow (&temporary_obstack, c);
482260684Skaiw      if (obstack_object_size (&temporary_obstack) > 0)
483260684Skaiw	{
484260684Skaiw	  const char *word, *p;
485260684Skaiw	  char *result;
486260684Skaiw	  obstack_1grow (&temporary_obstack, '\0');
487260684Skaiw	  word = obstack_finish (&temporary_obstack);
488260684Skaiw
489260684Skaiw	  if (*word == '.')
490260684Skaiw	    ++word, putc ('.', stderr);
491260684Skaiw	  p = word;
492260684Skaiw	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
493260684Skaiw	    p += strlen (USER_LABEL_PREFIX);
494260684Skaiw
495260684Skaiw	  if (no_demangle)
496260684Skaiw	    result = 0;
497260684Skaiw	  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	      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
1461/* Wait for a process to finish, and exit if a nonzero status is found.  */
1462
1463int
1464collect_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
1486static void
1487do_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
1498/* Execute a program, and wait for the reply.  */
1499
1500void
1501collect_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
1570static void
1571fork_execute (const char *prog, char **argv)
1572{
1573  collect_execute (prog, argv, NULL);
1574  do_wait (prog);
1575}
1576
1577/* Unlink a file unless we are debugging.  */
1578
1579static void
1580maybe_unlink (const char *file)
1581{
1582  if (!debug)
1583    unlink (file);
1584  else
1585    notice ("[Leaving %s]\n", file);
1586}
1587
1588
1589static long sequence_number = 0;
1590
1591/* Add a name to a linked list.  */
1592
1593static void
1594add_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
1625static int
1626extract_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
1642static void
1643sort_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
1683static void
1684write_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
1697static int
1698is_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
1712static int
1713is_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
1727static void
1728dump_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
1739static void
1740dump_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
1750static void
1751write_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
1764static void
1765write_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
1893static void
1894write_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
1956static void
1957write_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
1970static void
1971write_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
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
1992static void
1993scan_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 */
2168unsigned object;	/* address of memory mapped file */
2169unsigned objsize;	/* size of memory mapped to file */
2170char * code;		/* pointer to code segment */
2171char * data;		/* pointer to data segment */
2172struct nlist *symtab;	/* pointer to symbol table */
2173struct link_dynamic *ld;
2174struct link_dynamic_2 *ld_2;
2175struct head libraries;
2176
2177/* Map the file indicated by NAME into memory and store its address.  */
2178
2179static void
2180mapfile (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
2200static const char *libname;
2201
2202static int
2203libselect (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
2216static int
2217libcompare (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
2259static void
2260locatelib (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
2348static void
2349scan_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
2422static void
2423scan_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
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.  */
2615static 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.  */
2635static int ignore_library (const char *);
2636static int
2637ignore_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
2647extern 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
2659static void
2660scan_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.  */
2823static char *
2824resolve_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 */
2869