1/* Collect static initialization info into data structures that can be
2   traversed by C++ initialization and finalization routines.
3   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5   Contributed by Chris Smith (csmith@convex.com).
6   Heavily modified by Michael Meissner (meissner@cygnus.com),
7   Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
13Software Foundation; either version 2, or (at your option) any later
14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
22along with GCC; see the file COPYING.  If not, write to the Free
23Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2402111-1307, USA.  */
25
26
27/* Build tables of static constructors and destructors and run ld.  */
28
29#include "config.h"
30#include "system.h"
31#include <signal.h>
32#if ! defined( SIGCHLD ) && defined( SIGCLD )
33#  define SIGCHLD SIGCLD
34#endif
35
36#ifdef vfork /* Autoconf may define this to fork for us.  */
37# define VFORK_STRING "fork"
38#else
39# define VFORK_STRING "vfork"
40#endif
41#ifdef HAVE_VFORK_H
42#include <vfork.h>
43#endif
44#ifdef VMS
45#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
46               lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
47#endif /* VMS */
48
49#ifndef LIBRARY_PATH_ENV
50#define LIBRARY_PATH_ENV "LIBRARY_PATH"
51#endif
52
53#define COLLECT
54
55#include "collect2.h"
56#include "demangle.h"
57#include "obstack.h"
58#include "intl.h"
59#include "version.h"
60
61/* On certain systems, we have code that works by scanning the object file
62   directly.  But this code uses system-specific header files and library
63   functions, so turn it off in a cross-compiler.  Likewise, the names of
64   the utilities are not correct for a cross-compiler; we have to hope that
65   cross-versions are in the proper directories.  */
66
67#ifdef CROSS_COMPILE
68#undef SUNOS4_SHARED_LIBRARIES
69#undef OBJECT_FORMAT_COFF
70#undef OBJECT_FORMAT_ROSE
71#undef MD_EXEC_PREFIX
72#undef REAL_LD_FILE_NAME
73#undef REAL_NM_FILE_NAME
74#undef REAL_STRIP_FILE_NAME
75#endif
76
77/* If we cannot use a special method, use the ordinary one:
78   run nm to find what symbols are present.
79   In a cross-compiler, this means you need a cross nm,
80   but that is not quite as unpleasant as special headers.  */
81
82#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
83#define OBJECT_FORMAT_NONE
84#endif
85
86#ifdef OBJECT_FORMAT_COFF
87
88#include <a.out.h>
89#include <ar.h>
90
91#ifdef UMAX
92#include <sgs.h>
93#endif
94
95/* Many versions of ldfcn.h define these.  */
96#ifdef FREAD
97#undef FREAD
98#undef FWRITE
99#endif
100
101#include <ldfcn.h>
102
103/* Some systems have an ISCOFF macro, but others do not.  In some cases
104   the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
105   that either do not have an ISCOFF macro in /usr/include or for those
106   where it is wrong.  */
107
108#ifndef MY_ISCOFF
109#define MY_ISCOFF(X) ISCOFF (X)
110#endif
111
112#endif /* OBJECT_FORMAT_COFF */
113
114#ifdef OBJECT_FORMAT_ROSE
115
116#ifdef _OSF_SOURCE
117#define USE_MMAP
118#endif
119
120#ifdef USE_MMAP
121#include <sys/mman.h>
122#endif
123
124#include <unistd.h>
125#include <mach_o_format.h>
126#include <mach_o_header.h>
127#include <mach_o_vals.h>
128#include <mach_o_types.h>
129
130#endif /* OBJECT_FORMAT_ROSE */
131
132#ifdef OBJECT_FORMAT_NONE
133
134/* Default flags to pass to nm.  */
135#ifndef NM_FLAGS
136#define NM_FLAGS "-n"
137#endif
138
139#endif /* OBJECT_FORMAT_NONE */
140
141/* Some systems use __main in a way incompatible with its use in gcc, in these
142   cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
143   give the same symbol without quotes for an alternative entry point.  */
144#ifndef NAME__MAIN
145#define NAME__MAIN "__main"
146#endif
147
148/* This must match tree.h.  */
149#define DEFAULT_INIT_PRIORITY 65535
150
151#ifndef COLLECT_SHARED_INIT_FUNC
152#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
153  fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
154#endif
155#ifndef COLLECT_SHARED_FINI_FUNC
156#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
157  fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
158#endif
159
160#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
161#define SCAN_LIBRARIES
162#endif
163
164#ifdef USE_COLLECT2
165int do_collecting = 1;
166#else
167int do_collecting = 0;
168#endif
169
170/* Nonzero if we should suppress the automatic demangling of identifiers
171   in linker error messages.  Set from COLLECT_NO_DEMANGLE.  */
172int no_demangle;
173
174/* Linked lists of constructor and destructor names.  */
175
176struct id
177{
178  struct id *next;
179  int sequence;
180  char name[1];
181};
182
183struct head
184{
185  struct id *first;
186  struct id *last;
187  int number;
188};
189
190/* Enumeration giving which pass this is for scanning the program file.  */
191
192enum pass {
193  PASS_FIRST,				/* without constructors */
194  PASS_OBJ,				/* individual objects */
195  PASS_LIB,			        /* looking for shared libraries */
196  PASS_SECOND				/* with constructors linked in */
197};
198
199int vflag;				/* true if -v */
200static int rflag;			/* true if -r */
201static int strip_flag;			/* true if -s */
202#ifdef COLLECT_EXPORT_LIST
203static int export_flag;                 /* true if -bE */
204static int aix64_flag;			/* true if -b64 */
205#endif
206
207int debug;				/* true if -debug */
208
209static int shared_obj;		        /* true if -shared */
210
211static const char *c_file;		/* <xxx>.c for constructor/destructor list.  */
212static const char *o_file;		/* <xxx>.o for constructor/destructor list.  */
213#ifdef COLLECT_EXPORT_LIST
214static const char *export_file;	        /* <xxx>.x for AIX export list.  */
215#endif
216const char *ldout;			/* File for ld stdout.  */
217const char *lderrout;			/* File for ld stderr.  */
218static const char *output_file;		/* Output file for ld.  */
219static const char *nm_file_name;	/* pathname of nm */
220#ifdef LDD_SUFFIX
221static const char *ldd_file_name;	/* pathname of ldd (or equivalent) */
222#endif
223static const char *strip_file_name;		/* pathname of strip */
224const char *c_file_name;	        /* pathname of gcc */
225static char *initname, *fininame;	/* names of init and fini funcs */
226
227static struct head constructors;	/* list of constructors found */
228static struct head destructors;		/* list of destructors found */
229#ifdef COLLECT_EXPORT_LIST
230static struct head exports;		/* list of exported symbols */
231#endif
232static struct head frame_tables;	/* list of frame unwind info tables */
233
234struct obstack temporary_obstack;
235char * temporary_firstobj;
236
237/* Holds the return value of pexecute.  */
238int pid;
239
240/* Structure to hold all the directories in which to search for files to
241   execute.  */
242
243struct prefix_list
244{
245  const char *prefix;         /* String to prepend to the path.  */
246  struct prefix_list *next;   /* Next in linked list.  */
247};
248
249struct path_prefix
250{
251  struct prefix_list *plist;  /* List of prefixes to try */
252  int max_len;                /* Max length of a prefix in PLIST */
253  const char *name;           /* Name of this list (used in config stuff) */
254};
255
256#ifdef COLLECT_EXPORT_LIST
257/* Lists to keep libraries to be scanned for global constructors/destructors.  */
258static struct head libs;                    /* list of libraries */
259static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
260static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
261static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
262					  &libpath_lib_dirs, NULL};
263static const char *const libexts[3] = {"a", "so", NULL};  /* possible library extensions */
264#endif
265
266static void handler		PARAMS ((int));
267static int is_ctor_dtor		PARAMS ((const char *));
268static char *find_a_file	PARAMS ((struct path_prefix *, const char *));
269static void add_prefix		PARAMS ((struct path_prefix *, const char *));
270static void prefix_from_env	PARAMS ((const char *, struct path_prefix *));
271static void prefix_from_string	PARAMS ((const char *, struct path_prefix *));
272static void do_wait		PARAMS ((const char *));
273static void fork_execute	PARAMS ((const char *, char **));
274static void maybe_unlink	PARAMS ((const char *));
275static void add_to_list		PARAMS ((struct head *, const char *));
276static int extract_init_priority PARAMS ((const char *));
277static void sort_ids		PARAMS ((struct head *));
278static void write_list		PARAMS ((FILE *, const char *, struct id *));
279#ifdef COLLECT_EXPORT_LIST
280static void dump_list		PARAMS ((FILE *, const char *, struct id *));
281#endif
282#if 0
283static void dump_prefix_list	PARAMS ((FILE *, const char *, struct prefix_list *));
284#endif
285static void write_list_with_asm PARAMS ((FILE *, const char *, struct id *));
286static void write_c_file	PARAMS ((FILE *, const char *));
287static void write_c_file_stat	PARAMS ((FILE *, const char *));
288#ifndef LD_INIT_SWITCH
289static void write_c_file_glob	PARAMS ((FILE *, const char *));
290#endif
291static void scan_prog_file	PARAMS ((const char *, enum pass));
292#ifdef SCAN_LIBRARIES
293static void scan_libraries	PARAMS ((const char *));
294#endif
295#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
296static int is_in_args		PARAMS ((const char *, const char **, const char **));
297#endif
298#ifdef COLLECT_EXPORT_LIST
299#if 0
300static int is_in_list		PARAMS ((const char *, struct id *));
301#endif
302static void write_aix_file	PARAMS ((FILE *, struct id *));
303static char *resolve_lib_name	PARAMS ((const char *));
304static int ignore_library	PARAMS ((const char *));
305#endif
306static char *extract_string	PARAMS ((const char **));
307
308#ifndef HAVE_DUP2
309static int dup2 PARAMS ((int, int));
310static int
311dup2 (oldfd, newfd)
312     int oldfd;
313     int newfd;
314{
315  int fdtmp[256];
316  int fdx = 0;
317  int fd;
318
319  if (oldfd == newfd)
320    return oldfd;
321  close (newfd);
322  while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
323    fdtmp[fdx++] = fd;
324  while (fdx > 0)
325    close (fdtmp[--fdx]);
326
327  return fd;
328}
329#endif /* ! HAVE_DUP2 */
330
331/* Delete tempfiles and exit function.  */
332
333void
334collect_exit (status)
335     int status;
336{
337  if (c_file != 0 && c_file[0])
338    maybe_unlink (c_file);
339
340  if (o_file != 0 && o_file[0])
341    maybe_unlink (o_file);
342
343#ifdef COLLECT_EXPORT_LIST
344  if (export_file != 0 && export_file[0])
345    maybe_unlink (export_file);
346#endif
347
348  if (ldout != 0 && ldout[0])
349    {
350      dump_file (ldout, stdout);
351      maybe_unlink (ldout);
352    }
353
354  if (lderrout != 0 && lderrout[0])
355    {
356      dump_file (lderrout, stderr);
357      maybe_unlink (lderrout);
358    }
359
360  if (status != 0 && output_file != 0 && output_file[0])
361    maybe_unlink (output_file);
362
363  exit (status);
364}
365
366
367/* Notify user of a non-error.  */
368void
369notice VPARAMS ((const char *msgid, ...))
370{
371  VA_OPEN (ap, msgid);
372  VA_FIXEDARG (ap, const char *, msgid);
373
374  vfprintf (stderr, _(msgid), ap);
375  VA_CLOSE (ap);
376}
377
378/* Die when sys call fails.  */
379
380void
381fatal_perror VPARAMS ((const char * msgid, ...))
382{
383  int e = errno;
384
385  VA_OPEN (ap, msgid);
386  VA_FIXEDARG (ap, const char *, msgid);
387
388  fprintf (stderr, "collect2: ");
389  vfprintf (stderr, _(msgid), ap);
390  fprintf (stderr, ": %s\n", xstrerror (e));
391  VA_CLOSE (ap);
392
393  collect_exit (FATAL_EXIT_CODE);
394}
395
396/* Just die.  */
397
398void
399fatal VPARAMS ((const char * msgid, ...))
400{
401  VA_OPEN (ap, msgid);
402  VA_FIXEDARG (ap, const char *, msgid);
403
404  fprintf (stderr, "collect2: ");
405  vfprintf (stderr, _(msgid), ap);
406  fprintf (stderr, "\n");
407  VA_CLOSE (ap);
408
409  collect_exit (FATAL_EXIT_CODE);
410}
411
412/* Write error message.  */
413
414void
415error VPARAMS ((const char * msgid, ...))
416{
417  VA_OPEN (ap, msgid);
418  VA_FIXEDARG (ap, const char *, msgid);
419
420  fprintf (stderr, "collect2: ");
421  vfprintf (stderr, _(msgid), ap);
422  fprintf (stderr, "\n");
423  VA_CLOSE(ap);
424}
425
426/* In case obstack is linked in, and abort is defined to fancy_abort,
427   provide a default entry.  */
428
429void
430fancy_abort ()
431{
432  fatal ("internal error");
433}
434
435static void
436handler (signo)
437     int signo;
438{
439  if (c_file != 0 && c_file[0])
440    maybe_unlink (c_file);
441
442  if (o_file != 0 && o_file[0])
443    maybe_unlink (o_file);
444
445  if (ldout != 0 && ldout[0])
446    maybe_unlink (ldout);
447
448  if (lderrout != 0 && lderrout[0])
449    maybe_unlink (lderrout);
450
451#ifdef COLLECT_EXPORT_LIST
452  if (export_file != 0 && export_file[0])
453    maybe_unlink (export_file);
454#endif
455
456  signal (signo, SIG_DFL);
457  kill (getpid (), signo);
458}
459
460
461int
462file_exists (name)
463     const char *name;
464{
465  return access (name, R_OK) == 0;
466}
467
468/* Parse a reasonable subset of shell quoting syntax.  */
469
470static char *
471extract_string (pp)
472     const char **pp;
473{
474  const char *p = *pp;
475  int backquote = 0;
476  int inside = 0;
477
478  for (;;)
479    {
480      char c = *p;
481      if (c == '\0')
482	break;
483      ++p;
484      if (backquote)
485	obstack_1grow (&temporary_obstack, c);
486      else if (! inside && c == ' ')
487	break;
488      else if (! inside && c == '\\')
489	backquote = 1;
490      else if (c == '\'')
491	inside = !inside;
492      else
493	obstack_1grow (&temporary_obstack, c);
494    }
495
496  obstack_1grow (&temporary_obstack, '\0');
497  *pp = p;
498  return obstack_finish (&temporary_obstack);
499}
500
501void
502dump_file (name, to)
503     const char *name;
504     FILE *to;
505{
506  FILE *stream = fopen (name, "r");
507
508  if (stream == 0)
509    return;
510  while (1)
511    {
512      int c;
513      while (c = getc (stream),
514	     c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
515	obstack_1grow (&temporary_obstack, c);
516      if (obstack_object_size (&temporary_obstack) > 0)
517	{
518	  const char *word, *p;
519	  char *result;
520	  obstack_1grow (&temporary_obstack, '\0');
521	  word = obstack_finish (&temporary_obstack);
522
523	  if (*word == '.')
524	    ++word, putc ('.', to);
525	  p = word;
526	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
527	    p += strlen (USER_LABEL_PREFIX);
528
529	  if (no_demangle)
530	    result = 0;
531	  else
532	    result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
533
534	  if (result)
535	    {
536	      int diff;
537	      fputs (result, to);
538
539	      diff = strlen (word) - strlen (result);
540	      while (diff > 0 && c == ' ')
541		--diff, putc (' ', to);
542	      while (diff < 0 && c == ' ')
543		++diff, c = getc (stream);
544
545	      free (result);
546	    }
547	  else
548	    fputs (word, to);
549
550	  fflush (to);
551	  obstack_free (&temporary_obstack, temporary_firstobj);
552	}
553      if (c == EOF)
554	break;
555      putc (c, to);
556    }
557  fclose (stream);
558}
559
560/* Decide whether the given symbol is: a constructor (1), a destructor
561   (2), a routine in a shared object that calls all the constructors
562   (3) or destructors (4), a DWARF exception-handling table (5), or
563   nothing special (0).  */
564
565static int
566is_ctor_dtor (s)
567     const char *s;
568{
569  struct names { const char *const name; const int len; const int ret;
570    const int two_underscores; };
571
572  const struct names *p;
573  int ch;
574  const char *orig_s = s;
575
576  static const struct names special[] = {
577#ifndef NO_DOLLAR_IN_LABEL
578    { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 },
579    { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 },
580#else
581#ifndef NO_DOT_IN_LABEL
582    { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 },
583    { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 },
584#endif /* NO_DOT_IN_LABEL */
585#endif /* NO_DOLLAR_IN_LABEL */
586    { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
587    { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
588    { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
589    { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
590    { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
591#ifdef CFRONT_LOSSAGE /* Do not collect cfront initialization functions.
592			 cfront has its own linker procedure to collect them;
593			 if collect2 gets them too, they get collected twice
594			 when the cfront procedure is run and the compiler used
595			 for linking happens to be GCC.  */
596    { "sti__", sizeof ("sti__")-1, 1, 1 },
597    { "std__", sizeof ("std__")-1, 2, 1 },
598#endif /* CFRONT_LOSSAGE */
599    { NULL, 0, 0, 0 }
600  };
601
602  while ((ch = *s) == '_')
603    ++s;
604
605  if (s == orig_s)
606    return 0;
607
608  for (p = &special[0]; p->len > 0; p++)
609    {
610      if (ch == p->name[0]
611	  && (!p->two_underscores || ((s - orig_s) >= 2))
612	  && strncmp(s, p->name, p->len) == 0)
613	{
614	  return p->ret;
615	}
616    }
617  return 0;
618}
619
620/* We maintain two prefix lists: one from COMPILER_PATH environment variable
621   and one from the PATH variable.  */
622
623static struct path_prefix cpath, path;
624
625#ifdef CROSS_COMPILE
626/* This is the name of the target machine.  We use it to form the name
627   of the files to execute.  */
628
629static const char *const target_machine = TARGET_MACHINE;
630#endif
631
632/* Search for NAME using prefix list PPREFIX.  We only look for executable
633   files.
634
635   Return 0 if not found, otherwise return its name, allocated with malloc.  */
636
637static char *
638find_a_file (pprefix, name)
639     struct path_prefix *pprefix;
640     const char *name;
641{
642  char *temp;
643  struct prefix_list *pl;
644  int len = pprefix->max_len + strlen (name) + 1;
645
646  if (debug)
647    fprintf (stderr, "Looking for '%s'\n", name);
648
649#ifdef HOST_EXECUTABLE_SUFFIX
650  len += strlen (HOST_EXECUTABLE_SUFFIX);
651#endif
652
653  temp = xmalloc (len);
654
655  /* Determine the filename to execute (special case for absolute paths).  */
656
657  if (*name == '/'
658#ifdef HAVE_DOS_BASED_FILE_SYSTEM
659      || (*name && name[1] == ':')
660#endif
661      )
662    {
663      if (access (name, X_OK) == 0)
664	{
665	  strcpy (temp, name);
666
667	  if (debug)
668	    fprintf (stderr, "  - found: absolute path\n");
669
670	  return temp;
671	}
672
673#ifdef HOST_EXECUTABLE_SUFFIX
674	/* Some systems have a suffix for executable files.
675	   So try appending that.  */
676      strcpy (temp, name);
677	strcat (temp, HOST_EXECUTABLE_SUFFIX);
678
679	if (access (temp, X_OK) == 0)
680	  return temp;
681#endif
682
683      if (debug)
684	fprintf (stderr, "  - failed to locate using absolute path\n");
685    }
686  else
687    for (pl = pprefix->plist; pl; pl = pl->next)
688      {
689	struct stat st;
690
691	strcpy (temp, pl->prefix);
692	strcat (temp, name);
693
694	if (stat (temp, &st) >= 0
695	    && ! S_ISDIR (st.st_mode)
696	    && access (temp, X_OK) == 0)
697	  return temp;
698
699#ifdef HOST_EXECUTABLE_SUFFIX
700	/* Some systems have a suffix for executable files.
701	   So try appending that.  */
702	strcat (temp, HOST_EXECUTABLE_SUFFIX);
703
704	if (stat (temp, &st) >= 0
705	    && ! S_ISDIR (st.st_mode)
706	    && access (temp, X_OK) == 0)
707	  return temp;
708#endif
709      }
710
711  if (debug && pprefix->plist == NULL)
712    fprintf (stderr, "  - failed: no entries in prefix list\n");
713
714  free (temp);
715  return 0;
716}
717
718/* Add an entry for PREFIX to prefix list PPREFIX.  */
719
720static void
721add_prefix (pprefix, prefix)
722     struct path_prefix *pprefix;
723     const char *prefix;
724{
725  struct prefix_list *pl, **prev;
726  int len;
727
728  if (pprefix->plist)
729    {
730      for (pl = pprefix->plist; pl->next; pl = pl->next)
731	;
732      prev = &pl->next;
733    }
734  else
735    prev = &pprefix->plist;
736
737  /* Keep track of the longest prefix */
738
739  len = strlen (prefix);
740  if (len > pprefix->max_len)
741    pprefix->max_len = len;
742
743  pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
744  pl->prefix = xstrdup (prefix);
745
746  if (*prev)
747    pl->next = *prev;
748  else
749    pl->next = (struct prefix_list *) 0;
750  *prev = pl;
751}
752
753/* Take the value of the environment variable ENV, break it into a path, and
754   add of the entries to PPREFIX.  */
755
756static void
757prefix_from_env (env, pprefix)
758     const char *env;
759     struct path_prefix *pprefix;
760{
761  const char *p;
762  GET_ENVIRONMENT (p, env);
763
764  if (p)
765    prefix_from_string (p, pprefix);
766}
767
768static void
769prefix_from_string (p, pprefix)
770     const char *p;
771     struct path_prefix *pprefix;
772{
773  const char *startp, *endp;
774  char *nstore = (char *) xmalloc (strlen (p) + 3);
775
776  if (debug)
777    fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
778
779  startp = endp = p;
780  while (1)
781    {
782      if (*endp == PATH_SEPARATOR || *endp == 0)
783	{
784	  strncpy (nstore, startp, endp-startp);
785	  if (endp == startp)
786	    {
787	      strcpy (nstore, "./");
788	    }
789	  else if (! IS_DIR_SEPARATOR (endp[-1]))
790	    {
791	      nstore[endp-startp] = DIR_SEPARATOR;
792	      nstore[endp-startp+1] = 0;
793	    }
794	  else
795	    nstore[endp-startp] = 0;
796
797	  if (debug)
798	    fprintf (stderr, "  - add prefix: %s\n", nstore);
799
800	  add_prefix (pprefix, nstore);
801	  if (*endp == 0)
802	    break;
803	  endp = startp = endp + 1;
804	}
805      else
806	endp++;
807    }
808}
809
810/* Main program.  */
811
812int main 		PARAMS ((int, char *[]));
813int
814main (argc, argv)
815     int argc;
816     char *argv[];
817{
818  static const char *const ld_suffix	= "ld";
819  static const char *const real_ld_suffix = "real-ld";
820  static const char *const collect_ld_suffix = "collect-ld";
821  static const char *const nm_suffix	= "nm";
822  static const char *const gnm_suffix	= "gnm";
823#ifdef LDD_SUFFIX
824  static const char *const ldd_suffix	= LDD_SUFFIX;
825#endif
826  static const char *const strip_suffix = "strip";
827  static const char *const gstrip_suffix = "gstrip";
828
829#ifdef CROSS_COMPILE
830  /* If we look for a program in the compiler directories, we just use
831     the short name, since these directories are already system-specific.
832     But it we look for a program in the system directories, we need to
833     qualify the program name with the target machine.  */
834
835  const char *const full_ld_suffix =
836    concat(target_machine, "-", ld_suffix, NULL);
837  const char *const full_nm_suffix =
838    concat (target_machine, "-", nm_suffix, NULL);
839  const char *const full_gnm_suffix =
840    concat (target_machine, "-", gnm_suffix, NULL);
841#ifdef LDD_SUFFIX
842  const char *const full_ldd_suffix =
843    concat (target_machine, "-", ldd_suffix, NULL);
844#endif
845  const char *const full_strip_suffix =
846    concat (target_machine, "-", strip_suffix, NULL);
847  const char *const full_gstrip_suffix =
848    concat (target_machine, "-", gstrip_suffix, NULL);
849#else
850  const char *const full_ld_suffix	= ld_suffix;
851  const char *const full_nm_suffix	= nm_suffix;
852  const char *const full_gnm_suffix	= gnm_suffix;
853#ifdef LDD_SUFFIX
854  const char *const full_ldd_suffix	= ldd_suffix;
855#endif
856  const char *const full_strip_suffix	= strip_suffix;
857  const char *const full_gstrip_suffix	= gstrip_suffix;
858#endif /* CROSS_COMPILE */
859
860  const char *arg;
861  FILE *outf;
862#ifdef COLLECT_EXPORT_LIST
863  FILE *exportf;
864#endif
865  const char *ld_file_name;
866  const char *p;
867  char **c_argv;
868  const char **c_ptr;
869  char **ld1_argv;
870  const char **ld1;
871  char **ld2_argv;
872  const char **ld2;
873  char **object_lst;
874  const char **object;
875  int first_file;
876  int num_c_args	= argc+9;
877
878  no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
879
880  /* Suppress demangling by the real linker, which may be broken.  */
881  putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
882
883#if defined (COLLECT2_HOST_INITIALIZATION)
884  /* Perform system dependent initialization, if necessary.  */
885  COLLECT2_HOST_INITIALIZATION;
886#endif
887
888#ifdef SIGCHLD
889  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
890     receive the signal.  A different setting is inheritable */
891  signal (SIGCHLD, SIG_DFL);
892#endif
893
894  gcc_init_libintl ();
895
896  /* Do not invoke xcalloc before this point, since locale needs to be
897     set first, in case a diagnostic is issued.  */
898
899  ld1 = (const char **)(ld1_argv = (char **) xcalloc(sizeof (char *), argc+3));
900  ld2 = (const char **)(ld2_argv = (char **) xcalloc(sizeof (char *), argc+10));
901  object = (const char **)(object_lst = (char **) xcalloc(sizeof (char *), argc));
902
903#ifdef DEBUG
904  debug = 1;
905#endif
906
907  /* Parse command line early for instances of -debug.  This allows
908     the debug flag to be set before functions like find_a_file()
909     are called.  */
910  {
911    int i;
912
913    for (i = 1; argv[i] != NULL; i ++)
914      if (! strcmp (argv[i], "-debug"))
915	debug = 1;
916    vflag = debug;
917  }
918
919#ifndef DEFAULT_A_OUT_NAME
920  output_file = "a.out";
921#else
922  output_file = DEFAULT_A_OUT_NAME;
923#endif
924
925  obstack_begin (&temporary_obstack, 0);
926  temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
927
928  current_demangling_style = auto_demangling;
929  p = getenv ("COLLECT_GCC_OPTIONS");
930  while (p && *p)
931    {
932      const char *q = extract_string (&p);
933      if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
934	num_c_args++;
935    }
936  obstack_free (&temporary_obstack, temporary_firstobj);
937
938  /* -fno-exceptions -w */
939  num_c_args += 2;
940
941  c_ptr = (const char **)
942    (c_argv = (char **) xcalloc (sizeof (char *), num_c_args));
943
944  if (argc < 2)
945    fatal ("no arguments");
946
947#ifdef SIGQUIT
948  if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
949    signal (SIGQUIT, handler);
950#endif
951  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
952    signal (SIGINT, handler);
953#ifdef SIGALRM
954  if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
955    signal (SIGALRM, handler);
956#endif
957#ifdef SIGHUP
958  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
959    signal (SIGHUP, handler);
960#endif
961  if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
962    signal (SIGSEGV, handler);
963#ifdef SIGBUS
964  if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
965    signal (SIGBUS, handler);
966#endif
967#ifdef SIGPIPE
968  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
969    signal (SIGPIPE, handler);
970#endif
971
972  /* Extract COMPILER_PATH and PATH into our prefix list.  */
973  prefix_from_env ("COMPILER_PATH", &cpath);
974  prefix_from_env ("PATH", &path);
975
976  /* Try to discover a valid linker/nm/strip to use.  */
977
978  /* Maybe we know the right file to use (if not cross).  */
979  ld_file_name = 0;
980#ifdef DEFAULT_LINKER
981  if (access (DEFAULT_LINKER, X_OK) == 0)
982    ld_file_name = DEFAULT_LINKER;
983  if (ld_file_name == 0)
984#endif
985#ifdef REAL_LD_FILE_NAME
986  ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
987  if (ld_file_name == 0)
988#endif
989  /* Search the (target-specific) compiler dirs for ld'.  */
990  ld_file_name = find_a_file (&cpath, real_ld_suffix);
991  /* Likewise for `collect-ld'.  */
992  if (ld_file_name == 0)
993    ld_file_name = find_a_file (&cpath, collect_ld_suffix);
994  /* Search the compiler directories for `ld'.  We have protection against
995     recursive calls in find_a_file.  */
996  if (ld_file_name == 0)
997    ld_file_name = find_a_file (&cpath, ld_suffix);
998  /* Search the ordinary system bin directories
999     for `ld' (if native linking) or `TARGET-ld' (if cross).  */
1000  if (ld_file_name == 0)
1001    ld_file_name = find_a_file (&path, full_ld_suffix);
1002
1003#ifdef REAL_NM_FILE_NAME
1004  nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
1005  if (nm_file_name == 0)
1006#endif
1007  nm_file_name = find_a_file (&cpath, gnm_suffix);
1008  if (nm_file_name == 0)
1009    nm_file_name = find_a_file (&path, full_gnm_suffix);
1010  if (nm_file_name == 0)
1011    nm_file_name = find_a_file (&cpath, nm_suffix);
1012  if (nm_file_name == 0)
1013    nm_file_name = find_a_file (&path, full_nm_suffix);
1014
1015#ifdef LDD_SUFFIX
1016  ldd_file_name = find_a_file (&cpath, ldd_suffix);
1017  if (ldd_file_name == 0)
1018    ldd_file_name = find_a_file (&path, full_ldd_suffix);
1019#endif
1020
1021#ifdef REAL_STRIP_FILE_NAME
1022  strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1023  if (strip_file_name == 0)
1024#endif
1025  strip_file_name = find_a_file (&cpath, gstrip_suffix);
1026  if (strip_file_name == 0)
1027    strip_file_name = find_a_file (&path, full_gstrip_suffix);
1028  if (strip_file_name == 0)
1029    strip_file_name = find_a_file (&cpath, strip_suffix);
1030  if (strip_file_name == 0)
1031    strip_file_name = find_a_file (&path, full_strip_suffix);
1032
1033  /* Determine the full path name of the C compiler to use.  */
1034  c_file_name = getenv ("COLLECT_GCC");
1035  if (c_file_name == 0)
1036    {
1037#ifdef CROSS_COMPILE
1038      c_file_name = concat (target_machine, "-gcc", NULL);
1039#else
1040      c_file_name = "gcc";
1041#endif
1042    }
1043
1044  p = find_a_file (&cpath, c_file_name);
1045
1046  /* Here it should be safe to use the system search path since we should have
1047     already qualified the name of the compiler when it is needed.  */
1048  if (p == 0)
1049    p = find_a_file (&path, c_file_name);
1050
1051  if (p)
1052    c_file_name = p;
1053
1054  *ld1++ = *ld2++ = ld_file_name;
1055
1056  /* Make temp file names.  */
1057  c_file = make_temp_file (".c");
1058  o_file = make_temp_file (".o");
1059#ifdef COLLECT_EXPORT_LIST
1060  export_file = make_temp_file (".x");
1061#endif
1062  ldout = make_temp_file (".ld");
1063  lderrout = make_temp_file (".le");
1064  *c_ptr++ = c_file_name;
1065  *c_ptr++ = "-x";
1066  *c_ptr++ = "c";
1067  *c_ptr++ = "-c";
1068  *c_ptr++ = "-o";
1069  *c_ptr++ = o_file;
1070
1071#ifdef COLLECT_EXPORT_LIST
1072  /* Generate a list of directories from LIBPATH.  */
1073  prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1074  /* Add to this list also two standard directories where
1075     AIX loader always searches for libraries.  */
1076  add_prefix (&libpath_lib_dirs, "/lib");
1077  add_prefix (&libpath_lib_dirs, "/usr/lib");
1078#endif
1079
1080  /* Get any options that the upper GCC wants to pass to the sub-GCC.
1081
1082     AIX support needs to know if -shared has been specified before
1083     parsing commandline arguments.  */
1084
1085  p = getenv ("COLLECT_GCC_OPTIONS");
1086  while (p && *p)
1087    {
1088      const char *q = extract_string (&p);
1089      if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1090	*c_ptr++ = xstrdup (q);
1091      if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1092	*c_ptr++ = xstrdup (q);
1093      if (strcmp (q, "-shared") == 0)
1094	shared_obj = 1;
1095      if (*q == '-' && q[1] == 'B')
1096	{
1097	  *c_ptr++ = xstrdup (q);
1098	  if (q[2] == 0)
1099	    {
1100	      q = extract_string (&p);
1101	      *c_ptr++ = xstrdup (q);
1102	    }
1103	}
1104    }
1105  obstack_free (&temporary_obstack, temporary_firstobj);
1106  *c_ptr++ = "-fno-exceptions";
1107  *c_ptr++ = "-w";
1108
1109  /* !!! When GCC calls collect2,
1110     it does not know whether it is calling collect2 or ld.
1111     So collect2 cannot meaningfully understand any options
1112     except those ld understands.
1113     If you propose to make GCC pass some other option,
1114     just imagine what will happen if ld is really ld!!!  */
1115
1116  /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
1117  /* After the first file, put in the c++ rt0.  */
1118
1119  first_file = 1;
1120  while ((arg = *++argv) != (char *) 0)
1121    {
1122      *ld1++ = *ld2++ = arg;
1123
1124      if (arg[0] == '-')
1125	{
1126	  switch (arg[1])
1127	    {
1128#ifdef COLLECT_EXPORT_LIST
1129	    /* We want to disable automatic exports on AIX when user
1130	       explicitly puts an export list in command line */
1131	    case 'b':
1132	      if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1133                export_flag = 1;
1134	      else if (arg[2] == '6' && arg[3] == '4')
1135		aix64_flag = 1;
1136	      break;
1137#endif
1138
1139	    case 'd':
1140	      if (!strcmp (arg, "-debug"))
1141		{
1142		  /* Already parsed.  */
1143		  ld1--;
1144		  ld2--;
1145		}
1146	      if (!strcmp (arg, "-dynamic-linker") && argv[1])
1147	        {
1148		  ++argv;
1149		  *ld1++ = *ld2++ = *argv;
1150		}
1151	      break;
1152
1153	    case 'l':
1154	      if (first_file)
1155		{
1156		  /* place o_file BEFORE this argument! */
1157		  first_file = 0;
1158		  ld2--;
1159		  *ld2++ = o_file;
1160		  *ld2++ = arg;
1161		}
1162#ifdef COLLECT_EXPORT_LIST
1163	      {
1164	        /* Resolving full library name.  */
1165		const char *s = resolve_lib_name (arg+2);
1166
1167		/* Saving a full library name.  */
1168		add_to_list (&libs, s);
1169	      }
1170#endif
1171	      break;
1172
1173#ifdef COLLECT_EXPORT_LIST
1174	    /* Saving directories where to search for libraries.  */
1175       	    case 'L':
1176	      add_prefix (&cmdline_lib_dirs, arg+2);
1177	      break;
1178#else
1179#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1180	    case 'L':
1181	      if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
1182		--ld1;
1183	      break;
1184#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1185#endif
1186
1187	    case 'o':
1188	      if (arg[2] == '\0')
1189		output_file = *ld1++ = *ld2++ = *++argv;
1190	      else if (1
1191#ifdef SWITCHES_NEED_SPACES
1192		       && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1193#endif
1194		       )
1195
1196		output_file = &arg[2];
1197	      break;
1198
1199	    case 'r':
1200	      if (arg[2] == '\0')
1201		rflag = 1;
1202	      break;
1203
1204	    case 's':
1205	      if (arg[2] == '\0' && do_collecting)
1206		{
1207		  /* We must strip after the nm run, otherwise C++ linking
1208		     will not work.  Thus we strip in the second ld run, or
1209		     else with strip if there is no second ld run.  */
1210		  strip_flag = 1;
1211		  ld1--;
1212		}
1213	      break;
1214
1215	    case 'v':
1216	      if (arg[2] == '\0')
1217		vflag = 1;
1218	      break;
1219	    }
1220	}
1221      else if ((p = strrchr (arg, '.')) != (char *) 0
1222	       && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1223		   || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
1224		   || strcmp (p, ".obj") == 0))
1225	{
1226	  if (first_file)
1227	    {
1228	      first_file = 0;
1229	      if (p[1] == 'o')
1230		*ld2++ = o_file;
1231	      else
1232		{
1233		  /* place o_file BEFORE this argument! */
1234		  ld2--;
1235		  *ld2++ = o_file;
1236		  *ld2++ = arg;
1237		}
1238	    }
1239	  if (p[1] == 'o' || p[1] == 'l')
1240	    *object++ = arg;
1241#ifdef COLLECT_EXPORT_LIST
1242	  /* libraries can be specified directly, i.e. without -l flag.  */
1243       	  else
1244       	    {
1245	      /* Saving a full library name.  */
1246              add_to_list (&libs, arg);
1247            }
1248#endif
1249	}
1250    }
1251
1252#ifdef COLLECT_EXPORT_LIST
1253  /* This is added only for debugging purposes.  */
1254  if (debug)
1255    {
1256      fprintf (stderr, "List of libraries:\n");
1257      dump_list (stderr, "\t", libs.first);
1258    }
1259
1260  /* The AIX linker will discard static constructors in object files if
1261     nothing else in the file is referenced, so look at them first.  */
1262  {
1263      const char **export_object_lst = (const char **)object_lst;
1264
1265      while (export_object_lst < object)
1266	scan_prog_file (*export_object_lst++, PASS_OBJ);
1267  }
1268  {
1269    struct id *list = libs.first;
1270
1271    for (; list; list = list->next)
1272      scan_prog_file (list->name, PASS_FIRST);
1273  }
1274
1275  if (exports.first)
1276    {
1277      char *buf = concat ("-bE:", export_file, NULL);
1278
1279      *ld1++ = buf;
1280      *ld2++ = buf;
1281
1282      exportf = fopen (export_file, "w");
1283      if (exportf == (FILE *) 0)
1284	fatal_perror ("fopen %s", export_file);
1285      write_aix_file (exportf, exports.first);
1286      if (fclose (exportf))
1287	fatal_perror ("fclose %s", export_file);
1288    }
1289#endif
1290
1291  *c_ptr++ = c_file;
1292  *c_ptr = *ld1 = *object = (char *) 0;
1293
1294  if (vflag)
1295    {
1296      notice ("collect2 version %s", version_string);
1297#ifdef TARGET_VERSION
1298      TARGET_VERSION;
1299#endif
1300      fprintf (stderr, "\n");
1301    }
1302
1303  if (debug)
1304    {
1305      const char *ptr;
1306      fprintf (stderr, "ld_file_name        = %s\n",
1307	       (ld_file_name ? ld_file_name : "not found"));
1308      fprintf (stderr, "c_file_name         = %s\n",
1309	       (c_file_name ? c_file_name : "not found"));
1310      fprintf (stderr, "nm_file_name        = %s\n",
1311	       (nm_file_name ? nm_file_name : "not found"));
1312#ifdef LDD_SUFFIX
1313      fprintf (stderr, "ldd_file_name       = %s\n",
1314	       (ldd_file_name ? ldd_file_name : "not found"));
1315#endif
1316      fprintf (stderr, "strip_file_name     = %s\n",
1317	       (strip_file_name ? strip_file_name : "not found"));
1318      fprintf (stderr, "c_file              = %s\n",
1319	       (c_file ? c_file : "not found"));
1320      fprintf (stderr, "o_file              = %s\n",
1321	       (o_file ? o_file : "not found"));
1322
1323      ptr = getenv ("COLLECT_GCC_OPTIONS");
1324      if (ptr)
1325	fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1326
1327      ptr = getenv ("COLLECT_GCC");
1328      if (ptr)
1329	fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1330
1331      ptr = getenv ("COMPILER_PATH");
1332      if (ptr)
1333	fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1334
1335      ptr = getenv (LIBRARY_PATH_ENV);
1336      if (ptr)
1337	fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
1338
1339      fprintf (stderr, "\n");
1340    }
1341
1342  /* Load the program, searching all libraries and attempting to provide
1343     undefined symbols from repository information.  */
1344
1345  /* On AIX we do this later.  */
1346#ifndef COLLECT_EXPORT_LIST
1347  do_tlink (ld1_argv, object_lst);
1348#endif
1349
1350  /* If -r or they will be run via some other method, do not build the
1351     constructor or destructor list, just return now.  */
1352  if (rflag
1353#ifndef COLLECT_EXPORT_LIST
1354      || ! do_collecting
1355#endif
1356      )
1357    {
1358#ifdef COLLECT_EXPORT_LIST
1359      /* Do the link we avoided above if we are exiting.  */
1360      do_tlink (ld1_argv, object_lst);
1361
1362      /* But make sure we delete the export file we may have created.  */
1363      if (export_file != 0 && export_file[0])
1364	maybe_unlink (export_file);
1365#endif
1366      maybe_unlink (c_file);
1367      maybe_unlink (o_file);
1368      return 0;
1369    }
1370
1371  /* Examine the namelist with nm and search it for static constructors
1372     and destructors to call.
1373     Write the constructor and destructor tables to a .s file and reload.  */
1374
1375  /* On AIX we already scanned for global constructors/destructors.  */
1376#ifndef COLLECT_EXPORT_LIST
1377  scan_prog_file (output_file, PASS_FIRST);
1378#endif
1379
1380#ifdef SCAN_LIBRARIES
1381  scan_libraries (output_file);
1382#endif
1383
1384  if (debug)
1385    {
1386      notice ("%d constructor(s) found\n", constructors.number);
1387      notice ("%d destructor(s)  found\n", destructors.number);
1388      notice ("%d frame table(s) found\n", frame_tables.number);
1389    }
1390
1391  if (constructors.number == 0 && destructors.number == 0
1392      && frame_tables.number == 0
1393#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1394      /* If we will be running these functions ourselves, we want to emit
1395	 stubs into the shared library so that we do not have to relink
1396	 dependent programs when we add static objects.  */
1397      && ! shared_obj
1398#endif
1399      )
1400    {
1401#ifdef COLLECT_EXPORT_LIST
1402      /* Do tlink without additional code generation */
1403      do_tlink (ld1_argv, object_lst);
1404#endif
1405      /* Strip now if it was requested on the command line.  */
1406      if (strip_flag)
1407	{
1408	  char **real_strip_argv = (char **) xcalloc (sizeof (char *), 3);
1409	  const char ** strip_argv = (const char **) real_strip_argv;
1410
1411	  strip_argv[0] = strip_file_name;
1412	  strip_argv[1] = output_file;
1413	  strip_argv[2] = (char *) 0;
1414	  fork_execute ("strip", real_strip_argv);
1415	}
1416
1417#ifdef COLLECT_EXPORT_LIST
1418      maybe_unlink (export_file);
1419#endif
1420      maybe_unlink (c_file);
1421      maybe_unlink (o_file);
1422      return 0;
1423    }
1424
1425  /* Sort ctor and dtor lists by priority.  */
1426  sort_ids (&constructors);
1427  sort_ids (&destructors);
1428
1429  maybe_unlink(output_file);
1430  outf = fopen (c_file, "w");
1431  if (outf == (FILE *) 0)
1432    fatal_perror ("fopen %s", c_file);
1433
1434  write_c_file (outf, c_file);
1435
1436  if (fclose (outf))
1437    fatal_perror ("fclose %s", c_file);
1438
1439  /* Tell the linker that we have initializer and finalizer functions.  */
1440#ifdef LD_INIT_SWITCH
1441#ifdef COLLECT_EXPORT_LIST
1442  *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
1443#else
1444  *ld2++ = LD_INIT_SWITCH;
1445  *ld2++ = initname;
1446  *ld2++ = LD_FINI_SWITCH;
1447  *ld2++ = fininame;
1448#endif
1449#endif
1450
1451#ifdef COLLECT_EXPORT_LIST
1452  if (shared_obj)
1453    {
1454      /* If we did not add export flag to link arguments before, add it to
1455	 second link phase now.  No new exports should have been added.  */
1456      if (! exports.first)
1457	*ld2++ = concat ("-bE:", export_file, NULL);
1458
1459      add_to_list (&exports, initname);
1460      add_to_list (&exports, fininame);
1461      add_to_list (&exports, "_GLOBAL__DI");
1462      add_to_list (&exports, "_GLOBAL__DD");
1463      exportf = fopen (export_file, "w");
1464      if (exportf == (FILE *) 0)
1465	fatal_perror ("fopen %s", export_file);
1466      write_aix_file (exportf, exports.first);
1467      if (fclose (exportf))
1468	fatal_perror ("fclose %s", export_file);
1469    }
1470#endif
1471
1472  /* End of arguments to second link phase.  */
1473  *ld2 = (char*) 0;
1474
1475  if (debug)
1476    {
1477      fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1478	       output_file, c_file);
1479      write_c_file (stderr, "stderr");
1480      fprintf (stderr, "========== end of c_file\n\n");
1481#ifdef COLLECT_EXPORT_LIST
1482      fprintf (stderr, "\n========== export_file = %s\n", export_file);
1483      write_aix_file (stderr, exports.first);
1484      fprintf (stderr, "========== end of export_file\n\n");
1485#endif
1486    }
1487
1488  /* Assemble the constructor and destructor tables.
1489     Link the tables in with the rest of the program.  */
1490
1491  fork_execute ("gcc",  c_argv);
1492#ifdef COLLECT_EXPORT_LIST
1493  /* On AIX we must call tlink because of possible templates resolution */
1494  do_tlink (ld2_argv, object_lst);
1495#else
1496  /* Otherwise, simply call ld because tlink is already done */
1497  fork_execute ("ld", ld2_argv);
1498
1499  /* Let scan_prog_file do any final mods (OSF/rose needs this for
1500     constructors/destructors in shared libraries.  */
1501  scan_prog_file (output_file, PASS_SECOND);
1502#endif
1503
1504  maybe_unlink (c_file);
1505  maybe_unlink (o_file);
1506
1507#ifdef COLLECT_EXPORT_LIST
1508  maybe_unlink (export_file);
1509#endif
1510
1511  return 0;
1512}
1513
1514
1515/* Wait for a process to finish, and exit if a nonzero status is found.  */
1516
1517int
1518collect_wait (prog)
1519     const char *prog;
1520{
1521  int status;
1522
1523  pwait (pid, &status, 0);
1524  if (status)
1525    {
1526      if (WIFSIGNALED (status))
1527	{
1528	  int sig = WTERMSIG (status);
1529	  error ("%s terminated with signal %d [%s]%s",
1530		 prog, sig, strsignal(sig),
1531		 WCOREDUMP(status) ? ", core dumped" : "");
1532	  collect_exit (FATAL_EXIT_CODE);
1533	}
1534
1535      if (WIFEXITED (status))
1536	return WEXITSTATUS (status);
1537    }
1538  return 0;
1539}
1540
1541static void
1542do_wait (prog)
1543     const char *prog;
1544{
1545  int ret = collect_wait (prog);
1546  if (ret != 0)
1547    {
1548      error ("%s returned %d exit status", prog, ret);
1549      collect_exit (ret);
1550    }
1551}
1552
1553
1554/* Execute a program, and wait for the reply.  */
1555
1556void
1557collect_execute (prog, argv, outname, errname)
1558     const char *prog;
1559     char **argv;
1560     const char *outname;
1561     const char *errname;
1562{
1563  char *errmsg_fmt;
1564  char *errmsg_arg;
1565  int out_handle = -1;
1566  int err_handle = -1;
1567  int stdout_save = -1;
1568  int stderr_save = -1;
1569
1570  if (vflag || debug)
1571    {
1572      char **p_argv;
1573      const char *str;
1574
1575      if (argv[0])
1576	fprintf (stderr, "%s", argv[0]);
1577      else
1578	notice ("[cannot find %s]", prog);
1579
1580      for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1581	fprintf (stderr, " %s", str);
1582
1583      fprintf (stderr, "\n");
1584    }
1585
1586  fflush (stdout);
1587  fflush (stderr);
1588
1589  /* If we cannot find a program we need, complain error.  Do this here
1590     since we might not end up needing something that we could not find.  */
1591
1592  if (argv[0] == 0)
1593    fatal ("cannot find `%s'", prog);
1594
1595  if (outname)
1596    {
1597      /* Open response file.  */
1598      out_handle = open (outname, O_WRONLY | O_TRUNC | O_CREAT, 0666);
1599
1600      /* Duplicate the stdout file handle so it can be restored later.  */
1601      stdout_save = dup (STDOUT_FILENO);
1602      if (stdout_save == -1)
1603	fatal_perror ("redirecting stdout: %s", outname);
1604
1605      /* Redirect stdout to our response file.  */
1606      dup2 (out_handle, STDOUT_FILENO);
1607    }
1608
1609  if (errname)
1610    {
1611      /* Open response file.  */
1612      err_handle = open (errname, O_WRONLY | O_TRUNC | O_CREAT, 0666);
1613
1614      /* Duplicate the stderr file handle so it can be restored later.  */
1615      stderr_save = dup (STDERR_FILENO);
1616      if (stderr_save == -1)
1617	fatal_perror ("redirecting stderr: %s", errname);
1618
1619      /* Redirect stderr to our response file.  */
1620      dup2 (err_handle, STDERR_FILENO);
1621    }
1622
1623  pid = pexecute (argv[0], argv, argv[0], NULL,
1624		  &errmsg_fmt, &errmsg_arg,
1625		  (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1626
1627  if (outname)
1628    {
1629      /* Restore stdout to its previous setting.  */
1630      dup2 (stdout_save, STDOUT_FILENO);
1631
1632      /* Close response file.  */
1633      close (out_handle);
1634    }
1635
1636  if (errname)
1637    {
1638      /* Restore stderr to its previous setting.  */
1639      dup2 (stderr_save, STDERR_FILENO);
1640
1641      /* Close response file.  */
1642      close (err_handle);
1643    }
1644
1645 if (pid == -1)
1646   fatal_perror (errmsg_fmt, errmsg_arg);
1647}
1648
1649static void
1650fork_execute (prog, argv)
1651     const char *prog;
1652     char **argv;
1653{
1654  collect_execute (prog, argv, NULL, NULL);
1655  do_wait (prog);
1656}
1657
1658/* Unlink a file unless we are debugging.  */
1659
1660static void
1661maybe_unlink (file)
1662     const char *file;
1663{
1664  if (!debug)
1665    unlink (file);
1666  else
1667    notice ("[Leaving %s]\n", file);
1668}
1669
1670
1671static long sequence_number = 0;
1672
1673/* Add a name to a linked list.  */
1674
1675static void
1676add_to_list (head_ptr, name)
1677     struct head *head_ptr;
1678     const char *name;
1679{
1680  struct id *newid
1681    = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1682  struct id *p;
1683  strcpy (newid->name, name);
1684
1685  if (head_ptr->first)
1686    head_ptr->last->next = newid;
1687  else
1688    head_ptr->first = newid;
1689
1690  /* Check for duplicate symbols.  */
1691  for (p = head_ptr->first;
1692       strcmp (name, p->name) != 0;
1693       p = p->next)
1694    ;
1695  if (p != newid)
1696    {
1697      head_ptr->last->next = 0;
1698      free (newid);
1699      return;
1700    }
1701
1702  newid->sequence = ++sequence_number;
1703  head_ptr->last = newid;
1704  head_ptr->number++;
1705}
1706
1707/* Grab the init priority number from an init function name that
1708   looks like "_GLOBAL_.I.12345.foo".  */
1709
1710static int
1711extract_init_priority (name)
1712     const char *name;
1713{
1714  int pos = 0, pri;
1715
1716  while (name[pos] == '_')
1717    ++pos;
1718  pos += 10; /* strlen ("GLOBAL__X_") */
1719
1720  /* Extract init_p number from ctor/dtor name.  */
1721  pri = atoi (name + pos);
1722  return pri ? pri : DEFAULT_INIT_PRIORITY;
1723}
1724
1725/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1726   ctors will be run from right to left, dtors from left to right.  */
1727
1728static void
1729sort_ids (head_ptr)
1730     struct head *head_ptr;
1731{
1732  /* id holds the current element to insert.  id_next holds the next
1733     element to insert.  id_ptr iterates through the already sorted elements
1734     looking for the place to insert id.  */
1735  struct id *id, *id_next, **id_ptr;
1736
1737  id = head_ptr->first;
1738
1739  /* We don't have any sorted elements yet.  */
1740  head_ptr->first = NULL;
1741
1742  for (; id; id = id_next)
1743    {
1744      id_next = id->next;
1745      id->sequence = extract_init_priority (id->name);
1746
1747      for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1748	if (*id_ptr == NULL
1749	    /* If the sequence numbers are the same, we put the id from the
1750	       file later on the command line later in the list.  */
1751	    || id->sequence > (*id_ptr)->sequence
1752	    /* Hack: do lexical compare, too.
1753	    || (id->sequence == (*id_ptr)->sequence
1754	        && strcmp (id->name, (*id_ptr)->name) > 0) */
1755	    )
1756	  {
1757	    id->next = *id_ptr;
1758	    *id_ptr = id;
1759	    break;
1760	  }
1761    }
1762
1763  /* Now set the sequence numbers properly so write_c_file works.  */
1764  for (id = head_ptr->first; id; id = id->next)
1765    id->sequence = ++sequence_number;
1766}
1767
1768/* Write: `prefix', the names on list LIST, `suffix'.  */
1769
1770static void
1771write_list (stream, prefix, list)
1772     FILE *stream;
1773     const char *prefix;
1774     struct id *list;
1775{
1776  while (list)
1777    {
1778      fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1779      list = list->next;
1780    }
1781}
1782
1783#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
1784/* Given a STRING, return nonzero if it occurs in the list in range
1785   [ARGS_BEGIN,ARGS_END).  */
1786
1787static int
1788is_in_args (string, args_begin, args_end)
1789     const char *string;
1790     const char **args_begin;
1791     const char **args_end;
1792{
1793  const char **args_pointer;
1794  for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
1795    if (strcmp (string, *args_pointer) == 0)
1796      return 1;
1797  return 0;
1798}
1799#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
1800
1801#ifdef COLLECT_EXPORT_LIST
1802/* This function is really used only on AIX, but may be useful.  */
1803#if 0
1804static int
1805is_in_list (prefix, list)
1806     const char *prefix;
1807     struct id *list;
1808{
1809  while (list)
1810    {
1811      if (!strcmp (prefix, list->name)) return 1;
1812      list = list->next;
1813    }
1814    return 0;
1815}
1816#endif
1817#endif /* COLLECT_EXPORT_LIST */
1818
1819/* Added for debugging purpose.  */
1820#ifdef COLLECT_EXPORT_LIST
1821static void
1822dump_list (stream, prefix, list)
1823     FILE *stream;
1824     const char *prefix;
1825     struct id *list;
1826{
1827  while (list)
1828    {
1829      fprintf (stream, "%s%s,\n", prefix, list->name);
1830      list = list->next;
1831    }
1832}
1833#endif
1834
1835#if 0
1836static void
1837dump_prefix_list (stream, prefix, list)
1838     FILE *stream;
1839     const char *prefix;
1840     struct prefix_list *list;
1841{
1842  while (list)
1843    {
1844      fprintf (stream, "%s%s,\n", prefix, list->prefix);
1845      list = list->next;
1846    }
1847}
1848#endif
1849
1850static void
1851write_list_with_asm (stream, prefix, list)
1852     FILE *stream;
1853     const char *prefix;
1854     struct id *list;
1855{
1856  while (list)
1857    {
1858      fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1859	       prefix, list->sequence, list->name);
1860      list = list->next;
1861    }
1862}
1863
1864/* Write out the constructor and destructor tables statically (for a shared
1865   object), along with the functions to execute them.  */
1866
1867static void
1868write_c_file_stat (stream, name)
1869     FILE *stream;
1870     const char *name ATTRIBUTE_UNUSED;
1871{
1872  const char *p, *q;
1873  char *prefix, *r;
1874  int frames = (frame_tables.number > 0);
1875
1876  /* Figure out name of output_file, stripping off .so version.  */
1877  p = strrchr (output_file, '/');
1878  if (p == 0)
1879    p = output_file;
1880  else
1881    p++;
1882  q = p;
1883  while (q)
1884    {
1885      q = strchr (q,'.');
1886      if (q == 0)
1887	{
1888	  q = p + strlen (p);
1889	  break;
1890	}
1891      else
1892	{
1893	  if (strncmp (q, ".so", 3) == 0)
1894	    {
1895	      q += 3;
1896	      break;
1897	    }
1898	  else
1899	    q++;
1900	}
1901    }
1902  /* q points to null at end of the string (or . of the .so version) */
1903  prefix = xmalloc (q - p + 1);
1904  strncpy (prefix, p, q - p);
1905  prefix[q - p] = 0;
1906  for (r = prefix; *r; r++)
1907    if (!ISALNUM ((unsigned char)*r))
1908      *r = '_';
1909  if (debug)
1910    notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
1911	    output_file, prefix);
1912
1913  initname = concat ("_GLOBAL__FI_", prefix, NULL);
1914  fininame = concat ("_GLOBAL__FD_", prefix, NULL);
1915
1916  free (prefix);
1917
1918  /* Write the tables as C code  */
1919
1920  fprintf (stream, "static int count;\n");
1921  fprintf (stream, "typedef void entry_pt();\n");
1922  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1923
1924  if (frames)
1925    {
1926      write_list_with_asm (stream, "extern void *", frame_tables.first);
1927
1928      fprintf (stream, "\tstatic void *frame_table[] = {\n");
1929      write_list (stream, "\t\t&", frame_tables.first);
1930      fprintf (stream, "\t0\n};\n");
1931
1932      /* This must match what's in frame.h.  */
1933      fprintf (stream, "struct object {\n");
1934      fprintf (stream, "  void *pc_begin;\n");
1935      fprintf (stream, "  void *pc_end;\n");
1936      fprintf (stream, "  void *fde_begin;\n");
1937      fprintf (stream, "  void *fde_array;\n");
1938      fprintf (stream, "  __SIZE_TYPE__ count;\n");
1939      fprintf (stream, "  struct object *next;\n");
1940      fprintf (stream, "};\n");
1941
1942      fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1943      fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1944
1945      fprintf (stream, "static void reg_frame () {\n");
1946      fprintf (stream, "\tstatic struct object ob;\n");
1947      fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1948      fprintf (stream, "\t}\n");
1949
1950      fprintf (stream, "static void dereg_frame () {\n");
1951      fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1952      fprintf (stream, "\t}\n");
1953    }
1954
1955  fprintf (stream, "void %s() {\n", initname);
1956  if (constructors.number > 0 || frames)
1957    {
1958      fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1959      write_list (stream, "\t\t", constructors.first);
1960      if (frames)
1961	fprintf (stream, "\treg_frame,\n");
1962      fprintf (stream, "\t};\n");
1963      fprintf (stream, "\tentry_pt **p;\n");
1964      fprintf (stream, "\tif (count++ != 0) return;\n");
1965      fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
1966      fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1967    }
1968  else
1969    fprintf (stream, "\t++count;\n");
1970  fprintf (stream, "}\n");
1971  write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1972  fprintf (stream, "void %s() {\n", fininame);
1973  if (destructors.number > 0 || frames)
1974    {
1975      fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1976      write_list (stream, "\t\t", destructors.first);
1977      if (frames)
1978	fprintf (stream, "\tdereg_frame,\n");
1979      fprintf (stream, "\t};\n");
1980      fprintf (stream, "\tentry_pt **p;\n");
1981      fprintf (stream, "\tif (--count != 0) return;\n");
1982      fprintf (stream, "\tp = dtors;\n");
1983      fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1984	       destructors.number + frames);
1985    }
1986  fprintf (stream, "}\n");
1987
1988  if (shared_obj)
1989    {
1990      COLLECT_SHARED_INIT_FUNC(stream, initname);
1991      COLLECT_SHARED_FINI_FUNC(stream, fininame);
1992    }
1993}
1994
1995/* Write the constructor/destructor tables.  */
1996
1997#ifndef LD_INIT_SWITCH
1998static void
1999write_c_file_glob (stream, name)
2000     FILE *stream;
2001     const char *name ATTRIBUTE_UNUSED;
2002{
2003  /* Write the tables as C code  */
2004
2005  int frames = (frame_tables.number > 0);
2006
2007  fprintf (stream, "typedef void entry_pt();\n\n");
2008
2009  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
2010
2011  if (frames)
2012    {
2013      write_list_with_asm (stream, "extern void *", frame_tables.first);
2014
2015      fprintf (stream, "\tstatic void *frame_table[] = {\n");
2016      write_list (stream, "\t\t&", frame_tables.first);
2017      fprintf (stream, "\t0\n};\n");
2018
2019      /* This must match what's in frame.h.  */
2020      fprintf (stream, "struct object {\n");
2021      fprintf (stream, "  void *pc_begin;\n");
2022      fprintf (stream, "  void *pc_end;\n");
2023      fprintf (stream, "  void *fde_begin;\n");
2024      fprintf (stream, "  void *fde_array;\n");
2025      fprintf (stream, "  __SIZE_TYPE__ count;\n");
2026      fprintf (stream, "  struct object *next;\n");
2027      fprintf (stream, "};\n");
2028
2029      fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
2030      fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2031
2032      fprintf (stream, "static void reg_frame () {\n");
2033      fprintf (stream, "\tstatic struct object ob;\n");
2034      fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2035      fprintf (stream, "\t}\n");
2036
2037      fprintf (stream, "static void dereg_frame () {\n");
2038      fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2039      fprintf (stream, "\t}\n");
2040    }
2041
2042  fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
2043  fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
2044  write_list (stream, "\t", constructors.first);
2045  if (frames)
2046    fprintf (stream, "\treg_frame,\n");
2047  fprintf (stream, "\t0\n};\n\n");
2048
2049  write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2050
2051  fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
2052  fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
2053  write_list (stream, "\t", destructors.first);
2054  if (frames)
2055    fprintf (stream, "\tdereg_frame,\n");
2056  fprintf (stream, "\t0\n};\n\n");
2057
2058  fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
2059  fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
2060}
2061#endif /* ! LD_INIT_SWITCH */
2062
2063static void
2064write_c_file (stream, name)
2065     FILE *stream;
2066     const char *name;
2067{
2068  fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
2069#ifndef LD_INIT_SWITCH
2070  if (! shared_obj)
2071    write_c_file_glob (stream, name);
2072  else
2073#endif
2074    write_c_file_stat (stream, name);
2075  fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
2076}
2077
2078#ifdef COLLECT_EXPORT_LIST
2079static void
2080write_aix_file (stream, list)
2081     FILE *stream;
2082     struct id *list;
2083{
2084  for (; list; list = list->next)
2085    {
2086      fputs (list->name, stream);
2087      putc ('\n', stream);
2088    }
2089}
2090#endif
2091
2092#ifdef OBJECT_FORMAT_NONE
2093
2094/* Generic version to scan the name list of the loaded program for
2095   the symbols g++ uses for static constructors and destructors.
2096
2097   The constructor table begins at __CTOR_LIST__ and contains a count
2098   of the number of pointers (or -1 if the constructors are built in a
2099   separate section by the linker), followed by the pointers to the
2100   constructor functions, terminated with a null pointer.  The
2101   destructor table has the same format, and begins at __DTOR_LIST__.  */
2102
2103static void
2104scan_prog_file (prog_name, which_pass)
2105     const char *prog_name;
2106     enum pass which_pass;
2107{
2108  void (*int_handler) PARAMS ((int));
2109  void (*quit_handler) PARAMS ((int));
2110  char *real_nm_argv[4];
2111  const char **nm_argv = (const char **) real_nm_argv;
2112  int argc = 0;
2113  int pipe_fd[2];
2114  char *p, buf[1024];
2115  FILE *inf;
2116
2117  if (which_pass == PASS_SECOND)
2118    return;
2119
2120  /* If we do not have an `nm', complain.  */
2121  if (nm_file_name == 0)
2122    fatal ("cannot find `nm'");
2123
2124  nm_argv[argc++] = nm_file_name;
2125  if (NM_FLAGS[0] != '\0')
2126    nm_argv[argc++] = NM_FLAGS;
2127
2128  nm_argv[argc++] = prog_name;
2129  nm_argv[argc++] = (char *) 0;
2130
2131  if (pipe (pipe_fd) < 0)
2132    fatal_perror ("pipe");
2133
2134  inf = fdopen (pipe_fd[0], "r");
2135  if (inf == (FILE *) 0)
2136    fatal_perror ("fdopen");
2137
2138  /* Trace if needed.  */
2139  if (vflag)
2140    {
2141      const char **p_argv;
2142      const char *str;
2143
2144      for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2145	fprintf (stderr, " %s", str);
2146
2147      fprintf (stderr, "\n");
2148    }
2149
2150  fflush (stdout);
2151  fflush (stderr);
2152
2153  /* Spawn child nm on pipe */
2154  pid = vfork ();
2155  if (pid == -1)
2156    fatal_perror (VFORK_STRING);
2157
2158  if (pid == 0)			/* child context */
2159    {
2160      /* setup stdout */
2161      if (dup2 (pipe_fd[1], 1) < 0)
2162	fatal_perror ("dup2 %d 1", pipe_fd[1]);
2163
2164      if (close (pipe_fd[0]) < 0)
2165	fatal_perror ("close %d", pipe_fd[0]);
2166
2167      if (close (pipe_fd[1]) < 0)
2168	fatal_perror ("close %d", pipe_fd[1]);
2169
2170      execv (nm_file_name, real_nm_argv);
2171      fatal_perror ("execv %s", nm_file_name);
2172    }
2173
2174  /* Parent context from here on.  */
2175  int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
2176#ifdef SIGQUIT
2177  quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
2178#endif
2179
2180  if (close (pipe_fd[1]) < 0)
2181    fatal_perror ("close %d", pipe_fd[1]);
2182
2183  if (debug)
2184    fprintf (stderr, "\nnm output with constructors/destructors.\n");
2185
2186  /* Read each line of nm output.  */
2187  while (fgets (buf, sizeof buf, inf) != (char *) 0)
2188    {
2189      int ch, ch2;
2190      char *name, *end;
2191
2192      /* If it contains a constructor or destructor name, add the name
2193	 to the appropriate list.  */
2194
2195      for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2196	if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2197	  break;
2198
2199      if (ch != '_')
2200	continue;
2201
2202      name = p;
2203      /* Find the end of the symbol name.
2204	 Do not include `|', because Encore nm can tack that on the end.  */
2205      for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2206	   end++)
2207	continue;
2208
2209
2210      *end = '\0';
2211      switch (is_ctor_dtor (name))
2212	{
2213	case 1:
2214	  if (which_pass != PASS_LIB)
2215	    add_to_list (&constructors, name);
2216	  break;
2217
2218	case 2:
2219	  if (which_pass != PASS_LIB)
2220	    add_to_list (&destructors, name);
2221	  break;
2222
2223	case 3:
2224	  if (which_pass != PASS_LIB)
2225	    fatal ("init function found in object %s", prog_name);
2226#ifndef LD_INIT_SWITCH
2227	  add_to_list (&constructors, name);
2228#endif
2229	  break;
2230
2231	case 4:
2232	  if (which_pass != PASS_LIB)
2233	    fatal ("fini function found in object %s", prog_name);
2234#ifndef LD_FINI_SWITCH
2235	  add_to_list (&destructors, name);
2236#endif
2237	  break;
2238
2239	case 5:
2240	  if (which_pass != PASS_LIB)
2241	    add_to_list (&frame_tables, name);
2242	  break;
2243
2244	default:		/* not a constructor or destructor */
2245	  continue;
2246	}
2247
2248      if (debug)
2249	fprintf (stderr, "\t%s\n", buf);
2250    }
2251
2252  if (debug)
2253    fprintf (stderr, "\n");
2254
2255  if (fclose (inf) != 0)
2256    fatal_perror ("fclose");
2257
2258  do_wait (nm_file_name);
2259
2260  signal (SIGINT,  int_handler);
2261#ifdef SIGQUIT
2262  signal (SIGQUIT, quit_handler);
2263#endif
2264}
2265
2266#if SUNOS4_SHARED_LIBRARIES
2267
2268/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2269   that the output file depends upon and their initialization/finalization
2270   routines, if any.  */
2271
2272#include <a.out.h>
2273#include <fcntl.h>
2274#include <link.h>
2275#include <sys/mman.h>
2276#include <sys/param.h>
2277#include <unistd.h>
2278#include <sys/dir.h>
2279
2280/* pointers to the object file */
2281unsigned object;    	/* address of memory mapped file */
2282unsigned objsize;    	/* size of memory mapped to file */
2283char * code;		/* pointer to code segment */
2284char * data;		/* pointer to data segment */
2285struct nlist *symtab;	/* pointer to symbol table */
2286struct link_dynamic *ld;
2287struct link_dynamic_2 *ld_2;
2288struct head libraries;
2289
2290/* Map the file indicated by NAME into memory and store its address.  */
2291
2292static void mapfile			PARAMS ((const char *));
2293
2294static void
2295mapfile (name)
2296     const char *name;
2297{
2298  int fp;
2299  struct stat s;
2300  if ((fp = open (name, O_RDONLY)) == -1)
2301    fatal ("unable to open file '%s'", name);
2302  if (fstat (fp, &s) == -1)
2303    fatal ("unable to stat file '%s'", name);
2304
2305  objsize = s.st_size;
2306  object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2307			    fp, 0);
2308  if (object == (unsigned)-1)
2309    fatal ("unable to mmap file '%s'", name);
2310
2311  close (fp);
2312}
2313
2314/* Helpers for locatelib.  */
2315
2316static const char *libname;
2317
2318static int libselect			PARAMS ((struct direct *));
2319
2320static int
2321libselect (d)
2322     struct direct *d;
2323{
2324  return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2325}
2326
2327/* If one file has an additional numeric extension past LIBNAME, then put
2328   that one first in the sort.  If both files have additional numeric
2329   extensions, then put the one with the higher number first in the sort.
2330
2331   We must verify that the extension is numeric, because Sun saves the
2332   original versions of patched libraries with a .FCS extension.  Files with
2333   invalid extensions must go last in the sort, so that they will not be used.  */
2334static int libcompare		PARAMS ((struct direct **, struct direct **));
2335
2336static int
2337libcompare (d1, d2)
2338     struct direct **d1, **d2;
2339{
2340  int i1, i2 = strlen (libname);
2341  char *e1 = (*d1)->d_name + i2;
2342  char *e2 = (*d2)->d_name + i2;
2343
2344  while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2345	 && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2346    {
2347      ++e1;
2348      ++e2;
2349      i1 = strtol (e1, &e1, 10);
2350      i2 = strtol (e2, &e2, 10);
2351      if (i1 != i2)
2352	return i1 - i2;
2353    }
2354
2355  if (*e1)
2356    {
2357      /* It has a valid numeric extension, prefer this one.  */
2358      if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2359	return 1;
2360      /* It has an invalid numeric extension, must prefer the other one.  */
2361      else
2362	return -1;
2363    }
2364  else if (*e2)
2365    {
2366      /* It has a valid numeric extension, prefer this one.  */
2367      if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2368	return -1;
2369      /* It has an invalid numeric extension, must prefer the other one.  */
2370      else
2371	return 1;
2372    }
2373  else
2374    return 0;
2375}
2376
2377/* Given the name NAME of a dynamic dependency, find its pathname and add
2378   it to the list of libraries.  */
2379static void locatelib			PARAMS ((const char *));
2380
2381static void
2382locatelib (name)
2383     const char *name;
2384{
2385  static const char **l;
2386  static int cnt;
2387  char buf[MAXPATHLEN];
2388  char *p, *q;
2389  const char **pp;
2390
2391  if (l == 0)
2392    {
2393      char *ld_rules;
2394      char *ldr = 0;
2395      /* counting elements in array, need 1 extra for null */
2396      cnt = 1;
2397      ld_rules = (char *) (ld_2->ld_rules + code);
2398      if (ld_rules)
2399	{
2400	  cnt++;
2401	  for (; *ld_rules != 0; ld_rules++)
2402	    if (*ld_rules == ':')
2403	      cnt++;
2404	  ld_rules = (char *) (ld_2->ld_rules + code);
2405	  ldr = xstrdup (ld_rules);
2406	}
2407      p = getenv ("LD_LIBRARY_PATH");
2408      q = 0;
2409      if (p)
2410	{
2411	  cnt++;
2412	  for (q = p ; *q != 0; q++)
2413	    if (*q == ':')
2414	      cnt++;
2415	  q = xstrdup (p);
2416	}
2417      l = (const char **) xmalloc ((cnt + 3) * sizeof (char *));
2418      pp = l;
2419      if (ldr)
2420	{
2421	  *pp++ = ldr;
2422	  for (; *ldr != 0; ldr++)
2423	    if (*ldr == ':')
2424	      {
2425		*ldr++ = 0;
2426		*pp++ = ldr;
2427	      }
2428	}
2429      if (q)
2430	{
2431	  *pp++ = q;
2432	  for (; *q != 0; q++)
2433	    if (*q == ':')
2434	      {
2435		*q++ = 0;
2436		*pp++ = q;
2437	      }
2438	}
2439      /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2440      *pp++ = "/lib";
2441      *pp++ = "/usr/lib";
2442      *pp++ = "/usr/local/lib";
2443      *pp = 0;
2444    }
2445  libname = name;
2446  for (pp = l; *pp != 0 ; pp++)
2447    {
2448      struct direct **namelist;
2449      int entries;
2450      if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2451	{
2452	  sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2453	  add_to_list (&libraries, buf);
2454	  if (debug)
2455	    fprintf (stderr, "%s\n", buf);
2456	  break;
2457	}
2458    }
2459  if (*pp == 0)
2460    {
2461      if (debug)
2462	notice ("not found\n");
2463      else
2464	fatal ("dynamic dependency %s not found", name);
2465    }
2466}
2467
2468/* Scan the _DYNAMIC structure of the output file to find shared libraries
2469   that it depends upon and any constructors or destructors they contain.  */
2470
2471static void
2472scan_libraries (prog_name)
2473     const char *prog_name;
2474{
2475  struct exec *header;
2476  char *base;
2477  struct link_object *lo;
2478  char buff[MAXPATHLEN];
2479  struct id *list;
2480
2481  mapfile (prog_name);
2482  header = (struct exec *)object;
2483  if (N_BADMAG (*header))
2484    fatal ("bad magic number in file '%s'", prog_name);
2485  if (header->a_dynamic == 0)
2486    return;
2487
2488  code = (char *) (N_TXTOFF (*header) + (long) header);
2489  data = (char *) (N_DATOFF (*header) + (long) header);
2490  symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2491
2492  if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2493    {
2494      /* shared object */
2495      ld = (struct link_dynamic *) (symtab->n_value + code);
2496      base = code;
2497    }
2498  else
2499    {
2500      /* executable */
2501      ld = (struct link_dynamic *) data;
2502      base = code-PAGSIZ;
2503    }
2504
2505  if (debug)
2506    notice ("dynamic dependencies.\n");
2507
2508  ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2509  for (lo = (struct link_object *) ld_2->ld_need; lo;
2510       lo = (struct link_object *) lo->lo_next)
2511    {
2512      char *name;
2513      lo = (struct link_object *) ((long) lo + code);
2514      name = (char *) (code + lo->lo_name);
2515      if (lo->lo_library)
2516	{
2517	  if (debug)
2518	    fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2519	  sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2520	  locatelib (buff);
2521	}
2522      else
2523	{
2524	  if (debug)
2525	    fprintf (stderr, "\t%s\n", name);
2526	  add_to_list (&libraries, name);
2527	}
2528    }
2529
2530  if (debug)
2531    fprintf (stderr, "\n");
2532
2533  /* now iterate through the library list adding their symbols to
2534     the list.  */
2535  for (list = libraries.first; list; list = list->next)
2536    scan_prog_file (list->name, PASS_LIB);
2537}
2538
2539#else  /* SUNOS4_SHARED_LIBRARIES */
2540#ifdef LDD_SUFFIX
2541
2542/* Use the List Dynamic Dependencies program to find shared libraries that
2543   the output file depends upon and their initialization/finalization
2544   routines, if any.  */
2545
2546static void
2547scan_libraries (prog_name)
2548     const char *prog_name;
2549{
2550  static struct head libraries;		/* list of shared libraries found */
2551  struct id *list;
2552  void (*int_handler) PARAMS ((int));
2553  void (*quit_handler) PARAMS ((int));
2554  char *real_ldd_argv[4];
2555  const char **ldd_argv = (const char **) real_ldd_argv;
2556  int argc = 0;
2557  int pipe_fd[2];
2558  char buf[1024];
2559  FILE *inf;
2560
2561  /* If we do not have an `ldd', complain.  */
2562  if (ldd_file_name == 0)
2563    {
2564      error ("cannot find `ldd'");
2565      return;
2566    }
2567
2568  ldd_argv[argc++] = ldd_file_name;
2569  ldd_argv[argc++] = prog_name;
2570  ldd_argv[argc++] = (char *) 0;
2571
2572  if (pipe (pipe_fd) < 0)
2573    fatal_perror ("pipe");
2574
2575  inf = fdopen (pipe_fd[0], "r");
2576  if (inf == (FILE *) 0)
2577    fatal_perror ("fdopen");
2578
2579  /* Trace if needed.  */
2580  if (vflag)
2581    {
2582      const char **p_argv;
2583      const char *str;
2584
2585      for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2586	fprintf (stderr, " %s", str);
2587
2588      fprintf (stderr, "\n");
2589    }
2590
2591  fflush (stdout);
2592  fflush (stderr);
2593
2594  /* Spawn child ldd on pipe */
2595  pid = vfork ();
2596  if (pid == -1)
2597    fatal_perror (VFORK_STRING);
2598
2599  if (pid == 0)			/* child context */
2600    {
2601      /* setup stdout */
2602      if (dup2 (pipe_fd[1], 1) < 0)
2603	fatal_perror ("dup2 %d 1", pipe_fd[1]);
2604
2605      if (close (pipe_fd[0]) < 0)
2606	fatal_perror ("close %d", pipe_fd[0]);
2607
2608      if (close (pipe_fd[1]) < 0)
2609	fatal_perror ("close %d", pipe_fd[1]);
2610
2611      execv (ldd_file_name, real_ldd_argv);
2612      fatal_perror ("execv %s", ldd_file_name);
2613    }
2614
2615  /* Parent context from here on.  */
2616  int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
2617#ifdef SIGQUIT
2618  quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
2619#endif
2620
2621  if (close (pipe_fd[1]) < 0)
2622    fatal_perror ("close %d", pipe_fd[1]);
2623
2624  if (debug)
2625    notice ("\nldd output with constructors/destructors.\n");
2626
2627  /* Read each line of ldd output.  */
2628  while (fgets (buf, sizeof buf, inf) != (char *) 0)
2629    {
2630      int ch2;
2631      char *name, *end, *p = buf;
2632
2633      /* Extract names of libraries and add to list.  */
2634      PARSE_LDD_OUTPUT (p);
2635      if (p == 0)
2636	continue;
2637
2638      name = p;
2639      if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2640	fatal ("dynamic dependency %s not found", buf);
2641
2642      /* Find the end of the symbol name.  */
2643      for (end = p;
2644	   (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2645	   end++)
2646	continue;
2647      *end = '\0';
2648
2649      if (access (name, R_OK) == 0)
2650        add_to_list (&libraries, name);
2651      else
2652	fatal ("unable to open dynamic dependency '%s'", buf);
2653
2654      if (debug)
2655	fprintf (stderr, "\t%s\n", buf);
2656    }
2657  if (debug)
2658    fprintf (stderr, "\n");
2659
2660  if (fclose (inf) != 0)
2661    fatal_perror ("fclose");
2662
2663  do_wait (ldd_file_name);
2664
2665  signal (SIGINT,  int_handler);
2666#ifdef SIGQUIT
2667  signal (SIGQUIT, quit_handler);
2668#endif
2669
2670  /* now iterate through the library list adding their symbols to
2671     the list.  */
2672  for (list = libraries.first; list; list = list->next)
2673    scan_prog_file (list->name, PASS_LIB);
2674}
2675
2676#endif /* LDD_SUFFIX */
2677#endif /* SUNOS4_SHARED_LIBRARIES */
2678
2679#endif /* OBJECT_FORMAT_NONE */
2680
2681
2682/*
2683 * COFF specific stuff.
2684 */
2685
2686#ifdef OBJECT_FORMAT_COFF
2687
2688#if defined (EXTENDED_COFF)
2689
2690#   define GCC_SYMBOLS(X)	(SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2691#   define GCC_SYMENT		SYMR
2692#   define GCC_OK_SYMBOL(X)	((X).st == stProc || (X).st == stGlobal)
2693#   define GCC_SYMINC(X)	(1)
2694#   define GCC_SYMZERO(X)	(SYMHEADER(X).isymMax)
2695#   define GCC_CHECK_HDR(X)	(PSYMTAB(X) != 0)
2696
2697#else
2698
2699#   define GCC_SYMBOLS(X)	(HEADER(ldptr).f_nsyms)
2700#   define GCC_SYMENT		SYMENT
2701#   if defined (C_WEAKEXT)
2702#     define GCC_OK_SYMBOL(X) \
2703       (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
2704        ((X).n_scnum > N_UNDEF) && \
2705        (aix64_flag \
2706         || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2707             || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2708#     define GCC_UNDEF_SYMBOL(X) \
2709       (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
2710        ((X).n_scnum == N_UNDEF))
2711#   else
2712#     define GCC_OK_SYMBOL(X) \
2713       (((X).n_sclass == C_EXT) && \
2714        ((X).n_scnum > N_UNDEF) && \
2715        (aix64_flag \
2716         || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2717             || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2718#     define GCC_UNDEF_SYMBOL(X) \
2719       (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2720#   endif
2721#   define GCC_SYMINC(X)	((X).n_numaux+1)
2722#   define GCC_SYMZERO(X)	0
2723
2724/* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
2725#ifdef _AIX51
2726#   define GCC_CHECK_HDR(X) \
2727     ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2728      || (HEADER (X).f_magic == 0767 && aix64_flag))
2729#else
2730#   define GCC_CHECK_HDR(X) \
2731     ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2732      || (HEADER (X).f_magic == 0757 && aix64_flag))
2733#endif
2734
2735#endif
2736
2737extern char *ldgetname ();
2738
2739/* COFF version to scan the name list of the loaded program for
2740   the symbols g++ uses for static constructors and destructors.
2741
2742   The constructor table begins at __CTOR_LIST__ and contains a count
2743   of the number of pointers (or -1 if the constructors are built in a
2744   separate section by the linker), followed by the pointers to the
2745   constructor functions, terminated with a null pointer.  The
2746   destructor table has the same format, and begins at __DTOR_LIST__.  */
2747
2748static void
2749scan_prog_file (prog_name, which_pass)
2750     const char *prog_name;
2751     enum pass which_pass;
2752{
2753  LDFILE *ldptr = NULL;
2754  int sym_index, sym_count;
2755  int is_shared = 0;
2756
2757  if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2758    return;
2759
2760#ifdef COLLECT_EXPORT_LIST
2761  /* We do not need scanning for some standard C libraries.  */
2762  if (which_pass == PASS_FIRST && ignore_library (prog_name))
2763    return;
2764
2765  /* On AIX we have a loop, because there is not much difference
2766     between an object and an archive. This trick allows us to
2767     eliminate scan_libraries() function.  */
2768  do
2769    {
2770#endif
2771      /* Some platforms (e.g. OSF4) declare ldopen as taking a
2772         non-const char * filename parameter, even though it will not
2773         modify that string.  So we must cast away const-ness here,
2774         which will cause -Wcast-qual to burp.  */
2775      if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2776	{
2777	  if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2778	    fatal ("%s: not a COFF file", prog_name);
2779
2780	  if (GCC_CHECK_HDR (ldptr))
2781	    {
2782	      sym_count = GCC_SYMBOLS (ldptr);
2783	      sym_index = GCC_SYMZERO (ldptr);
2784
2785#ifdef COLLECT_EXPORT_LIST
2786	      /* Is current archive member a shared object?  */
2787	      is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2788#endif
2789
2790	      while (sym_index < sym_count)
2791		{
2792		  GCC_SYMENT symbol;
2793
2794		  if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2795		    break;
2796		  sym_index += GCC_SYMINC (symbol);
2797
2798		  if (GCC_OK_SYMBOL (symbol))
2799		    {
2800		      char *name;
2801
2802		      if ((name = ldgetname (ldptr, &symbol)) == NULL)
2803			continue;		/* should never happen */
2804
2805#ifdef XCOFF_DEBUGGING_INFO
2806		      /* All AIX function names have a duplicate entry
2807			 beginning with a dot.  */
2808		      if (*name == '.')
2809			++name;
2810#endif
2811
2812		      switch (is_ctor_dtor (name))
2813			{
2814			case 1:
2815			  if (! is_shared)
2816			    add_to_list (&constructors, name);
2817#ifdef COLLECT_EXPORT_LIST
2818			  if (which_pass == PASS_OBJ)
2819			    add_to_list (&exports, name);
2820#endif
2821			  break;
2822
2823			case 2:
2824			  if (! is_shared)
2825			    add_to_list (&destructors, name);
2826#ifdef COLLECT_EXPORT_LIST
2827			  if (which_pass == PASS_OBJ)
2828			    add_to_list (&exports, name);
2829#endif
2830			  break;
2831
2832#ifdef COLLECT_EXPORT_LIST
2833			case 3:
2834#ifndef LD_INIT_SWITCH
2835			  if (is_shared)
2836			    add_to_list (&constructors, name);
2837#endif
2838			  break;
2839
2840			case 4:
2841#ifndef LD_INIT_SWITCH
2842			  if (is_shared)
2843			    add_to_list (&destructors, name);
2844#endif
2845			  break;
2846#endif
2847
2848			case 5:
2849			  if (! is_shared)
2850			    add_to_list (&frame_tables, name);
2851#ifdef COLLECT_EXPORT_LIST
2852			  if (which_pass == PASS_OBJ)
2853			    add_to_list (&exports, name);
2854#endif
2855			  break;
2856
2857			default:	/* not a constructor or destructor */
2858#ifdef COLLECT_EXPORT_LIST
2859			  /* If we are building a shared object on AIX we need
2860			     to explicitly export all global symbols.  */
2861			  if (shared_obj)
2862			    {
2863			      if (which_pass == PASS_OBJ && (! export_flag))
2864				add_to_list (&exports, name);
2865			    }
2866#endif
2867			  continue;
2868			}
2869
2870		      if (debug)
2871#if !defined(EXTENDED_COFF)
2872			fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2873				 symbol.n_scnum, symbol.n_sclass,
2874				 (symbol.n_type ? "0" : ""), symbol.n_type,
2875				 name);
2876#else
2877			fprintf (stderr,
2878				 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2879				 symbol.iss, (long) symbol.value, symbol.index, name);
2880#endif
2881		    }
2882		}
2883	    }
2884#ifdef COLLECT_EXPORT_LIST
2885	  else
2886	    {
2887	      /* If archive contains both 32-bit and 64-bit objects,
2888		 we want to skip objects in other mode so mismatch normal.  */
2889	      if (debug)
2890		fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2891			 prog_name, HEADER (ldptr).f_magic, aix64_flag);
2892	    }
2893#endif
2894	}
2895      else
2896	{
2897	  fatal ("%s: cannot open as COFF file", prog_name);
2898	}
2899#ifdef COLLECT_EXPORT_LIST
2900      /* On AIX loop continues while there are more members in archive.  */
2901    }
2902  while (ldclose (ldptr) == FAILURE);
2903#else
2904  /* Otherwise we simply close ldptr.  */
2905  (void) ldclose(ldptr);
2906#endif
2907}
2908#endif /* OBJECT_FORMAT_COFF */
2909
2910#ifdef COLLECT_EXPORT_LIST
2911/* Given a library name without "lib" prefix, this function
2912   returns a full library name including a path.  */
2913static char *
2914resolve_lib_name (name)
2915     const char *name;
2916{
2917  char *lib_buf;
2918  int i, j, l = 0;
2919
2920  for (i = 0; libpaths[i]; i++)
2921    if (libpaths[i]->max_len > l)
2922      l = libpaths[i]->max_len;
2923
2924  lib_buf = xmalloc (l + strlen(name) + 10);
2925
2926  for (i = 0; libpaths[i]; i++)
2927    {
2928      struct prefix_list *list = libpaths[i]->plist;
2929      for (; list; list = list->next)
2930	{
2931	  /* The following lines are needed because path_prefix list
2932	     may contain directories both with trailing '/' and
2933	     without it.  */
2934	  const char *p = "";
2935	  if (list->prefix[strlen(list->prefix)-1] != '/')
2936	    p = "/";
2937	  for (j = 0; libexts[j]; j++)
2938	    {
2939       	      sprintf (lib_buf, "%s%slib%s.%s",
2940		       list->prefix, p, name, libexts[j]);
2941if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2942	      if (file_exists (lib_buf))
2943		{
2944if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2945		  return (lib_buf);
2946		}
2947	    }
2948	}
2949    }
2950  if (debug)
2951    fprintf (stderr, "not found\n");
2952  else
2953    fatal ("library lib%s not found", name);
2954  return (NULL);
2955}
2956
2957/* Array of standard AIX libraries which should not
2958   be scanned for ctors/dtors.  */
2959static const char *const aix_std_libs[] = {
2960  "/unix",
2961  "/lib/libc.a",
2962  "/lib/libm.a",
2963  "/lib/libc_r.a",
2964  "/lib/libm_r.a",
2965  "/usr/lib/libc.a",
2966  "/usr/lib/libm.a",
2967  "/usr/lib/libc_r.a",
2968  "/usr/lib/libm_r.a",
2969  "/usr/lib/threads/libc.a",
2970  "/usr/ccs/lib/libc.a",
2971  "/usr/ccs/lib/libm.a",
2972  "/usr/ccs/lib/libc_r.a",
2973  "/usr/ccs/lib/libm_r.a",
2974  NULL
2975};
2976
2977/* This function checks the filename and returns 1
2978   if this name matches the location of a standard AIX library.  */
2979static int
2980ignore_library (name)
2981     const char *name;
2982{
2983  const char *const *p = &aix_std_libs[0];
2984  while (*p++ != NULL)
2985    if (! strcmp (name, *p)) return 1;
2986  return 0;
2987}
2988#endif /* COLLECT_EXPORT_LIST */
2989
2990
2991/*
2992 * OSF/rose specific stuff.
2993 */
2994
2995#ifdef OBJECT_FORMAT_ROSE
2996
2997/* Union of the various load commands */
2998
2999typedef union load_union
3000{
3001  ldc_header_t			hdr;	/* common header */
3002  load_cmd_map_command_t	map;	/* map indexing other load cmds */
3003  interpreter_command_t		iprtr;	/* interpreter pathname */
3004  strings_command_t		str;	/* load commands strings section */
3005  region_command_t		region;	/* region load command */
3006  reloc_command_t		reloc;	/* relocation section */
3007  package_command_t		pkg;	/* package load command */
3008  symbols_command_t		sym;	/* symbol sections */
3009  entry_command_t		ent;	/* program start section */
3010  gen_info_command_t		info;	/* object information */
3011  func_table_command_t		func;	/* function constructors/destructors */
3012} load_union_t;
3013
3014/* Structure to point to load command and data section in memory.  */
3015
3016typedef struct load_all
3017{
3018  load_union_t *load;			/* load command */
3019  char *section;			/* pointer to section */
3020} load_all_t;
3021
3022/* Structure to contain information about a file mapped into memory.  */
3023
3024struct file_info
3025{
3026  char *start;				/* start of map */
3027  char *name;				/* filename */
3028  long	size;				/* size of the file */
3029  long  rounded_size;			/* size rounded to page boundary */
3030  int	fd;				/* file descriptor */
3031  int	rw;				/* != 0 if opened read/write */
3032  int	use_mmap;			/* != 0 if mmap'ed */
3033};
3034
3035extern int decode_mach_o_hdr ();
3036extern int encode_mach_o_hdr ();
3037
3038static void add_func_table	PARAMS ((mo_header_t *, load_all_t *,
3039				       symbol_info_t *, int));
3040static void print_header	PARAMS ((mo_header_t *));
3041static void print_load_command	PARAMS ((load_union_t *, size_t, int));
3042static void bad_header		PARAMS ((int));
3043static struct file_info	*read_file  PARAMS ((const char *, int, int));
3044static void end_file		PARAMS ((struct file_info *));
3045
3046/* OSF/rose specific version to scan the name list of the loaded
3047   program for the symbols g++ uses for static constructors and
3048   destructors.
3049
3050   The constructor table begins at __CTOR_LIST__ and contains a count
3051   of the number of pointers (or -1 if the constructors are built in a
3052   separate section by the linker), followed by the pointers to the
3053   constructor functions, terminated with a null pointer.  The
3054   destructor table has the same format, and begins at __DTOR_LIST__.  */
3055
3056static void
3057scan_prog_file (prog_name, which_pass)
3058     const char *prog_name;
3059     enum pass which_pass;
3060{
3061  char *obj;
3062  mo_header_t hdr;
3063  load_all_t *load_array;
3064  load_all_t *load_end;
3065  load_all_t *load_cmd;
3066  int symbol_load_cmds;
3067  off_t offset;
3068  int i;
3069  int num_syms;
3070  int status;
3071  char *str_sect;
3072  struct file_info *obj_file;
3073  int prog_fd;
3074  mo_lcid_t cmd_strings	  = -1;
3075  symbol_info_t *main_sym = 0;
3076  int rw		  = (which_pass != PASS_FIRST);
3077
3078  prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3079  if (prog_fd < 0)
3080    fatal_perror ("open %s", prog_name);
3081
3082  obj_file = read_file (prog_name, prog_fd, rw);
3083  obj = obj_file->start;
3084
3085  status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3086  if (status != MO_HDR_CONV_SUCCESS)
3087    bad_header (status);
3088
3089
3090  /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
3091     since the hardware will automatically swap bytes for us on loading little endian
3092     integers.  */
3093
3094#ifndef CROSS_COMPILE
3095  if (hdr.moh_magic != MOH_MAGIC_MSB
3096      || hdr.moh_header_version != MOH_HEADER_VERSION
3097      || hdr.moh_byte_order != OUR_BYTE_ORDER
3098      || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3099      || hdr.moh_cpu_type != OUR_CPU_TYPE
3100      || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3101      || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3102    {
3103      fatal ("incompatibilities between object file & expected values");
3104    }
3105#endif
3106
3107  if (debug)
3108    print_header (&hdr);
3109
3110  offset = hdr.moh_first_cmd_off;
3111  load_end = load_array
3112    = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3113
3114  /* Build array of load commands, calculating the offsets */
3115  for (i = 0; i < hdr.moh_n_load_cmds; i++)
3116    {
3117      load_union_t *load_hdr;		/* load command header */
3118
3119      load_cmd = load_end++;
3120      load_hdr = (load_union_t *) (obj + offset);
3121
3122      /* If modifying the program file, copy the header.  */
3123      if (rw)
3124	{
3125	  load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3126	  memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
3127	  load_hdr = ptr;
3128
3129	  /* null out old command map, because we will rewrite at the end.  */
3130	  if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3131	    {
3132	      cmd_strings = ptr->map.lcm_ld_cmd_strings;
3133	      ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3134	    }
3135	}
3136
3137      load_cmd->load = load_hdr;
3138      if (load_hdr->hdr.ldci_section_off > 0)
3139	load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3140
3141      if (debug)
3142	print_load_command (load_hdr, offset, i);
3143
3144      offset += load_hdr->hdr.ldci_cmd_size;
3145    }
3146
3147  /* If the last command is the load command map and is not undefined,
3148     decrement the count of load commands.  */
3149  if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3150    {
3151      load_end--;
3152      hdr.moh_n_load_cmds--;
3153    }
3154
3155  /* Go through and process each symbol table section.  */
3156  symbol_load_cmds = 0;
3157  for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3158    {
3159      load_union_t *load_hdr = load_cmd->load;
3160
3161      if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3162	{
3163	  symbol_load_cmds++;
3164
3165	  if (debug)
3166	    {
3167	      const char *kind = "unknown";
3168
3169	      switch (load_hdr->sym.symc_kind)
3170		{
3171		case SYMC_IMPORTS:	   kind = "imports"; break;
3172		case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3173		case SYMC_STABS:	   kind = "stabs";   break;
3174		}
3175
3176	      notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3177		      symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3178	    }
3179
3180	  if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3181	    continue;
3182
3183	  str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3184	  if (str_sect == (char *) 0)
3185	    fatal ("string section missing");
3186
3187	  if (load_cmd->section == (char *) 0)
3188	    fatal ("section pointer missing");
3189
3190	  num_syms = load_hdr->sym.symc_nentries;
3191	  for (i = 0; i < num_syms; i++)
3192	    {
3193	      symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3194	      char *name = sym->si_name.symbol_name + str_sect;
3195
3196	      if (name[0] != '_')
3197		continue;
3198
3199	      if (rw)
3200		{
3201		  char *n = name + strlen (name) - strlen (NAME__MAIN);
3202
3203		  if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3204		    continue;
3205		  while (n != name)
3206		    if (*--n != '_')
3207		      continue;
3208
3209		  main_sym = sym;
3210		}
3211	      else
3212		{
3213		  switch (is_ctor_dtor (name))
3214		    {
3215		    case 1:
3216		      add_to_list (&constructors, name);
3217		      break;
3218
3219		    case 2:
3220		      add_to_list (&destructors, name);
3221		      break;
3222
3223		    default:	/* not a constructor or destructor */
3224		      continue;
3225		    }
3226		}
3227
3228	      if (debug)
3229		fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3230			 sym->si_type, sym->si_sc_type, sym->si_flags, name);
3231	    }
3232	}
3233    }
3234
3235  if (symbol_load_cmds == 0)
3236    fatal ("no symbol table found");
3237
3238  /* Update the program file now, rewrite header and load commands.  At present,
3239     we assume that there is enough space after the last load command to insert
3240     one more.  Since the first section written out is page aligned, and the
3241     number of load commands is small, this is ok for the present.  */
3242
3243  if (rw)
3244    {
3245      load_union_t *load_map;
3246      size_t size;
3247
3248      if (cmd_strings == -1)
3249	fatal ("no cmd_strings found");
3250
3251      /* Add __main to initializer list.
3252	 If we are building a program instead of a shared library, do not
3253	 do anything, since in the current version, you cannot do mallocs
3254	 and such in the constructors.  */
3255
3256      if (main_sym != (symbol_info_t *) 0
3257	  && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3258	add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3259
3260      if (debug)
3261	notice ("\nUpdating header and load commands.\n\n");
3262
3263      hdr.moh_n_load_cmds++;
3264      size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3265
3266      /* Create new load command map.  */
3267      if (debug)
3268	notice ("load command map, %d cmds, new size %ld.\n",
3269		(int) hdr.moh_n_load_cmds, (long) size);
3270
3271      load_map = (load_union_t *) xcalloc (1, size);
3272      load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3273      load_map->map.ldc_header.ldci_cmd_size = size;
3274      load_map->map.lcm_ld_cmd_strings = cmd_strings;
3275      load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3276      load_array[hdr.moh_n_load_cmds-1].load = load_map;
3277
3278      offset = hdr.moh_first_cmd_off;
3279      for (i = 0; i < hdr.moh_n_load_cmds; i++)
3280	{
3281	  load_map->map.lcm_map[i] = offset;
3282	  if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3283	    hdr.moh_load_map_cmd_off = offset;
3284
3285	  offset += load_array[i].load->hdr.ldci_cmd_size;
3286	}
3287
3288      hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3289
3290      if (debug)
3291	print_header (&hdr);
3292
3293      /* Write header */
3294      status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3295      if (status != MO_HDR_CONV_SUCCESS)
3296	bad_header (status);
3297
3298      if (debug)
3299	notice ("writing load commands.\n\n");
3300
3301      /* Write load commands */
3302      offset = hdr.moh_first_cmd_off;
3303      for (i = 0; i < hdr.moh_n_load_cmds; i++)
3304	{
3305	  load_union_t *load_hdr = load_array[i].load;
3306	  size_t size = load_hdr->hdr.ldci_cmd_size;
3307
3308	  if (debug)
3309	    print_load_command (load_hdr, offset, i);
3310
3311	  bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3312	  offset += size;
3313	}
3314    }
3315
3316  end_file (obj_file);
3317
3318  if (close (prog_fd))
3319    fatal_perror ("close %s", prog_name);
3320
3321  if (debug)
3322    fprintf (stderr, "\n");
3323}
3324
3325
3326/* Add a function table to the load commands to call a function
3327   on initiation or termination of the process.  */
3328
3329static void
3330add_func_table (hdr_p, load_array, sym, type)
3331     mo_header_t *hdr_p;		/* pointer to global header */
3332     load_all_t *load_array;		/* array of ptrs to load cmds */
3333     symbol_info_t *sym;		/* pointer to symbol entry */
3334     int type;				/* fntc_type value */
3335{
3336  /* Add a new load command.  */
3337  int num_cmds = ++hdr_p->moh_n_load_cmds;
3338  int load_index = num_cmds - 1;
3339  size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3340  load_union_t *ptr = xcalloc (1, size);
3341  load_all_t *load_cmd;
3342  int i;
3343
3344  /* Set the unresolved address bit in the header to force the loader to be
3345     used, since kernel exec does not call the initialization functions.  */
3346  hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3347
3348  load_cmd = &load_array[load_index];
3349  load_cmd->load = ptr;
3350  load_cmd->section = (char *) 0;
3351
3352  /* Fill in func table load command.  */
3353  ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3354  ptr->func.ldc_header.ldci_cmd_size = size;
3355  ptr->func.ldc_header.ldci_section_off = 0;
3356  ptr->func.ldc_header.ldci_section_len = 0;
3357  ptr->func.fntc_type = type;
3358  ptr->func.fntc_nentries = 1;
3359
3360  /* copy address, turn it from abs. address to (region,offset) if necessary.  */
3361  /* Is the symbol already expressed as (region, offset)?  */
3362  if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3363    {
3364      ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3365      ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3366    }
3367
3368  /* If not, figure out which region it's in.  */
3369  else
3370    {
3371      mo_vm_addr_t addr = sym->si_value.abs_val;
3372      int found = 0;
3373
3374      for (i = 0; i < load_index; i++)
3375	{
3376	  if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3377	    {
3378	      region_command_t *region_ptr = &load_array[i].load->region;
3379
3380	      if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3381		  && addr >= region_ptr->regc_addr.vm_addr
3382		  && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3383		{
3384		  ptr->func.fntc_entry_loc[0].adr_lcid = i;
3385		  ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3386		  found++;
3387		  break;
3388		}
3389	    }
3390	}
3391
3392      if (!found)
3393	fatal ("could not convert 0x%l.8x into a region", addr);
3394    }
3395
3396  if (debug)
3397    notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3398	    type == FNTC_INITIALIZATION ? "init" : "term",
3399	    (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3400	    (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3401	    (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3402
3403}
3404
3405
3406/* Print the global header for an OSF/rose object.  */
3407
3408static void
3409print_header (hdr_ptr)
3410     mo_header_t *hdr_ptr;
3411{
3412  fprintf (stderr, "\nglobal header:\n");
3413  fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
3414  fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
3415  fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
3416  fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
3417  fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
3418  fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
3419  fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
3420  fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
3421  fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3422  fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
3423  fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3424  fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3425  fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3426  fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3427  fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
3428
3429  if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3430    fprintf (stderr, ", relocatable");
3431
3432  if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3433    fprintf (stderr, ", linkable");
3434
3435  if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3436    fprintf (stderr, ", execable");
3437
3438  if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3439    fprintf (stderr, ", executable");
3440
3441  if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3442    fprintf (stderr, ", unresolved");
3443
3444  fprintf (stderr, "\n\n");
3445  return;
3446}
3447
3448
3449/* Print a short summary of a load command.  */
3450
3451static void
3452print_load_command (load_hdr, offset, number)
3453     load_union_t *load_hdr;
3454     size_t offset;
3455     int number;
3456{
3457  mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3458  const char *type_str = (char *) 0;
3459
3460  switch (type)
3461    {
3462    case LDC_UNDEFINED:   type_str = "UNDEFINED";	break;
3463    case LDC_CMD_MAP:	  type_str = "CMD_MAP";		break;
3464    case LDC_INTERPRETER: type_str = "INTERPRETER";	break;
3465    case LDC_STRINGS:	  type_str = "STRINGS";		break;
3466    case LDC_REGION:	  type_str = "REGION";		break;
3467    case LDC_RELOC:	  type_str = "RELOC";		break;
3468    case LDC_PACKAGE:	  type_str = "PACKAGE";		break;
3469    case LDC_SYMBOLS:	  type_str = "SYMBOLS";		break;
3470    case LDC_ENTRY:	  type_str = "ENTRY";		break;
3471    case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";	break;
3472    case LDC_GEN_INFO:	  type_str = "GEN_INFO";	break;
3473    }
3474
3475  fprintf (stderr,
3476	   "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3477	   number,
3478	   (long) load_hdr->hdr.ldci_cmd_size,
3479	   (long) offset,
3480	   (long) load_hdr->hdr.ldci_section_off,
3481	   (long) load_hdr->hdr.ldci_section_len);
3482
3483  if (type_str == (char *) 0)
3484    fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3485
3486  else if (type != LDC_REGION)
3487    fprintf (stderr, ", ty: %s\n", type_str);
3488
3489  else
3490    {
3491      const char *region = "";
3492      switch (load_hdr->region.regc_usage_type)
3493	{
3494	case REG_TEXT_T:	region = ", .text";	break;
3495	case REG_DATA_T:	region = ", .data";	break;
3496	case REG_BSS_T:		region = ", .bss";	break;
3497	case REG_GLUE_T:	region = ", .glue";	break;
3498#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3499	case REG_RDATA_T:	region = ", .rdata";	break;
3500	case REG_SDATA_T:	region = ", .sdata";	break;
3501	case REG_SBSS_T:	region = ", .sbss";	break;
3502#endif
3503	}
3504
3505      fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3506	       type_str,
3507	       (long) load_hdr->region.regc_vm_addr,
3508	       (long) load_hdr->region.regc_vm_size,
3509	       region);
3510    }
3511
3512  return;
3513}
3514
3515
3516/* Fatal error when {en,de}code_mach_o_header fails.  */
3517
3518static void
3519bad_header (status)
3520     int status;
3521{
3522  switch (status)
3523    {
3524    case MO_ERROR_BAD_MAGIC:		fatal ("bad magic number");
3525    case MO_ERROR_BAD_HDR_VERS:		fatal ("bad header version");
3526    case MO_ERROR_BAD_RAW_HDR_VERS:	fatal ("bad raw header version");
3527    case MO_ERROR_BUF2SML:		fatal ("raw header buffer too small");
3528    case MO_ERROR_OLD_RAW_HDR_FILE:	fatal ("old raw header file");
3529    case MO_ERROR_UNSUPPORTED_VERS:	fatal ("unsupported version");
3530    default:
3531      fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3532    }
3533}
3534
3535
3536/* Read a file into a memory buffer.  */
3537
3538static struct file_info *
3539read_file (name, fd, rw)
3540     const char *name;		/* filename */
3541     int fd;			/* file descriptor */
3542     int rw;			/* read/write */
3543{
3544  struct stat stat_pkt;
3545  struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3546#ifdef USE_MMAP
3547  static int page_size;
3548#endif
3549
3550  if (fstat (fd, &stat_pkt) < 0)
3551    fatal_perror ("fstat %s", name);
3552
3553  p->name	  = name;
3554  p->size	  = stat_pkt.st_size;
3555  p->rounded_size = stat_pkt.st_size;
3556  p->fd		  = fd;
3557  p->rw		  = rw;
3558
3559#ifdef USE_MMAP
3560  if (debug)
3561    fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3562
3563  if (page_size == 0)
3564    page_size = sysconf (_SC_PAGE_SIZE);
3565
3566  p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3567  p->start = mmap ((caddr_t) 0,
3568		   (rw) ? p->rounded_size : p->size,
3569		   (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3570		   MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3571		   fd,
3572		   0L);
3573
3574  if (p->start != (char *) 0 && p->start != (char *) -1)
3575    p->use_mmap = 1;
3576
3577  else
3578#endif /* USE_MMAP */
3579    {
3580      long len;
3581
3582      if (debug)
3583	fprintf (stderr, "read %s\n", name);
3584
3585      p->use_mmap = 0;
3586      p->start = xmalloc (p->size);
3587      if (lseek (fd, 0L, SEEK_SET) < 0)
3588	fatal_perror ("lseek %s 0", name);
3589
3590      len = read (fd, p->start, p->size);
3591      if (len < 0)
3592	fatal_perror ("read %s", name);
3593
3594      if (len != p->size)
3595	fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3596    }
3597
3598  return p;
3599}
3600
3601/* Do anything necessary to write a file back from memory.  */
3602
3603static void
3604end_file (ptr)
3605     struct file_info *ptr;	/* file information block */
3606{
3607#ifdef USE_MMAP
3608  if (ptr->use_mmap)
3609    {
3610      if (ptr->rw)
3611	{
3612	  if (debug)
3613	    fprintf (stderr, "msync %s\n", ptr->name);
3614
3615	  if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3616	    fatal_perror ("msync %s", ptr->name);
3617	}
3618
3619      if (debug)
3620	fprintf (stderr, "munmap %s\n", ptr->name);
3621
3622      if (munmap (ptr->start, ptr->size))
3623	fatal_perror ("munmap %s", ptr->name);
3624    }
3625  else
3626#endif /* USE_MMAP */
3627    {
3628      if (ptr->rw)
3629	{
3630	  long len;
3631
3632	  if (debug)
3633	    fprintf (stderr, "write %s\n", ptr->name);
3634
3635	  if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3636	    fatal_perror ("lseek %s 0", ptr->name);
3637
3638	  len = write (ptr->fd, ptr->start, ptr->size);
3639	  if (len < 0)
3640	    fatal_perror ("write %s", ptr->name);
3641
3642	  if (len != ptr->size)
3643	    fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3644	}
3645
3646      free (ptr->start);
3647    }
3648
3649  free (ptr);
3650}
3651
3652#endif /* OBJECT_FORMAT_ROSE */
3653