OSDN Git Service

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