OSDN Git Service

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