collect2.c revision 70635
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      /* Do the link we avoided above if we are exiting.  */
1531      do_tlink (ld1_argv, object_lst);
1532
1533      /* But make sure we delete the export file we may have created.  */
1534      if (export_file != 0 && export_file[0])
1535	maybe_unlink (export_file);
1536      if (import_file != 0 && import_file[0])
1537	maybe_unlink (import_file);
1538#endif
1539      maybe_unlink (c_file);
1540      maybe_unlink (o_file);
1541      return 0;
1542    }
1543
1544  /* Examine the namelist with nm and search it for static constructors
1545     and destructors to call.
1546     Write the constructor and destructor tables to a .s file and reload.  */
1547
1548  /* On AIX we already done scanning for global constructors/destructors.  */
1549#ifndef COLLECT_EXPORT_LIST
1550  scan_prog_file (output_file, PASS_FIRST);
1551#endif
1552
1553#ifdef SCAN_LIBRARIES
1554  scan_libraries (output_file);
1555#endif
1556
1557  if (debug)
1558    {
1559      notice ("%d constructor(s) found\n", constructors.number);
1560      notice ("%d destructor(s)  found\n", destructors.number);
1561      notice ("%d frame table(s) found\n", frame_tables.number);
1562    }
1563
1564  if (constructors.number == 0 && destructors.number == 0
1565      && frame_tables.number == 0
1566#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1567      /* If we will be running these functions ourselves, we want to emit
1568	 stubs into the shared library so that we do not have to relink
1569	 dependent programs when we add static objects.  */
1570      && ! shared_obj
1571#endif
1572      )
1573    {
1574#ifdef COLLECT_EXPORT_LIST
1575      /* Doing tlink without additional code generation */
1576      do_tlink (ld1_argv, object_lst);
1577#endif
1578      /* Strip now if it was requested on the command line.  */
1579      if (strip_flag)
1580	{
1581	  char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
1582	  strip_argv[0] = strip_file_name;
1583	  strip_argv[1] = output_file;
1584	  strip_argv[2] = (char *) 0;
1585	  fork_execute ("strip", strip_argv);
1586	}
1587
1588#ifdef COLLECT_EXPORT_LIST
1589      maybe_unlink (export_file);
1590      maybe_unlink (import_file);
1591#endif
1592      maybe_unlink (c_file);
1593      maybe_unlink (o_file);
1594      return 0;
1595    }
1596
1597  /* Sort ctor and dtor lists by priority. */
1598  sort_ids (&constructors);
1599  sort_ids (&destructors);
1600
1601  maybe_unlink(output_file);
1602  outf = fopen (c_file, "w");
1603  if (outf == (FILE *) 0)
1604    fatal_perror ("fopen %s", c_file);
1605
1606  write_c_file (outf, c_file);
1607
1608  if (fclose (outf))
1609    fatal_perror ("fclose %s", c_file);
1610
1611  /* Tell the linker that we have initializer and finalizer functions.  */
1612#ifdef LD_INIT_SWITCH
1613  *ld2++ = LD_INIT_SWITCH;
1614  *ld2++ = initname;
1615  *ld2++ = LD_FINI_SWITCH;
1616  *ld2++ = fininame;
1617#endif
1618  *ld2 = (char*) 0;
1619
1620#ifdef COLLECT_EXPORT_LIST
1621  if (shared_obj)
1622    {
1623      add_to_list (&exports, initname);
1624      add_to_list (&exports, fininame);
1625      add_to_list (&exports, "_GLOBAL__DI");
1626      add_to_list (&exports, "_GLOBAL__DD");
1627      exportf = fopen (export_file, "w");
1628      if (exportf == (FILE *) 0)
1629	fatal_perror ("fopen %s", export_file);
1630      write_export_file (exportf);
1631      if (fclose (exportf))
1632	fatal_perror ("fclose %s", export_file);
1633    }
1634#endif
1635
1636  if (debug)
1637    {
1638      fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1639	       output_file, c_file);
1640      write_c_file (stderr, "stderr");
1641      fprintf (stderr, "========== end of c_file\n\n");
1642#ifdef COLLECT_EXPORT_LIST
1643      fprintf (stderr, "\n========== export_file = %s\n", export_file);
1644      write_export_file (stderr);
1645      fprintf (stderr, "========== end of export_file\n\n");
1646#endif
1647    }
1648
1649  /* Assemble the constructor and destructor tables.
1650     Link the tables in with the rest of the program.  */
1651
1652  fork_execute ("gcc",  c_argv);
1653#ifdef COLLECT_EXPORT_LIST
1654  /* On AIX we must call tlink because of possible templates resolution */
1655  do_tlink (ld2_argv, object_lst);
1656#else
1657  /* Otherwise, simply call ld because tlink is already done */
1658  fork_execute ("ld", ld2_argv);
1659
1660  /* Let scan_prog_file do any final mods (OSF/rose needs this for
1661     constructors/destructors in shared libraries.  */
1662  scan_prog_file (output_file, PASS_SECOND);
1663#endif
1664
1665  maybe_unlink (c_file);
1666  maybe_unlink (o_file);
1667
1668#ifdef COLLECT_EXPORT_LIST
1669  maybe_unlink (export_file);
1670  maybe_unlink (import_file);
1671#endif
1672
1673  return 0;
1674}
1675
1676
1677/* Wait for a process to finish, and exit if a non-zero status is found.  */
1678
1679int
1680collect_wait (prog)
1681     char *prog;
1682{
1683  int status;
1684
1685  pwait (pexecute_pid, &status, 0);
1686  if (status)
1687    {
1688      if (WIFSIGNALED (status))
1689	{
1690	  int sig = WTERMSIG (status);
1691	  error ((status & 0200
1692		  ? "%s terminated with signal %d [%s]"
1693		  : "%s terminated with signal %d [%s], core dumped"),
1694		 prog,
1695		 sig,
1696		 my_strsignal(sig));
1697	  collect_exit (FATAL_EXIT_CODE);
1698	}
1699
1700      if (WIFEXITED (status))
1701	return WEXITSTATUS (status);
1702    }
1703  return 0;
1704}
1705
1706static void
1707do_wait (prog)
1708     char *prog;
1709{
1710  int ret = collect_wait (prog);
1711  if (ret != 0)
1712    {
1713      error ("%s returned %d exit status", prog, ret);
1714      collect_exit (ret);
1715    }
1716}
1717
1718
1719/* Execute a program, and wait for the reply.  */
1720
1721void
1722collect_execute (prog, argv, redir)
1723     char *prog;
1724     char **argv;
1725     char *redir;
1726{
1727  char *errmsg_fmt;
1728  char *errmsg_arg;
1729  int redir_handle = -1;
1730  int stdout_save = -1;
1731  int stderr_save = -1;
1732
1733  if (vflag || debug)
1734    {
1735      char **p_argv;
1736      char *str;
1737
1738      if (argv[0])
1739	fprintf (stderr, "%s", argv[0]);
1740      else
1741	notice ("[cannot find %s]", prog);
1742
1743      for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1744	fprintf (stderr, " %s", str);
1745
1746      fprintf (stderr, "\n");
1747    }
1748
1749  fflush (stdout);
1750  fflush (stderr);
1751
1752  /* If we cannot find a program we need, complain error.  Do this here
1753     since we might not end up needing something that we could not find.  */
1754
1755  if (argv[0] == 0)
1756    fatal ("cannot find `%s'", prog);
1757
1758  if (redir)
1759    {
1760      /* Open response file.  */
1761      redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1762
1763      /* Duplicate the stdout and stderr file handles
1764	 so they can be restored later.  */
1765      stdout_save = dup (STDOUT_FILENO);
1766      if (stdout_save == -1)
1767	fatal_perror ("redirecting stdout: %s", redir);
1768      stderr_save = dup (STDERR_FILENO);
1769      if (stderr_save == -1)
1770	fatal_perror ("redirecting stdout: %s", redir);
1771
1772      /* Redirect stdout & stderr to our response file.  */
1773      dup2 (redir_handle, STDOUT_FILENO);
1774      dup2 (redir_handle, STDERR_FILENO);
1775    }
1776
1777  pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
1778			   &errmsg_fmt, &errmsg_arg,
1779			   (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1780
1781  if (redir)
1782    {
1783      /* Restore stdout and stderr to their previous settings.  */
1784      dup2 (stdout_save, STDOUT_FILENO);
1785      dup2 (stderr_save, STDERR_FILENO);
1786
1787      /* Close reponse file.  */
1788      close (redir_handle);
1789    }
1790
1791 if (pexecute_pid == -1)
1792   fatal_perror (errmsg_fmt, errmsg_arg);
1793}
1794
1795static void
1796fork_execute (prog, argv)
1797     char *prog;
1798     char **argv;
1799{
1800  collect_execute (prog, argv, NULL);
1801  do_wait (prog);
1802}
1803
1804/* Unlink a file unless we are debugging.  */
1805
1806static void
1807maybe_unlink (file)
1808     char *file;
1809{
1810  if (!debug)
1811    unlink (file);
1812  else
1813    notice ("[Leaving %s]\n", file);
1814}
1815
1816
1817static long sequence_number = 0;
1818
1819/* Add a name to a linked list.  */
1820
1821static void
1822add_to_list (head_ptr, name)
1823     struct head *head_ptr;
1824     char *name;
1825{
1826  struct id *newid
1827    = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1828  struct id *p;
1829  strcpy (newid->name, name);
1830
1831  if (head_ptr->first)
1832    head_ptr->last->next = newid;
1833  else
1834    head_ptr->first = newid;
1835
1836  /* Check for duplicate symbols.  */
1837  for (p = head_ptr->first;
1838       strcmp (name, p->name) != 0;
1839       p = p->next)
1840    ;
1841  if (p != newid)
1842    {
1843      head_ptr->last->next = 0;
1844      free (newid);
1845      return;
1846    }
1847
1848  newid->sequence = ++sequence_number;
1849  head_ptr->last = newid;
1850  head_ptr->number++;
1851}
1852
1853/* Grab the init priority number from an init function name that
1854   looks like "_GLOBAL_.I.12345.foo".  */
1855
1856static int
1857extract_init_priority (name)
1858     char *name;
1859{
1860  int pos = 0, pri;
1861
1862  while (name[pos] == '_')
1863    ++pos;
1864  pos += 10; /* strlen ("GLOBAL__X_") */
1865
1866  /* Extract init_p number from ctor/dtor name. */
1867  pri = atoi (name + pos);
1868  return pri ? pri : DEFAULT_INIT_PRIORITY;
1869}
1870
1871/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1872   ctors will be run from right to left, dtors from left to right.  */
1873
1874static void
1875sort_ids (head_ptr)
1876     struct head *head_ptr;
1877{
1878  /* id holds the current element to insert.  id_next holds the next
1879     element to insert.  id_ptr iterates through the already sorted elements
1880     looking for the place to insert id.  */
1881  struct id *id, *id_next, **id_ptr;
1882
1883  id = head_ptr->first;
1884
1885  /* We don't have any sorted elements yet.  */
1886  head_ptr->first = NULL;
1887
1888  for (; id; id = id_next)
1889    {
1890      id_next = id->next;
1891      id->sequence = extract_init_priority (id->name);
1892
1893      for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1894	if (*id_ptr == NULL
1895	    /* If the sequence numbers are the same, we put the id from the
1896	       file later on the command line later in the list.  */
1897	    || id->sequence > (*id_ptr)->sequence
1898	    /* Hack: do lexical compare, too.
1899	    || (id->sequence == (*id_ptr)->sequence
1900	        && strcmp (id->name, (*id_ptr)->name) > 0) */
1901	    )
1902	  {
1903	    id->next = *id_ptr;
1904	    *id_ptr = id;
1905	    break;
1906	  }
1907    }
1908
1909  /* Now set the sequence numbers properly so write_c_file works.  */
1910  for (id = head_ptr->first; id; id = id->next)
1911    id->sequence = ++sequence_number;
1912}
1913
1914/* Write: `prefix', the names on list LIST, `suffix'.  */
1915
1916static void
1917write_list (stream, prefix, list)
1918     FILE *stream;
1919     char *prefix;
1920     struct id *list;
1921{
1922  while (list)
1923    {
1924      fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1925      list = list->next;
1926    }
1927}
1928
1929#ifdef COLLECT_EXPORT_LIST
1930/* This function is really used only on AIX, but may be useful.  */
1931static int
1932is_in_list (prefix, list)
1933     char *prefix;
1934     struct id *list;
1935{
1936  while (list)
1937    {
1938      if (!strcmp (prefix, list->name)) return 1;
1939      list = list->next;
1940    }
1941    return 0;
1942}
1943#endif
1944
1945/* Added for debugging purpose.  */
1946#ifdef COLLECT_EXPORT_LIST
1947static void
1948dump_list (stream, prefix, list)
1949     FILE *stream;
1950     char *prefix;
1951     struct id *list;
1952{
1953  while (list)
1954    {
1955      fprintf (stream, "%s%s,\n", prefix, list->name);
1956      list = list->next;
1957    }
1958}
1959#endif
1960
1961#if 0
1962static void
1963dump_prefix_list (stream, prefix, list)
1964     FILE *stream;
1965     char *prefix;
1966     struct prefix_list *list;
1967{
1968  while (list)
1969    {
1970      fprintf (stream, "%s%s,\n", prefix, list->prefix);
1971      list = list->next;
1972    }
1973}
1974#endif
1975
1976static void
1977write_list_with_asm (stream, prefix, list)
1978     FILE *stream;
1979     char *prefix;
1980     struct id *list;
1981{
1982  while (list)
1983    {
1984      fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1985	       prefix, list->sequence, list->name);
1986      list = list->next;
1987    }
1988}
1989
1990/* Write out the constructor and destructor tables statically (for a shared
1991   object), along with the functions to execute them.  */
1992
1993static void
1994write_c_file_stat (stream, name)
1995     FILE *stream;
1996     char *name;
1997{
1998  char *prefix, *p, *q;
1999  int frames = (frame_tables.number > 0);
2000
2001  /* Figure out name of output_file, stripping off .so version.  */
2002  p = rindex (output_file, '/');
2003  if (p == 0)
2004    p = (char *) output_file;
2005  else
2006    p++;
2007  q = p;
2008  while (q)
2009    {
2010      q = index (q,'.');
2011      if (q == 0)
2012	{
2013	  q = p + strlen (p);
2014	  break;
2015	}
2016      else
2017	{
2018	  if (strncmp (q, ".so", 3) == 0)
2019	    {
2020	      q += 3;
2021	      break;
2022	    }
2023	  else
2024	    q++;
2025	}
2026    }
2027  /* q points to null at end of the string (or . of the .so version) */
2028  prefix = xmalloc (q - p + 1);
2029  strncpy (prefix, p, q - p);
2030  prefix[q - p] = 0;
2031  for (q = prefix; *q; q++)
2032    if (!ISALNUM ((unsigned char)*q))
2033      *q = '_';
2034  if (debug)
2035    notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
2036	    output_file, prefix);
2037
2038#define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
2039  initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
2040  sprintf (initname, INIT_NAME_FORMAT, prefix);
2041
2042#define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
2043  fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
2044  sprintf (fininame, FINI_NAME_FORMAT, prefix);
2045
2046  free (prefix);
2047
2048  /* Write the tables as C code  */
2049
2050  fprintf (stream, "static int count;\n");
2051  fprintf (stream, "typedef void entry_pt();\n");
2052  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
2053
2054  if (frames)
2055    {
2056      write_list_with_asm (stream, "extern void *", frame_tables.first);
2057
2058      fprintf (stream, "\tstatic void *frame_table[] = {\n");
2059      write_list (stream, "\t\t&", frame_tables.first);
2060      fprintf (stream, "\t0\n};\n");
2061
2062      /* This must match what's in frame.h.  */
2063      fprintf (stream, "struct object {\n");
2064      fprintf (stream, "  void *pc_begin;\n");
2065      fprintf (stream, "  void *pc_end;\n");
2066      fprintf (stream, "  void *fde_begin;\n");
2067      fprintf (stream, "  void *fde_array;\n");
2068      fprintf (stream, "  __SIZE_TYPE__ count;\n");
2069      fprintf (stream, "  struct object *next;\n");
2070      fprintf (stream, "};\n");
2071
2072      fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
2073      fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2074
2075      fprintf (stream, "static void reg_frame () {\n");
2076      fprintf (stream, "\tstatic struct object ob;\n");
2077      fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2078      fprintf (stream, "\t}\n");
2079
2080      fprintf (stream, "static void dereg_frame () {\n");
2081      fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2082      fprintf (stream, "\t}\n");
2083    }
2084
2085  fprintf (stream, "void %s() {\n", initname);
2086  if (constructors.number > 0 || frames)
2087    {
2088      fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
2089      write_list (stream, "\t\t", constructors.first);
2090      if (frames)
2091	fprintf (stream, "\treg_frame,\n");
2092      fprintf (stream, "\t};\n");
2093      fprintf (stream, "\tentry_pt **p;\n");
2094      fprintf (stream, "\tif (count++ != 0) return;\n");
2095      fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
2096      fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
2097    }
2098  else
2099    fprintf (stream, "\t++count;\n");
2100  fprintf (stream, "}\n");
2101  write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2102  fprintf (stream, "void %s() {\n", fininame);
2103  if (destructors.number > 0 || frames)
2104    {
2105      fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
2106      write_list (stream, "\t\t", destructors.first);
2107      if (frames)
2108	fprintf (stream, "\tdereg_frame,\n");
2109      fprintf (stream, "\t};\n");
2110      fprintf (stream, "\tentry_pt **p;\n");
2111      fprintf (stream, "\tif (--count != 0) return;\n");
2112      fprintf (stream, "\tp = dtors;\n");
2113      fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
2114	       destructors.number + frames);
2115    }
2116  fprintf (stream, "}\n");
2117
2118  if (shared_obj)
2119    {
2120      fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
2121      fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
2122    }
2123}
2124
2125/* Write the constructor/destructor tables.  */
2126
2127#ifndef LD_INIT_SWITCH
2128static void
2129write_c_file_glob (stream, name)
2130     FILE *stream;
2131     char *name;
2132{
2133  /* Write the tables as C code  */
2134
2135  int frames = (frame_tables.number > 0);
2136
2137  fprintf (stream, "typedef void entry_pt();\n\n");
2138
2139  write_list_with_asm (stream, "extern entry_pt ", constructors.first);
2140
2141  if (frames)
2142    {
2143      write_list_with_asm (stream, "extern void *", frame_tables.first);
2144
2145      fprintf (stream, "\tstatic void *frame_table[] = {\n");
2146      write_list (stream, "\t\t&", frame_tables.first);
2147      fprintf (stream, "\t0\n};\n");
2148
2149      /* This must match what's in frame.h.  */
2150      fprintf (stream, "struct object {\n");
2151      fprintf (stream, "  void *pc_begin;\n");
2152      fprintf (stream, "  void *pc_end;\n");
2153      fprintf (stream, "  void *fde_begin;\n");
2154      fprintf (stream, "  void *fde_array;\n");
2155      fprintf (stream, "  __SIZE_TYPE__ count;\n");
2156      fprintf (stream, "  struct object *next;\n");
2157      fprintf (stream, "};\n");
2158
2159      fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
2160      fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2161
2162      fprintf (stream, "static void reg_frame () {\n");
2163      fprintf (stream, "\tstatic struct object ob;\n");
2164      fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2165      fprintf (stream, "\t}\n");
2166
2167      fprintf (stream, "static void dereg_frame () {\n");
2168      fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2169      fprintf (stream, "\t}\n");
2170    }
2171
2172  fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
2173  fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
2174  write_list (stream, "\t", constructors.first);
2175  if (frames)
2176    fprintf (stream, "\treg_frame,\n");
2177  fprintf (stream, "\t0\n};\n\n");
2178
2179  write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2180
2181  fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
2182  fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
2183  write_list (stream, "\t", destructors.first);
2184  if (frames)
2185    fprintf (stream, "\tdereg_frame,\n");
2186  fprintf (stream, "\t0\n};\n\n");
2187
2188  fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
2189  fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
2190}
2191#endif /* ! LD_INIT_SWITCH */
2192
2193static void
2194write_c_file (stream, name)
2195     FILE *stream;
2196     char *name;
2197{
2198  fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
2199#ifndef LD_INIT_SWITCH
2200  if (! shared_obj)
2201    write_c_file_glob (stream, name);
2202  else
2203#endif
2204    write_c_file_stat (stream, name);
2205  fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
2206}
2207
2208#ifdef COLLECT_EXPORT_LIST
2209static void
2210write_export_file (stream)
2211     FILE *stream;
2212{
2213  struct id *list = exports.first;
2214  for (; list; list = list->next)
2215    fprintf (stream, "%s\n", list->name);
2216}
2217
2218static void
2219write_import_file (stream)
2220     FILE *stream;
2221{
2222  struct id *list = imports.first;
2223  fprintf (stream, "%s\n", "#! .");
2224  for (; list; list = list->next)
2225    fprintf (stream, "%s\n", list->name);
2226}
2227#endif
2228
2229#ifdef OBJECT_FORMAT_NONE
2230
2231/* Generic version to scan the name list of the loaded program for
2232   the symbols g++ uses for static constructors and destructors.
2233
2234   The constructor table begins at __CTOR_LIST__ and contains a count
2235   of the number of pointers (or -1 if the constructors are built in a
2236   separate section by the linker), followed by the pointers to the
2237   constructor functions, terminated with a null pointer.  The
2238   destructor table has the same format, and begins at __DTOR_LIST__.  */
2239
2240static void
2241scan_prog_file (prog_name, which_pass)
2242     char *prog_name;
2243     enum pass which_pass;
2244{
2245  void (*int_handler) ();
2246  void (*quit_handler) ();
2247  char *nm_argv[4];
2248  int pid;
2249  int argc = 0;
2250  int pipe_fd[2];
2251  char *p, buf[1024];
2252  FILE *inf;
2253
2254  if (which_pass == PASS_SECOND)
2255    return;
2256
2257  /* If we do not have an `nm', complain.  */
2258  if (nm_file_name == 0)
2259    fatal ("cannot find `nm'");
2260
2261  nm_argv[argc++] = nm_file_name;
2262  if (NM_FLAGS[0] != '\0')
2263    nm_argv[argc++] = NM_FLAGS;
2264
2265  nm_argv[argc++] = prog_name;
2266  nm_argv[argc++] = (char *) 0;
2267
2268  if (pipe (pipe_fd) < 0)
2269    fatal_perror ("pipe");
2270
2271  inf = fdopen (pipe_fd[0], "r");
2272  if (inf == (FILE *) 0)
2273    fatal_perror ("fdopen");
2274
2275  /* Trace if needed.  */
2276  if (vflag)
2277    {
2278      char **p_argv;
2279      char *str;
2280
2281      for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2282	fprintf (stderr, " %s", str);
2283
2284      fprintf (stderr, "\n");
2285    }
2286
2287  fflush (stdout);
2288  fflush (stderr);
2289
2290  /* Spawn child nm on pipe */
2291  pid = vfork ();
2292  if (pid == -1)
2293    fatal_perror (VFORK_STRING);
2294
2295  if (pid == 0)			/* child context */
2296    {
2297      /* setup stdout */
2298      if (dup2 (pipe_fd[1], 1) < 0)
2299	fatal_perror ("dup2 %d 1", pipe_fd[1]);
2300
2301      if (close (pipe_fd[0]) < 0)
2302	fatal_perror ("close %d", pipe_fd[0]);
2303
2304      if (close (pipe_fd[1]) < 0)
2305	fatal_perror ("close %d", pipe_fd[1]);
2306
2307      execv (nm_file_name, nm_argv);
2308      fatal_perror ("execvp %s", nm_file_name);
2309    }
2310
2311  /* Parent context from here on.  */
2312  int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
2313#ifdef SIGQUIT
2314  quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
2315#endif
2316
2317  if (close (pipe_fd[1]) < 0)
2318    fatal_perror ("close %d", pipe_fd[1]);
2319
2320  if (debug)
2321    fprintf (stderr, "\nnm output with constructors/destructors.\n");
2322
2323  /* Read each line of nm output.  */
2324  while (fgets (buf, sizeof buf, inf) != (char *) 0)
2325    {
2326      int ch, ch2;
2327      char *name, *end;
2328
2329      /* If it contains a constructor or destructor name, add the name
2330	 to the appropriate list.  */
2331
2332      for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2333	if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2334	  break;
2335
2336      if (ch != '_')
2337	continue;
2338
2339      name = p;
2340      /* Find the end of the symbol name.
2341	 Do not include `|', because Encore nm can tack that on the end.  */
2342      for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2343	   end++)
2344	continue;
2345
2346
2347      *end = '\0';
2348      switch (is_ctor_dtor (name))
2349	{
2350	case 1:
2351	  if (which_pass != PASS_LIB)
2352	    add_to_list (&constructors, name);
2353	  break;
2354
2355	case 2:
2356	  if (which_pass != PASS_LIB)
2357	    add_to_list (&destructors, name);
2358	  break;
2359
2360	case 3:
2361	  if (which_pass != PASS_LIB)
2362	    fatal ("init function found in object %s", prog_name);
2363#ifndef LD_INIT_SWITCH
2364	  add_to_list (&constructors, name);
2365#endif
2366	  break;
2367
2368	case 4:
2369	  if (which_pass != PASS_LIB)
2370	    fatal ("fini function found in object %s", prog_name);
2371#ifndef LD_FINI_SWITCH
2372	  add_to_list (&destructors, name);
2373#endif
2374	  break;
2375
2376	case 5:
2377	  if (which_pass != PASS_LIB)
2378	    add_to_list (&frame_tables, name);
2379	  break;
2380
2381	default:		/* not a constructor or destructor */
2382	  continue;
2383	}
2384
2385      if (debug)
2386	fprintf (stderr, "\t%s\n", buf);
2387    }
2388
2389  if (debug)
2390    fprintf (stderr, "\n");
2391
2392  if (fclose (inf) != 0)
2393    fatal_perror ("fclose");
2394
2395  do_wait (nm_file_name);
2396
2397  signal (SIGINT,  int_handler);
2398#ifdef SIGQUIT
2399  signal (SIGQUIT, quit_handler);
2400#endif
2401}
2402
2403#if SUNOS4_SHARED_LIBRARIES
2404
2405/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2406   that the output file depends upon and their initialization/finalization
2407   routines, if any.  */
2408
2409#include <a.out.h>
2410#include <fcntl.h>
2411#include <link.h>
2412#include <sys/mman.h>
2413#include <sys/param.h>
2414#include <unistd.h>
2415#include <sys/dir.h>
2416
2417/* pointers to the object file */
2418unsigned object;    	/* address of memory mapped file */
2419unsigned objsize;    	/* size of memory mapped to file */
2420char * code;		/* pointer to code segment */
2421char * data;		/* pointer to data segment */
2422struct nlist *symtab;	/* pointer to symbol table */
2423struct link_dynamic *ld;
2424struct link_dynamic_2 *ld_2;
2425struct head libraries;
2426
2427/* Map the file indicated by NAME into memory and store its address.  */
2428
2429static void
2430mapfile (name)
2431     char *name;
2432{
2433  int fp;
2434  struct stat s;
2435  if ((fp = open (name, O_RDONLY)) == -1)
2436    fatal ("unable to open file '%s'", name);
2437  if (fstat (fp, &s) == -1)
2438    fatal ("unable to stat file '%s'", name);
2439
2440  objsize = s.st_size;
2441  object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2442			    fp, 0);
2443  if (object == -1)
2444    fatal ("unable to mmap file '%s'", name);
2445
2446  close (fp);
2447}
2448
2449/* Helpers for locatelib.  */
2450
2451static char *libname;
2452
2453static int
2454libselect (d)
2455     struct direct *d;
2456{
2457  return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2458}
2459
2460/* If one file has an additional numeric extension past LIBNAME, then put
2461   that one first in the sort.  If both files have additional numeric
2462   extensions, then put the one with the higher number first in the sort.
2463
2464   We must verify that the extension is numeric, because Sun saves the
2465   original versions of patched libraries with a .FCS extension.  Files with
2466   invalid extensions must go last in the sort, so that they will not be used.  */
2467
2468static int
2469libcompare (d1, d2)
2470     struct direct **d1, **d2;
2471{
2472  int i1, i2 = strlen (libname);
2473  char *e1 = (*d1)->d_name + i2;
2474  char *e2 = (*d2)->d_name + i2;
2475
2476  while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2477	 && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2478    {
2479      ++e1;
2480      ++e2;
2481      i1 = strtol (e1, &e1, 10);
2482      i2 = strtol (e2, &e2, 10);
2483      if (i1 != i2)
2484	return i1 - i2;
2485    }
2486
2487  if (*e1)
2488    {
2489      /* It has a valid numeric extension, prefer this one.  */
2490      if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2491	return 1;
2492      /* It has a invalid numeric extension, must prefer the other one.  */
2493      else
2494	return -1;
2495    }
2496  else if (*e2)
2497    {
2498      /* It has a valid numeric extension, prefer this one.  */
2499      if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2500	return -1;
2501      /* It has a invalid numeric extension, must prefer the other one.  */
2502      else
2503	return 1;
2504    }
2505  else
2506    return 0;
2507}
2508
2509/* Given the name NAME of a dynamic dependency, find its pathname and add
2510   it to the list of libraries.  */
2511
2512static void
2513locatelib (name)
2514     char *name;
2515{
2516  static char **l;
2517  static int cnt;
2518  char buf[MAXPATHLEN];
2519  char *p, *q;
2520  char **pp;
2521
2522  if (l == 0)
2523    {
2524      char *ld_rules;
2525      char *ldr = 0;
2526      /* counting elements in array, need 1 extra for null */
2527      cnt = 1;
2528      ld_rules = (char *) (ld_2->ld_rules + code);
2529      if (ld_rules)
2530	{
2531	  cnt++;
2532	  for (; *ld_rules != 0; ld_rules++)
2533	    if (*ld_rules == ':')
2534	      cnt++;
2535	  ld_rules = (char *) (ld_2->ld_rules + code);
2536	  ldr = (char *) malloc (strlen (ld_rules) + 1);
2537	  strcpy (ldr, ld_rules);
2538	}
2539      p = getenv ("LD_LIBRARY_PATH");
2540      q = 0;
2541      if (p)
2542	{
2543	  cnt++;
2544	  for (q = p ; *q != 0; q++)
2545	    if (*q == ':')
2546	      cnt++;
2547	  q = (char *) malloc (strlen (p) + 1);
2548	  strcpy (q, p);
2549	}
2550      l = (char **) malloc ((cnt + 3) * sizeof (char *));
2551      pp = l;
2552      if (ldr)
2553	{
2554	  *pp++ = ldr;
2555	  for (; *ldr != 0; ldr++)
2556	    if (*ldr == ':')
2557	      {
2558		*ldr++ = 0;
2559		*pp++ = ldr;
2560	      }
2561	}
2562      if (q)
2563	{
2564	  *pp++ = q;
2565	  for (; *q != 0; q++)
2566	    if (*q == ':')
2567	      {
2568		*q++ = 0;
2569		*pp++ = q;
2570	      }
2571	}
2572      /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2573      *pp++ = "/lib";
2574      *pp++ = "/usr/lib";
2575      *pp++ = "/usr/local/lib";
2576      *pp = 0;
2577    }
2578  libname = name;
2579  for (pp = l; *pp != 0 ; pp++)
2580    {
2581      struct direct **namelist;
2582      int entries;
2583      if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2584	{
2585	  sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2586	  add_to_list (&libraries, buf);
2587	  if (debug)
2588	    fprintf (stderr, "%s\n", buf);
2589	  break;
2590	}
2591    }
2592  if (*pp == 0)
2593    {
2594      if (debug)
2595	notice ("not found\n");
2596      else
2597	fatal ("dynamic dependency %s not found", name);
2598    }
2599}
2600
2601/* Scan the _DYNAMIC structure of the output file to find shared libraries
2602   that it depends upon and any constructors or destructors they contain.  */
2603
2604static void
2605scan_libraries (prog_name)
2606     char *prog_name;
2607{
2608  struct exec *header;
2609  char *base;
2610  struct link_object *lo;
2611  char buff[MAXPATHLEN];
2612  struct id *list;
2613
2614  mapfile (prog_name);
2615  header = (struct exec *)object;
2616  if (N_BADMAG (*header))
2617    fatal ("bad magic number in file '%s'", prog_name);
2618  if (header->a_dynamic == 0)
2619    return;
2620
2621  code = (char *) (N_TXTOFF (*header) + (long) header);
2622  data = (char *) (N_DATOFF (*header) + (long) header);
2623  symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2624
2625  if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2626    {
2627      /* shared object */
2628      ld = (struct link_dynamic *) (symtab->n_value + code);
2629      base = code;
2630    }
2631  else
2632    {
2633      /* executable */
2634      ld = (struct link_dynamic *) data;
2635      base = code-PAGSIZ;
2636    }
2637
2638  if (debug)
2639    notice ("dynamic dependencies.\n");
2640
2641  ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2642  for (lo = (struct link_object *) ld_2->ld_need; lo;
2643       lo = (struct link_object *) lo->lo_next)
2644    {
2645      char *name;
2646      lo = (struct link_object *) ((long) lo + code);
2647      name = (char *) (code + lo->lo_name);
2648      if (lo->lo_library)
2649	{
2650	  if (debug)
2651	    fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2652	  sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2653	  locatelib (buff);
2654	}
2655      else
2656	{
2657	  if (debug)
2658	    fprintf (stderr, "\t%s\n", name);
2659	  add_to_list (&libraries, name);
2660	}
2661    }
2662
2663  if (debug)
2664    fprintf (stderr, "\n");
2665
2666  /* now iterate through the library list adding their symbols to
2667     the list.  */
2668  for (list = libraries.first; list; list = list->next)
2669    scan_prog_file (list->name, PASS_LIB);
2670}
2671
2672#else  /* SUNOS4_SHARED_LIBRARIES */
2673#ifdef LDD_SUFFIX
2674
2675/* Use the List Dynamic Dependencies program to find shared libraries that
2676   the output file depends upon and their initialization/finalization
2677   routines, if any.  */
2678
2679static void
2680scan_libraries (prog_name)
2681     char *prog_name;
2682{
2683  static struct head libraries;		/* list of shared libraries found */
2684  struct id *list;
2685  void (*int_handler) ();
2686  void (*quit_handler) ();
2687  char *ldd_argv[4];
2688  int pid;
2689  int argc = 0;
2690  int pipe_fd[2];
2691  char buf[1024];
2692  FILE *inf;
2693
2694  /* If we do not have an `ldd', complain.  */
2695  if (ldd_file_name == 0)
2696    {
2697      error ("cannot find `ldd'");
2698      return;
2699    }
2700
2701  ldd_argv[argc++] = ldd_file_name;
2702  ldd_argv[argc++] = prog_name;
2703  ldd_argv[argc++] = (char *) 0;
2704
2705  if (pipe (pipe_fd) < 0)
2706    fatal_perror ("pipe");
2707
2708  inf = fdopen (pipe_fd[0], "r");
2709  if (inf == (FILE *) 0)
2710    fatal_perror ("fdopen");
2711
2712  /* Trace if needed.  */
2713  if (vflag)
2714    {
2715      char **p_argv;
2716      char *str;
2717
2718      for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2719	fprintf (stderr, " %s", str);
2720
2721      fprintf (stderr, "\n");
2722    }
2723
2724  fflush (stdout);
2725  fflush (stderr);
2726
2727  /* Spawn child ldd on pipe */
2728  pid = vfork ();
2729  if (pid == -1)
2730    fatal_perror (VFORK_STRING);
2731
2732  if (pid == 0)			/* child context */
2733    {
2734      /* setup stdout */
2735      if (dup2 (pipe_fd[1], 1) < 0)
2736	fatal_perror ("dup2 %d 1", pipe_fd[1]);
2737
2738      if (close (pipe_fd[0]) < 0)
2739	fatal_perror ("close %d", pipe_fd[0]);
2740
2741      if (close (pipe_fd[1]) < 0)
2742	fatal_perror ("close %d", pipe_fd[1]);
2743
2744      execv (ldd_file_name, ldd_argv);
2745      fatal_perror ("execv %s", ldd_file_name);
2746    }
2747
2748  /* Parent context from here on.  */
2749  int_handler  = (void (*) ()) signal (SIGINT,  SIG_IGN);
2750#ifdef SIGQUIT
2751  quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
2752#endif
2753
2754  if (close (pipe_fd[1]) < 0)
2755    fatal_perror ("close %d", pipe_fd[1]);
2756
2757  if (debug)
2758    notice ("\nldd output with constructors/destructors.\n");
2759
2760  /* Read each line of ldd output.  */
2761  while (fgets (buf, sizeof buf, inf) != (char *) 0)
2762    {
2763      int ch, ch2;
2764      char *name, *end, *p = buf;
2765
2766      /* Extract names of libraries and add to list.  */
2767      PARSE_LDD_OUTPUT (p);
2768      if (p == 0)
2769	continue;
2770
2771      name = p;
2772      if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2773	fatal ("dynamic dependency %s not found", buf);
2774
2775      /* Find the end of the symbol name.  */
2776      for (end = p;
2777	   (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2778	   end++)
2779	continue;
2780      *end = '\0';
2781
2782      if (access (name, R_OK) == 0)
2783        add_to_list (&libraries, name);
2784      else
2785	fatal ("unable to open dynamic dependency '%s'", buf);
2786
2787      if (debug)
2788	fprintf (stderr, "\t%s\n", buf);
2789    }
2790  if (debug)
2791    fprintf (stderr, "\n");
2792
2793  if (fclose (inf) != 0)
2794    fatal_perror ("fclose");
2795
2796  do_wait (ldd_file_name);
2797
2798  signal (SIGINT,  int_handler);
2799#ifdef SIGQUIT
2800  signal (SIGQUIT, quit_handler);
2801#endif
2802
2803  /* now iterate through the library list adding their symbols to
2804     the list.  */
2805  for (list = libraries.first; list; list = list->next)
2806    scan_prog_file (list->name, PASS_LIB);
2807}
2808
2809#endif /* LDD_SUFFIX */
2810#endif /* SUNOS4_SHARED_LIBRARIES */
2811
2812#endif /* OBJECT_FORMAT_NONE */
2813
2814
2815/*
2816 * COFF specific stuff.
2817 */
2818
2819#ifdef OBJECT_FORMAT_COFF
2820
2821#if defined(EXTENDED_COFF)
2822#   define GCC_SYMBOLS(X)	(SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2823#   define GCC_SYMENT		SYMR
2824#   define GCC_OK_SYMBOL(X)	((X).st == stProc || (X).st == stGlobal)
2825#   define GCC_SYMINC(X)	(1)
2826#   define GCC_SYMZERO(X)	(SYMHEADER(X).isymMax)
2827#   define GCC_CHECK_HDR(X)	(PSYMTAB(X) != 0)
2828#else
2829#   define GCC_SYMBOLS(X)	(HEADER(ldptr).f_nsyms)
2830#   define GCC_SYMENT		SYMENT
2831#   define GCC_OK_SYMBOL(X) \
2832     (((X).n_sclass == C_EXT) && \
2833      ((X).n_scnum > N_UNDEF) && \
2834      (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
2835       ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
2836#   define GCC_UNDEF_SYMBOL(X) \
2837     (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2838#   define GCC_SYMINC(X)	((X).n_numaux+1)
2839#   define GCC_SYMZERO(X)	0
2840#   define GCC_CHECK_HDR(X) \
2841     ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2842      || (HEADER (X).f_magic == 0757 && aix64_flag))
2843#endif
2844
2845extern char *ldgetname ();
2846
2847/* COFF version to scan the name list of the loaded program for
2848   the symbols g++ uses for static constructors and destructors.
2849
2850   The constructor table begins at __CTOR_LIST__ and contains a count
2851   of the number of pointers (or -1 if the constructors are built in a
2852   separate section by the linker), followed by the pointers to the
2853   constructor functions, terminated with a null pointer.  The
2854   destructor table has the same format, and begins at __DTOR_LIST__.  */
2855
2856static void
2857scan_prog_file (prog_name, which_pass)
2858     char *prog_name;
2859     enum pass which_pass;
2860{
2861  LDFILE *ldptr = NULL;
2862  int sym_index, sym_count;
2863  int is_shared = 0;
2864#ifdef COLLECT_EXPORT_LIST
2865  /* Should we generate an import list for given prog_name?  */
2866  int import_flag = (which_pass == PASS_OBJ ? 0 : use_import_list (prog_name));
2867#endif
2868
2869  if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2870    return;
2871
2872#ifdef COLLECT_EXPORT_LIST
2873  /* We do not need scanning for some standard C libraries.  */
2874  if (which_pass == PASS_FIRST && ignore_library (prog_name))
2875    return;
2876
2877  /* On AIX we have a loop, because there is not much difference
2878     between an object and an archive. This trick allows us to
2879     eliminate scan_libraries() function.  */
2880  do
2881    {
2882#endif
2883      if ((ldptr = ldopen (prog_name, ldptr)) != NULL)
2884	{
2885	  if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2886	    fatal ("%s: not a COFF file", prog_name);
2887
2888	  if (GCC_CHECK_HDR (ldptr))
2889	    {
2890	      sym_count = GCC_SYMBOLS (ldptr);
2891	      sym_index = GCC_SYMZERO (ldptr);
2892
2893#ifdef COLLECT_EXPORT_LIST
2894	      /* Is current archive member a shared object?  */
2895	      is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2896#endif
2897
2898	      while (sym_index < sym_count)
2899		{
2900		  GCC_SYMENT symbol;
2901
2902		  if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2903		    break;
2904		  sym_index += GCC_SYMINC (symbol);
2905
2906		  if (GCC_OK_SYMBOL (symbol))
2907		    {
2908		      char *name;
2909
2910		      if ((name = ldgetname (ldptr, &symbol)) == NULL)
2911			continue;		/* should never happen */
2912
2913#ifdef XCOFF_DEBUGGING_INFO
2914		      /* All AIX function names have a duplicate entry
2915			 beginning with a dot.  */
2916		      if (*name == '.')
2917			++name;
2918#endif
2919
2920		      switch (is_ctor_dtor (name))
2921			{
2922			case 1:
2923			  if (! is_shared) add_to_list (&constructors, name);
2924#ifdef COLLECT_EXPORT_LIST
2925			  if (which_pass == PASS_OBJ)
2926			    add_to_list (&exports, name);
2927			  /* If this symbol was undefined and we are building
2928			     an import list, we should add a symbol to this
2929			     list.  */
2930			  else
2931			    if (import_flag
2932				&& is_in_list (name, undefined.first))
2933			      add_to_list (&imports, name);
2934#endif
2935			  break;
2936
2937			case 2:
2938			  if (! is_shared) add_to_list (&destructors, name);
2939#ifdef COLLECT_EXPORT_LIST
2940			  if (which_pass == PASS_OBJ)
2941			    add_to_list (&exports, name);
2942			  /* If this symbol was undefined and we are building
2943			     an import list, we should add a symbol to this
2944			     list.  */
2945			  else
2946			    if (import_flag
2947				&& is_in_list (name, undefined.first))
2948			      add_to_list (&imports, name);
2949#endif
2950			  break;
2951
2952#ifdef COLLECT_EXPORT_LIST
2953			case 3:
2954			  if (is_shared)
2955			    add_to_list (&constructors, name);
2956			  break;
2957
2958			case 4:
2959			  if (is_shared)
2960			    add_to_list (&destructors, name);
2961			  break;
2962#endif
2963
2964			case 5:
2965			  if (! is_shared)
2966			    add_to_list (&frame_tables, name);
2967			  break;
2968
2969			default:	/* not a constructor or destructor */
2970#ifdef COLLECT_EXPORT_LIST
2971			  /* If we are building a shared object on AIX we need
2972			     to explicitly export all global symbols or add
2973			     them to import list.  */
2974			  if (shared_obj)
2975			    {
2976			      if (which_pass == PASS_OBJ && (! export_flag))
2977				add_to_list (&exports, name);
2978			      else if (! is_shared && which_pass == PASS_FIRST
2979				       && import_flag
2980				       && is_in_list(name, undefined.first))
2981				add_to_list (&imports, name);
2982			    }
2983#endif
2984			  continue;
2985			}
2986
2987#if !defined(EXTENDED_COFF)
2988		      if (debug)
2989			fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2990				 symbol.n_scnum, symbol.n_sclass,
2991				 (symbol.n_type ? "0" : ""), symbol.n_type,
2992				 name);
2993#else
2994		      if (debug)
2995			fprintf (stderr,
2996				 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2997				 symbol.iss, (long) symbol.value, symbol.index, name);
2998#endif
2999		    }
3000#ifdef COLLECT_EXPORT_LIST
3001		  /* If we are building a shared object we should collect
3002		     information about undefined symbols for later
3003		     import list generation.  */
3004		  else if (shared_obj && GCC_UNDEF_SYMBOL (symbol))
3005		    {
3006		      char *name;
3007
3008		      if ((name = ldgetname (ldptr, &symbol)) == NULL)
3009			continue;		/* should never happen */
3010
3011		      /* All AIX function names have a duplicate entry
3012			 beginning with a dot.  */
3013		      if (*name == '.')
3014			++name;
3015		      add_to_list (&undefined, name);
3016		    }
3017#endif
3018		}
3019	    }
3020#ifdef COLLECT_EXPORT_LIST
3021	  else
3022	    {
3023	      /* If archive contains both 32-bit and 64-bit objects,
3024		 we want to skip objects in other mode so mismatch normal.  */
3025	      if (debug)
3026		fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
3027			 prog_name, HEADER (ldptr).f_magic, aix64_flag);
3028	    }
3029#endif
3030	}
3031      else
3032	{
3033	  fatal ("%s: cannot open as COFF file", prog_name);
3034	}
3035#ifdef COLLECT_EXPORT_LIST
3036      /* On AIX loop continues while there are more members in archive.  */
3037    }
3038  while (ldclose (ldptr) == FAILURE);
3039#else
3040  /* Otherwise we simply close ldptr.  */
3041  (void) ldclose(ldptr);
3042#endif
3043}
3044
3045
3046#ifdef COLLECT_EXPORT_LIST
3047
3048/* Never generate import list (gcc-2.95 branch).  */
3049static int
3050use_import_list (prog_name)
3051     char *prog_name;
3052{
3053  return 0;
3054}
3055
3056/* Given a library name without "lib" prefix, this function
3057   returns a full library name including a path.  */
3058static char *
3059resolve_lib_name (name)
3060     char *name;
3061{
3062  char *lib_buf;
3063  int i, j, l = 0;
3064
3065  for (i = 0; libpaths[i]; i++)
3066    if (libpaths[i]->max_len > l)
3067      l = libpaths[i]->max_len;
3068
3069  lib_buf = xmalloc (l + strlen(name) + 10);
3070
3071  for (i = 0; libpaths[i]; i++)
3072    {
3073      struct prefix_list *list = libpaths[i]->plist;
3074      for (; list; list = list->next)
3075	{
3076	  for (j = 0; libexts[j]; j++)
3077	    {
3078              /* The following lines are needed because path_prefix list
3079                 may contain directories both with trailing '/' and
3080                 without it.  */
3081              char *p = "";
3082              if (list->prefix[strlen(list->prefix)-1] != '/')
3083                p = "/";
3084       	      sprintf (lib_buf, "%s%slib%s.%s",
3085		       list->prefix, p, name, libexts[j]);
3086if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
3087	      if (file_exists (lib_buf))
3088		{
3089if (debug) fprintf (stderr, "found: %s\n", lib_buf);
3090		  return (lib_buf);
3091		}
3092	    }
3093	}
3094    }
3095  if (debug)
3096    fprintf (stderr, "not found\n");
3097  else
3098    fatal ("Library lib%s not found", name);
3099  return (NULL);
3100}
3101
3102/* Array of standard AIX libraries which should not
3103   be scanned for ctors/dtors.  */
3104static char* aix_std_libs[] = {
3105  "/unix",
3106  "/lib/libc.a",
3107  "/lib/libc_r.a",
3108  "/usr/lib/libc.a",
3109  "/usr/lib/libc_r.a",
3110  "/usr/lib/threads/libc.a",
3111  "/usr/ccs/lib/libc.a",
3112  "/usr/ccs/lib/libc_r.a",
3113  NULL
3114};
3115
3116/* This function checks the filename and returns 1
3117   if this name matches the location of a standard AIX library. */
3118static int
3119ignore_library (name)
3120     char *name;
3121{
3122  char **p = &aix_std_libs[0];
3123  while (*p++ != NULL)
3124    if (! strcmp (name, *p)) return 1;
3125  return 0;
3126}
3127
3128#endif
3129
3130#endif /* OBJECT_FORMAT_COFF */
3131
3132
3133/*
3134 * OSF/rose specific stuff.
3135 */
3136
3137#ifdef OBJECT_FORMAT_ROSE
3138
3139/* Union of the various load commands */
3140
3141typedef union load_union
3142{
3143  ldc_header_t			hdr;	/* common header */
3144  load_cmd_map_command_t	map;	/* map indexing other load cmds */
3145  interpreter_command_t		iprtr;	/* interpreter pathname */
3146  strings_command_t		str;	/* load commands strings section */
3147  region_command_t		region;	/* region load command */
3148  reloc_command_t		reloc;	/* relocation section */
3149  package_command_t		pkg;	/* package load command */
3150  symbols_command_t		sym;	/* symbol sections */
3151  entry_command_t		ent;	/* program start section */
3152  gen_info_command_t		info;	/* object information */
3153  func_table_command_t		func;	/* function constructors/destructors */
3154} load_union_t;
3155
3156/* Structure to point to load command and data section in memory.  */
3157
3158typedef struct load_all
3159{
3160  load_union_t *load;			/* load command */
3161  char *section;			/* pointer to section */
3162} load_all_t;
3163
3164/* Structure to contain information about a file mapped into memory.  */
3165
3166struct file_info
3167{
3168  char *start;				/* start of map */
3169  char *name;				/* filename */
3170  long	size;				/* size of the file */
3171  long  rounded_size;			/* size rounded to page boundary */
3172  int	fd;				/* file descriptor */
3173  int	rw;				/* != 0 if opened read/write */
3174  int	use_mmap;			/* != 0 if mmap'ed */
3175};
3176
3177extern int decode_mach_o_hdr ();
3178extern int encode_mach_o_hdr ();
3179
3180static void add_func_table	PROTO((mo_header_t *, load_all_t *,
3181				       symbol_info_t *, int));
3182static void print_header	PROTO((mo_header_t *));
3183static void print_load_command	PROTO((load_union_t *, size_t, int));
3184static void bad_header		PROTO((int));
3185static struct file_info	*read_file  PROTO((char *, int, int));
3186static void end_file		PROTO((struct file_info *));
3187
3188/* OSF/rose specific version to scan the name list of the loaded
3189   program for the symbols g++ uses for static constructors and
3190   destructors.
3191
3192   The constructor table begins at __CTOR_LIST__ and contains a count
3193   of the number of pointers (or -1 if the constructors are built in a
3194   separate section by the linker), followed by the pointers to the
3195   constructor functions, terminated with a null pointer.  The
3196   destructor table has the same format, and begins at __DTOR_LIST__.  */
3197
3198static void
3199scan_prog_file (prog_name, which_pass)
3200     char *prog_name;
3201     enum pass which_pass;
3202{
3203  char *obj;
3204  mo_header_t hdr;
3205  load_all_t *load_array;
3206  load_all_t *load_end;
3207  load_all_t *load_cmd;
3208  int symbol_load_cmds;
3209  off_t offset;
3210  int i;
3211  int num_syms;
3212  int status;
3213  char *str_sect;
3214  struct file_info *obj_file;
3215  int prog_fd;
3216  mo_lcid_t cmd_strings	  = -1;
3217  symbol_info_t *main_sym = 0;
3218  int rw		  = (which_pass != PASS_FIRST);
3219
3220  prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3221  if (prog_fd < 0)
3222    fatal_perror ("open %s", prog_name);
3223
3224  obj_file = read_file (prog_name, prog_fd, rw);
3225  obj = obj_file->start;
3226
3227  status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3228  if (status != MO_HDR_CONV_SUCCESS)
3229    bad_header (status);
3230
3231
3232  /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
3233     since the hardware will automatically swap bytes for us on loading little endian
3234     integers.  */
3235
3236#ifndef CROSS_COMPILE
3237  if (hdr.moh_magic != MOH_MAGIC_MSB
3238      || hdr.moh_header_version != MOH_HEADER_VERSION
3239      || hdr.moh_byte_order != OUR_BYTE_ORDER
3240      || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3241      || hdr.moh_cpu_type != OUR_CPU_TYPE
3242      || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3243      || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3244    {
3245      fatal ("incompatibilities between object file & expected values");
3246    }
3247#endif
3248
3249  if (debug)
3250    print_header (&hdr);
3251
3252  offset = hdr.moh_first_cmd_off;
3253  load_end = load_array
3254    = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3255
3256  /* Build array of load commands, calculating the offsets */
3257  for (i = 0; i < hdr.moh_n_load_cmds; i++)
3258    {
3259      load_union_t *load_hdr;		/* load command header */
3260
3261      load_cmd = load_end++;
3262      load_hdr = (load_union_t *) (obj + offset);
3263
3264      /* If modifying the program file, copy the header.  */
3265      if (rw)
3266	{
3267	  load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3268	  bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
3269	  load_hdr = ptr;
3270
3271	  /* null out old command map, because we will rewrite at the end.  */
3272	  if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3273	    {
3274	      cmd_strings = ptr->map.lcm_ld_cmd_strings;
3275	      ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3276	    }
3277	}
3278
3279      load_cmd->load = load_hdr;
3280      if (load_hdr->hdr.ldci_section_off > 0)
3281	load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3282
3283      if (debug)
3284	print_load_command (load_hdr, offset, i);
3285
3286      offset += load_hdr->hdr.ldci_cmd_size;
3287    }
3288
3289  /* If the last command is the load command map and is not undefined,
3290     decrement the count of load commands.  */
3291  if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3292    {
3293      load_end--;
3294      hdr.moh_n_load_cmds--;
3295    }
3296
3297  /* Go through and process each symbol table section.  */
3298  symbol_load_cmds = 0;
3299  for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3300    {
3301      load_union_t *load_hdr = load_cmd->load;
3302
3303      if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3304	{
3305	  symbol_load_cmds++;
3306
3307	  if (debug)
3308	    {
3309	      char *kind = "unknown";
3310
3311	      switch (load_hdr->sym.symc_kind)
3312		{
3313		case SYMC_IMPORTS:	   kind = "imports"; break;
3314		case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3315		case SYMC_STABS:	   kind = "stabs";   break;
3316		}
3317
3318	      notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3319		      symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3320	    }
3321
3322	  if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3323	    continue;
3324
3325	  str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3326	  if (str_sect == (char *) 0)
3327	    fatal ("string section missing");
3328
3329	  if (load_cmd->section == (char *) 0)
3330	    fatal ("section pointer missing");
3331
3332	  num_syms = load_hdr->sym.symc_nentries;
3333	  for (i = 0; i < num_syms; i++)
3334	    {
3335	      symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3336	      char *name = sym->si_name.symbol_name + str_sect;
3337
3338	      if (name[0] != '_')
3339		continue;
3340
3341	      if (rw)
3342		{
3343		  char *n = name + strlen (name) - strlen (NAME__MAIN);
3344
3345		  if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3346		    continue;
3347		  while (n != name)
3348		    if (*--n != '_')
3349		      continue;
3350
3351		  main_sym = sym;
3352		}
3353	      else
3354		{
3355		  switch (is_ctor_dtor (name))
3356		    {
3357		    case 1:
3358		      add_to_list (&constructors, name);
3359		      break;
3360
3361		    case 2:
3362		      add_to_list (&destructors, name);
3363		      break;
3364
3365		    default:	/* not a constructor or destructor */
3366		      continue;
3367		    }
3368		}
3369
3370	      if (debug)
3371		fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3372			 sym->si_type, sym->si_sc_type, sym->si_flags, name);
3373	    }
3374	}
3375    }
3376
3377  if (symbol_load_cmds == 0)
3378    fatal ("no symbol table found");
3379
3380  /* Update the program file now, rewrite header and load commands.  At present,
3381     we assume that there is enough space after the last load command to insert
3382     one more.  Since the first section written out is page aligned, and the
3383     number of load commands is small, this is ok for the present.  */
3384
3385  if (rw)
3386    {
3387      load_union_t *load_map;
3388      size_t size;
3389
3390      if (cmd_strings == -1)
3391	fatal ("no cmd_strings found");
3392
3393      /* Add __main to initializer list.
3394	 If we are building a program instead of a shared library, do not
3395	 do anything, since in the current version, you cannot do mallocs
3396	 and such in the constructors.  */
3397
3398      if (main_sym != (symbol_info_t *) 0
3399	  && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3400	add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3401
3402      if (debug)
3403	notice ("\nUpdating header and load commands.\n\n");
3404
3405      hdr.moh_n_load_cmds++;
3406      size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3407
3408      /* Create new load command map.  */
3409      if (debug)
3410	notice ("load command map, %d cmds, new size %ld.\n",
3411		(int) hdr.moh_n_load_cmds, (long) size);
3412
3413      load_map = (load_union_t *) xcalloc (1, size);
3414      load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3415      load_map->map.ldc_header.ldci_cmd_size = size;
3416      load_map->map.lcm_ld_cmd_strings = cmd_strings;
3417      load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3418      load_array[hdr.moh_n_load_cmds-1].load = load_map;
3419
3420      offset = hdr.moh_first_cmd_off;
3421      for (i = 0; i < hdr.moh_n_load_cmds; i++)
3422	{
3423	  load_map->map.lcm_map[i] = offset;
3424	  if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3425	    hdr.moh_load_map_cmd_off = offset;
3426
3427	  offset += load_array[i].load->hdr.ldci_cmd_size;
3428	}
3429
3430      hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3431
3432      if (debug)
3433	print_header (&hdr);
3434
3435      /* Write header */
3436      status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3437      if (status != MO_HDR_CONV_SUCCESS)
3438	bad_header (status);
3439
3440      if (debug)
3441	notice ("writing load commands.\n\n");
3442
3443      /* Write load commands */
3444      offset = hdr.moh_first_cmd_off;
3445      for (i = 0; i < hdr.moh_n_load_cmds; i++)
3446	{
3447	  load_union_t *load_hdr = load_array[i].load;
3448	  size_t size = load_hdr->hdr.ldci_cmd_size;
3449
3450	  if (debug)
3451	    print_load_command (load_hdr, offset, i);
3452
3453	  bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3454	  offset += size;
3455	}
3456    }
3457
3458  end_file (obj_file);
3459
3460  if (close (prog_fd))
3461    fatal_perror ("close %s", prog_name);
3462
3463  if (debug)
3464    fprintf (stderr, "\n");
3465}
3466
3467
3468/* Add a function table to the load commands to call a function
3469   on initiation or termination of the process.  */
3470
3471static void
3472add_func_table (hdr_p, load_array, sym, type)
3473     mo_header_t *hdr_p;		/* pointer to global header */
3474     load_all_t *load_array;		/* array of ptrs to load cmds */
3475     symbol_info_t *sym;		/* pointer to symbol entry */
3476     int type;				/* fntc_type value */
3477{
3478  /* Add a new load command.  */
3479  int num_cmds = ++hdr_p->moh_n_load_cmds;
3480  int load_index = num_cmds - 1;
3481  size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3482  load_union_t *ptr = xcalloc (1, size);
3483  load_all_t *load_cmd;
3484  int i;
3485
3486  /* Set the unresolved address bit in the header to force the loader to be
3487     used, since kernel exec does not call the initialization functions.  */
3488  hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3489
3490  load_cmd = &load_array[load_index];
3491  load_cmd->load = ptr;
3492  load_cmd->section = (char *) 0;
3493
3494  /* Fill in func table load command.  */
3495  ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3496  ptr->func.ldc_header.ldci_cmd_size = size;
3497  ptr->func.ldc_header.ldci_section_off = 0;
3498  ptr->func.ldc_header.ldci_section_len = 0;
3499  ptr->func.fntc_type = type;
3500  ptr->func.fntc_nentries = 1;
3501
3502  /* copy address, turn it from abs. address to (region,offset) if necessary.  */
3503  /* Is the symbol already expressed as (region, offset)?  */
3504  if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3505    {
3506      ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3507      ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3508    }
3509
3510  /* If not, figure out which region it's in.  */
3511  else
3512    {
3513      mo_vm_addr_t addr = sym->si_value.abs_val;
3514      int found = 0;
3515
3516      for (i = 0; i < load_index; i++)
3517	{
3518	  if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3519	    {
3520	      region_command_t *region_ptr = &load_array[i].load->region;
3521
3522	      if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3523		  && addr >= region_ptr->regc_addr.vm_addr
3524		  && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3525		{
3526		  ptr->func.fntc_entry_loc[0].adr_lcid = i;
3527		  ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3528		  found++;
3529		  break;
3530		}
3531	    }
3532	}
3533
3534      if (!found)
3535	fatal ("could not convert 0x%l.8x into a region", addr);
3536    }
3537
3538  if (debug)
3539    notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3540	    type == FNTC_INITIALIZATION ? "init" : "term",
3541	    (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3542	    (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3543	    (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3544
3545}
3546
3547
3548/* Print the global header for an OSF/rose object.  */
3549
3550static void
3551print_header (hdr_ptr)
3552     mo_header_t *hdr_ptr;
3553{
3554  fprintf (stderr, "\nglobal header:\n");
3555  fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
3556  fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
3557  fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
3558  fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
3559  fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
3560  fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
3561  fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
3562  fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
3563  fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3564  fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
3565  fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3566  fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3567  fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3568  fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3569  fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
3570
3571  if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3572    fprintf (stderr, ", relocatable");
3573
3574  if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3575    fprintf (stderr, ", linkable");
3576
3577  if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3578    fprintf (stderr, ", execable");
3579
3580  if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3581    fprintf (stderr, ", executable");
3582
3583  if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3584    fprintf (stderr, ", unresolved");
3585
3586  fprintf (stderr, "\n\n");
3587  return;
3588}
3589
3590
3591/* Print a short summary of a load command.  */
3592
3593static void
3594print_load_command (load_hdr, offset, number)
3595     load_union_t *load_hdr;
3596     size_t offset;
3597     int number;
3598{
3599  mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3600  char *type_str = (char *) 0;
3601
3602  switch (type)
3603    {
3604    case LDC_UNDEFINED:   type_str = "UNDEFINED";	break;
3605    case LDC_CMD_MAP:	  type_str = "CMD_MAP";		break;
3606    case LDC_INTERPRETER: type_str = "INTERPRETER";	break;
3607    case LDC_STRINGS:	  type_str = "STRINGS";		break;
3608    case LDC_REGION:	  type_str = "REGION";		break;
3609    case LDC_RELOC:	  type_str = "RELOC";		break;
3610    case LDC_PACKAGE:	  type_str = "PACKAGE";		break;
3611    case LDC_SYMBOLS:	  type_str = "SYMBOLS";		break;
3612    case LDC_ENTRY:	  type_str = "ENTRY";		break;
3613    case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";	break;
3614    case LDC_GEN_INFO:	  type_str = "GEN_INFO";	break;
3615    }
3616
3617  fprintf (stderr,
3618	   "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3619	   number,
3620	   (long) load_hdr->hdr.ldci_cmd_size,
3621	   (long) offset,
3622	   (long) load_hdr->hdr.ldci_section_off,
3623	   (long) load_hdr->hdr.ldci_section_len);
3624
3625  if (type_str == (char *) 0)
3626    fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3627
3628  else if (type != LDC_REGION)
3629    fprintf (stderr, ", ty: %s\n", type_str);
3630
3631  else
3632    {
3633      char *region = "";
3634      switch (load_hdr->region.regc_usage_type)
3635	{
3636	case REG_TEXT_T:	region = ", .text";	break;
3637	case REG_DATA_T:	region = ", .data";	break;
3638	case REG_BSS_T:		region = ", .bss";	break;
3639	case REG_GLUE_T:	region = ", .glue";	break;
3640#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3641	case REG_RDATA_T:	region = ", .rdata";	break;
3642	case REG_SDATA_T:	region = ", .sdata";	break;
3643	case REG_SBSS_T:	region = ", .sbss";	break;
3644#endif
3645	}
3646
3647      fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3648	       type_str,
3649	       (long) load_hdr->region.regc_vm_addr,
3650	       (long) load_hdr->region.regc_vm_size,
3651	       region);
3652    }
3653
3654  return;
3655}
3656
3657
3658/* Fatal error when {en,de}code_mach_o_header fails.  */
3659
3660static void
3661bad_header (status)
3662     int status;
3663{
3664  switch (status)
3665    {
3666    case MO_ERROR_BAD_MAGIC:		fatal ("bad magic number");
3667    case MO_ERROR_BAD_HDR_VERS:		fatal ("bad header version");
3668    case MO_ERROR_BAD_RAW_HDR_VERS:	fatal ("bad raw header version");
3669    case MO_ERROR_BUF2SML:		fatal ("raw header buffer too small");
3670    case MO_ERROR_OLD_RAW_HDR_FILE:	fatal ("old raw header file");
3671    case MO_ERROR_UNSUPPORTED_VERS:	fatal ("unsupported version");
3672    default:
3673      fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3674    }
3675}
3676
3677
3678/* Read a file into a memory buffer.  */
3679
3680static struct file_info *
3681read_file (name, fd, rw)
3682     char *name;		/* filename */
3683     int fd;			/* file descriptor */
3684     int rw;			/* read/write */
3685{
3686  struct stat stat_pkt;
3687  struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3688#ifdef USE_MMAP
3689  static int page_size;
3690#endif
3691
3692  if (fstat (fd, &stat_pkt) < 0)
3693    fatal_perror ("fstat %s", name);
3694
3695  p->name	  = name;
3696  p->size	  = stat_pkt.st_size;
3697  p->rounded_size = stat_pkt.st_size;
3698  p->fd		  = fd;
3699  p->rw		  = rw;
3700
3701#ifdef USE_MMAP
3702  if (debug)
3703    fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3704
3705  if (page_size == 0)
3706    page_size = sysconf (_SC_PAGE_SIZE);
3707
3708  p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3709  p->start = mmap ((caddr_t) 0,
3710		   (rw) ? p->rounded_size : p->size,
3711		   (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3712		   MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3713		   fd,
3714		   0L);
3715
3716  if (p->start != (char *) 0 && p->start != (char *) -1)
3717    p->use_mmap = 1;
3718
3719  else
3720#endif /* USE_MMAP */
3721    {
3722      long len;
3723
3724      if (debug)
3725	fprintf (stderr, "read %s\n", name);
3726
3727      p->use_mmap = 0;
3728      p->start = xmalloc (p->size);
3729      if (lseek (fd, 0L, SEEK_SET) < 0)
3730	fatal_perror ("lseek %s 0", name);
3731
3732      len = read (fd, p->start, p->size);
3733      if (len < 0)
3734	fatal_perror ("read %s", name);
3735
3736      if (len != p->size)
3737	fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3738    }
3739
3740  return p;
3741}
3742
3743/* Do anything necessary to write a file back from memory.  */
3744
3745static void
3746end_file (ptr)
3747     struct file_info *ptr;	/* file information block */
3748{
3749#ifdef USE_MMAP
3750  if (ptr->use_mmap)
3751    {
3752      if (ptr->rw)
3753	{
3754	  if (debug)
3755	    fprintf (stderr, "msync %s\n", ptr->name);
3756
3757	  if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3758	    fatal_perror ("msync %s", ptr->name);
3759	}
3760
3761      if (debug)
3762	fprintf (stderr, "munmap %s\n", ptr->name);
3763
3764      if (munmap (ptr->start, ptr->size))
3765	fatal_perror ("munmap %s", ptr->name);
3766    }
3767  else
3768#endif /* USE_MMAP */
3769    {
3770      if (ptr->rw)
3771	{
3772	  long len;
3773
3774	  if (debug)
3775	    fprintf (stderr, "write %s\n", ptr->name);
3776
3777	  if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3778	    fatal_perror ("lseek %s 0", ptr->name);
3779
3780	  len = write (ptr->fd, ptr->start, ptr->size);
3781	  if (len < 0)
3782	    fatal_perror ("write %s", ptr->name);
3783
3784	  if (len != ptr->size)
3785	    fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3786	}
3787
3788      free (ptr->start);
3789    }
3790
3791  free (ptr);
3792}
3793
3794#endif /* OBJECT_FORMAT_ROSE */
3795