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