OSDN Git Service

2000-12-14 Philipp Thomas <pthomas@suse.de>
[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 = gnu_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 PARAMS ((LDFILE *, GCC_SYMENT *));
2692 extern int ldtbread PARAMS ((LDFILE *, long, GCC_SYMENT *));
2693 extern int ldclose PARAMS ((LDFILE *));
2694
2695 /* COFF version to scan the name list of the loaded program for
2696    the symbols g++ uses for static constructors and destructors.
2697
2698    The constructor table begins at __CTOR_LIST__ and contains a count
2699    of the number of pointers (or -1 if the constructors are built in a
2700    separate section by the linker), followed by the pointers to the
2701    constructor functions, terminated with a null pointer.  The
2702    destructor table has the same format, and begins at __DTOR_LIST__.  */
2703
2704 static void
2705 scan_prog_file (prog_name, which_pass)
2706      const char *prog_name;
2707      enum pass which_pass;
2708 {
2709   LDFILE *ldptr = NULL;
2710   int sym_index, sym_count;
2711   int is_shared = 0;
2712
2713   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2714     return;
2715
2716 #ifdef COLLECT_EXPORT_LIST
2717   /* We do not need scanning for some standard C libraries.  */
2718   if (which_pass == PASS_FIRST && ignore_library (prog_name))
2719     return;
2720
2721   /* On AIX we have a loop, because there is not much difference
2722      between an object and an archive. This trick allows us to
2723      eliminate scan_libraries() function.  */
2724   do
2725     {
2726 #endif
2727       /* Some platforms (e.g. OSF4) declare ldopen as taking a
2728          non-const char * filename parameter, even though it will not
2729          modify that string.  So we must cast away const-ness here,
2730          which will cause -Wcast-qual to burp.  */
2731       if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2732         {
2733           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2734             fatal ("%s: not a COFF file", prog_name);
2735
2736           if (GCC_CHECK_HDR (ldptr))
2737             {
2738               sym_count = GCC_SYMBOLS (ldptr);
2739               sym_index = GCC_SYMZERO (ldptr);
2740
2741 #ifdef COLLECT_EXPORT_LIST
2742               /* Is current archive member a shared object?  */
2743               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2744 #endif
2745
2746               while (sym_index < sym_count)
2747                 {
2748                   GCC_SYMENT symbol;
2749
2750                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2751                     break;
2752                   sym_index += GCC_SYMINC (symbol);
2753
2754                   if (GCC_OK_SYMBOL (symbol))
2755                     {
2756                       char *name;
2757
2758                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
2759                         continue;               /* should never happen */
2760
2761 #ifdef XCOFF_DEBUGGING_INFO
2762                       /* All AIX function names have a duplicate entry
2763                          beginning with a dot.  */
2764                       if (*name == '.')
2765                         ++name;
2766 #endif
2767
2768                       switch (is_ctor_dtor (name))
2769                         {
2770                         case 1:
2771                           if (! is_shared)
2772                             add_to_list (&constructors, name);
2773 #ifdef COLLECT_EXPORT_LIST
2774                           if (which_pass == PASS_OBJ)
2775                             add_to_list (&exports, name);
2776 #endif
2777                           break;
2778
2779                         case 2:
2780                           if (! is_shared)
2781                             add_to_list (&destructors, name);
2782 #ifdef COLLECT_EXPORT_LIST
2783                           if (which_pass == PASS_OBJ)
2784                             add_to_list (&exports, name);
2785 #endif
2786                           break;
2787
2788 #ifdef COLLECT_EXPORT_LIST
2789                         case 3:
2790 #ifndef LD_INIT_SWITCH
2791                           if (is_shared)
2792                             add_to_list (&constructors, name);
2793 #endif
2794                           break;
2795
2796                         case 4:
2797 #ifndef LD_INIT_SWITCH
2798                           if (is_shared)
2799                             add_to_list (&destructors, name);
2800 #endif
2801                           break;
2802 #endif
2803
2804                         case 5:
2805                           if (! is_shared)
2806                             add_to_list (&frame_tables, name);
2807 #ifdef COLLECT_EXPORT_LIST
2808                           if (which_pass == PASS_OBJ)
2809                             add_to_list (&exports, name);
2810 #endif
2811                           break;
2812
2813                         default:        /* not a constructor or destructor */
2814 #ifdef COLLECT_EXPORT_LIST
2815                           /* If we are building a shared object on AIX we need
2816                              to explicitly export all global symbols.  */
2817                           if (shared_obj) 
2818                             {
2819                               if (which_pass == PASS_OBJ && (! export_flag))
2820                                 add_to_list (&exports, name);
2821                             }
2822 #endif
2823                           continue;
2824                         }
2825
2826                       if (debug)
2827 #if !defined(EXTENDED_COFF)
2828                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2829                                  symbol.n_scnum, symbol.n_sclass,
2830                                  (symbol.n_type ? "0" : ""), symbol.n_type,
2831                                  name);
2832 #else
2833                         fprintf (stderr,
2834                                  "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2835                                  symbol.iss, (long) symbol.value, symbol.index, name);
2836 #endif
2837                     }
2838                 }
2839             }
2840 #ifdef COLLECT_EXPORT_LIST
2841           else
2842             {
2843               /* If archive contains both 32-bit and 64-bit objects,
2844                  we want to skip objects in other mode so mismatch normal.  */
2845               if (debug)
2846                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2847                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
2848             }
2849 #endif
2850         }
2851       else
2852         {
2853           fatal ("%s: cannot open as COFF file", prog_name);
2854         }
2855 #ifdef COLLECT_EXPORT_LIST
2856       /* On AIX loop continues while there are more members in archive.  */
2857     }
2858   while (ldclose (ldptr) == FAILURE);
2859 #else
2860   /* Otherwise we simply close ldptr.  */
2861   (void) ldclose(ldptr);
2862 #endif
2863 }
2864
2865
2866 #ifdef COLLECT_EXPORT_LIST
2867 /* Given a library name without "lib" prefix, this function
2868    returns a full library name including a path.  */
2869 static char *
2870 resolve_lib_name (name)
2871      const char *name;
2872 {
2873   char *lib_buf;
2874   int i, j, l = 0;
2875
2876   for (i = 0; libpaths[i]; i++)
2877     if (libpaths[i]->max_len > l)
2878       l = libpaths[i]->max_len;
2879
2880   lib_buf = xmalloc (l + strlen(name) + 10);
2881
2882   for (i = 0; libpaths[i]; i++)
2883     {
2884       struct prefix_list *list = libpaths[i]->plist;
2885       for (; list; list = list->next)
2886         {
2887           /* The following lines are needed because path_prefix list
2888              may contain directories both with trailing '/' and
2889              without it.  */
2890           const char *p = "";
2891           if (list->prefix[strlen(list->prefix)-1] != '/')
2892             p = "/";
2893           for (j = 0; libexts[j]; j++)
2894             {
2895               sprintf (lib_buf, "%s%slib%s.%s",
2896                        list->prefix, p, name, libexts[j]);
2897 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2898               if (file_exists (lib_buf))
2899                 {
2900 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2901                   return (lib_buf);
2902                 }
2903             }
2904         }
2905     }
2906   if (debug)
2907     fprintf (stderr, "not found\n");
2908   else
2909     fatal ("Library lib%s not found", name);
2910   return (NULL);
2911 }
2912
2913 /* Array of standard AIX libraries which should not
2914    be scanned for ctors/dtors.  */
2915 static const char *aix_std_libs[] = {
2916   "/unix",
2917   "/lib/libc.a",
2918   "/lib/libc_r.a",
2919   "/usr/lib/libc.a",
2920   "/usr/lib/libc_r.a",
2921   "/usr/lib/threads/libc.a",
2922   "/usr/ccs/lib/libc.a",
2923   "/usr/ccs/lib/libc_r.a",
2924   NULL
2925 };
2926
2927 /* This function checks the filename and returns 1
2928    if this name matches the location of a standard AIX library. */
2929 static int
2930 ignore_library (name)
2931      const char *name;
2932 {
2933   const char **p = &aix_std_libs[0];
2934   while (*p++ != NULL)
2935     if (! strcmp (name, *p)) return 1;
2936   return 0;
2937 }
2938 #endif
2939
2940 #endif /* OBJECT_FORMAT_COFF */
2941
2942 \f
2943 /*
2944  * OSF/rose specific stuff.
2945  */
2946
2947 #ifdef OBJECT_FORMAT_ROSE
2948
2949 /* Union of the various load commands */
2950
2951 typedef union load_union
2952 {
2953   ldc_header_t                  hdr;    /* common header */
2954   load_cmd_map_command_t        map;    /* map indexing other load cmds */
2955   interpreter_command_t         iprtr;  /* interpreter pathname */
2956   strings_command_t             str;    /* load commands strings section */
2957   region_command_t              region; /* region load command */
2958   reloc_command_t               reloc;  /* relocation section */
2959   package_command_t             pkg;    /* package load command */
2960   symbols_command_t             sym;    /* symbol sections */
2961   entry_command_t               ent;    /* program start section */
2962   gen_info_command_t            info;   /* object information */
2963   func_table_command_t          func;   /* function constructors/destructors */
2964 } load_union_t;
2965
2966 /* Structure to point to load command and data section in memory.  */
2967
2968 typedef struct load_all
2969 {
2970   load_union_t *load;                   /* load command */
2971   char *section;                        /* pointer to section */
2972 } load_all_t;
2973
2974 /* Structure to contain information about a file mapped into memory.  */
2975
2976 struct file_info
2977 {
2978   char *start;                          /* start of map */
2979   char *name;                           /* filename */
2980   long  size;                           /* size of the file */
2981   long  rounded_size;                   /* size rounded to page boundary */
2982   int   fd;                             /* file descriptor */
2983   int   rw;                             /* != 0 if opened read/write */
2984   int   use_mmap;                       /* != 0 if mmap'ed */
2985 };
2986
2987 extern int decode_mach_o_hdr ();
2988 extern int encode_mach_o_hdr ();
2989
2990 static void add_func_table      PARAMS ((mo_header_t *, load_all_t *,
2991                                        symbol_info_t *, int));
2992 static void print_header        PARAMS ((mo_header_t *));
2993 static void print_load_command  PARAMS ((load_union_t *, size_t, int));
2994 static void bad_header          PARAMS ((int));
2995 static struct file_info *read_file  PARAMS ((const char *, int, int));
2996 static void end_file            PARAMS ((struct file_info *));
2997 \f
2998 /* OSF/rose specific version to scan the name list of the loaded
2999    program for the symbols g++ uses for static constructors and
3000    destructors.
3001
3002    The constructor table begins at __CTOR_LIST__ and contains a count
3003    of the number of pointers (or -1 if the constructors are built in a
3004    separate section by the linker), followed by the pointers to the
3005    constructor functions, terminated with a null pointer.  The
3006    destructor table has the same format, and begins at __DTOR_LIST__.  */
3007
3008 static void
3009 scan_prog_file (prog_name, which_pass)
3010      const char *prog_name;
3011      enum pass which_pass;
3012 {
3013   char *obj;
3014   mo_header_t hdr;
3015   load_all_t *load_array;
3016   load_all_t *load_end;
3017   load_all_t *load_cmd;
3018   int symbol_load_cmds;
3019   off_t offset;
3020   int i;
3021   int num_syms;
3022   int status;
3023   char *str_sect;
3024   struct file_info *obj_file;
3025   int prog_fd;
3026   mo_lcid_t cmd_strings   = -1;
3027   symbol_info_t *main_sym = 0;
3028   int rw                  = (which_pass != PASS_FIRST);
3029
3030   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3031   if (prog_fd < 0)
3032     fatal_perror ("open %s", prog_name);
3033
3034   obj_file = read_file (prog_name, prog_fd, rw);
3035   obj = obj_file->start;
3036
3037   status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3038   if (status != MO_HDR_CONV_SUCCESS)
3039     bad_header (status);
3040
3041
3042   /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
3043      since the hardware will automatically swap bytes for us on loading little endian
3044      integers.  */
3045
3046 #ifndef CROSS_COMPILE
3047   if (hdr.moh_magic != MOH_MAGIC_MSB
3048       || hdr.moh_header_version != MOH_HEADER_VERSION
3049       || hdr.moh_byte_order != OUR_BYTE_ORDER
3050       || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3051       || hdr.moh_cpu_type != OUR_CPU_TYPE
3052       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3053       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3054     {
3055       fatal ("incompatibilities between object file & expected values");
3056     }
3057 #endif
3058
3059   if (debug)
3060     print_header (&hdr);
3061
3062   offset = hdr.moh_first_cmd_off;
3063   load_end = load_array
3064     = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3065
3066   /* Build array of load commands, calculating the offsets */
3067   for (i = 0; i < hdr.moh_n_load_cmds; i++)
3068     {
3069       load_union_t *load_hdr;           /* load command header */
3070
3071       load_cmd = load_end++;
3072       load_hdr = (load_union_t *) (obj + offset);
3073
3074       /* If modifying the program file, copy the header.  */
3075       if (rw)
3076         {
3077           load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3078           memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
3079           load_hdr = ptr;
3080
3081           /* null out old command map, because we will rewrite at the end.  */
3082           if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3083             {
3084               cmd_strings = ptr->map.lcm_ld_cmd_strings;
3085               ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3086             }
3087         }
3088
3089       load_cmd->load = load_hdr;
3090       if (load_hdr->hdr.ldci_section_off > 0)
3091         load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3092
3093       if (debug)
3094         print_load_command (load_hdr, offset, i);
3095
3096       offset += load_hdr->hdr.ldci_cmd_size;
3097     }
3098
3099   /* If the last command is the load command map and is not undefined,
3100      decrement the count of load commands.  */
3101   if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3102     {
3103       load_end--;
3104       hdr.moh_n_load_cmds--;
3105     }
3106
3107   /* Go through and process each symbol table section.  */
3108   symbol_load_cmds = 0;
3109   for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3110     {
3111       load_union_t *load_hdr = load_cmd->load;
3112
3113       if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3114         {
3115           symbol_load_cmds++;
3116
3117           if (debug)
3118             {
3119               const char *kind = "unknown";
3120
3121               switch (load_hdr->sym.symc_kind)
3122                 {
3123                 case SYMC_IMPORTS:         kind = "imports"; break;
3124                 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3125                 case SYMC_STABS:           kind = "stabs";   break;
3126                 }
3127
3128               notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3129                       symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3130             }
3131
3132           if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3133             continue;
3134
3135           str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3136           if (str_sect == (char *) 0)
3137             fatal ("string section missing");
3138
3139           if (load_cmd->section == (char *) 0)
3140             fatal ("section pointer missing");
3141
3142           num_syms = load_hdr->sym.symc_nentries;
3143           for (i = 0; i < num_syms; i++)
3144             {
3145               symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3146               char *name = sym->si_name.symbol_name + str_sect;
3147
3148               if (name[0] != '_')
3149                 continue;
3150
3151               if (rw)
3152                 {
3153                   char *n = name + strlen (name) - strlen (NAME__MAIN);
3154
3155                   if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3156                     continue;
3157                   while (n != name)
3158                     if (*--n != '_')
3159                       continue;
3160
3161                   main_sym = sym;
3162                 }
3163               else
3164                 {
3165                   switch (is_ctor_dtor (name))
3166                     {
3167                     case 1:
3168                       add_to_list (&constructors, name);
3169                       break;
3170
3171                     case 2:
3172                       add_to_list (&destructors, name);
3173                       break;
3174
3175                     default:    /* not a constructor or destructor */
3176                       continue;
3177                     }
3178                 }
3179
3180               if (debug)
3181                 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3182                          sym->si_type, sym->si_sc_type, sym->si_flags, name);
3183             }
3184         }
3185     }
3186
3187   if (symbol_load_cmds == 0)
3188     fatal ("no symbol table found");
3189
3190   /* Update the program file now, rewrite header and load commands.  At present,
3191      we assume that there is enough space after the last load command to insert
3192      one more.  Since the first section written out is page aligned, and the
3193      number of load commands is small, this is ok for the present.  */
3194
3195   if (rw)
3196     {
3197       load_union_t *load_map;
3198       size_t size;
3199
3200       if (cmd_strings == -1)
3201         fatal ("no cmd_strings found");
3202
3203       /* Add __main to initializer list.
3204          If we are building a program instead of a shared library, do not
3205          do anything, since in the current version, you cannot do mallocs
3206          and such in the constructors.  */
3207
3208       if (main_sym != (symbol_info_t *) 0
3209           && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3210         add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3211
3212       if (debug)
3213         notice ("\nUpdating header and load commands.\n\n");
3214
3215       hdr.moh_n_load_cmds++;
3216       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3217
3218       /* Create new load command map.  */
3219       if (debug)
3220         notice ("load command map, %d cmds, new size %ld.\n",
3221                 (int) hdr.moh_n_load_cmds, (long) size);
3222
3223       load_map = (load_union_t *) xcalloc (1, size);
3224       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3225       load_map->map.ldc_header.ldci_cmd_size = size;
3226       load_map->map.lcm_ld_cmd_strings = cmd_strings;
3227       load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3228       load_array[hdr.moh_n_load_cmds-1].load = load_map;
3229
3230       offset = hdr.moh_first_cmd_off;
3231       for (i = 0; i < hdr.moh_n_load_cmds; i++)
3232         {
3233           load_map->map.lcm_map[i] = offset;
3234           if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3235             hdr.moh_load_map_cmd_off = offset;
3236
3237           offset += load_array[i].load->hdr.ldci_cmd_size;
3238         }
3239
3240       hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3241
3242       if (debug)
3243         print_header (&hdr);
3244
3245       /* Write header */
3246       status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3247       if (status != MO_HDR_CONV_SUCCESS)
3248         bad_header (status);
3249
3250       if (debug)
3251         notice ("writing load commands.\n\n");
3252
3253       /* Write load commands */
3254       offset = hdr.moh_first_cmd_off;
3255       for (i = 0; i < hdr.moh_n_load_cmds; i++)
3256         {
3257           load_union_t *load_hdr = load_array[i].load;
3258           size_t size = load_hdr->hdr.ldci_cmd_size;
3259
3260           if (debug)
3261             print_load_command (load_hdr, offset, i);
3262
3263           bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3264           offset += size;
3265         }
3266     }
3267
3268   end_file (obj_file);
3269
3270   if (close (prog_fd))
3271     fatal_perror ("close %s", prog_name);
3272
3273   if (debug)
3274     fprintf (stderr, "\n");
3275 }
3276
3277 \f
3278 /* Add a function table to the load commands to call a function
3279    on initiation or termination of the process.  */
3280
3281 static void
3282 add_func_table (hdr_p, load_array, sym, type)
3283      mo_header_t *hdr_p;                /* pointer to global header */
3284      load_all_t *load_array;            /* array of ptrs to load cmds */
3285      symbol_info_t *sym;                /* pointer to symbol entry */
3286      int type;                          /* fntc_type value */
3287 {
3288   /* Add a new load command.  */
3289   int num_cmds = ++hdr_p->moh_n_load_cmds;
3290   int load_index = num_cmds - 1;
3291   size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3292   load_union_t *ptr = xcalloc (1, size);
3293   load_all_t *load_cmd;
3294   int i;
3295
3296   /* Set the unresolved address bit in the header to force the loader to be
3297      used, since kernel exec does not call the initialization functions.  */
3298   hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3299
3300   load_cmd = &load_array[load_index];
3301   load_cmd->load = ptr;
3302   load_cmd->section = (char *) 0;
3303
3304   /* Fill in func table load command.  */
3305   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3306   ptr->func.ldc_header.ldci_cmd_size = size;
3307   ptr->func.ldc_header.ldci_section_off = 0;
3308   ptr->func.ldc_header.ldci_section_len = 0;
3309   ptr->func.fntc_type = type;
3310   ptr->func.fntc_nentries = 1;
3311
3312   /* copy address, turn it from abs. address to (region,offset) if necessary.  */
3313   /* Is the symbol already expressed as (region, offset)?  */
3314   if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3315     {
3316       ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3317       ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3318     }
3319
3320   /* If not, figure out which region it's in.  */
3321   else
3322     {
3323       mo_vm_addr_t addr = sym->si_value.abs_val;
3324       int found = 0;
3325
3326       for (i = 0; i < load_index; i++)
3327         {
3328           if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3329             {
3330               region_command_t *region_ptr = &load_array[i].load->region;
3331
3332               if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3333                   && addr >= region_ptr->regc_addr.vm_addr
3334                   && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3335                 {
3336                   ptr->func.fntc_entry_loc[0].adr_lcid = i;
3337                   ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3338                   found++;
3339                   break;
3340                 }
3341             }
3342         }
3343
3344       if (!found)
3345         fatal ("could not convert 0x%l.8x into a region", addr);
3346     }
3347
3348   if (debug)
3349     notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3350             type == FNTC_INITIALIZATION ? "init" : "term",
3351             (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3352             (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3353             (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3354
3355 }
3356
3357 \f
3358 /* Print the global header for an OSF/rose object.  */
3359
3360 static void
3361 print_header (hdr_ptr)
3362      mo_header_t *hdr_ptr;
3363 {
3364   fprintf (stderr, "\nglobal header:\n");
3365   fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
3366   fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
3367   fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
3368   fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
3369   fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
3370   fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
3371   fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
3372   fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
3373   fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3374   fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
3375   fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3376   fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3377   fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3378   fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3379   fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
3380
3381   if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3382     fprintf (stderr, ", relocatable");
3383
3384   if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3385     fprintf (stderr, ", linkable");
3386
3387   if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3388     fprintf (stderr, ", execable");
3389
3390   if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3391     fprintf (stderr, ", executable");
3392
3393   if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3394     fprintf (stderr, ", unresolved");
3395
3396   fprintf (stderr, "\n\n");
3397   return;
3398 }
3399
3400 \f
3401 /* Print a short summary of a load command.  */
3402
3403 static void
3404 print_load_command (load_hdr, offset, number)
3405      load_union_t *load_hdr;
3406      size_t offset;
3407      int number;
3408 {
3409   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3410   const char *type_str = (char *) 0;
3411
3412   switch (type)
3413     {
3414     case LDC_UNDEFINED:   type_str = "UNDEFINED";       break;
3415     case LDC_CMD_MAP:     type_str = "CMD_MAP";         break;
3416     case LDC_INTERPRETER: type_str = "INTERPRETER";     break;
3417     case LDC_STRINGS:     type_str = "STRINGS";         break;
3418     case LDC_REGION:      type_str = "REGION";          break;
3419     case LDC_RELOC:       type_str = "RELOC";           break;
3420     case LDC_PACKAGE:     type_str = "PACKAGE";         break;
3421     case LDC_SYMBOLS:     type_str = "SYMBOLS";         break;
3422     case LDC_ENTRY:       type_str = "ENTRY";           break;
3423     case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";      break;
3424     case LDC_GEN_INFO:    type_str = "GEN_INFO";        break;
3425     }
3426
3427   fprintf (stderr,
3428            "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3429            number,
3430            (long) load_hdr->hdr.ldci_cmd_size,
3431            (long) offset,
3432            (long) load_hdr->hdr.ldci_section_off,
3433            (long) load_hdr->hdr.ldci_section_len);
3434
3435   if (type_str == (char *) 0)
3436     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3437
3438   else if (type != LDC_REGION)
3439     fprintf (stderr, ", ty: %s\n", type_str);
3440
3441   else
3442     {
3443       const char *region = "";
3444       switch (load_hdr->region.regc_usage_type)
3445         {
3446         case REG_TEXT_T:        region = ", .text";     break;
3447         case REG_DATA_T:        region = ", .data";     break;
3448         case REG_BSS_T:         region = ", .bss";      break;
3449         case REG_GLUE_T:        region = ", .glue";     break;
3450 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3451         case REG_RDATA_T:       region = ", .rdata";    break;
3452         case REG_SDATA_T:       region = ", .sdata";    break;
3453         case REG_SBSS_T:        region = ", .sbss";     break;
3454 #endif
3455         }
3456
3457       fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3458                type_str,
3459                (long) load_hdr->region.regc_vm_addr,
3460                (long) load_hdr->region.regc_vm_size,
3461                region);
3462     }
3463
3464   return;
3465 }
3466
3467 \f
3468 /* Fatal error when {en,de}code_mach_o_header fails.  */
3469
3470 static void
3471 bad_header (status)
3472      int status;
3473 {
3474   switch (status)
3475     {
3476     case MO_ERROR_BAD_MAGIC:            fatal ("bad magic number");
3477     case MO_ERROR_BAD_HDR_VERS:         fatal ("bad header version");
3478     case MO_ERROR_BAD_RAW_HDR_VERS:     fatal ("bad raw header version");
3479     case MO_ERROR_BUF2SML:              fatal ("raw header buffer too small");
3480     case MO_ERROR_OLD_RAW_HDR_FILE:     fatal ("old raw header file");
3481     case MO_ERROR_UNSUPPORTED_VERS:     fatal ("unsupported version");
3482     default:
3483       fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3484     }
3485 }
3486
3487 \f
3488 /* Read a file into a memory buffer.  */
3489
3490 static struct file_info *
3491 read_file (name, fd, rw)
3492      const char *name;          /* filename */
3493      int fd;                    /* file descriptor */
3494      int rw;                    /* read/write */
3495 {
3496   struct stat stat_pkt;
3497   struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3498 #ifdef USE_MMAP
3499   static int page_size;
3500 #endif
3501
3502   if (fstat (fd, &stat_pkt) < 0)
3503     fatal_perror ("fstat %s", name);
3504
3505   p->name         = name;
3506   p->size         = stat_pkt.st_size;
3507   p->rounded_size = stat_pkt.st_size;
3508   p->fd           = fd;
3509   p->rw           = rw;
3510
3511 #ifdef USE_MMAP
3512   if (debug)
3513     fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3514
3515   if (page_size == 0)
3516     page_size = sysconf (_SC_PAGE_SIZE);
3517
3518   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3519   p->start = mmap ((caddr_t) 0,
3520                    (rw) ? p->rounded_size : p->size,
3521                    (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3522                    MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3523                    fd,
3524                    0L);
3525
3526   if (p->start != (char *) 0 && p->start != (char *) -1)
3527     p->use_mmap = 1;
3528
3529   else
3530 #endif /* USE_MMAP */
3531     {
3532       long len;
3533
3534       if (debug)
3535         fprintf (stderr, "read %s\n", name);
3536
3537       p->use_mmap = 0;
3538       p->start = xmalloc (p->size);
3539       if (lseek (fd, 0L, SEEK_SET) < 0)
3540         fatal_perror ("lseek %s 0", name);
3541
3542       len = read (fd, p->start, p->size);
3543       if (len < 0)
3544         fatal_perror ("read %s", name);
3545
3546       if (len != p->size)
3547         fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3548     }
3549
3550   return p;
3551 }
3552 \f
3553 /* Do anything necessary to write a file back from memory.  */
3554
3555 static void
3556 end_file (ptr)
3557      struct file_info *ptr;     /* file information block */
3558 {
3559 #ifdef USE_MMAP
3560   if (ptr->use_mmap)
3561     {
3562       if (ptr->rw)
3563         {
3564           if (debug)
3565             fprintf (stderr, "msync %s\n", ptr->name);
3566
3567           if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3568             fatal_perror ("msync %s", ptr->name);
3569         }
3570
3571       if (debug)
3572         fprintf (stderr, "munmap %s\n", ptr->name);
3573
3574       if (munmap (ptr->start, ptr->size))
3575         fatal_perror ("munmap %s", ptr->name);
3576     }
3577   else
3578 #endif /* USE_MMAP */
3579     {
3580       if (ptr->rw)
3581         {
3582           long len;
3583
3584           if (debug)
3585             fprintf (stderr, "write %s\n", ptr->name);
3586
3587           if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3588             fatal_perror ("lseek %s 0", ptr->name);
3589
3590           len = write (ptr->fd, ptr->start, ptr->size);
3591           if (len < 0)
3592             fatal_perror ("write %s", ptr->name);
3593
3594           if (len != ptr->size)
3595             fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3596         }
3597
3598       free (ptr->start);
3599     }
3600
3601   free (ptr);
3602 }
3603
3604 #endif /* OBJECT_FORMAT_ROSE */