OSDN Git Service

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