OSDN Git Service

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