OSDN Git Service

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