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