OSDN Git Service

Daily bump.
[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       if (*q == '-' && q[1] == 'B')
1100         {
1101           *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1102           if (q[2] == 0)
1103             {
1104               q = extract_string (&p);
1105               *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1106             }
1107         }
1108     }
1109   obstack_free (&temporary_obstack, temporary_firstobj);
1110   *c_ptr++ = "-fno-exceptions";
1111   *c_ptr++ = "-w";
1112
1113   /* !!! When GCC calls collect2,
1114      it does not know whether it is calling collect2 or ld.
1115      So collect2 cannot meaningfully understand any options
1116      except those ld understands.
1117      If you propose to make GCC pass some other option,
1118      just imagine what will happen if ld is really ld!!!  */
1119
1120   /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
1121   /* After the first file, put in the c++ rt0.  */
1122
1123   first_file = 1;
1124   while ((arg = *++argv) != (char *) 0)
1125     {
1126       *ld1++ = *ld2++ = arg;
1127
1128       if (arg[0] == '-')
1129         {
1130           switch (arg[1])
1131             {
1132 #ifdef COLLECT_EXPORT_LIST
1133             /* We want to disable automatic exports on AIX when user
1134                explicitly puts an export list in command line */
1135             case 'b':
1136               if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1137                 export_flag = 1;
1138               else if (arg[2] == '6' && arg[3] == '4')
1139                 aix64_flag = 1;
1140               break;
1141 #endif
1142
1143             case 'd':
1144               if (!strcmp (arg, "-debug"))
1145                 {
1146                   /* Already parsed.  */
1147                   ld1--;
1148                   ld2--;
1149                 }
1150               break;
1151
1152             case 'l':
1153               if (first_file)
1154                 {
1155                   /* place o_file BEFORE this argument! */
1156                   first_file = 0;
1157                   ld2--;
1158                   *ld2++ = o_file;
1159                   *ld2++ = arg;
1160                 }
1161 #ifdef COLLECT_EXPORT_LIST
1162               {
1163                 /* Resolving full library name.  */
1164                 const char *s = resolve_lib_name (arg+2);
1165
1166                 /* Saving a full library name.  */
1167                 add_to_list (&libs, s);
1168               }
1169 #endif
1170               break;
1171
1172 #ifdef COLLECT_EXPORT_LIST
1173             /* Saving directories where to search for libraries.  */
1174             case 'L':
1175               add_prefix (&cmdline_lib_dirs, arg+2);
1176               break;
1177 #endif
1178
1179             case 'o':
1180               if (arg[2] == '\0')
1181                 output_file = *ld1++ = *ld2++ = *++argv;
1182               else if (1
1183 #ifdef SWITCHES_NEED_SPACES
1184                        && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1185 #endif
1186                        )
1187
1188                 output_file = &arg[2];
1189               break;
1190
1191             case 'r':
1192               if (arg[2] == '\0')
1193                 rflag = 1;
1194               break;
1195
1196             case 's':
1197               if (arg[2] == '\0' && do_collecting)
1198                 {
1199                   /* We must strip after the nm run, otherwise C++ linking
1200                      will not work.  Thus we strip in the second ld run, or
1201                      else with strip if there is no second ld run.  */
1202                   strip_flag = 1;
1203                   ld1--;
1204                 }
1205               break;
1206
1207             case 'v':
1208               if (arg[2] == '\0')
1209                 vflag = 1;
1210               break;
1211             }
1212         }
1213       else if ((p = strrchr (arg, '.')) != (char *) 0
1214                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1215                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0))
1216         {
1217           if (first_file)
1218             {
1219               first_file = 0;
1220               if (p[1] == 'o')
1221                 *ld2++ = o_file;
1222               else
1223                 {
1224                   /* place o_file BEFORE this argument! */
1225                   ld2--;
1226                   *ld2++ = o_file;
1227                   *ld2++ = arg;
1228                 }
1229             }
1230           if (p[1] == 'o' || p[1] == 'l')
1231             *object++ = arg;
1232 #ifdef COLLECT_EXPORT_LIST
1233           /* libraries can be specified directly, i.e. without -l flag.  */
1234           else
1235             { 
1236               /* Saving a full library name.  */
1237               add_to_list (&libs, arg);
1238             }
1239 #endif
1240         }
1241     }
1242
1243 #ifdef COLLECT_EXPORT_LIST
1244   /* This is added only for debugging purposes.  */
1245   if (debug)
1246     {
1247       fprintf (stderr, "List of libraries:\n");
1248       dump_list (stderr, "\t", libs.first);
1249     }
1250
1251   /* The AIX linker will discard static constructors in object files if
1252      nothing else in the file is referenced, so look at them first.  */
1253   {
1254       const char **export_object_lst = (const char **)object_lst;
1255
1256       while (export_object_lst < object)
1257         scan_prog_file (*export_object_lst++, PASS_OBJ);
1258   }
1259   {
1260     struct id *list = libs.first;
1261
1262     for (; list; list = list->next)
1263       scan_prog_file (list->name, PASS_FIRST);
1264   }
1265
1266   if (exports.first)
1267     {
1268       char *buf = xmalloc (strlen (export_file) + 5);
1269
1270       sprintf (buf, "-bE:%s", export_file);
1271       *ld1++ = buf;
1272       *ld2++ = buf;
1273
1274       exportf = fopen (export_file, "w");
1275       if (exportf == (FILE *) 0)
1276         fatal_perror ("fopen %s", export_file);
1277       write_aix_file (exportf, exports.first);
1278       if (fclose (exportf))
1279         fatal_perror ("fclose %s", export_file);
1280     }
1281 #endif
1282
1283   *c_ptr++ = c_file;
1284   *c_ptr = *ld1 = *object = (char *) 0;
1285
1286   if (vflag)
1287     {
1288       notice ("collect2 version %s", version_string);
1289 #ifdef TARGET_VERSION
1290       TARGET_VERSION;
1291 #endif
1292       fprintf (stderr, "\n");
1293     }
1294
1295   if (debug)
1296     {
1297       const char *ptr;
1298       fprintf (stderr, "ld_file_name        = %s\n",
1299                (ld_file_name ? ld_file_name : "not found"));
1300       fprintf (stderr, "c_file_name         = %s\n",
1301                (c_file_name ? c_file_name : "not found"));
1302       fprintf (stderr, "nm_file_name        = %s\n",
1303                (nm_file_name ? nm_file_name : "not found"));
1304 #ifdef LDD_SUFFIX
1305       fprintf (stderr, "ldd_file_name       = %s\n",
1306                (ldd_file_name ? ldd_file_name : "not found"));
1307 #endif
1308       fprintf (stderr, "strip_file_name     = %s\n",
1309                (strip_file_name ? strip_file_name : "not found"));
1310       fprintf (stderr, "c_file              = %s\n",
1311                (c_file ? c_file : "not found"));
1312       fprintf (stderr, "o_file              = %s\n",
1313                (o_file ? o_file : "not found"));
1314
1315       ptr = getenv ("COLLECT_GCC_OPTIONS");
1316       if (ptr)
1317         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1318
1319       ptr = getenv ("COLLECT_GCC");
1320       if (ptr)
1321         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1322
1323       ptr = getenv ("COMPILER_PATH");
1324       if (ptr)
1325         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1326
1327       ptr = getenv (LIBRARY_PATH_ENV);
1328       if (ptr)
1329         fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
1330
1331       fprintf (stderr, "\n");
1332     }
1333
1334   /* Load the program, searching all libraries and attempting to provide
1335      undefined symbols from repository information.  */
1336
1337   /* On AIX we do this later.  */
1338 #ifndef COLLECT_EXPORT_LIST
1339   do_tlink (ld1_argv, object_lst);
1340 #endif
1341
1342   /* If -r or they will be run via some other method, do not build the
1343      constructor or destructor list, just return now.  */
1344   if (rflag
1345 #ifndef COLLECT_EXPORT_LIST
1346       || ! do_collecting
1347 #endif
1348       )
1349     {
1350 #ifdef COLLECT_EXPORT_LIST
1351       /* Do the link we avoided above if we are exiting.  */
1352       do_tlink (ld1_argv, object_lst);
1353
1354       /* But make sure we delete the export file we may have created.  */
1355       if (export_file != 0 && export_file[0])
1356         maybe_unlink (export_file);
1357 #endif
1358       maybe_unlink (c_file);
1359       maybe_unlink (o_file);
1360       return 0;
1361     }
1362
1363   /* Examine the namelist with nm and search it for static constructors
1364      and destructors to call.
1365      Write the constructor and destructor tables to a .s file and reload.  */
1366
1367   /* On AIX we already scanned for global constructors/destructors.  */
1368 #ifndef COLLECT_EXPORT_LIST
1369   scan_prog_file (output_file, PASS_FIRST);
1370 #endif
1371
1372 #ifdef SCAN_LIBRARIES
1373   scan_libraries (output_file);
1374 #endif
1375
1376   if (debug)
1377     {
1378       notice ("%d constructor(s) found\n", constructors.number);
1379       notice ("%d destructor(s)  found\n", destructors.number);
1380       notice ("%d frame table(s) found\n", frame_tables.number);
1381     }
1382
1383   if (constructors.number == 0 && destructors.number == 0
1384       && frame_tables.number == 0
1385 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1386       /* If we will be running these functions ourselves, we want to emit
1387          stubs into the shared library so that we do not have to relink
1388          dependent programs when we add static objects.  */
1389       && ! shared_obj
1390 #endif
1391       )
1392     {
1393 #ifdef COLLECT_EXPORT_LIST
1394       /* Do tlink without additional code generation */
1395       do_tlink (ld1_argv, object_lst);
1396 #endif
1397       /* Strip now if it was requested on the command line.  */
1398       if (strip_flag)
1399         {
1400           char **real_strip_argv = (char **) xcalloc (sizeof (char *), 3);
1401           const char ** strip_argv = (const char **) real_strip_argv;
1402           
1403           strip_argv[0] = strip_file_name;
1404           strip_argv[1] = output_file;
1405           strip_argv[2] = (char *) 0;
1406           fork_execute ("strip", real_strip_argv);
1407         }
1408
1409 #ifdef COLLECT_EXPORT_LIST
1410       maybe_unlink (export_file);
1411 #endif
1412       maybe_unlink (c_file);
1413       maybe_unlink (o_file);
1414       return 0;
1415     }
1416
1417   /* Sort ctor and dtor lists by priority. */
1418   sort_ids (&constructors);
1419   sort_ids (&destructors);
1420
1421   maybe_unlink(output_file);
1422   outf = fopen (c_file, "w");
1423   if (outf == (FILE *) 0)
1424     fatal_perror ("fopen %s", c_file);
1425
1426   write_c_file (outf, c_file);
1427
1428   if (fclose (outf))
1429     fatal_perror ("fclose %s", c_file);
1430
1431   /* Tell the linker that we have initializer and finalizer functions.  */
1432 #ifdef LD_INIT_SWITCH
1433 #ifdef COLLECT_EXPORT_LIST
1434   {
1435     /* option name + functions + colons + NULL */
1436     char *buf = xmalloc (strlen (LD_INIT_SWITCH)
1437                          + strlen(initname) + strlen(fininame) + 3);
1438     sprintf (buf, "%s:%s:%s", LD_INIT_SWITCH, initname, fininame);
1439     *ld2++ = buf;
1440   }
1441 #else
1442   *ld2++ = LD_INIT_SWITCH;
1443   *ld2++ = initname;
1444   *ld2++ = LD_FINI_SWITCH;
1445   *ld2++ = fininame;
1446 #endif
1447 #endif
1448
1449 #ifdef COLLECT_EXPORT_LIST
1450   if (shared_obj)
1451     {
1452       /* If we did not add export flag to link arguments before, add it to
1453          second link phase now.  No new exports should have been added.  */
1454       if (! exports.first)
1455         {
1456           char *buf = xmalloc (strlen (export_file) + 5);
1457
1458           sprintf (buf, "-bE:%s", export_file);
1459           *ld2++ = buf;
1460         }
1461
1462       add_to_list (&exports, initname);
1463       add_to_list (&exports, fininame);
1464       add_to_list (&exports, "_GLOBAL__DI");
1465       add_to_list (&exports, "_GLOBAL__DD");
1466       exportf = fopen (export_file, "w");
1467       if (exportf == (FILE *) 0)
1468         fatal_perror ("fopen %s", export_file);
1469       write_aix_file (exportf, exports.first);
1470       if (fclose (exportf))
1471         fatal_perror ("fclose %s", export_file);
1472     }
1473 #endif
1474
1475   /* End of arguments to second link phase.  */
1476   *ld2 = (char*) 0;
1477
1478   if (debug)
1479     {
1480       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1481                output_file, c_file);
1482       write_c_file (stderr, "stderr");
1483       fprintf (stderr, "========== end of c_file\n\n");
1484 #ifdef COLLECT_EXPORT_LIST
1485       fprintf (stderr, "\n========== export_file = %s\n", export_file);
1486       write_aix_file (stderr, exports.first);
1487       fprintf (stderr, "========== end of export_file\n\n");
1488 #endif
1489     }
1490
1491   /* Assemble the constructor and destructor tables.
1492      Link the tables in with the rest of the program.  */
1493
1494   fork_execute ("gcc",  c_argv);
1495 #ifdef COLLECT_EXPORT_LIST
1496   /* On AIX we must call tlink because of possible templates resolution */
1497   do_tlink (ld2_argv, object_lst);
1498 #else
1499   /* Otherwise, simply call ld because tlink is already done */
1500   fork_execute ("ld", ld2_argv);
1501
1502   /* Let scan_prog_file do any final mods (OSF/rose needs this for
1503      constructors/destructors in shared libraries.  */
1504   scan_prog_file (output_file, PASS_SECOND);
1505 #endif 
1506
1507   maybe_unlink (c_file);
1508   maybe_unlink (o_file);
1509
1510 #ifdef COLLECT_EXPORT_LIST
1511   maybe_unlink (export_file);
1512 #endif
1513
1514   return 0;
1515 }
1516
1517 \f
1518 /* Wait for a process to finish, and exit if a non-zero status is found.  */
1519
1520 int
1521 collect_wait (prog)
1522      const char *prog;
1523 {
1524   int status;
1525
1526   pwait (pexecute_pid, &status, 0);
1527   if (status)
1528     {
1529       if (WIFSIGNALED (status))
1530         {
1531           int sig = WTERMSIG (status);
1532           error ("%s terminated with signal %d [%s]%s",
1533                  prog, sig, strsignal(sig),
1534                  status & 0200 ? "" : ", core dumped");
1535           collect_exit (FATAL_EXIT_CODE);
1536         }
1537
1538       if (WIFEXITED (status))
1539         return WEXITSTATUS (status);
1540     }
1541   return 0;
1542 }
1543
1544 static void
1545 do_wait (prog)
1546      const char *prog;
1547 {
1548   int ret = collect_wait (prog);
1549   if (ret != 0)
1550     {
1551       error ("%s returned %d exit status", prog, ret);
1552       collect_exit (ret);
1553     }
1554 }
1555
1556 \f
1557 /* Execute a program, and wait for the reply.  */
1558
1559 void
1560 collect_execute (prog, argv, redir)
1561      const char *prog;
1562      char **argv;
1563      const char *redir;
1564 {
1565   char *errmsg_fmt;
1566   char *errmsg_arg;
1567   int redir_handle = -1;
1568   int stdout_save = -1;
1569   int stderr_save = -1;
1570
1571   if (vflag || debug)
1572     {
1573       char **p_argv;
1574       const char *str;
1575
1576       if (argv[0])
1577         fprintf (stderr, "%s", argv[0]);
1578       else
1579         notice ("[cannot find %s]", prog);
1580
1581       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1582         fprintf (stderr, " %s", str);
1583
1584       fprintf (stderr, "\n");
1585     }
1586
1587   fflush (stdout);
1588   fflush (stderr);
1589
1590   /* If we cannot find a program we need, complain error.  Do this here
1591      since we might not end up needing something that we could not find.  */
1592
1593   if (argv[0] == 0)
1594     fatal ("cannot find `%s'", prog);
1595
1596   if (redir)
1597     {
1598       /* Open response file.  */
1599       redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1600
1601       /* Duplicate the stdout and stderr file handles
1602          so they can be restored later.  */
1603       stdout_save = dup (STDOUT_FILENO);
1604       if (stdout_save == -1)
1605         fatal_perror ("redirecting stdout: %s", redir);
1606       stderr_save = dup (STDERR_FILENO);
1607       if (stderr_save == -1)
1608         fatal_perror ("redirecting stdout: %s", redir);
1609
1610       /* Redirect stdout & stderr to our response file.  */
1611       dup2 (redir_handle, STDOUT_FILENO);
1612       dup2 (redir_handle, STDERR_FILENO);
1613     }
1614
1615   pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
1616                            &errmsg_fmt, &errmsg_arg,
1617                            (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1618
1619   if (redir)
1620     {
1621       /* Restore stdout and stderr to their previous settings.  */
1622       dup2 (stdout_save, STDOUT_FILENO);
1623       dup2 (stderr_save, STDERR_FILENO);
1624
1625       /* Close reponse file.  */
1626       close (redir_handle);
1627     }
1628
1629  if (pexecute_pid == -1)
1630    fatal_perror (errmsg_fmt, errmsg_arg);
1631 }
1632
1633 static void
1634 fork_execute (prog, argv)
1635      const char *prog;
1636      char **argv;
1637 {
1638   collect_execute (prog, argv, NULL);
1639   do_wait (prog);
1640 }
1641 \f
1642 /* Unlink a file unless we are debugging.  */
1643
1644 static void
1645 maybe_unlink (file)
1646      const char *file;
1647 {
1648   if (!debug)
1649     unlink (file);
1650   else
1651     notice ("[Leaving %s]\n", file);
1652 }
1653
1654 \f
1655 static long sequence_number = 0;
1656
1657 /* Add a name to a linked list.  */
1658
1659 static void
1660 add_to_list (head_ptr, name)
1661      struct head *head_ptr;
1662      const char *name;
1663 {
1664   struct id *newid
1665     = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1666   struct id *p;
1667   strcpy (newid->name, name);
1668
1669   if (head_ptr->first)
1670     head_ptr->last->next = newid;
1671   else
1672     head_ptr->first = newid;
1673
1674   /* Check for duplicate symbols.  */
1675   for (p = head_ptr->first;
1676        strcmp (name, p->name) != 0;
1677        p = p->next)
1678     ;
1679   if (p != newid)
1680     {
1681       head_ptr->last->next = 0;
1682       free (newid);
1683       return;
1684     }
1685
1686   newid->sequence = ++sequence_number;
1687   head_ptr->last = newid;
1688   head_ptr->number++;
1689 }
1690
1691 /* Grab the init priority number from an init function name that
1692    looks like "_GLOBAL_.I.12345.foo".  */
1693
1694 static int
1695 extract_init_priority (name)
1696      const char *name;
1697 {
1698   int pos = 0, pri;
1699
1700   while (name[pos] == '_')
1701     ++pos;
1702   pos += 10; /* strlen ("GLOBAL__X_") */
1703
1704   /* Extract init_p number from ctor/dtor name. */
1705   pri = atoi (name + pos);
1706   return pri ? pri : DEFAULT_INIT_PRIORITY;
1707 }
1708
1709 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1710    ctors will be run from right to left, dtors from left to right.  */
1711
1712 static void
1713 sort_ids (head_ptr)
1714      struct head *head_ptr;
1715 {
1716   /* id holds the current element to insert.  id_next holds the next
1717      element to insert.  id_ptr iterates through the already sorted elements
1718      looking for the place to insert id.  */
1719   struct id *id, *id_next, **id_ptr;
1720
1721   id = head_ptr->first;
1722
1723   /* We don't have any sorted elements yet.  */
1724   head_ptr->first = NULL;
1725
1726   for (; id; id = id_next)
1727     {
1728       id_next = id->next;
1729       id->sequence = extract_init_priority (id->name);
1730
1731       for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1732         if (*id_ptr == NULL
1733             /* If the sequence numbers are the same, we put the id from the
1734                file later on the command line later in the list.  */
1735             || id->sequence > (*id_ptr)->sequence
1736             /* Hack: do lexical compare, too.
1737             || (id->sequence == (*id_ptr)->sequence
1738                 && strcmp (id->name, (*id_ptr)->name) > 0) */
1739             )
1740           {
1741             id->next = *id_ptr;
1742             *id_ptr = id;
1743             break;
1744           }
1745     }
1746
1747   /* Now set the sequence numbers properly so write_c_file works.  */
1748   for (id = head_ptr->first; id; id = id->next)
1749     id->sequence = ++sequence_number;
1750 }
1751
1752 /* Write: `prefix', the names on list LIST, `suffix'.  */
1753
1754 static void
1755 write_list (stream, prefix, list)
1756      FILE *stream;
1757      const char *prefix;
1758      struct id *list;
1759 {
1760   while (list)
1761     {
1762       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1763       list = list->next;
1764     }
1765 }
1766
1767 #ifdef COLLECT_EXPORT_LIST
1768 /* This function is really used only on AIX, but may be useful.  */
1769 static int
1770 is_in_list (prefix, list)
1771      const char *prefix;
1772      struct id *list;
1773 {
1774   while (list)
1775     {
1776       if (!strcmp (prefix, list->name)) return 1;
1777       list = list->next;
1778     }
1779     return 0;
1780 }
1781 #endif
1782
1783 /* Added for debugging purpose.  */
1784 #ifdef COLLECT_EXPORT_LIST
1785 static void
1786 dump_list (stream, prefix, list)
1787      FILE *stream;
1788      const char *prefix;
1789      struct id *list;
1790 {
1791   while (list)
1792     {
1793       fprintf (stream, "%s%s,\n", prefix, list->name);
1794       list = list->next;
1795     }
1796 }
1797 #endif
1798
1799 #if 0
1800 static void
1801 dump_prefix_list (stream, prefix, list)
1802      FILE *stream;
1803      const char *prefix;
1804      struct prefix_list *list;
1805 {
1806   while (list)
1807     {
1808       fprintf (stream, "%s%s,\n", prefix, list->prefix);
1809       list = list->next;
1810     }
1811 }
1812 #endif
1813
1814 static void
1815 write_list_with_asm (stream, prefix, list)
1816      FILE *stream;
1817      const char *prefix;
1818      struct id *list;
1819 {
1820   while (list)
1821     {
1822       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1823                prefix, list->sequence, list->name);
1824       list = list->next;
1825     }
1826 }
1827
1828 /* Write out the constructor and destructor tables statically (for a shared
1829    object), along with the functions to execute them.  */
1830
1831 static void
1832 write_c_file_stat (stream, name)
1833      FILE *stream;
1834      const char *name ATTRIBUTE_UNUSED;
1835 {
1836   const char *p, *q;
1837   char *prefix, *r;
1838   int frames = (frame_tables.number > 0);
1839
1840   /* Figure out name of output_file, stripping off .so version.  */
1841   p = strrchr (output_file, '/');
1842   if (p == 0)
1843     p = output_file;
1844   else
1845     p++;
1846   q = p;
1847   while (q)
1848     {
1849       q = strchr (q,'.');
1850       if (q == 0)
1851         {
1852           q = p + strlen (p);
1853           break;
1854         }
1855       else
1856         {
1857           if (strncmp (q, ".so", 3) == 0)
1858             {
1859               q += 3;
1860               break;
1861             }
1862           else
1863             q++;
1864         }
1865     }
1866   /* q points to null at end of the string (or . of the .so version) */
1867   prefix = xmalloc (q - p + 1);
1868   strncpy (prefix, p, q - p);
1869   prefix[q - p] = 0;
1870   for (r = prefix; *r; r++)
1871     if (!ISALNUM ((unsigned char)*r))
1872       *r = '_';
1873   if (debug)
1874     notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
1875             output_file, prefix);
1876
1877 #define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
1878   initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
1879   sprintf (initname, INIT_NAME_FORMAT, prefix);
1880
1881 #define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
1882   fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
1883   sprintf (fininame, FINI_NAME_FORMAT, prefix);
1884
1885   free (prefix);
1886
1887   /* Write the tables as C code  */
1888
1889   fprintf (stream, "static int count;\n");
1890   fprintf (stream, "typedef void entry_pt();\n");
1891   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1892
1893   if (frames)
1894     {
1895       write_list_with_asm (stream, "extern void *", frame_tables.first);
1896
1897       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1898       write_list (stream, "\t\t&", frame_tables.first);
1899       fprintf (stream, "\t0\n};\n");
1900
1901       /* This must match what's in frame.h.  */
1902       fprintf (stream, "struct object {\n");
1903       fprintf (stream, "  void *pc_begin;\n");
1904       fprintf (stream, "  void *pc_end;\n");
1905       fprintf (stream, "  void *fde_begin;\n");
1906       fprintf (stream, "  void *fde_array;\n");
1907       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1908       fprintf (stream, "  struct object *next;\n");
1909       fprintf (stream, "};\n");
1910
1911       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1912       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1913
1914       fprintf (stream, "static void reg_frame () {\n");
1915       fprintf (stream, "\tstatic struct object ob;\n");
1916       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1917       fprintf (stream, "\t}\n");
1918
1919       fprintf (stream, "static void dereg_frame () {\n");
1920       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1921       fprintf (stream, "\t}\n");
1922     }
1923
1924   fprintf (stream, "void %s() {\n", initname);
1925   if (constructors.number > 0 || frames)
1926     {
1927       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1928       write_list (stream, "\t\t", constructors.first);
1929       if (frames)
1930         fprintf (stream, "\treg_frame,\n");
1931       fprintf (stream, "\t};\n");
1932       fprintf (stream, "\tentry_pt **p;\n");
1933       fprintf (stream, "\tif (count++ != 0) return;\n");
1934       fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
1935       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1936     }
1937   else
1938     fprintf (stream, "\t++count;\n");
1939   fprintf (stream, "}\n");
1940   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1941   fprintf (stream, "void %s() {\n", fininame);
1942   if (destructors.number > 0 || frames)
1943     {
1944       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1945       write_list (stream, "\t\t", destructors.first);
1946       if (frames)
1947         fprintf (stream, "\tdereg_frame,\n");
1948       fprintf (stream, "\t};\n");
1949       fprintf (stream, "\tentry_pt **p;\n");
1950       fprintf (stream, "\tif (--count != 0) return;\n");
1951       fprintf (stream, "\tp = dtors;\n");
1952       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1953                destructors.number + frames);
1954     }
1955   fprintf (stream, "}\n");
1956
1957   if (shared_obj)
1958     {
1959       fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
1960       fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
1961     }
1962 }
1963
1964 /* Write the constructor/destructor tables.  */
1965
1966 #ifndef LD_INIT_SWITCH
1967 static void
1968 write_c_file_glob (stream, name)
1969      FILE *stream;
1970      const char *name ATTRIBUTE_UNUSED;
1971 {
1972   /* Write the tables as C code  */
1973
1974   int frames = (frame_tables.number > 0);
1975
1976   fprintf (stream, "typedef void entry_pt();\n\n");
1977     
1978   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1979
1980   if (frames)
1981     {
1982       write_list_with_asm (stream, "extern void *", frame_tables.first);
1983
1984       fprintf (stream, "\tstatic void *frame_table[] = {\n");
1985       write_list (stream, "\t\t&", frame_tables.first);
1986       fprintf (stream, "\t0\n};\n");
1987
1988       /* This must match what's in frame.h.  */
1989       fprintf (stream, "struct object {\n");
1990       fprintf (stream, "  void *pc_begin;\n");
1991       fprintf (stream, "  void *pc_end;\n");
1992       fprintf (stream, "  void *fde_begin;\n");
1993       fprintf (stream, "  void *fde_array;\n");
1994       fprintf (stream, "  __SIZE_TYPE__ count;\n");
1995       fprintf (stream, "  struct object *next;\n");
1996       fprintf (stream, "};\n");
1997
1998       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1999       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2000
2001       fprintf (stream, "static void reg_frame () {\n");
2002       fprintf (stream, "\tstatic struct object ob;\n");
2003       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2004       fprintf (stream, "\t}\n");
2005
2006       fprintf (stream, "static void dereg_frame () {\n");
2007       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2008       fprintf (stream, "\t}\n");
2009     }
2010
2011   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
2012   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
2013   write_list (stream, "\t", constructors.first);
2014   if (frames)
2015     fprintf (stream, "\treg_frame,\n");
2016   fprintf (stream, "\t0\n};\n\n");
2017
2018   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2019
2020   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
2021   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
2022   write_list (stream, "\t", destructors.first);
2023   if (frames)
2024     fprintf (stream, "\tdereg_frame,\n");
2025   fprintf (stream, "\t0\n};\n\n");
2026
2027   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
2028   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
2029 }
2030 #endif /* ! LD_INIT_SWITCH */
2031
2032 static void
2033 write_c_file (stream, name)
2034      FILE *stream;
2035      const char *name;
2036 {
2037   fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
2038 #ifndef LD_INIT_SWITCH
2039   if (! shared_obj)
2040     write_c_file_glob (stream, name);
2041   else
2042 #endif
2043     write_c_file_stat (stream, name);
2044   fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
2045 }
2046
2047 #ifdef COLLECT_EXPORT_LIST
2048 static void
2049 write_aix_file (stream, list)
2050      FILE *stream;
2051      struct id *list;
2052 {
2053   for (; list; list = list->next)
2054     {
2055       fputs (list->name, stream);
2056       putc ('\n', stream);
2057     }
2058 }
2059 #endif
2060 \f
2061 #ifdef OBJECT_FORMAT_NONE
2062
2063 /* Generic version to scan the name list of the loaded program for
2064    the symbols g++ uses for static constructors and destructors.
2065
2066    The constructor table begins at __CTOR_LIST__ and contains a count
2067    of the number of pointers (or -1 if the constructors are built in a
2068    separate section by the linker), followed by the pointers to the
2069    constructor functions, terminated with a null pointer.  The
2070    destructor table has the same format, and begins at __DTOR_LIST__.  */
2071
2072 static void
2073 scan_prog_file (prog_name, which_pass)
2074      const char *prog_name;
2075      enum pass which_pass;
2076 {
2077   void (*int_handler) PARAMS ((int));
2078   void (*quit_handler) PARAMS ((int));
2079   char *real_nm_argv[4];
2080   const char **nm_argv = (const char **) real_nm_argv;
2081   int pid;
2082   int argc = 0;
2083   int pipe_fd[2];
2084   char *p, buf[1024];
2085   FILE *inf;
2086
2087   if (which_pass == PASS_SECOND)
2088     return;
2089
2090   /* If we do not have an `nm', complain.  */
2091   if (nm_file_name == 0)
2092     fatal ("cannot find `nm'");
2093
2094   nm_argv[argc++] = nm_file_name;
2095   if (NM_FLAGS[0] != '\0')
2096     nm_argv[argc++] = NM_FLAGS;
2097
2098   nm_argv[argc++] = prog_name;
2099   nm_argv[argc++] = (char *) 0;
2100
2101   if (pipe (pipe_fd) < 0)
2102     fatal_perror ("pipe");
2103
2104   inf = fdopen (pipe_fd[0], "r");
2105   if (inf == (FILE *) 0)
2106     fatal_perror ("fdopen");
2107
2108   /* Trace if needed.  */
2109   if (vflag)
2110     {
2111       const char **p_argv;
2112       const char *str;
2113
2114       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2115         fprintf (stderr, " %s", str);
2116
2117       fprintf (stderr, "\n");
2118     }
2119
2120   fflush (stdout);
2121   fflush (stderr);
2122
2123   /* Spawn child nm on pipe */
2124   pid = vfork ();
2125   if (pid == -1)
2126     fatal_perror (VFORK_STRING);
2127
2128   if (pid == 0)                 /* child context */
2129     {
2130       /* setup stdout */
2131       if (dup2 (pipe_fd[1], 1) < 0)
2132         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2133
2134       if (close (pipe_fd[0]) < 0)
2135         fatal_perror ("close %d", pipe_fd[0]);
2136
2137       if (close (pipe_fd[1]) < 0)
2138         fatal_perror ("close %d", pipe_fd[1]);
2139
2140       execv (nm_file_name, real_nm_argv);
2141       fatal_perror ("execvp %s", nm_file_name);
2142     }
2143
2144   /* Parent context from here on.  */
2145   int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
2146 #ifdef SIGQUIT
2147   quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
2148 #endif
2149
2150   if (close (pipe_fd[1]) < 0)
2151     fatal_perror ("close %d", pipe_fd[1]);
2152
2153   if (debug)
2154     fprintf (stderr, "\nnm output with constructors/destructors.\n");
2155
2156   /* Read each line of nm output.  */
2157   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2158     {
2159       int ch, ch2;
2160       char *name, *end;
2161
2162       /* If it contains a constructor or destructor name, add the name
2163          to the appropriate list.  */
2164
2165       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2166         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2167           break;
2168
2169       if (ch != '_')
2170         continue;
2171   
2172       name = p;
2173       /* Find the end of the symbol name.
2174          Do not include `|', because Encore nm can tack that on the end.  */
2175       for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2176            end++)
2177         continue;
2178
2179
2180       *end = '\0';
2181       switch (is_ctor_dtor (name))
2182         {
2183         case 1:
2184           if (which_pass != PASS_LIB)
2185             add_to_list (&constructors, name);
2186           break;
2187
2188         case 2:
2189           if (which_pass != PASS_LIB)
2190             add_to_list (&destructors, name);
2191           break;
2192
2193         case 3:
2194           if (which_pass != PASS_LIB)
2195             fatal ("init function found in object %s", prog_name);
2196 #ifndef LD_INIT_SWITCH
2197           add_to_list (&constructors, name);
2198 #endif
2199           break;
2200
2201         case 4:
2202           if (which_pass != PASS_LIB)
2203             fatal ("fini function found in object %s", prog_name);
2204 #ifndef LD_FINI_SWITCH
2205           add_to_list (&destructors, name);
2206 #endif
2207           break;
2208
2209         case 5:
2210           if (which_pass != PASS_LIB)
2211             add_to_list (&frame_tables, name);
2212           break;
2213
2214         default:                /* not a constructor or destructor */
2215           continue;
2216         }
2217
2218       if (debug)
2219         fprintf (stderr, "\t%s\n", buf);
2220     }
2221
2222   if (debug)
2223     fprintf (stderr, "\n");
2224
2225   if (fclose (inf) != 0)
2226     fatal_perror ("fclose");
2227
2228   do_wait (nm_file_name);
2229
2230   signal (SIGINT,  int_handler);
2231 #ifdef SIGQUIT
2232   signal (SIGQUIT, quit_handler);
2233 #endif
2234 }
2235
2236 #if SUNOS4_SHARED_LIBRARIES
2237
2238 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2239    that the output file depends upon and their initialization/finalization
2240    routines, if any.  */
2241
2242 #include <a.out.h>
2243 #include <fcntl.h>
2244 #include <link.h>
2245 #include <sys/mman.h>
2246 #include <sys/param.h>
2247 #include <unistd.h>
2248 #include <sys/dir.h>
2249
2250 /* pointers to the object file */
2251 unsigned object;        /* address of memory mapped file */
2252 unsigned objsize;       /* size of memory mapped to file */
2253 char * code;            /* pointer to code segment */
2254 char * data;            /* pointer to data segment */
2255 struct nlist *symtab;   /* pointer to symbol table */
2256 struct link_dynamic *ld;
2257 struct link_dynamic_2 *ld_2;
2258 struct head libraries;
2259
2260 /* Map the file indicated by NAME into memory and store its address.  */
2261
2262 static void mapfile                     PARAMS ((const char *));
2263
2264 static void
2265 mapfile (name)
2266      const char *name;
2267 {
2268   int fp;
2269   struct stat s;
2270   if ((fp = open (name, O_RDONLY)) == -1)
2271     fatal ("unable to open file '%s'", name);
2272   if (fstat (fp, &s) == -1)
2273     fatal ("unable to stat file '%s'", name);
2274
2275   objsize = s.st_size;
2276   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2277                             fp, 0);
2278   if (object == (unsigned)-1)
2279     fatal ("unable to mmap file '%s'", name);
2280
2281   close (fp);
2282 }
2283
2284 /* Helpers for locatelib.  */
2285
2286 static const char *libname;
2287
2288 static int libselect                    PARAMS ((struct direct *));
2289
2290 static int
2291 libselect (d)
2292      struct direct *d;
2293 {
2294   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2295 }
2296
2297 /* If one file has an additional numeric extension past LIBNAME, then put
2298    that one first in the sort.  If both files have additional numeric
2299    extensions, then put the one with the higher number first in the sort.
2300
2301    We must verify that the extension is numeric, because Sun saves the
2302    original versions of patched libraries with a .FCS extension.  Files with
2303    invalid extensions must go last in the sort, so that they will not be used.  */
2304 static int libcompare           PARAMS ((struct direct **, struct direct **));
2305
2306 static int
2307 libcompare (d1, d2)
2308      struct direct **d1, **d2;
2309 {
2310   int i1, i2 = strlen (libname);
2311   char *e1 = (*d1)->d_name + i2;
2312   char *e2 = (*d2)->d_name + i2;
2313
2314   while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2315          && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2316     {
2317       ++e1;
2318       ++e2;
2319       i1 = strtol (e1, &e1, 10);
2320       i2 = strtol (e2, &e2, 10);
2321       if (i1 != i2)
2322         return i1 - i2;
2323     }
2324
2325   if (*e1)
2326     {
2327       /* It has a valid numeric extension, prefer this one.  */
2328       if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2329         return 1;
2330       /* It has a invalid numeric extension, must prefer the other one.  */
2331       else
2332         return -1;
2333     }
2334   else if (*e2)
2335     {
2336       /* It has a valid numeric extension, prefer this one.  */
2337       if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2338         return -1;
2339       /* It has a invalid numeric extension, must prefer the other one.  */
2340       else
2341         return 1;
2342     }
2343   else
2344     return 0;
2345 }
2346
2347 /* Given the name NAME of a dynamic dependency, find its pathname and add
2348    it to the list of libraries.  */
2349 static void locatelib                   PARAMS ((const char *));
2350
2351 static void
2352 locatelib (name)
2353      const char *name;
2354 {
2355   static const char **l;
2356   static int cnt;
2357   char buf[MAXPATHLEN];
2358   char *p, *q;
2359   const char **pp;
2360
2361   if (l == 0)
2362     {
2363       char *ld_rules;
2364       char *ldr = 0;
2365       /* counting elements in array, need 1 extra for null */
2366       cnt = 1;  
2367       ld_rules = (char *) (ld_2->ld_rules + code);
2368       if (ld_rules)
2369         {
2370           cnt++;
2371           for (; *ld_rules != 0; ld_rules++)
2372             if (*ld_rules == ':')
2373               cnt++;
2374           ld_rules = (char *) (ld_2->ld_rules + code);
2375           ldr = xstrdup (ld_rules);
2376         }
2377       p = getenv ("LD_LIBRARY_PATH");
2378       q = 0;
2379       if (p)
2380         {
2381           cnt++;
2382           for (q = p ; *q != 0; q++)
2383             if (*q == ':')
2384               cnt++;
2385           q = xstrdup (p);
2386         }
2387       l = (const char **) xmalloc ((cnt + 3) * sizeof (char *));
2388       pp = l;
2389       if (ldr)
2390         {
2391           *pp++ = ldr;
2392           for (; *ldr != 0; ldr++) 
2393             if (*ldr == ':')
2394               {
2395                 *ldr++ = 0;
2396                 *pp++ = ldr;
2397               }
2398         }
2399       if (q)
2400         {
2401           *pp++ = q;
2402           for (; *q != 0; q++) 
2403             if (*q == ':')
2404               {
2405                 *q++ = 0;
2406                 *pp++ = q;
2407               }
2408         }
2409       /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2410       *pp++ = "/lib";
2411       *pp++ = "/usr/lib";
2412       *pp++ = "/usr/local/lib";
2413       *pp = 0;
2414     }
2415   libname = name;
2416   for (pp = l; *pp != 0 ; pp++)
2417     {
2418       struct direct **namelist;
2419       int entries;
2420       if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2421         {
2422           sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2423           add_to_list (&libraries, buf);
2424           if (debug)
2425             fprintf (stderr, "%s\n", buf);
2426           break;
2427         }
2428     }
2429   if (*pp == 0)
2430     {
2431       if (debug)
2432         notice ("not found\n");
2433       else
2434         fatal ("dynamic dependency %s not found", name);
2435     }
2436 }
2437
2438 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2439    that it depends upon and any constructors or destructors they contain.  */
2440
2441 static void 
2442 scan_libraries (prog_name)
2443      const char *prog_name;
2444 {
2445   struct exec *header;
2446   char *base;
2447   struct link_object *lo;
2448   char buff[MAXPATHLEN];
2449   struct id *list;
2450
2451   mapfile (prog_name);
2452   header = (struct exec *)object;
2453   if (N_BADMAG (*header))
2454     fatal ("bad magic number in file '%s'", prog_name);
2455   if (header->a_dynamic == 0)
2456     return;
2457
2458   code = (char *) (N_TXTOFF (*header) + (long) header);
2459   data = (char *) (N_DATOFF (*header) + (long) header);
2460   symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2461
2462   if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2463     {
2464       /* shared object */
2465       ld = (struct link_dynamic *) (symtab->n_value + code);
2466       base = code;
2467     }
2468   else
2469     {
2470       /* executable */
2471       ld = (struct link_dynamic *) data;
2472       base = code-PAGSIZ;
2473     }
2474
2475   if (debug)
2476     notice ("dynamic dependencies.\n");
2477
2478   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2479   for (lo = (struct link_object *) ld_2->ld_need; lo;
2480        lo = (struct link_object *) lo->lo_next)
2481     {
2482       char *name;
2483       lo = (struct link_object *) ((long) lo + code);
2484       name = (char *) (code + lo->lo_name);
2485       if (lo->lo_library)
2486         {
2487           if (debug)
2488             fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2489           sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2490           locatelib (buff);
2491         }
2492       else
2493         {
2494           if (debug)
2495             fprintf (stderr, "\t%s\n", name);
2496           add_to_list (&libraries, name);
2497         }
2498     }
2499
2500   if (debug)
2501     fprintf (stderr, "\n");
2502
2503   /* now iterate through the library list adding their symbols to
2504      the list.  */
2505   for (list = libraries.first; list; list = list->next)
2506     scan_prog_file (list->name, PASS_LIB);
2507 }
2508
2509 #else  /* SUNOS4_SHARED_LIBRARIES */
2510 #ifdef LDD_SUFFIX
2511
2512 /* Use the List Dynamic Dependencies program to find shared libraries that
2513    the output file depends upon and their initialization/finalization
2514    routines, if any.  */
2515
2516 static void 
2517 scan_libraries (prog_name)
2518      const char *prog_name;
2519 {
2520   static struct head libraries;         /* list of shared libraries found */
2521   struct id *list;
2522   void (*int_handler) PARAMS ((int));
2523   void (*quit_handler) PARAMS ((int));
2524   char *real_ldd_argv[4];
2525   const char **ldd_argv = (const char **) real_ldd_argv;
2526   int pid;
2527   int argc = 0;
2528   int pipe_fd[2];
2529   char buf[1024];
2530   FILE *inf;
2531
2532   /* If we do not have an `ldd', complain.  */
2533   if (ldd_file_name == 0)
2534     {
2535       error ("cannot find `ldd'");
2536       return;
2537     }
2538
2539   ldd_argv[argc++] = ldd_file_name;
2540   ldd_argv[argc++] = prog_name;
2541   ldd_argv[argc++] = (char *) 0;
2542
2543   if (pipe (pipe_fd) < 0)
2544     fatal_perror ("pipe");
2545
2546   inf = fdopen (pipe_fd[0], "r");
2547   if (inf == (FILE *) 0)
2548     fatal_perror ("fdopen");
2549
2550   /* Trace if needed.  */
2551   if (vflag)
2552     {
2553       const char **p_argv;
2554       const char *str;
2555
2556       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2557         fprintf (stderr, " %s", str);
2558
2559       fprintf (stderr, "\n");
2560     }
2561
2562   fflush (stdout);
2563   fflush (stderr);
2564
2565   /* Spawn child ldd on pipe */
2566   pid = vfork ();
2567   if (pid == -1)
2568     fatal_perror (VFORK_STRING);
2569
2570   if (pid == 0)                 /* child context */
2571     {
2572       /* setup stdout */
2573       if (dup2 (pipe_fd[1], 1) < 0)
2574         fatal_perror ("dup2 %d 1", pipe_fd[1]);
2575
2576       if (close (pipe_fd[0]) < 0)
2577         fatal_perror ("close %d", pipe_fd[0]);
2578
2579       if (close (pipe_fd[1]) < 0)
2580         fatal_perror ("close %d", pipe_fd[1]);
2581
2582       execv (ldd_file_name, real_ldd_argv);
2583       fatal_perror ("execv %s", ldd_file_name);
2584     }
2585
2586   /* Parent context from here on.  */
2587   int_handler  = (void (*) PARAMS ((int))) signal (SIGINT,  SIG_IGN);
2588 #ifdef SIGQUIT
2589   quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
2590 #endif
2591
2592   if (close (pipe_fd[1]) < 0)
2593     fatal_perror ("close %d", pipe_fd[1]);
2594
2595   if (debug)
2596     notice ("\nldd output with constructors/destructors.\n");
2597
2598   /* Read each line of ldd output.  */
2599   while (fgets (buf, sizeof buf, inf) != (char *) 0)
2600     {
2601       int ch2;
2602       char *name, *end, *p = buf;
2603
2604       /* Extract names of libraries and add to list.  */
2605       PARSE_LDD_OUTPUT (p);
2606       if (p == 0)
2607         continue;
2608
2609       name = p;
2610       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2611         fatal ("dynamic dependency %s not found", buf);
2612
2613       /* Find the end of the symbol name.  */
2614       for (end = p; 
2615            (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2616            end++)
2617         continue;
2618       *end = '\0';
2619
2620       if (access (name, R_OK) == 0)
2621         add_to_list (&libraries, name);
2622       else
2623         fatal ("unable to open dynamic dependency '%s'", buf);
2624
2625       if (debug)
2626         fprintf (stderr, "\t%s\n", buf);
2627     }
2628   if (debug)
2629     fprintf (stderr, "\n");
2630
2631   if (fclose (inf) != 0)
2632     fatal_perror ("fclose");
2633
2634   do_wait (ldd_file_name);
2635
2636   signal (SIGINT,  int_handler);
2637 #ifdef SIGQUIT
2638   signal (SIGQUIT, quit_handler);
2639 #endif
2640
2641   /* now iterate through the library list adding their symbols to
2642      the list.  */
2643   for (list = libraries.first; list; list = list->next)
2644     scan_prog_file (list->name, PASS_LIB);
2645 }
2646
2647 #endif /* LDD_SUFFIX */
2648 #endif /* SUNOS4_SHARED_LIBRARIES */
2649
2650 #endif /* OBJECT_FORMAT_NONE */
2651
2652 \f
2653 /*
2654  * COFF specific stuff.
2655  */
2656
2657 #ifdef OBJECT_FORMAT_COFF
2658
2659 #if defined(EXTENDED_COFF)
2660 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2661 #   define GCC_SYMENT           SYMR
2662 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc || (X).st == stGlobal)
2663 #   define GCC_SYMINC(X)        (1)
2664 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
2665 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
2666 #else
2667 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
2668 #   define GCC_SYMENT           SYMENT
2669 #   define GCC_OK_SYMBOL(X) \
2670      (((X).n_sclass == C_EXT) && \
2671       ((X).n_scnum > N_UNDEF) && \
2672       (aix64_flag \
2673        || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2674            || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2675 #   define GCC_UNDEF_SYMBOL(X) \
2676      (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2677 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
2678 #   define GCC_SYMZERO(X)       0
2679 #   define GCC_CHECK_HDR(X) \
2680      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2681       || (HEADER (X).f_magic == 0757 && aix64_flag))
2682 #endif
2683
2684 extern char *ldgetname PARAMS ((LDFILE *, GCC_SYMENT *));
2685 extern int ldtbread PARAMS ((LDFILE *, long, GCC_SYMENT *));
2686 extern int ldclose PARAMS ((LDFILE *));
2687
2688 /* COFF version to scan the name list of the loaded program for
2689    the symbols g++ uses for static constructors and destructors.
2690
2691    The constructor table begins at __CTOR_LIST__ and contains a count
2692    of the number of pointers (or -1 if the constructors are built in a
2693    separate section by the linker), followed by the pointers to the
2694    constructor functions, terminated with a null pointer.  The
2695    destructor table has the same format, and begins at __DTOR_LIST__.  */
2696
2697 static void
2698 scan_prog_file (prog_name, which_pass)
2699      const char *prog_name;
2700      enum pass which_pass;
2701 {
2702   LDFILE *ldptr = NULL;
2703   int sym_index, sym_count;
2704   int is_shared = 0;
2705
2706   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2707     return;
2708
2709 #ifdef COLLECT_EXPORT_LIST
2710   /* We do not need scanning for some standard C libraries.  */
2711   if (which_pass == PASS_FIRST && ignore_library (prog_name))
2712     return;
2713
2714   /* On AIX we have a loop, because there is not much difference
2715      between an object and an archive. This trick allows us to
2716      eliminate scan_libraries() function.  */
2717   do
2718     {
2719 #endif
2720       /* Some platforms (e.g. OSF4) declare ldopen as taking a
2721          non-const char * filename parameter, even though it will not
2722          modify that string.  So we must cast away const-ness here,
2723          which will cause -Wcast-qual to burp.  */
2724       if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2725         {
2726           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2727             fatal ("%s: not a COFF file", prog_name);
2728
2729           if (GCC_CHECK_HDR (ldptr))
2730             {
2731               sym_count = GCC_SYMBOLS (ldptr);
2732               sym_index = GCC_SYMZERO (ldptr);
2733
2734 #ifdef COLLECT_EXPORT_LIST
2735               /* Is current archive member a shared object?  */
2736               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2737 #endif
2738
2739               while (sym_index < sym_count)
2740                 {
2741                   GCC_SYMENT symbol;
2742
2743                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2744                     break;
2745                   sym_index += GCC_SYMINC (symbol);
2746
2747                   if (GCC_OK_SYMBOL (symbol))
2748                     {
2749                       char *name;
2750
2751                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
2752                         continue;               /* should never happen */
2753
2754 #ifdef XCOFF_DEBUGGING_INFO
2755                       /* All AIX function names have a duplicate entry
2756                          beginning with a dot.  */
2757                       if (*name == '.')
2758                         ++name;
2759 #endif
2760
2761                       switch (is_ctor_dtor (name))
2762                         {
2763                         case 1:
2764                           if (! is_shared)
2765                             add_to_list (&constructors, name);
2766 #ifdef COLLECT_EXPORT_LIST
2767                           if (which_pass == PASS_OBJ)
2768                             add_to_list (&exports, name);
2769 #endif
2770                           break;
2771
2772                         case 2:
2773                           if (! is_shared)
2774                             add_to_list (&destructors, name);
2775 #ifdef COLLECT_EXPORT_LIST
2776                           if (which_pass == PASS_OBJ)
2777                             add_to_list (&exports, name);
2778 #endif
2779                           break;
2780
2781 #ifdef COLLECT_EXPORT_LIST
2782                         case 3:
2783 #ifndef LD_INIT_SWITCH
2784                           if (is_shared)
2785                             add_to_list (&constructors, name);
2786 #endif
2787                           break;
2788
2789                         case 4:
2790 #ifndef LD_INIT_SWITCH
2791                           if (is_shared)
2792                             add_to_list (&destructors, name);
2793 #endif
2794                           break;
2795 #endif
2796
2797                         case 5:
2798                           if (! is_shared)
2799                             add_to_list (&frame_tables, name);
2800 #ifdef COLLECT_EXPORT_LIST
2801                           if (which_pass == PASS_OBJ)
2802                             add_to_list (&exports, name);
2803 #endif
2804                           break;
2805
2806                         default:        /* not a constructor or destructor */
2807 #ifdef COLLECT_EXPORT_LIST
2808                           /* If we are building a shared object on AIX we need
2809                              to explicitly export all global symbols.  */
2810                           if (shared_obj) 
2811                             {
2812                               if (which_pass == PASS_OBJ && (! export_flag))
2813                                 add_to_list (&exports, name);
2814                             }
2815 #endif
2816                           continue;
2817                         }
2818
2819                       if (debug)
2820 #if !defined(EXTENDED_COFF)
2821                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2822                                  symbol.n_scnum, symbol.n_sclass,
2823                                  (symbol.n_type ? "0" : ""), symbol.n_type,
2824                                  name);
2825 #else
2826                         fprintf (stderr,
2827                                  "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2828                                  symbol.iss, (long) symbol.value, symbol.index, name);
2829 #endif
2830                     }
2831                 }
2832             }
2833 #ifdef COLLECT_EXPORT_LIST
2834           else
2835             {
2836               /* If archive contains both 32-bit and 64-bit objects,
2837                  we want to skip objects in other mode so mismatch normal.  */
2838               if (debug)
2839                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2840                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
2841             }
2842 #endif
2843         }
2844       else
2845         {
2846           fatal ("%s: cannot open as COFF file", prog_name);
2847         }
2848 #ifdef COLLECT_EXPORT_LIST
2849       /* On AIX loop continues while there are more members in archive.  */
2850     }
2851   while (ldclose (ldptr) == FAILURE);
2852 #else
2853   /* Otherwise we simply close ldptr.  */
2854   (void) ldclose(ldptr);
2855 #endif
2856 }
2857
2858
2859 #ifdef COLLECT_EXPORT_LIST
2860 /* Given a library name without "lib" prefix, this function
2861    returns a full library name including a path.  */
2862 static char *
2863 resolve_lib_name (name)
2864      const char *name;
2865 {
2866   char *lib_buf;
2867   int i, j, l = 0;
2868
2869   for (i = 0; libpaths[i]; i++)
2870     if (libpaths[i]->max_len > l)
2871       l = libpaths[i]->max_len;
2872
2873   lib_buf = xmalloc (l + strlen(name) + 10);
2874
2875   for (i = 0; libpaths[i]; i++)
2876     {
2877       struct prefix_list *list = libpaths[i]->plist;
2878       for (; list; list = list->next)
2879         {
2880           /* The following lines are needed because path_prefix list
2881              may contain directories both with trailing '/' and
2882              without it.  */
2883           const char *p = "";
2884           if (list->prefix[strlen(list->prefix)-1] != '/')
2885             p = "/";
2886           for (j = 0; libexts[j]; j++)
2887             {
2888               sprintf (lib_buf, "%s%slib%s.%s",
2889                        list->prefix, p, name, libexts[j]);
2890 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2891               if (file_exists (lib_buf))
2892                 {
2893 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2894                   return (lib_buf);
2895                 }
2896             }
2897         }
2898     }
2899   if (debug)
2900     fprintf (stderr, "not found\n");
2901   else
2902     fatal ("Library lib%s not found", name);
2903   return (NULL);
2904 }
2905
2906 /* Array of standard AIX libraries which should not
2907    be scanned for ctors/dtors.  */
2908 static const char *aix_std_libs[] = {
2909   "/unix",
2910   "/lib/libc.a",
2911   "/lib/libc_r.a",
2912   "/usr/lib/libc.a",
2913   "/usr/lib/libc_r.a",
2914   "/usr/lib/threads/libc.a",
2915   "/usr/ccs/lib/libc.a",
2916   "/usr/ccs/lib/libc_r.a",
2917   NULL
2918 };
2919
2920 /* This function checks the filename and returns 1
2921    if this name matches the location of a standard AIX library. */
2922 static int
2923 ignore_library (name)
2924      const char *name;
2925 {
2926   const char **p = &aix_std_libs[0];
2927   while (*p++ != NULL)
2928     if (! strcmp (name, *p)) return 1;
2929   return 0;
2930 }
2931 #endif
2932
2933 #endif /* OBJECT_FORMAT_COFF */
2934
2935 \f
2936 /*
2937  * OSF/rose specific stuff.
2938  */
2939
2940 #ifdef OBJECT_FORMAT_ROSE
2941
2942 /* Union of the various load commands */
2943
2944 typedef union load_union
2945 {
2946   ldc_header_t                  hdr;    /* common header */
2947   load_cmd_map_command_t        map;    /* map indexing other load cmds */
2948   interpreter_command_t         iprtr;  /* interpreter pathname */
2949   strings_command_t             str;    /* load commands strings section */
2950   region_command_t              region; /* region load command */
2951   reloc_command_t               reloc;  /* relocation section */
2952   package_command_t             pkg;    /* package load command */
2953   symbols_command_t             sym;    /* symbol sections */
2954   entry_command_t               ent;    /* program start section */
2955   gen_info_command_t            info;   /* object information */
2956   func_table_command_t          func;   /* function constructors/destructors */
2957 } load_union_t;
2958
2959 /* Structure to point to load command and data section in memory.  */
2960
2961 typedef struct load_all
2962 {
2963   load_union_t *load;                   /* load command */
2964   char *section;                        /* pointer to section */
2965 } load_all_t;
2966
2967 /* Structure to contain information about a file mapped into memory.  */
2968
2969 struct file_info
2970 {
2971   char *start;                          /* start of map */
2972   char *name;                           /* filename */
2973   long  size;                           /* size of the file */
2974   long  rounded_size;                   /* size rounded to page boundary */
2975   int   fd;                             /* file descriptor */
2976   int   rw;                             /* != 0 if opened read/write */
2977   int   use_mmap;                       /* != 0 if mmap'ed */
2978 };
2979
2980 extern int decode_mach_o_hdr ();
2981 extern int encode_mach_o_hdr ();
2982
2983 static void add_func_table      PARAMS ((mo_header_t *, load_all_t *,
2984                                        symbol_info_t *, int));
2985 static void print_header        PARAMS ((mo_header_t *));
2986 static void print_load_command  PARAMS ((load_union_t *, size_t, int));
2987 static void bad_header          PARAMS ((int));
2988 static struct file_info *read_file  PARAMS ((const char *, int, int));
2989 static void end_file            PARAMS ((struct file_info *));
2990 \f
2991 /* OSF/rose specific version to scan the name list of the loaded
2992    program for the symbols g++ uses for static constructors and
2993    destructors.
2994
2995    The constructor table begins at __CTOR_LIST__ and contains a count
2996    of the number of pointers (or -1 if the constructors are built in a
2997    separate section by the linker), followed by the pointers to the
2998    constructor functions, terminated with a null pointer.  The
2999    destructor table has the same format, and begins at __DTOR_LIST__.  */
3000
3001 static void
3002 scan_prog_file (prog_name, which_pass)
3003      const char *prog_name;
3004      enum pass which_pass;
3005 {
3006   char *obj;
3007   mo_header_t hdr;
3008   load_all_t *load_array;
3009   load_all_t *load_end;
3010   load_all_t *load_cmd;
3011   int symbol_load_cmds;
3012   off_t offset;
3013   int i;
3014   int num_syms;
3015   int status;
3016   char *str_sect;
3017   struct file_info *obj_file;
3018   int prog_fd;
3019   mo_lcid_t cmd_strings   = -1;
3020   symbol_info_t *main_sym = 0;
3021   int rw                  = (which_pass != PASS_FIRST);
3022
3023   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3024   if (prog_fd < 0)
3025     fatal_perror ("open %s", prog_name);
3026
3027   obj_file = read_file (prog_name, prog_fd, rw);
3028   obj = obj_file->start;
3029
3030   status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3031   if (status != MO_HDR_CONV_SUCCESS)
3032     bad_header (status);
3033
3034
3035   /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
3036      since the hardware will automatically swap bytes for us on loading little endian
3037      integers.  */
3038
3039 #ifndef CROSS_COMPILE
3040   if (hdr.moh_magic != MOH_MAGIC_MSB
3041       || hdr.moh_header_version != MOH_HEADER_VERSION
3042       || hdr.moh_byte_order != OUR_BYTE_ORDER
3043       || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3044       || hdr.moh_cpu_type != OUR_CPU_TYPE
3045       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3046       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3047     {
3048       fatal ("incompatibilities between object file & expected values");
3049     }
3050 #endif
3051
3052   if (debug)
3053     print_header (&hdr);
3054
3055   offset = hdr.moh_first_cmd_off;
3056   load_end = load_array
3057     = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3058
3059   /* Build array of load commands, calculating the offsets */
3060   for (i = 0; i < hdr.moh_n_load_cmds; i++)
3061     {
3062       load_union_t *load_hdr;           /* load command header */
3063
3064       load_cmd = load_end++;
3065       load_hdr = (load_union_t *) (obj + offset);
3066
3067       /* If modifying the program file, copy the header.  */
3068       if (rw)
3069         {
3070           load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3071           memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
3072           load_hdr = ptr;
3073
3074           /* null out old command map, because we will rewrite at the end.  */
3075           if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3076             {
3077               cmd_strings = ptr->map.lcm_ld_cmd_strings;
3078               ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3079             }
3080         }
3081
3082       load_cmd->load = load_hdr;
3083       if (load_hdr->hdr.ldci_section_off > 0)
3084         load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3085
3086       if (debug)
3087         print_load_command (load_hdr, offset, i);
3088
3089       offset += load_hdr->hdr.ldci_cmd_size;
3090     }
3091
3092   /* If the last command is the load command map and is not undefined,
3093      decrement the count of load commands.  */
3094   if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3095     {
3096       load_end--;
3097       hdr.moh_n_load_cmds--;
3098     }
3099
3100   /* Go through and process each symbol table section.  */
3101   symbol_load_cmds = 0;
3102   for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3103     {
3104       load_union_t *load_hdr = load_cmd->load;
3105
3106       if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3107         {
3108           symbol_load_cmds++;
3109
3110           if (debug)
3111             {
3112               const char *kind = "unknown";
3113
3114               switch (load_hdr->sym.symc_kind)
3115                 {
3116                 case SYMC_IMPORTS:         kind = "imports"; break;
3117                 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3118                 case SYMC_STABS:           kind = "stabs";   break;
3119                 }
3120
3121               notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3122                       symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3123             }
3124
3125           if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3126             continue;
3127
3128           str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3129           if (str_sect == (char *) 0)
3130             fatal ("string section missing");
3131
3132           if (load_cmd->section == (char *) 0)
3133             fatal ("section pointer missing");
3134
3135           num_syms = load_hdr->sym.symc_nentries;
3136           for (i = 0; i < num_syms; i++)
3137             {
3138               symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3139               char *name = sym->si_name.symbol_name + str_sect;
3140
3141               if (name[0] != '_')
3142                 continue;
3143
3144               if (rw)
3145                 {
3146                   char *n = name + strlen (name) - strlen (NAME__MAIN);
3147
3148                   if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3149                     continue;
3150                   while (n != name)
3151                     if (*--n != '_')
3152                       continue;
3153
3154                   main_sym = sym;
3155                 }
3156               else
3157                 {
3158                   switch (is_ctor_dtor (name))
3159                     {
3160                     case 1:
3161                       add_to_list (&constructors, name);
3162                       break;
3163
3164                     case 2:
3165                       add_to_list (&destructors, name);
3166                       break;
3167
3168                     default:    /* not a constructor or destructor */
3169                       continue;
3170                     }
3171                 }
3172
3173               if (debug)
3174                 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3175                          sym->si_type, sym->si_sc_type, sym->si_flags, name);
3176             }
3177         }
3178     }
3179
3180   if (symbol_load_cmds == 0)
3181     fatal ("no symbol table found");
3182
3183   /* Update the program file now, rewrite header and load commands.  At present,
3184      we assume that there is enough space after the last load command to insert
3185      one more.  Since the first section written out is page aligned, and the
3186      number of load commands is small, this is ok for the present.  */
3187
3188   if (rw)
3189     {
3190       load_union_t *load_map;
3191       size_t size;
3192
3193       if (cmd_strings == -1)
3194         fatal ("no cmd_strings found");
3195
3196       /* Add __main to initializer list.
3197          If we are building a program instead of a shared library, do not
3198          do anything, since in the current version, you cannot do mallocs
3199          and such in the constructors.  */
3200
3201       if (main_sym != (symbol_info_t *) 0
3202           && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3203         add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3204
3205       if (debug)
3206         notice ("\nUpdating header and load commands.\n\n");
3207
3208       hdr.moh_n_load_cmds++;
3209       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3210
3211       /* Create new load command map.  */
3212       if (debug)
3213         notice ("load command map, %d cmds, new size %ld.\n",
3214                 (int) hdr.moh_n_load_cmds, (long) size);
3215
3216       load_map = (load_union_t *) xcalloc (1, size);
3217       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3218       load_map->map.ldc_header.ldci_cmd_size = size;
3219       load_map->map.lcm_ld_cmd_strings = cmd_strings;
3220       load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3221       load_array[hdr.moh_n_load_cmds-1].load = load_map;
3222
3223       offset = hdr.moh_first_cmd_off;
3224       for (i = 0; i < hdr.moh_n_load_cmds; i++)
3225         {
3226           load_map->map.lcm_map[i] = offset;
3227           if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3228             hdr.moh_load_map_cmd_off = offset;
3229
3230           offset += load_array[i].load->hdr.ldci_cmd_size;
3231         }
3232
3233       hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3234
3235       if (debug)
3236         print_header (&hdr);
3237
3238       /* Write header */
3239       status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3240       if (status != MO_HDR_CONV_SUCCESS)
3241         bad_header (status);
3242
3243       if (debug)
3244         notice ("writing load commands.\n\n");
3245
3246       /* Write load commands */
3247       offset = hdr.moh_first_cmd_off;
3248       for (i = 0; i < hdr.moh_n_load_cmds; i++)
3249         {
3250           load_union_t *load_hdr = load_array[i].load;
3251           size_t size = load_hdr->hdr.ldci_cmd_size;
3252
3253           if (debug)
3254             print_load_command (load_hdr, offset, i);
3255
3256           bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3257           offset += size;
3258         }
3259     }
3260
3261   end_file (obj_file);
3262
3263   if (close (prog_fd))
3264     fatal_perror ("close %s", prog_name);
3265
3266   if (debug)
3267     fprintf (stderr, "\n");
3268 }
3269
3270 \f
3271 /* Add a function table to the load commands to call a function
3272    on initiation or termination of the process.  */
3273
3274 static void
3275 add_func_table (hdr_p, load_array, sym, type)
3276      mo_header_t *hdr_p;                /* pointer to global header */
3277      load_all_t *load_array;            /* array of ptrs to load cmds */
3278      symbol_info_t *sym;                /* pointer to symbol entry */
3279      int type;                          /* fntc_type value */
3280 {
3281   /* Add a new load command.  */
3282   int num_cmds = ++hdr_p->moh_n_load_cmds;
3283   int load_index = num_cmds - 1;
3284   size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3285   load_union_t *ptr = xcalloc (1, size);
3286   load_all_t *load_cmd;
3287   int i;
3288
3289   /* Set the unresolved address bit in the header to force the loader to be
3290      used, since kernel exec does not call the initialization functions.  */
3291   hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3292
3293   load_cmd = &load_array[load_index];
3294   load_cmd->load = ptr;
3295   load_cmd->section = (char *) 0;
3296
3297   /* Fill in func table load command.  */
3298   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3299   ptr->func.ldc_header.ldci_cmd_size = size;
3300   ptr->func.ldc_header.ldci_section_off = 0;
3301   ptr->func.ldc_header.ldci_section_len = 0;
3302   ptr->func.fntc_type = type;
3303   ptr->func.fntc_nentries = 1;
3304
3305   /* copy address, turn it from abs. address to (region,offset) if necessary.  */
3306   /* Is the symbol already expressed as (region, offset)?  */
3307   if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3308     {
3309       ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3310       ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3311     }
3312
3313   /* If not, figure out which region it's in.  */
3314   else
3315     {
3316       mo_vm_addr_t addr = sym->si_value.abs_val;
3317       int found = 0;
3318
3319       for (i = 0; i < load_index; i++)
3320         {
3321           if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3322             {
3323               region_command_t *region_ptr = &load_array[i].load->region;
3324
3325               if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3326                   && addr >= region_ptr->regc_addr.vm_addr
3327                   && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3328                 {
3329                   ptr->func.fntc_entry_loc[0].adr_lcid = i;
3330                   ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3331                   found++;
3332                   break;
3333                 }
3334             }
3335         }
3336
3337       if (!found)
3338         fatal ("could not convert 0x%l.8x into a region", addr);
3339     }
3340
3341   if (debug)
3342     notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3343             type == FNTC_INITIALIZATION ? "init" : "term",
3344             (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3345             (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3346             (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3347
3348 }
3349
3350 \f
3351 /* Print the global header for an OSF/rose object.  */
3352
3353 static void
3354 print_header (hdr_ptr)
3355      mo_header_t *hdr_ptr;
3356 {
3357   fprintf (stderr, "\nglobal header:\n");
3358   fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
3359   fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
3360   fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
3361   fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
3362   fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
3363   fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
3364   fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
3365   fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
3366   fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3367   fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
3368   fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3369   fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3370   fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3371   fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3372   fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
3373
3374   if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3375     fprintf (stderr, ", relocatable");
3376
3377   if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3378     fprintf (stderr, ", linkable");
3379
3380   if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3381     fprintf (stderr, ", execable");
3382
3383   if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3384     fprintf (stderr, ", executable");
3385
3386   if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3387     fprintf (stderr, ", unresolved");
3388
3389   fprintf (stderr, "\n\n");
3390   return;
3391 }
3392
3393 \f
3394 /* Print a short summary of a load command.  */
3395
3396 static void
3397 print_load_command (load_hdr, offset, number)
3398      load_union_t *load_hdr;
3399      size_t offset;
3400      int number;
3401 {
3402   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3403   const char *type_str = (char *) 0;
3404
3405   switch (type)
3406     {
3407     case LDC_UNDEFINED:   type_str = "UNDEFINED";       break;
3408     case LDC_CMD_MAP:     type_str = "CMD_MAP";         break;
3409     case LDC_INTERPRETER: type_str = "INTERPRETER";     break;
3410     case LDC_STRINGS:     type_str = "STRINGS";         break;
3411     case LDC_REGION:      type_str = "REGION";          break;
3412     case LDC_RELOC:       type_str = "RELOC";           break;
3413     case LDC_PACKAGE:     type_str = "PACKAGE";         break;
3414     case LDC_SYMBOLS:     type_str = "SYMBOLS";         break;
3415     case LDC_ENTRY:       type_str = "ENTRY";           break;
3416     case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";      break;
3417     case LDC_GEN_INFO:    type_str = "GEN_INFO";        break;
3418     }
3419
3420   fprintf (stderr,
3421            "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3422            number,
3423            (long) load_hdr->hdr.ldci_cmd_size,
3424            (long) offset,
3425            (long) load_hdr->hdr.ldci_section_off,
3426            (long) load_hdr->hdr.ldci_section_len);
3427
3428   if (type_str == (char *) 0)
3429     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3430
3431   else if (type != LDC_REGION)
3432     fprintf (stderr, ", ty: %s\n", type_str);
3433
3434   else
3435     {
3436       const char *region = "";
3437       switch (load_hdr->region.regc_usage_type)
3438         {
3439         case REG_TEXT_T:        region = ", .text";     break;
3440         case REG_DATA_T:        region = ", .data";     break;
3441         case REG_BSS_T:         region = ", .bss";      break;
3442         case REG_GLUE_T:        region = ", .glue";     break;
3443 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3444         case REG_RDATA_T:       region = ", .rdata";    break;
3445         case REG_SDATA_T:       region = ", .sdata";    break;
3446         case REG_SBSS_T:        region = ", .sbss";     break;
3447 #endif
3448         }
3449
3450       fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3451                type_str,
3452                (long) load_hdr->region.regc_vm_addr,
3453                (long) load_hdr->region.regc_vm_size,
3454                region);
3455     }
3456
3457   return;
3458 }
3459
3460 \f
3461 /* Fatal error when {en,de}code_mach_o_header fails.  */
3462
3463 static void
3464 bad_header (status)
3465      int status;
3466 {
3467   switch (status)
3468     {
3469     case MO_ERROR_BAD_MAGIC:            fatal ("bad magic number");
3470     case MO_ERROR_BAD_HDR_VERS:         fatal ("bad header version");
3471     case MO_ERROR_BAD_RAW_HDR_VERS:     fatal ("bad raw header version");
3472     case MO_ERROR_BUF2SML:              fatal ("raw header buffer too small");
3473     case MO_ERROR_OLD_RAW_HDR_FILE:     fatal ("old raw header file");
3474     case MO_ERROR_UNSUPPORTED_VERS:     fatal ("unsupported version");
3475     default:
3476       fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3477     }
3478 }
3479
3480 \f
3481 /* Read a file into a memory buffer.  */
3482
3483 static struct file_info *
3484 read_file (name, fd, rw)
3485      const char *name;          /* filename */
3486      int fd;                    /* file descriptor */
3487      int rw;                    /* read/write */
3488 {
3489   struct stat stat_pkt;
3490   struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3491 #ifdef USE_MMAP
3492   static int page_size;
3493 #endif
3494
3495   if (fstat (fd, &stat_pkt) < 0)
3496     fatal_perror ("fstat %s", name);
3497
3498   p->name         = name;
3499   p->size         = stat_pkt.st_size;
3500   p->rounded_size = stat_pkt.st_size;
3501   p->fd           = fd;
3502   p->rw           = rw;
3503
3504 #ifdef USE_MMAP
3505   if (debug)
3506     fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3507
3508   if (page_size == 0)
3509     page_size = sysconf (_SC_PAGE_SIZE);
3510
3511   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3512   p->start = mmap ((caddr_t) 0,
3513                    (rw) ? p->rounded_size : p->size,
3514                    (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3515                    MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3516                    fd,
3517                    0L);
3518
3519   if (p->start != (char *) 0 && p->start != (char *) -1)
3520     p->use_mmap = 1;
3521
3522   else
3523 #endif /* USE_MMAP */
3524     {
3525       long len;
3526
3527       if (debug)
3528         fprintf (stderr, "read %s\n", name);
3529
3530       p->use_mmap = 0;
3531       p->start = xmalloc (p->size);
3532       if (lseek (fd, 0L, SEEK_SET) < 0)
3533         fatal_perror ("lseek %s 0", name);
3534
3535       len = read (fd, p->start, p->size);
3536       if (len < 0)
3537         fatal_perror ("read %s", name);
3538
3539       if (len != p->size)
3540         fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3541     }
3542
3543   return p;
3544 }
3545 \f
3546 /* Do anything necessary to write a file back from memory.  */
3547
3548 static void
3549 end_file (ptr)
3550      struct file_info *ptr;     /* file information block */
3551 {
3552 #ifdef USE_MMAP
3553   if (ptr->use_mmap)
3554     {
3555       if (ptr->rw)
3556         {
3557           if (debug)
3558             fprintf (stderr, "msync %s\n", ptr->name);
3559
3560           if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3561             fatal_perror ("msync %s", ptr->name);
3562         }
3563
3564       if (debug)
3565         fprintf (stderr, "munmap %s\n", ptr->name);
3566
3567       if (munmap (ptr->start, ptr->size))
3568         fatal_perror ("munmap %s", ptr->name);
3569     }
3570   else
3571 #endif /* USE_MMAP */
3572     {
3573       if (ptr->rw)
3574         {
3575           long len;
3576
3577           if (debug)
3578             fprintf (stderr, "write %s\n", ptr->name);
3579
3580           if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3581             fatal_perror ("lseek %s 0", ptr->name);
3582
3583           len = write (ptr->fd, ptr->start, ptr->size);
3584           if (len < 0)
3585             fatal_perror ("write %s", ptr->name);
3586
3587           if (len != ptr->size)
3588             fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3589         }
3590
3591       free (ptr->start);
3592     }
3593
3594   free (ptr);
3595 }
3596
3597 #endif /* OBJECT_FORMAT_ROSE */