source: trunk/third/gcc/collect2.c @ 8834

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