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