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