OSDN Git Service

AIX shared libraries
[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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
25
26
27 /* Build tables of static constructors and destructors and run ld. */
28
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <errno.h>
33 #include <signal.h>
34 #include <sys/file.h>
35 #include <sys/stat.h>
36 #ifdef NO_WAIT_H
37 #include <sys/wait.h>
38 #endif
39
40 #ifndef errno
41 extern int errno;
42 #endif
43
44 #ifndef HAVE_STRERROR
45 #if defined(bsd4_4) 
46 extern const char *const sys_errlist[];
47 #else
48 extern char *sys_errlist[];
49 #endif
50 extern int sys_nerr;
51 #else
52 char *strerror();
53 #endif
54
55 #define COLLECT
56
57 #include "config.h"
58 #include "demangle.h"
59
60 #include "obstack.h"
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 niether. */
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                 auto_export = 0;
1247               break;
1248 #endif
1249
1250             case 'l':
1251               if (first_file)
1252                 {
1253                   /* place o_file BEFORE this argument! */
1254                   first_file = 0;
1255                   ld2--;
1256                   *ld2++ = o_file;
1257                   *ld2++ = arg;
1258                 }
1259               break;
1260
1261             case 'o':
1262               output_file = (arg[2] == '\0') ? argv[1] : &arg[2];
1263               break;
1264
1265             case 'r':
1266               if (arg[2] == '\0')
1267                 rflag = 1;
1268               break;
1269
1270             case 's':
1271               if (arg[2] == '\0' && do_collecting)
1272                 {
1273                   /* We must strip after the nm run, otherwise C++ linking
1274                      won't work.  Thus we strip in the second ld run, or
1275                      else with strip if there is no second ld run.  */
1276                   strip_flag = 1;
1277                   ld1--;
1278                 }
1279               break;
1280
1281             case 'v':
1282               if (arg[2] == '\0')
1283                 vflag = 1;
1284               break;
1285             }
1286         }
1287       else if ((p = rindex (arg, '.')) != (char *)0
1288                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0))
1289         {
1290           if (first_file)
1291             {
1292               first_file = 0;
1293               /* place o_file BEFORE this argument! */
1294               ld2--;
1295               *ld2++ = o_file;
1296               *ld2++ = arg;
1297             }
1298           if (p[1] == 'o')
1299             *object++ = arg;
1300         }
1301     }
1302
1303   /* Get any options that the upper GCC wants to pass to the sub-GCC.  */
1304   p = (char *) getenv ("COLLECT_GCC_OPTIONS");
1305   if (p)
1306     while (*p)
1307       {
1308         char *q = p;
1309         while (*q && *q != ' ') q++;
1310         if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
1311           *c_ptr++ = savestring (p, q - p);
1312         if (strncmp (p, "-shared", sizeof ("shared") - 1) == 0)
1313           shared_obj = 1;
1314
1315         if (*q) q++;
1316         p = q;
1317       }
1318
1319   /* Tell the linker that we have initializer and finalizer functions.  */
1320   if (shared_obj)
1321     {
1322 #ifdef LD_INIT_SWITCH
1323       *ld2++ = LD_INIT_SWITCH;
1324       *ld2++ = "_GLOBAL__DI";
1325 #endif
1326 #ifdef LD_FINI_SWITCH
1327       *ld2++ = LD_FINI_SWITCH;
1328       *ld2++ = "_GLOBAL__DD";
1329 #endif
1330     }
1331
1332 #ifdef COLLECT_EXPORT_LIST
1333   /* The AIX linker will discard static constructors in object files if
1334      nothing else in the file is referenced, so look at them first.  */
1335   while (object_lst < object)
1336     scan_prog_file (*object_lst++, PASS_OBJ);
1337
1338   {
1339     char *buf = alloca (strlen (export_file) + 5);
1340     sprintf (buf, "-bE:%s", export_file);
1341     *ld1++ = buf;
1342     *ld2++ = buf;
1343     exportf = fopen (export_file, "w");
1344     if (exportf == (FILE *)0)
1345       fatal_perror ("%s", export_file);
1346     write_export_file (exportf);
1347     if (fclose (exportf))
1348       fatal_perror ("closing %s", export_file);
1349   }
1350 #endif
1351
1352   *c_ptr++ = c_file;
1353   *object = *c_ptr = *ld1 = *ld2 = (char *)0;
1354
1355   if (vflag)
1356     {
1357       fprintf (stderr, "collect2 version %s", version_string);
1358 #ifdef TARGET_VERSION
1359       TARGET_VERSION;
1360 #endif
1361       fprintf (stderr, "\n");
1362     }
1363
1364   if (debug)
1365     {
1366       char *ptr;
1367       fprintf (stderr, "ld_file_name        = %s\n",
1368                (ld_file_name ? ld_file_name : "not found"));
1369       fprintf (stderr, "c_file_name         = %s\n",
1370                (c_file_name ? c_file_name : "not found"));
1371       fprintf (stderr, "nm_file_name        = %s\n",
1372                (nm_file_name ? nm_file_name : "not found"));
1373 #ifdef LDD_SUFFIX
1374       fprintf (stderr, "ldd_file_name       = %s\n",
1375                (ldd_file_name ? ldd_file_name : "not found"));
1376 #endif
1377       fprintf (stderr, "strip_file_name     = %s\n",
1378                (strip_file_name ? strip_file_name : "not found"));
1379       fprintf (stderr, "c_file              = %s\n",
1380                (c_file ? c_file : "not found"));
1381       fprintf (stderr, "o_file              = %s\n",
1382                (o_file ? o_file : "not found"));
1383
1384       ptr = getenv ("COLLECT_NAMES");
1385       if (ptr)
1386         fprintf (stderr, "COLLECT_NAMES       = %s\n", ptr);
1387
1388       ptr = getenv ("COLLECT_GCC_OPTIONS");
1389       if (ptr)
1390         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1391
1392       ptr = getenv ("COLLECT_GCC");
1393       if (ptr)
1394         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1395
1396       ptr = getenv ("COMPILER_PATH");
1397       if (ptr)
1398         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1399
1400       ptr = getenv ("LIBRARY_PATH");
1401       if (ptr)
1402         fprintf (stderr, "LIBRARY_PATH        = %s\n", ptr);
1403
1404       fprintf (stderr, "\n");
1405     }
1406
1407   /* Load the program, searching all libraries.  */
1408
1409   collect_execute ("ld", ld1_argv, ldout);
1410   do_wait ("ld");
1411   dump_file (ldout);
1412   unlink (ldout);
1413
1414   /* If -r or they'll be run via some other method, don't build the
1415      constructor or destructor list, just return now. */
1416   if (rflag || ! do_collecting)
1417     return 0;
1418
1419   /* Examine the namelist with nm and search it for static constructors
1420      and destructors to call.
1421      Write the constructor and destructor tables to a .s file and reload. */
1422
1423   scan_prog_file (output_file, PASS_FIRST);
1424
1425 #ifdef SCAN_LIBRARIES
1426   scan_libraries (output_file);
1427 #endif
1428
1429   if (debug)
1430     {
1431       fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1432       fprintf (stderr, "%d destructor(s)  found\n", destructors.number);
1433     }
1434
1435   if (constructors.number == 0 && destructors.number == 0
1436 #ifdef LDD_SUFFIX
1437       /* If we will be running these functions ourselves, we want to emit
1438          stubs into the shared library so that we don't have to relink
1439          dependent programs when we add static objects.  */
1440       && ! shared_obj
1441 #endif
1442       )
1443     {
1444       /* Strip now if it was requested on the command line.  */
1445       if (strip_flag)
1446         {
1447           char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
1448           strip_argv[0] = strip_file_name;
1449           strip_argv[1] = output_file;
1450           strip_argv[2] = (char *) 0;
1451           fork_execute ("strip", strip_argv);
1452         }
1453       return 0;
1454     }
1455
1456   maybe_unlink(output_file);
1457   outf = fopen (c_file, "w");
1458   if (outf == (FILE *)0)
1459     fatal_perror ("%s", c_file);
1460
1461   write_c_file (outf, c_file);
1462
1463   if (fclose (outf))
1464     fatal_perror ("closing %s", c_file);
1465
1466 #ifdef COLLECT_EXPORT_LIST
1467   if (shared_obj)
1468     {
1469       add_to_list (&exports, initname);
1470       add_to_list (&exports, fininame);
1471       exportf = fopen (export_file, "w");
1472       if (exportf == (FILE *)0)
1473         fatal_perror ("%s", export_file);
1474       write_export_file (exportf);
1475       if (fclose (exportf))
1476         fatal_perror ("closing %s", export_file);
1477     }
1478 #endif
1479
1480   if (debug)
1481     {
1482       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1483                output_file, c_file);
1484       write_c_file (stderr, "stderr");
1485       fprintf (stderr, "========== end of c_file\n\n");
1486 #ifdef COLLECT_EXPORT_LIST
1487       fprintf (stderr, "\n========== export_file = %s\n", export_file);
1488       write_export_file (stderr);
1489       fprintf (stderr, "========== end of export_file\n\n");
1490 #endif
1491     }
1492
1493   /* Assemble the constructor and destructor tables.
1494      Link the tables in with the rest of the program. */
1495
1496   fork_execute ("gcc",  c_argv);
1497   fork_execute ("ld", ld2_argv);
1498
1499   /* Let scan_prog_file do any final mods (OSF/rose needs this for
1500      constructors/destructors in shared libraries.  */
1501   scan_prog_file (output_file, PASS_SECOND);
1502
1503   maybe_unlink (c_file);
1504   maybe_unlink (o_file);
1505   maybe_unlink (export_file);
1506   return 0;
1507 }
1508
1509 \f
1510 /* Wait for a process to finish, and exit if a non-zero status is found. */
1511
1512 int
1513 collect_wait (prog)
1514      char *prog;
1515 {
1516   int status;
1517
1518   wait (&status);
1519   if (status)
1520     {
1521       if (WIFSIGNALED (status))
1522         {
1523           int sig = WTERMSIG (status);
1524 #ifdef NO_SYS_SIGLIST
1525           error ("%s terminated with signal %d %s",
1526                  prog,
1527                  sig,
1528                  (status & 0200) ? ", core dumped" : "");
1529 #else
1530           error ("%s terminated with signal %d [%s]%s",
1531                  prog,
1532                  sig,
1533                  sys_siglist[sig],
1534                  (status & 0200) ? ", core dumped" : "");
1535 #endif
1536
1537           collect_exit (127);
1538         }
1539
1540       if (WIFEXITED (status))
1541         return WEXITSTATUS (status);
1542     }
1543   return 0;
1544 }
1545
1546 static void
1547 do_wait (prog)
1548      char *prog;
1549 {
1550   int ret = collect_wait (prog);
1551   if (ret != 0)
1552     {
1553       error ("%s returned %d exit status", prog, ret);
1554       collect_exit (ret);
1555     }
1556 }
1557
1558 \f
1559 /* Fork and execute a program, and wait for the reply.  */
1560
1561 void
1562 collect_execute (prog, argv, redir)
1563      char *prog;
1564      char **argv;
1565      char *redir;
1566 {
1567   int pid;
1568
1569   if (vflag || debug)
1570     {
1571       char **p_argv;
1572       char *str;
1573
1574       if (argv[0])
1575         fprintf (stderr, "%s", argv[0]);
1576       else
1577         fprintf (stderr, "[cannot find %s]", prog);
1578
1579       for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1580         fprintf (stderr, " %s", str);
1581
1582       fprintf (stderr, "\n");
1583     }
1584
1585   fflush (stdout);
1586   fflush (stderr);
1587
1588   /* If we can't find a program we need, complain error.  Do this here
1589      since we might not end up needing something that we couldn't find.  */
1590
1591   if (argv[0] == 0)
1592     fatal ("cannot find `%s'", prog);
1593
1594   pid = vfork ();
1595   if (pid == -1)
1596     {
1597 #ifdef vfork
1598       fatal_perror ("fork");
1599 #else
1600       fatal_perror ("vfork");
1601 #endif
1602     }
1603
1604   if (pid == 0)                 /* child context */
1605     {
1606       if (redir)
1607         {
1608           unlink (redir);
1609           if (freopen (redir, "a", stdout) == NULL)
1610             fatal_perror ("redirecting stdout");
1611           if (freopen (redir, "a", stderr) == NULL)
1612             fatal_perror ("redirecting stderr");
1613         }
1614
1615       execvp (argv[0], argv);
1616       fatal_perror ("executing %s", prog);
1617     }
1618 }
1619
1620 static void
1621 fork_execute (prog, argv)
1622      char *prog;
1623      char **argv;
1624 {
1625   collect_execute (prog, argv, NULL);
1626   do_wait (prog);
1627 }
1628 \f
1629 /* Unlink a file unless we are debugging.  */
1630
1631 static void
1632 maybe_unlink (file)
1633      char *file;
1634 {
1635   if (!debug)
1636     unlink (file);
1637   else
1638     fprintf (stderr, "[Leaving %s]\n", file);
1639 }
1640
1641 \f
1642 /* Add a name to a linked list.  */
1643
1644 static void
1645 add_to_list (head_ptr, name)
1646      struct head *head_ptr;
1647      char *name;
1648 {
1649   struct id *newid
1650     = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1651   struct id *p;
1652   static long sequence_number = 0;
1653   strcpy (newid->name, name);
1654
1655   if (head_ptr->first)
1656     head_ptr->last->next = newid;
1657   else
1658     head_ptr->first = newid;
1659
1660   /* Check for duplicate symbols.  */
1661   for (p = head_ptr->first;
1662        strcmp (name, p->name) != 0;
1663        p = p->next)
1664     ;
1665   if (p != newid)
1666     {
1667       head_ptr->last->next = 0;
1668       free (newid);
1669       return;
1670     }
1671
1672   newid->sequence = ++sequence_number;
1673   head_ptr->last = newid;
1674   head_ptr->number++;
1675 }
1676
1677 /* Write: `prefix', the names on list LIST, `suffix'.  */
1678
1679 static void
1680 write_list (stream, prefix, list)
1681      FILE *stream;
1682      char *prefix;
1683      struct id *list;
1684 {
1685   while (list)
1686     {
1687       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1688       list = list->next;
1689     }
1690 }
1691
1692 static void
1693 write_list_with_asm (stream, prefix, list)
1694      FILE *stream;
1695      char *prefix;
1696      struct id *list;
1697 {
1698   while (list)
1699     {
1700       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1701                prefix, list->sequence, list->name);
1702       list = list->next;
1703     }
1704 }
1705
1706 /* Write out the constructor and destructor tables statically (for a shared
1707    object), along with the functions to execute them.  */
1708
1709 static void
1710 write_c_file_stat (stream, name)
1711      FILE *stream;
1712      char *name;
1713 {
1714   char *prefix, *p, *q;
1715
1716   /* Figure out name of output_file, stripping off .so version.  */
1717   p = rindex (output_file, '/');
1718   if (p == 0)
1719     p = (char *) output_file;
1720   else
1721     p++;
1722   q = p;
1723   while (q)
1724     {
1725       q = index (q,'.');
1726       if (q == 0)
1727         {
1728           q = p + strlen (p);
1729           break;
1730         }
1731       else
1732         {
1733           if (strncmp (q, ".so", 3) == 0)
1734             {
1735               q += 3;
1736               break;
1737             }
1738           else
1739             q++;
1740         }
1741     }
1742   /* q points to null at end of the string (or . of the .so version) */
1743   prefix = xmalloc (q - p + 1);
1744   strncpy (prefix, p, q - p);
1745   prefix[q - p] = 0;
1746   for (q = prefix; *q; q++)
1747     if (!isalnum (*q))
1748       *q = '_';
1749   if (debug)
1750     fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n",
1751              output_file, prefix);
1752
1753 #define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
1754   initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
1755   sprintf (initname, INIT_NAME_FORMAT, prefix);
1756
1757 #define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
1758   fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
1759   sprintf (fininame, FINI_NAME_FORMAT, prefix);
1760
1761   free (prefix);
1762
1763   /* Write the tables as C code  */
1764
1765   fprintf (stream, "static int count;\n");
1766   fprintf (stream, "typedef void entry_pt();\n");
1767   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1768   fprintf (stream, "void %s() {\n", initname);
1769   if (constructors.number > 0)
1770     {
1771       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1772       write_list (stream, "\t\t", constructors.first);
1773       fprintf (stream, "\t};\n");
1774       fprintf (stream, "\tentry_pt **p;\n");
1775       fprintf (stream, "\tif (count++ != 0) return;\n");
1776       fprintf (stream, "\tp = ctors + %d;\n", constructors.number);
1777       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1778     }
1779   fprintf (stream, "}\n");
1780   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1781   fprintf (stream, "void %s() {\n", fininame);
1782   if (destructors.number > 0)
1783     {
1784       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1785       write_list (stream, "\t\t", destructors.first);
1786       fprintf (stream, "\t};\n");
1787       fprintf (stream, "\tentry_pt **p;\n");
1788       fprintf (stream, "\tif (--count != 0) return;\n");
1789       fprintf (stream, "\tp = dtors;\n");
1790       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1791                destructors.number);
1792     }
1793   fprintf (stream, "}\n");
1794
1795   fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
1796   fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
1797 }
1798
1799 /* Write the constructor/destructor tables. */
1800
1801 static void
1802 write_c_file_glob (stream, name)
1803      FILE *stream;
1804      char *name;
1805 {
1806   /* Write the tables as C code  */
1807
1808   fprintf (stream, "typedef void entry_pt();\n\n");
1809     
1810   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1811     
1812   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1813   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
1814   write_list (stream, "\t", constructors.first);
1815   fprintf (stream, "\t0\n};\n\n");
1816
1817   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1818
1819   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1820   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
1821   write_list (stream, "\t", destructors.first);
1822   fprintf (stream, "\t0\n};\n\n");
1823
1824   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1825   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
1826 }
1827
1828 static void
1829 write_c_file (stream, name)
1830      FILE *stream;
1831      char *name;
1832 {
1833   if (shared_obj)
1834     write_c_file_stat (stream, name);
1835   else
1836     write_c_file_glob (stream, name);
1837 }
1838
1839 static void
1840 write_export_file (stream)
1841      FILE *stream;
1842 {
1843   struct id *list = exports.first;
1844   for (; list; list = list->next)
1845     fprintf (stream, "%s\n", list->name);
1846 }
1847 \f
1848 #ifdef OBJECT_FORMAT_NONE
1849
1850 /* Generic version to scan the name list of the loaded program for
1851    the symbols g++ uses for static constructors and destructors.
1852
1853    The constructor table begins at __CTOR_LIST__ and contains a count
1854    of the number of pointers (or -1 if the constructors are built in a
1855    separate section by the linker), followed by the pointers to the
1856    constructor functions, terminated with a null pointer.  The
1857    destructor table has the same format, and begins at __DTOR_LIST__.  */
1858
1859 static void
1860 scan_prog_file (prog_name, which_pass)
1861      char *prog_name;
1862      enum pass which_pass;
1863 {
1864   void (*int_handler) ();
1865   void (*quit_handler) ();
1866   char *nm_argv[4];
1867   int pid;
1868   int argc = 0;
1869   int pipe_fd[2];
1870   char *p, buf[1024];
1871   FILE *inf;
1872
1873   if (which_pass == PASS_SECOND)
1874     return;
1875
1876   /* If we don't have an `nm', complain.  */
1877   if (nm_file_name == 0)
1878     fatal ("cannot find `nm'");
1879
1880   nm_argv[argc++] = nm_file_name;
1881   if (NM_FLAGS[0] != '\0')
1882     nm_argv[argc++] = NM_FLAGS;
1883
1884   nm_argv[argc++] = prog_name;
1885   nm_argv[argc++] = (char *)0;
1886
1887   if (pipe (pipe_fd) < 0)
1888     fatal_perror ("pipe");
1889
1890   inf = fdopen (pipe_fd[0], "r");
1891   if (inf == (FILE *)0)
1892     fatal_perror ("fdopen");
1893
1894   /* Trace if needed.  */
1895   if (vflag)
1896     {
1897       char **p_argv;
1898       char *str;
1899
1900       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++)
1901         fprintf (stderr, " %s", str);
1902
1903       fprintf (stderr, "\n");
1904     }
1905
1906   fflush (stdout);
1907   fflush (stderr);
1908
1909   /* Spawn child nm on pipe */
1910   pid = vfork ();
1911   if (pid == -1)
1912     {
1913 #ifdef vfork
1914       fatal_perror ("fork");
1915 #else
1916       fatal_perror ("vfork");
1917 #endif
1918     }
1919
1920   if (pid == 0)                 /* child context */
1921     {
1922       /* setup stdout */
1923       if (dup2 (pipe_fd[1], 1) < 0)
1924         fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
1925
1926       if (close (pipe_fd[0]) < 0)
1927         fatal_perror ("close (%d)", pipe_fd[0]);
1928
1929       if (close (pipe_fd[1]) < 0)
1930         fatal_perror ("close (%d)", pipe_fd[1]);
1931
1932       execv (nm_file_name, nm_argv);
1933       fatal_perror ("executing %s", nm_file_name);
1934     }
1935
1936   /* Parent context from here on.  */
1937   int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
1938 #ifdef SIGQUIT
1939   quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
1940 #endif
1941
1942   if (close (pipe_fd[1]) < 0)
1943     fatal_perror ("close (%d)", pipe_fd[1]);
1944
1945   if (debug)
1946     fprintf (stderr, "\nnm output with constructors/destructors.\n");
1947
1948   /* Read each line of nm output.  */
1949   while (fgets (buf, sizeof buf, inf) != (char *)0)
1950     {
1951       int ch, ch2;
1952       char *name, *end;
1953
1954       /* If it contains a constructor or destructor name, add the name
1955          to the appropriate list. */
1956
1957       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1958         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
1959           break;
1960
1961       if (ch != '_')
1962         continue;
1963   
1964       name = p;
1965       /* Find the end of the symbol name.
1966          Don't include `|', because Encore nm can tack that on the end.  */
1967       for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1968            end++)
1969         continue;
1970
1971
1972       *end = '\0';
1973       switch (is_ctor_dtor (name))
1974         {
1975         case 1:
1976           if (which_pass != PASS_LIB)
1977             add_to_list (&constructors, name);
1978           break;
1979
1980         case 2:
1981           if (which_pass != PASS_LIB)
1982             add_to_list (&destructors, name);
1983           break;
1984
1985         case 3:
1986           if (which_pass != PASS_LIB)
1987             fatal ("init function found in object %s", prog_name);
1988 #ifndef LD_INIT_SWITCH
1989           add_to_list (&constructors, name);
1990 #endif
1991           break;
1992
1993         case 4:
1994           if (which_pass != PASS_LIB)
1995             fatal ("fini function found in object %s", prog_name);
1996 #ifndef LD_FINI_SWITCH
1997           add_to_list (&destructors, name);
1998 #endif
1999           break;
2000
2001         default:                /* not a constructor or destructor */
2002           continue;
2003         }
2004
2005       if (debug)
2006         fprintf (stderr, "\t%s\n", buf);
2007     }
2008
2009   if (debug)
2010     fprintf (stderr, "\n");
2011
2012   if (fclose (inf) != 0)
2013     fatal_perror ("fclose of pipe");
2014
2015   do_wait (nm_file_name);
2016
2017   signal (SIGINT,  int_handler);
2018 #ifdef SIGQUIT
2019   signal (SIGQUIT, quit_handler);
2020 #endif
2021 }
2022
2023 #if SUNOS4_SHARED_LIBRARIES
2024
2025 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2026    that the output file depends upon and their initialization/finalization
2027    routines, if any.  */
2028
2029 #include <a.out.h>
2030 #include <fcntl.h>
2031 #include <link.h>
2032 #include <sys/mman.h>
2033 #include <sys/param.h>
2034 #include <sys/unistd.h>
2035 #include <sys/dir.h>
2036
2037 /* pointers to the object file */
2038 unsigned object;        /* address of memory mapped file */
2039 unsigned objsize;       /* size of memory mapped to file */
2040 char * code;            /* pointer to code segment */
2041 char * data;            /* pointer to data segment */
2042 struct nlist *symtab;   /* pointer to symbol table */
2043 struct link_dynamic *ld;
2044 struct link_dynamic_2 *ld_2;
2045 struct head libraries;
2046
2047 /* Map the file indicated by NAME into memory and store its address.  */
2048
2049 static void
2050 mapfile (name)
2051      char *name;
2052 {
2053   int fp;
2054   struct stat s;
2055   if ((fp = open (name, O_RDONLY)) == -1)
2056     fatal ("unable to open file '%s'", name);
2057   if (fstat (fp, &s) == -1)
2058     fatal ("unable to stat file '%s'", name);
2059
2060   objsize = s.st_size;
2061   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2062                             fp, 0);
2063   if (object == -1)
2064     fatal ("unable to mmap file '%s'", name);
2065
2066   close (fp);
2067 }
2068
2069 /* Helpers for locatelib.  */
2070
2071 static char *libname;
2072
2073 static int
2074 libselect (d)
2075      struct direct *d;
2076 {
2077   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2078 }
2079
2080 static int
2081 libcompare (d1, d2)
2082      struct direct **d1, **d2;
2083 {
2084   int i1, i2 = strlen (libname);
2085   char *e1 = (*d1)->d_name + i2;
2086   char *e2 = (*d2)->d_name + i2;
2087
2088   while (*e1 && *e2)
2089     {
2090       ++e1;
2091       ++e2;
2092       i1 = strtol (e1, &e1, 10);
2093       i2 = strtol (e2, &e2, 10);
2094       if (i1 != i2)
2095         return i1 - i2;
2096     }
2097
2098   if (*e1)
2099     return 1;
2100   else if (*e2)
2101     return -1;
2102   else
2103     return 0;
2104 }
2105
2106 /* Given the name NAME of a dynamic dependency, find its pathname and add
2107    it to the list of libraries.  */
2108
2109 static void
2110 locatelib (name)
2111      char *name;
2112 {
2113   static char **l;
2114   static int cnt;
2115   char buf[MAXPATHLEN];
2116   char *p, *q;
2117   char **pp;
2118
2119   if (l == 0)
2120     {
2121       char *ld_rules;
2122       char *ldr = 0;
2123       /* counting elements in array, need 1 extra for null */
2124       cnt = 1;  
2125       ld_rules = (char *) (ld_2->ld_rules + code);
2126       if (ld_rules)
2127         {
2128           cnt++;
2129           for (; *ld_rules != 0; ld_rules++)
2130             if (*ld_rules == ':')
2131               cnt++;
2132           ld_rules = (char *) (ld_2->ld_rules + code);
2133           ldr = (char *) malloc (strlen (ld_rules) + 1);
2134           strcpy (ldr, ld_rules);
2135         }
2136       p = getenv ("LD_LIBRARY_PATH");
2137       q = 0;
2138       if (p)
2139         {
2140           cnt++;
2141           for (q = p ; *q != 0; q++)
2142             if (*q == ':')
2143               cnt++;
2144           q = (char *) malloc (strlen (p) + 1);
2145           strcpy (q, p);
2146         }
2147       l = (char **) malloc ((cnt + 3) * sizeof (char *));
2148       pp = l;
2149       if (ldr)
2150         {
2151           *pp++ = ldr;
2152           for (; *ldr != 0; ldr++) 
2153             if (*ldr == ':')
2154               {
2155                 *ldr++ = 0;
2156                 *pp++ = ldr;
2157               }
2158         }
2159       if (q)
2160         {
2161           *pp++ = q;
2162           for (; *q != 0; q++) 
2163             if (*q == ':')
2164               {
2165                 *q++ = 0;
2166                 *pp++ = p;
2167               }
2168         }
2169       /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2170       *pp++ = "/lib";
2171       *pp++ = "/usr/lib";
2172       *pp++ = "/usr/local/lib";
2173       *pp = 0;
2174     }
2175   libname = name;
2176   for (pp = l; *pp != 0 ; pp++)
2177     {
2178       struct direct **namelist;
2179       int entries;
2180       if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2181         {
2182           sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2183           add_to_list (&libraries, buf);
2184           if (debug)
2185             fprintf (stderr, "%s\n", buf);
2186           break;
2187         }
2188     }
2189   if (*pp == 0)
2190     {
2191       if (debug)
2192         fprintf (stderr, "not found\n");
2193       else
2194         fatal ("dynamic dependency %s not found", name);
2195     }
2196 }
2197
2198 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2199    that it depends upon and any constructors or destructors they contain.  */
2200
2201 static void 
2202 scan_libraries (prog_name)
2203      char *prog_name;
2204 {
2205   struct exec *header;
2206   char *base;
2207   struct link_object *lo;
2208   char buff[MAXPATHLEN];
2209   struct id *list;
2210
2211   mapfile (prog_name);
2212   header = (struct exec *)object;
2213   if (N_BADMAG (*header))
2214     fatal ("bad magic number in file '%s'", prog_name);
2215   if (header->a_dynamic == 0)
2216     return;
2217
2218   code = (char *) (N_TXTOFF (*header) + (long) header);
2219   data = (char *) (N_DATOFF (*header) + (long) header);
2220   symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2221
2222   if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2223     {
2224       /* shared object */
2225       ld = (struct link_dynamic *) (symtab->n_value + code);
2226       base = code;
2227     }
2228   else
2229     {
2230       /* executable */
2231       ld = (struct link_dynamic *) data;
2232       base = code-PAGSIZ;
2233     }
2234
2235   if (debug)
2236     fprintf (stderr, "dynamic dependencies.\n");
2237
2238   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2239   for (lo = (struct link_object *) ld_2->ld_need; lo;
2240        lo = (struct link_object *) lo->lo_next)
2241     {
2242       char *name;
2243       lo = (struct link_object *) ((long) lo + code);
2244       name = (char *) (code + lo->lo_name);
2245       if (lo->lo_library)
2246         {
2247           if (debug)
2248             fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2249           sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2250           locatelib (buff);
2251         }
2252       else
2253         {
2254           if (debug)
2255             fprintf (stderr, "\t%s\n", name);
2256           add_to_list (&libraries, name);
2257         }
2258     }
2259
2260   if (debug)
2261     fprintf (stderr, "\n");
2262
2263   /* now iterate through the library list adding their symbols to
2264      the list.  */
2265   for (list = libraries.first; list; list = list->next)
2266     scan_prog_file (list->name, PASS_LIB);
2267 }
2268
2269 #else  /* SUNOS4_SHARED_LIBRARIES */
2270 #ifdef LDD_SUFFIX
2271
2272 /* Use the List Dynamic Dependencies program to find shared libraries that
2273    the output file depends upon and their initialization/finalization
2274    routines, if any.  */
2275
2276 static void 
2277 scan_libraries (prog_name)
2278      char *prog_name;
2279 {
2280   static struct head libraries;         /* list of shared libraries found */
2281   struct id *list;
2282   void (*int_handler) ();
2283   void (*quit_handler) ();
2284   char *ldd_argv[4];
2285   int pid;
2286   int argc = 0;
2287   int pipe_fd[2];
2288   char buf[1024];
2289   FILE *inf;
2290
2291   /* If we don't have an `ldd', complain.  */
2292   if (ldd_file_name == 0)
2293     {
2294       error ("cannot find `ldd'");
2295       return;
2296     }
2297
2298   ldd_argv[argc++] = ldd_file_name;
2299   ldd_argv[argc++] = prog_name;
2300   ldd_argv[argc++] = (char *) 0;
2301
2302   if (pipe (pipe_fd) < 0)
2303     fatal_perror ("pipe");
2304
2305   inf = fdopen (pipe_fd[0], "r");
2306   if (inf == (FILE *) 0)
2307     fatal_perror ("fdopen");
2308
2309   /* Trace if needed.  */
2310   if (vflag)
2311     {
2312       char **p_argv;
2313       char *str;
2314
2315       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2316         fprintf (stderr, " %s", str);
2317
2318       fprintf (stderr, "\n");
2319     }
2320
2321   fflush (stdout);
2322   fflush (stderr);
2323
2324   /* Spawn child ldd on pipe */
2325   pid = vfork ();
2326   if (pid == -1)
2327     {
2328 #ifdef vfork
2329       fatal_perror ("fork");
2330 #else
2331       fatal_perror ("vfork");
2332 #endif
2333     }
2334
2335   if (pid == 0)                 /* child context */
2336     {
2337       /* setup stdout */
2338       if (dup2 (pipe_fd[1], 1) < 0)
2339         fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
2340
2341       if (close (pipe_fd[0]) < 0)
2342         fatal_perror ("close (%d)", pipe_fd[0]);
2343
2344       if (close (pipe_fd[1]) < 0)
2345         fatal_perror ("close (%d)", pipe_fd[1]);
2346
2347       execv (ldd_file_name, ldd_argv);
2348       fatal_perror ("executing %s", ldd_file_name);
2349     }
2350
2351   /* Parent context from here on.  */
2352   int_handler  = (void (*) ()) signal (SIGINT,  SIG_IGN);
2353 #ifdef SIGQUIT
2354   quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
2355 #endif
2356
2357   if (close (pipe_fd[1]) < 0)
2358     fatal_perror ("close (%d)", pipe_fd[1]);
2359
2360   if (debug)
2361     fprintf (stderr, "\nldd output with constructors/destructors.\n");
2362
2363   /* Read each line of ldd output.  */
2364   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2365     {
2366       int ch, ch2;
2367       char *name, *end, *p = buf;
2368
2369       /* Extract names of libraries and add to list. */
2370       PARSE_LDD_OUTPUT (p);
2371       if (p == 0)
2372         continue;
2373
2374       name = p;
2375       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2376         fatal ("dynamic dependency %s not found", buf);
2377
2378       /* Find the end of the symbol name. */
2379       for (end = p; 
2380            (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|';
2381            end++)
2382         continue;
2383       *end = '\0';
2384
2385       if (access (name, R_OK) == 0)
2386         add_to_list (&libraries, name);
2387       else
2388         fatal ("unable to open dynamic dependency '%s'", buf);
2389
2390       if (debug)
2391         fprintf (stderr, "\t%s\n", buf);
2392     }
2393   if (debug)
2394     fprintf (stderr, "\n");
2395
2396   if (fclose (inf) != 0)
2397     fatal_perror ("fclose of pipe");
2398
2399   do_wait (ldd_file_name);
2400
2401   signal (SIGINT,  int_handler);
2402 #ifdef SIGQUIT
2403   signal (SIGQUIT, quit_handler);
2404 #endif
2405
2406   /* now iterate through the library list adding their symbols to
2407      the list.  */
2408   for (list = libraries.first; list; list = list->next)
2409     scan_prog_file (list->name, PASS_LIB);
2410 }
2411
2412 #endif /* LDD_SUFFIX */
2413 #endif /* SUNOS4_SHARED_LIBRARIES */
2414
2415 #endif /* OBJECT_FORMAT_NONE */
2416
2417 \f
2418 /*
2419  * COFF specific stuff.
2420  */
2421
2422 #ifdef OBJECT_FORMAT_COFF
2423
2424 #if defined(EXTENDED_COFF)
2425 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2426 #   define GCC_SYMENT           SYMR
2427 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc && (X).sc == scText)
2428 #   define GCC_SYMINC(X)        (1)
2429 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
2430 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
2431 #else
2432 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
2433 #   define GCC_SYMENT           SYMENT
2434 #   define GCC_OK_SYMBOL(X) \
2435      (((X).n_sclass == C_EXT) && \
2436         (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
2437          ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
2438 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
2439 #   define GCC_SYMZERO(X)       0
2440 #   define GCC_CHECK_HDR(X)     (1)
2441 #endif
2442
2443 extern char *ldgetname ();
2444
2445 /* COFF version to scan the name list of the loaded program for
2446    the symbols g++ uses for static constructors and destructors.
2447
2448    The constructor table begins at __CTOR_LIST__ and contains a count
2449    of the number of pointers (or -1 if the constructors are built in a
2450    separate section by the linker), followed by the pointers to the
2451    constructor functions, terminated with a null pointer.  The
2452    destructor table has the same format, and begins at __DTOR_LIST__.  */
2453
2454 static void
2455 scan_prog_file (prog_name, which_pass)
2456      char *prog_name;
2457      enum pass which_pass;
2458 {
2459   LDFILE *ldptr = NULL;
2460   int sym_index, sym_count;
2461
2462   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2463     return;
2464
2465   if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
2466     fatal ("%s: can't open as COFF file", prog_name);
2467       
2468   if (!MY_ISCOFF (HEADER (ldptr).f_magic))
2469     fatal ("%s: not a COFF file", prog_name);
2470
2471   if (GCC_CHECK_HDR (ldptr))
2472     {
2473       sym_count = GCC_SYMBOLS (ldptr);
2474       sym_index = GCC_SYMZERO (ldptr);
2475       while (sym_index < sym_count)
2476         {
2477           GCC_SYMENT symbol;
2478
2479           if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2480             break;
2481           sym_index += GCC_SYMINC (symbol);
2482
2483           if (GCC_OK_SYMBOL (symbol))
2484             {
2485               char *name;
2486
2487               if ((name = ldgetname (ldptr, &symbol)) == NULL)
2488                 continue;               /* should never happen */
2489
2490 #ifdef XCOFF_DEBUGGING_INFO
2491               /* All AIX function names have a duplicate entry beginning
2492                  with a dot. */
2493               if (*name == '.')
2494                 continue;
2495 #endif
2496
2497               switch (is_ctor_dtor (name))
2498                 {
2499                 case 1:
2500                   add_to_list (&constructors, name);
2501                   if (which_pass == PASS_OBJ)
2502                     add_to_list (&exports, name);
2503                   break;
2504
2505                 case 2:
2506                   add_to_list (&destructors, name);
2507                   if (which_pass == PASS_OBJ)
2508                     add_to_list (&exports, name);
2509                   break;
2510
2511                 default:                /* not a constructor or destructor */
2512                   if (which_pass == PASS_OBJ && auto_export)
2513                     add_to_list (&exports, name);
2514                   continue;
2515                 }
2516
2517 #if !defined(EXTENDED_COFF)
2518               if (debug)
2519                 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2520                          symbol.n_scnum, symbol.n_sclass,
2521                          (symbol.n_type ? "0" : ""), symbol.n_type,
2522                          name);
2523 #else
2524               if (debug)
2525                 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
2526                          symbol.iss, symbol.value, symbol.index, name);
2527 #endif
2528             }
2529         }
2530     }
2531
2532   (void) ldclose(ldptr);
2533 }
2534
2535 #endif /* OBJECT_FORMAT_COFF */
2536
2537 \f
2538 /*
2539  * OSF/rose specific stuff.
2540  */
2541
2542 #ifdef OBJECT_FORMAT_ROSE
2543
2544 /* Union of the various load commands */
2545
2546 typedef union load_union
2547 {
2548   ldc_header_t                  hdr;    /* common header */
2549   load_cmd_map_command_t        map;    /* map indexing other load cmds */
2550   interpreter_command_t         iprtr;  /* interpreter pathname */
2551   strings_command_t             str;    /* load commands strings section */
2552   region_command_t              region; /* region load command */
2553   reloc_command_t               reloc;  /* relocation section */
2554   package_command_t             pkg;    /* package load command */
2555   symbols_command_t             sym;    /* symbol sections */
2556   entry_command_t               ent;    /* program start section */
2557   gen_info_command_t            info;   /* object information */
2558   func_table_command_t          func;   /* function constructors/destructors */
2559 } load_union_t;
2560
2561 /* Structure to point to load command and data section in memory.  */
2562
2563 typedef struct load_all
2564 {
2565   load_union_t *load;                   /* load command */
2566   char *section;                        /* pointer to section */
2567 } load_all_t;
2568
2569 /* Structure to contain information about a file mapped into memory.  */
2570
2571 struct file_info
2572 {
2573   char *start;                          /* start of map */
2574   char *name;                           /* filename */
2575   long  size;                           /* size of the file */
2576   long  rounded_size;                   /* size rounded to page boundary */
2577   int   fd;                             /* file descriptor */
2578   int   rw;                             /* != 0 if opened read/write */
2579   int   use_mmap;                       /* != 0 if mmap'ed */
2580 };
2581
2582 extern int decode_mach_o_hdr ();
2583 extern int encode_mach_o_hdr ();
2584
2585 static void add_func_table      PROTO((mo_header_t *, load_all_t *,
2586                                        symbol_info_t *, int));
2587 static void print_header        PROTO((mo_header_t *));
2588 static void print_load_command  PROTO((load_union_t*, size_t, int));
2589 static void bad_header          PROTO((int));
2590 static struct file_info *read_file  PROTO((char *, int, int));
2591 static void end_file            PROTO((struct file_info *));
2592 \f
2593 /* OSF/rose specific version to scan the name list of the loaded
2594    program for the symbols g++ uses for static constructors and
2595    destructors.
2596
2597    The constructor table begins at __CTOR_LIST__ and contains a count
2598    of the number of pointers (or -1 if the constructors are built in a
2599    separate section by the linker), followed by the pointers to the
2600    constructor functions, terminated with a null pointer.  The
2601    destructor table has the same format, and begins at __DTOR_LIST__.  */
2602
2603 static void
2604 scan_prog_file (prog_name, which_pass)
2605      char *prog_name;
2606      enum pass which_pass;
2607 {
2608   char *obj;
2609   mo_header_t hdr;
2610   load_all_t *load_array;
2611   load_all_t *load_end;
2612   load_all_t *load_cmd;
2613   int symbol_load_cmds;
2614   off_t offset;
2615   int i;
2616   int num_syms;
2617   int status;
2618   char *str_sect;
2619   struct file_info *obj_file;
2620   int prog_fd;
2621   mo_lcid_t cmd_strings   = -1;
2622   symbol_info_t *main_sym = 0;
2623   int rw                  = (which_pass != PASS_FIRST);
2624
2625   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
2626   if (prog_fd < 0)
2627     fatal_perror ("can't read %s", prog_name);
2628
2629   obj_file = read_file (prog_name, prog_fd, rw);
2630   obj = obj_file->start;
2631
2632   status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
2633   if (status != MO_HDR_CONV_SUCCESS)
2634     bad_header (status);
2635
2636
2637   /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
2638      since the hardware will automatically swap bytes for us on loading little endian
2639      integers.  */
2640
2641 #ifndef CROSS_COMPILE
2642   if (hdr.moh_magic != MOH_MAGIC_MSB
2643       || hdr.moh_header_version != MOH_HEADER_VERSION
2644       || hdr.moh_byte_order != OUR_BYTE_ORDER
2645       || hdr.moh_data_rep_id != OUR_DATA_REP_ID
2646       || hdr.moh_cpu_type != OUR_CPU_TYPE
2647       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
2648       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
2649     {
2650       fatal ("incompatibilities between object file & expected values");
2651     }
2652 #endif
2653
2654   if (debug)
2655     print_header (&hdr);
2656
2657   offset = hdr.moh_first_cmd_off;
2658   load_end = load_array
2659     = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
2660
2661   /* Build array of load commands, calculating the offsets */
2662   for (i = 0; i < hdr.moh_n_load_cmds; i++)
2663     {
2664       load_union_t *load_hdr;           /* load command header */
2665
2666       load_cmd = load_end++;
2667       load_hdr = (load_union_t *) (obj + offset);
2668
2669       /* If modifying the program file, copy the header.  */
2670       if (rw)
2671         {
2672           load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
2673           bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
2674           load_hdr = ptr;
2675
2676           /* null out old command map, because we will rewrite at the end.  */
2677           if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
2678             {
2679               cmd_strings = ptr->map.lcm_ld_cmd_strings;
2680               ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
2681             }
2682         }
2683
2684       load_cmd->load = load_hdr;
2685       if (load_hdr->hdr.ldci_section_off > 0)
2686         load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
2687
2688       if (debug)
2689         print_load_command (load_hdr, offset, i);
2690
2691       offset += load_hdr->hdr.ldci_cmd_size;
2692     }
2693
2694   /* If the last command is the load command map and is not undefined,
2695      decrement the count of load commands.  */
2696   if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
2697     {
2698       load_end--;
2699       hdr.moh_n_load_cmds--;
2700     }
2701
2702   /* Go through and process each symbol table section.  */
2703   symbol_load_cmds = 0;
2704   for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
2705     {
2706       load_union_t *load_hdr = load_cmd->load;
2707
2708       if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
2709         {
2710           symbol_load_cmds++;
2711
2712           if (debug)
2713             {
2714               char *kind = "unknown";
2715
2716               switch (load_hdr->sym.symc_kind)
2717                 {
2718                 case SYMC_IMPORTS:         kind = "imports"; break;
2719                 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
2720                 case SYMC_STABS:           kind = "stabs";   break;
2721                 }
2722
2723               fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
2724                        symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
2725             }
2726
2727           if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
2728             continue;
2729
2730           str_sect = load_array[load_hdr->sym.symc_strings_section].section;
2731           if (str_sect == (char *)0)
2732             fatal ("string section missing");
2733
2734           if (load_cmd->section == (char *)0)
2735             fatal ("section pointer missing");
2736
2737           num_syms = load_hdr->sym.symc_nentries;
2738           for (i = 0; i < num_syms; i++)
2739             {
2740               symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
2741               char *name = sym->si_name.symbol_name + str_sect;
2742
2743               if (name[0] != '_')
2744                 continue;
2745
2746               if (rw)
2747                 {
2748                   char *n = name + strlen (name) - strlen (NAME__MAIN);
2749
2750                   if ((n - name) < 0 || strcmp (n, NAME__MAIN))
2751                     continue;
2752                   while (n != name)
2753                     if (*--n != '_')
2754                       continue;
2755
2756                   main_sym = sym;
2757                 }
2758               else
2759                 {
2760                   switch (is_ctor_dtor (name))
2761                     {
2762                     case 1:
2763                       add_to_list (&constructors, name);
2764                       break;
2765
2766                     case 2:
2767                       add_to_list (&destructors, name);
2768                       break;
2769
2770                     default:    /* not a constructor or destructor */
2771                       continue;
2772                     }
2773                 }
2774
2775               if (debug)
2776                 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
2777                          sym->si_type, sym->si_sc_type, sym->si_flags, name);
2778             }
2779         }
2780     }
2781
2782   if (symbol_load_cmds == 0)
2783     fatal ("no symbol table found");
2784
2785   /* Update the program file now, rewrite header and load commands.  At present,
2786      we assume that there is enough space after the last load command to insert
2787      one more.  Since the first section written out is page aligned, and the
2788      number of load commands is small, this is ok for the present.  */
2789
2790   if (rw)
2791     {
2792       load_union_t *load_map;
2793       size_t size;
2794
2795       if (cmd_strings == -1)
2796         fatal ("no cmd_strings found");
2797
2798       /* Add __main to initializer list.
2799          If we are building a program instead of a shared library, don't
2800          do anything, since in the current version, you cannot do mallocs
2801          and such in the constructors.  */
2802
2803       if (main_sym != (symbol_info_t *)0
2804           && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
2805         add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
2806
2807       if (debug)
2808         fprintf (stderr, "\nUpdating header and load commands.\n\n");
2809
2810       hdr.moh_n_load_cmds++;
2811       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
2812
2813       /* Create new load command map.  */
2814       if (debug)
2815         fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
2816                  (int)hdr.moh_n_load_cmds, (long)size);
2817
2818       load_map = (load_union_t *) xcalloc (1, size);
2819       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
2820       load_map->map.ldc_header.ldci_cmd_size = size;
2821       load_map->map.lcm_ld_cmd_strings = cmd_strings;
2822       load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
2823       load_array[hdr.moh_n_load_cmds-1].load = load_map;
2824
2825       offset = hdr.moh_first_cmd_off;
2826       for (i = 0; i < hdr.moh_n_load_cmds; i++)
2827         {
2828           load_map->map.lcm_map[i] = offset;
2829           if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
2830             hdr.moh_load_map_cmd_off = offset;
2831
2832           offset += load_array[i].load->hdr.ldci_cmd_size;
2833         }
2834
2835       hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
2836
2837       if (debug)
2838         print_header (&hdr);
2839
2840       /* Write header */
2841       status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
2842       if (status != MO_HDR_CONV_SUCCESS)
2843         bad_header (status);
2844
2845       if (debug)
2846         fprintf (stderr, "writing load commands.\n\n");
2847
2848       /* Write load commands */
2849       offset = hdr.moh_first_cmd_off;
2850       for (i = 0; i < hdr.moh_n_load_cmds; i++)
2851         {
2852           load_union_t *load_hdr = load_array[i].load;
2853           size_t size = load_hdr->hdr.ldci_cmd_size;
2854
2855           if (debug)
2856             print_load_command (load_hdr, offset, i);
2857
2858           bcopy ((char *)load_hdr, (char *)(obj + offset), size);
2859           offset += size;
2860         }
2861     }
2862
2863   end_file (obj_file);
2864
2865   if (close (prog_fd))
2866     fatal_perror ("closing %s", prog_name);
2867
2868   if (debug)
2869     fprintf (stderr, "\n");
2870 }
2871
2872 \f
2873 /* Add a function table to the load commands to call a function
2874    on initiation or termination of the process.  */
2875
2876 static void
2877 add_func_table (hdr_p, load_array, sym, type)
2878      mo_header_t *hdr_p;                /* pointer to global header */
2879      load_all_t *load_array;            /* array of ptrs to load cmds */
2880      symbol_info_t *sym;                /* pointer to symbol entry */
2881      int type;                          /* fntc_type value */
2882 {
2883   /* Add a new load command.  */
2884   int num_cmds = ++hdr_p->moh_n_load_cmds;
2885   int load_index = num_cmds - 1;
2886   size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
2887   load_union_t *ptr = xcalloc (1, size);
2888   load_all_t *load_cmd;
2889   int i;
2890
2891   /* Set the unresolved address bit in the header to force the loader to be
2892      used, since kernel exec does not call the initialization functions.  */
2893   hdr_p->moh_flags |= MOH_UNRESOLVED_F;
2894
2895   load_cmd = &load_array[load_index];
2896   load_cmd->load = ptr;
2897   load_cmd->section = (char *)0;
2898
2899   /* Fill in func table load command.  */
2900   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
2901   ptr->func.ldc_header.ldci_cmd_size = size;
2902   ptr->func.ldc_header.ldci_section_off = 0;
2903   ptr->func.ldc_header.ldci_section_len = 0;
2904   ptr->func.fntc_type = type;
2905   ptr->func.fntc_nentries = 1;
2906
2907   /* copy address, turn it from abs. address to (region,offset) if necessary.  */
2908   /* Is the symbol already expressed as (region, offset)?  */
2909   if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
2910     {
2911       ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
2912       ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
2913     }
2914
2915   /* If not, figure out which region it's in.  */
2916   else
2917     {
2918       mo_vm_addr_t addr = sym->si_value.abs_val;
2919       int found = 0;
2920
2921       for (i = 0; i < load_index; i++)
2922         {
2923           if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
2924             {
2925               region_command_t *region_ptr = &load_array[i].load->region;
2926
2927               if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
2928                   && addr >= region_ptr->regc_addr.vm_addr
2929                   && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
2930                 {
2931                   ptr->func.fntc_entry_loc[0].adr_lcid = i;
2932                   ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
2933                   found++;
2934                   break;
2935                 }
2936             }
2937         }
2938
2939       if (!found)
2940         fatal ("could not convert 0x%l.8x into a region", addr);
2941     }
2942
2943   if (debug)
2944     fprintf (stderr,
2945              "%s function, region %d, offset = %ld (0x%.8lx)\n",
2946              (type == FNTC_INITIALIZATION) ? "init" : "term",
2947              (int)ptr->func.fntc_entry_loc[i].adr_lcid,
2948              (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
2949              (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
2950
2951 }
2952
2953 \f
2954 /* Print the global header for an OSF/rose object.  */
2955
2956 static void
2957 print_header (hdr_ptr)
2958      mo_header_t *hdr_ptr;
2959 {
2960   fprintf (stderr, "\nglobal header:\n");
2961   fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
2962   fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
2963   fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
2964   fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
2965   fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
2966   fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
2967   fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
2968   fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
2969   fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
2970   fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
2971   fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
2972   fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
2973   fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
2974   fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
2975   fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
2976
2977   if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
2978     fprintf (stderr, ", relocatable");
2979
2980   if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
2981     fprintf (stderr, ", linkable");
2982
2983   if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
2984     fprintf (stderr, ", execable");
2985
2986   if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
2987     fprintf (stderr, ", executable");
2988
2989   if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
2990     fprintf (stderr, ", unresolved");
2991
2992   fprintf (stderr, "\n\n");
2993   return;
2994 }
2995
2996 \f
2997 /* Print a short summary of a load command.  */
2998
2999 static void
3000 print_load_command (load_hdr, offset, number)
3001      load_union_t *load_hdr;
3002      size_t offset;
3003      int number;
3004 {
3005   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3006   char *type_str = (char *)0;
3007
3008   switch (type)
3009     {
3010     case LDC_UNDEFINED:   type_str = "UNDEFINED";       break;
3011     case LDC_CMD_MAP:     type_str = "CMD_MAP";         break;
3012     case LDC_INTERPRETER: type_str = "INTERPRETER";     break;
3013     case LDC_STRINGS:     type_str = "STRINGS";         break;
3014     case LDC_REGION:      type_str = "REGION";          break;
3015     case LDC_RELOC:       type_str = "RELOC";           break;
3016     case LDC_PACKAGE:     type_str = "PACKAGE";         break;
3017     case LDC_SYMBOLS:     type_str = "SYMBOLS";         break;
3018     case LDC_ENTRY:       type_str = "ENTRY";           break;
3019     case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";      break;
3020     case LDC_GEN_INFO:    type_str = "GEN_INFO";        break;
3021     }
3022
3023   fprintf (stderr,
3024            "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3025            number,
3026            (long) load_hdr->hdr.ldci_cmd_size,
3027            (long) offset,
3028            (long) load_hdr->hdr.ldci_section_off,
3029            (long) load_hdr->hdr.ldci_section_len);
3030
3031   if (type_str == (char *)0)
3032     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3033
3034   else if (type != LDC_REGION)
3035     fprintf (stderr, ", ty: %s\n", type_str);
3036
3037   else
3038     {
3039       char *region = "";
3040       switch (load_hdr->region.regc_usage_type)
3041         {
3042         case REG_TEXT_T:        region = ", .text";     break;
3043         case REG_DATA_T:        region = ", .data";     break;
3044         case REG_BSS_T:         region = ", .bss";      break;
3045         case REG_GLUE_T:        region = ", .glue";     break;
3046 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3047         case REG_RDATA_T:       region = ", .rdata";    break;
3048         case REG_SDATA_T:       region = ", .sdata";    break;
3049         case REG_SBSS_T:        region = ", .sbss";     break;
3050 #endif
3051         }
3052
3053       fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3054                type_str,
3055                (long) load_hdr->region.regc_vm_addr,
3056                (long) load_hdr->region.regc_vm_size,
3057                region);
3058     }
3059
3060   return;
3061 }
3062
3063 \f
3064 /* Fatal error when {en,de}code_mach_o_header fails.  */
3065
3066 static void
3067 bad_header (status)
3068      int status;
3069 {
3070   char *msg = (char *)0;
3071
3072   switch (status)
3073     {
3074     case MO_ERROR_BAD_MAGIC:            msg = "bad magic number";               break;
3075     case MO_ERROR_BAD_HDR_VERS:         msg = "bad header version";             break;
3076     case MO_ERROR_BAD_RAW_HDR_VERS:     msg = "bad raw header version";         break;
3077     case MO_ERROR_BUF2SML:              msg = "raw header buffer too small";    break;
3078     case MO_ERROR_OLD_RAW_HDR_FILE:     msg = "old raw header file";            break;
3079     case MO_ERROR_UNSUPPORTED_VERS:     msg = "unsupported version";            break;
3080     }
3081
3082   if (msg == (char *)0)
3083     fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3084   else
3085     fatal ("%s", msg);
3086 }
3087
3088 \f
3089 /* Read a file into a memory buffer.  */
3090
3091 static struct file_info *
3092 read_file (name, fd, rw)
3093      char *name;                /* filename */
3094      int fd;                    /* file descriptor */
3095      int rw;                    /* read/write */
3096 {
3097   struct stat stat_pkt;
3098   struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3099 #ifdef USE_MMAP
3100   static int page_size;
3101 #endif
3102
3103   if (fstat (fd, &stat_pkt) < 0)
3104     fatal_perror ("fstat %s", name);
3105
3106   p->name         = name;
3107   p->size         = stat_pkt.st_size;
3108   p->rounded_size = stat_pkt.st_size;
3109   p->fd           = fd;
3110   p->rw           = rw;
3111
3112 #ifdef USE_MMAP
3113   if (debug)
3114     fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3115
3116   if (page_size == 0)
3117     page_size = sysconf (_SC_PAGE_SIZE);
3118
3119   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3120   p->start = mmap ((caddr_t)0,
3121                    (rw) ? p->rounded_size : p->size,
3122                    (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3123                    MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3124                    fd,
3125                    0L);
3126
3127   if (p->start != (char *)0 && p->start != (char *)-1)
3128     p->use_mmap = 1;
3129
3130   else
3131 #endif /* USE_MMAP */
3132     {
3133       long len;
3134
3135       if (debug)
3136         fprintf (stderr, "read %s\n", name);
3137
3138       p->use_mmap = 0;
3139       p->start = xmalloc (p->size);
3140       if (lseek (fd, 0L, SEEK_SET) < 0)
3141         fatal_perror ("lseek to 0 on %s", name);
3142
3143       len = read (fd, p->start, p->size);
3144       if (len < 0)
3145         fatal_perror ("read %s", name);
3146
3147       if (len != p->size)
3148         fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3149     }
3150
3151   return p;
3152 }
3153 \f
3154 /* Do anything necessary to write a file back from memory.  */
3155
3156 static void
3157 end_file (ptr)
3158      struct file_info *ptr;     /* file information block */
3159 {
3160 #ifdef USE_MMAP
3161   if (ptr->use_mmap)
3162     {
3163       if (ptr->rw)
3164         {
3165           if (debug)
3166             fprintf (stderr, "msync %s\n", ptr->name);
3167
3168           if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3169             fatal_perror ("msync %s", ptr->name);
3170         }
3171
3172       if (debug)
3173         fprintf (stderr, "munmap %s\n", ptr->name);
3174
3175       if (munmap (ptr->start, ptr->size))
3176         fatal_perror ("munmap %s", ptr->name);
3177     }
3178   else
3179 #endif /* USE_MMAP */
3180     {
3181       if (ptr->rw)
3182         {
3183           long len;
3184
3185           if (debug)
3186             fprintf (stderr, "write %s\n", ptr->name);
3187
3188           if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3189             fatal_perror ("lseek to 0 on %s", ptr->name);
3190
3191           len = write (ptr->fd, ptr->start, ptr->size);
3192           if (len < 0)
3193             fatal_perror ("read %s", ptr->name);
3194
3195           if (len != ptr->size)
3196             fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3197         }
3198
3199       free (ptr->start);
3200     }
3201
3202   free (ptr);
3203 }
3204
3205 #endif /* OBJECT_FORMAT_ROSE */