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