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