OSDN Git Service

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