OSDN Git Service

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