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