OSDN Git Service

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