OSDN Git Service

1541f7cbf22dce5be9262d9fdc3af1ddab3e5719
[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, 2001 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 #endif
854   const char *ld_file_name;
855   const char *p;
856   char **c_argv;
857   const char **c_ptr;
858   char **ld1_argv;
859   const char **ld1;
860   char **ld2_argv;
861   const char **ld2;
862   char **object_lst;
863   const char **object;
864   int first_file;
865   int num_c_args        = argc+9;
866
867 #if defined (COLLECT2_HOST_INITIALIZATION)
868   /* Perform system dependent initialization, if neccessary.  */
869   COLLECT2_HOST_INITIALIZATION;
870 #endif
871
872 /* LC_CTYPE determines the character set used by the terminal so it has be set
873    to output messages correctly.  */
874
875 #ifdef HAVE_LC_MESSAGES
876   setlocale (LC_CTYPE, "");
877   setlocale (LC_MESSAGES, "");
878 #else
879   setlocale (LC_ALL, "");
880 #endif
881
882   (void) bindtextdomain (PACKAGE, localedir);
883   (void) textdomain (PACKAGE);
884
885   /* Do not invoke xcalloc before this point, since locale needs to be
886      set first, in case a diagnostic is issued.  */
887
888   ld1 = (const char **)(ld1_argv = (char **) xcalloc(sizeof (char *), argc+3));
889   ld2 = (const char **)(ld2_argv = (char **) xcalloc(sizeof (char *), argc+10));
890   object = (const char **)(object_lst = (char **) xcalloc(sizeof (char *), argc));
891
892 #ifdef DEBUG
893   debug = 1;
894 #endif
895
896   /* Parse command line early for instances of -debug.  This allows
897      the debug flag to be set before functions like find_a_file()
898      are called.  */
899   {
900     int i;
901     
902     for (i = 1; argv[i] != NULL; i ++)
903       if (! strcmp (argv[i], "-debug"))
904         debug = 1;
905     vflag = debug;
906   }
907
908 #ifndef DEFAULT_A_OUT_NAME
909   output_file = "a.out";
910 #else
911   output_file = DEFAULT_A_OUT_NAME;
912 #endif
913
914   obstack_begin (&temporary_obstack, 0);
915   obstack_begin (&permanent_obstack, 0);
916   temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
917
918   current_demangling_style = auto_demangling;
919   p = getenv ("COLLECT_GCC_OPTIONS");
920   while (p && *p)
921     {
922       const char *q = extract_string (&p);
923       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
924         num_c_args++;
925     }
926   obstack_free (&temporary_obstack, temporary_firstobj);
927
928   /* -fno-exceptions -w */
929   num_c_args += 2;
930
931   c_ptr = (const char **)
932     (c_argv = (char **) xcalloc (sizeof (char *), num_c_args));
933
934   if (argc < 2)
935     fatal ("no arguments");
936
937 #ifdef SIGQUIT
938   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
939     signal (SIGQUIT, handler);
940 #endif
941   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
942     signal (SIGINT, handler);
943 #ifdef SIGALRM
944   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
945     signal (SIGALRM, handler);
946 #endif
947 #ifdef SIGHUP
948   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
949     signal (SIGHUP, handler);
950 #endif
951   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
952     signal (SIGSEGV, handler);
953 #ifdef SIGBUS
954   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
955     signal (SIGBUS, handler);
956 #endif
957
958   /* Extract COMPILER_PATH and PATH into our prefix list.  */
959   prefix_from_env ("COMPILER_PATH", &cpath);
960   prefix_from_env ("PATH", &path);
961
962 #ifdef CROSS_COMPILE
963   /* If we look for a program in the compiler directories, we just use
964      the short name, since these directories are already system-specific.
965      But it we look for a program in the system directories, we need to
966      qualify the program name with the target machine.  */
967
968   full_ld_suffix = concat(target_machine, "-", ld_suffix, NULL);
969
970 #if 0
971   full_gld_suffix = concat (target_machine, "-", gld_suffix, NULL);
972 #endif
973
974   full_nm_suffix = concat (target_machine, "-", nm_suffix, NULL);
975
976   full_gnm_suffix = concat (target_machine, "-", gnm_suffix, NULL);
977   
978 #ifdef LDD_SUFFIX
979   full_ldd_suffix = concat (target_machine, "-", ldd_suffix, NULL);
980 #endif
981
982   full_strip_suffix = concat (target_machine, "-", strip_suffix, NULL);
983   
984   full_gstrip_suffix = concat (target_machine, "-", gstrip_suffix, NULL);
985 #endif /* CROSS_COMPILE */
986
987   /* Try to discover a valid linker/nm/strip to use.  */
988
989   /* Maybe we know the right file to use (if not cross).  */
990   ld_file_name = 0;
991 #ifdef DEFAULT_LINKER
992   if (access (DEFAULT_LINKER, X_OK) == 0)
993     ld_file_name = DEFAULT_LINKER;
994   if (ld_file_name == 0)
995 #endif
996 #ifdef REAL_LD_FILE_NAME
997   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
998   if (ld_file_name == 0)
999 #endif
1000   /* Search the (target-specific) compiler dirs for ld'.  */
1001   ld_file_name = find_a_file (&cpath, real_ld_suffix);
1002   /* Likewise for `collect-ld'.  */
1003   if (ld_file_name == 0)
1004     ld_file_name = find_a_file (&cpath, collect_ld_suffix);
1005   /* Search the compiler directories for `ld'.  We have protection against
1006      recursive calls in find_a_file.  */
1007   if (ld_file_name == 0)
1008     ld_file_name = find_a_file (&cpath, ld_suffix);
1009   /* Search the ordinary system bin directories
1010      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
1011   if (ld_file_name == 0)
1012     ld_file_name = find_a_file (&path, full_ld_suffix);
1013
1014 #ifdef REAL_NM_FILE_NAME
1015   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
1016   if (nm_file_name == 0)
1017 #endif
1018   nm_file_name = find_a_file (&cpath, gnm_suffix);
1019   if (nm_file_name == 0)
1020     nm_file_name = find_a_file (&path, full_gnm_suffix);
1021   if (nm_file_name == 0)
1022     nm_file_name = find_a_file (&cpath, nm_suffix);
1023   if (nm_file_name == 0)
1024     nm_file_name = find_a_file (&path, full_nm_suffix);
1025
1026 #ifdef LDD_SUFFIX
1027   ldd_file_name = find_a_file (&cpath, ldd_suffix);
1028   if (ldd_file_name == 0)
1029     ldd_file_name = find_a_file (&path, full_ldd_suffix);
1030 #endif
1031
1032 #ifdef REAL_STRIP_FILE_NAME
1033   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1034   if (strip_file_name == 0)
1035 #endif
1036   strip_file_name = find_a_file (&cpath, gstrip_suffix);
1037   if (strip_file_name == 0)
1038     strip_file_name = find_a_file (&path, full_gstrip_suffix);
1039   if (strip_file_name == 0)
1040     strip_file_name = find_a_file (&cpath, strip_suffix);
1041   if (strip_file_name == 0)
1042     strip_file_name = find_a_file (&path, full_strip_suffix);
1043
1044   /* Determine the full path name of the C compiler to use.  */
1045   c_file_name = getenv ("COLLECT_GCC");
1046   if (c_file_name == 0)
1047     {
1048 #ifdef CROSS_COMPILE
1049       c_file_name = concat (target_machine, "-gcc", NULL);
1050 #else
1051       c_file_name = "gcc";
1052 #endif
1053     }
1054
1055   p = find_a_file (&cpath, c_file_name);
1056
1057   /* Here it should be safe to use the system search path since we should have
1058      already qualified the name of the compiler when it is needed.  */
1059   if (p == 0)
1060     p = find_a_file (&path, c_file_name);
1061
1062   if (p)
1063     c_file_name = p;
1064
1065   *ld1++ = *ld2++ = ld_file_name;
1066
1067   /* Make temp file names.  */
1068   c_file = make_temp_file (".c");
1069   o_file = make_temp_file (".o");
1070 #ifdef COLLECT_EXPORT_LIST
1071   export_file = make_temp_file (".x");
1072 #endif
1073   ldout = make_temp_file (".ld");
1074   *c_ptr++ = c_file_name;
1075   *c_ptr++ = "-x";
1076   *c_ptr++ = "c";
1077   *c_ptr++ = "-c";
1078   *c_ptr++ = "-o";
1079   *c_ptr++ = o_file;
1080
1081 #ifdef COLLECT_EXPORT_LIST
1082   /* Generate a list of directories from LIBPATH.  */
1083   prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1084   /* Add to this list also two standard directories where
1085      AIX loader always searches for libraries.  */
1086   add_prefix (&libpath_lib_dirs, "/lib");
1087   add_prefix (&libpath_lib_dirs, "/usr/lib");
1088 #endif
1089
1090   /* Get any options that the upper GCC wants to pass to the sub-GCC.  
1091
1092      AIX support needs to know if -shared has been specified before
1093      parsing commandline arguments.  */
1094
1095   p = getenv ("COLLECT_GCC_OPTIONS");
1096   while (p && *p)
1097     {
1098       const char *q = extract_string (&p);
1099       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1100         *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1101       if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1102         *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1103       if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0)
1104         shared_obj = 1;
1105       if (*q == '-' && q[1] == 'B')
1106         {
1107           *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1108           if (q[2] == 0)
1109             {
1110               q = extract_string (&p);
1111               *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1112             }
1113         }
1114     }
1115   obstack_free (&temporary_obstack, temporary_firstobj);
1116   *c_ptr++ = "-fno-exceptions";
1117   *c_ptr++ = "-w";
1118
1119   /* !!! When GCC calls collect2,
1120      it does not know whether it is calling collect2 or ld.
1121      So collect2 cannot meaningfully understand any options
1122      except those ld understands.
1123      If you propose to make GCC pass some other option,
1124      just imagine what will happen if ld is really ld!!!  */
1125
1126   /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
1127   /* After the first file, put in the c++ rt0.  */
1128
1129   first_file = 1;
1130   while ((arg = *++argv) != (char *) 0)
1131     {
1132       *ld1++ = *ld2++ = arg;
1133
1134       if (arg[0] == '-')
1135         {
1136           switch (arg[1])
1137             {
1138 #ifdef COLLECT_EXPORT_LIST
1139             /* We want to disable automatic exports on AIX when user
1140                explicitly puts an export list in command line */
1141             case 'b':
1142               if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1143                 export_flag = 1;
1144               else if (arg[2] == '6' && arg[3] == '4')
1145                 aix64_flag = 1;
1146               break;
1147 #endif
1148
1149             case 'd':
1150               if (!strcmp (arg, "-debug"))
1151                 {
1152                   /* Already parsed.  */
1153                   ld1--;
1154                   ld2--;
1155                 }
1156               break;
1157
1158             case 'l':
1159               if (first_file)
1160                 {
1161                   /* place o_file BEFORE this argument! */
1162                   first_file = 0;
1163                   ld2--;
1164                   *ld2++ = o_file;
1165                   *ld2++ = arg;
1166                 }
1167 #ifdef COLLECT_EXPORT_LIST
1168               {
1169                 /* Resolving full library name.  */
1170                 const char *s = resolve_lib_name (arg+2);
1171
1172                 /* Saving a full library name.  */
1173                 add_to_list (&libs, s);
1174               }
1175 #endif
1176               break;
1177
1178 #ifdef COLLECT_EXPORT_LIST
1179             /* Saving directories where to search for libraries.  */
1180             case 'L':
1181               add_prefix (&cmdline_lib_dirs, arg+2);
1182               break;
1183 #endif
1184
1185             case 'o':
1186               if (arg[2] == '\0')
1187                 output_file = *ld1++ = *ld2++ = *++argv;
1188               else if (1
1189 #ifdef SWITCHES_NEED_SPACES
1190                        && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1191 #endif
1192                        )
1193
1194                 output_file = &arg[2];
1195               break;
1196
1197             case 'r':
1198               if (arg[2] == '\0')
1199                 rflag = 1;
1200               break;
1201
1202             case 's':
1203               if (arg[2] == '\0' && do_collecting)
1204                 {
1205                   /* We must strip after the nm run, otherwise C++ linking
1206                      will not work.  Thus we strip in the second ld run, or
1207                      else with strip if there is no second ld run.  */
1208                   strip_flag = 1;
1209                   ld1--;
1210                 }
1211               break;
1212
1213             case 'v':
1214               if (arg[2] == '\0')
1215                 vflag = 1;
1216               break;
1217             }
1218         }
1219       else if ((p = strrchr (arg, '.')) != (char *) 0
1220                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1221                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
1222                    || strcmp (p, ".obj") == 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
2668 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2669 #   define GCC_SYMENT           SYMR
2670 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc || (X).st == stGlobal)
2671 #   define GCC_SYMINC(X)        (1)
2672 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
2673 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
2674
2675 #else
2676
2677 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
2678 #   define GCC_SYMENT           SYMENT
2679 #   define GCC_OK_SYMBOL(X) \
2680      (((X).n_sclass == C_EXT) && \
2681       ((X).n_scnum > N_UNDEF) && \
2682       (aix64_flag \
2683        || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2684            || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2685 #   define GCC_UNDEF_SYMBOL(X) \
2686      (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2687 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
2688 #   define GCC_SYMZERO(X)       0
2689
2690 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
2691 #ifdef _AIX51
2692 #   define GCC_CHECK_HDR(X) \
2693      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2694       || (HEADER (X).f_magic == 0767 && aix64_flag))
2695 #else
2696 #   define GCC_CHECK_HDR(X) \
2697      ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2698       || (HEADER (X).f_magic == 0757 && aix64_flag))
2699 #endif
2700
2701 #endif
2702
2703 extern char *ldgetname ();
2704
2705 /* COFF version to scan the name list of the loaded program for
2706    the symbols g++ uses for static constructors and destructors.
2707
2708    The constructor table begins at __CTOR_LIST__ and contains a count
2709    of the number of pointers (or -1 if the constructors are built in a
2710    separate section by the linker), followed by the pointers to the
2711    constructor functions, terminated with a null pointer.  The
2712    destructor table has the same format, and begins at __DTOR_LIST__.  */
2713
2714 static void
2715 scan_prog_file (prog_name, which_pass)
2716      const char *prog_name;
2717      enum pass which_pass;
2718 {
2719   LDFILE *ldptr = NULL;
2720   int sym_index, sym_count;
2721   int is_shared = 0;
2722
2723   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2724     return;
2725
2726 #ifdef COLLECT_EXPORT_LIST
2727   /* We do not need scanning for some standard C libraries.  */
2728   if (which_pass == PASS_FIRST && ignore_library (prog_name))
2729     return;
2730
2731   /* On AIX we have a loop, because there is not much difference
2732      between an object and an archive. This trick allows us to
2733      eliminate scan_libraries() function.  */
2734   do
2735     {
2736 #endif
2737       /* Some platforms (e.g. OSF4) declare ldopen as taking a
2738          non-const char * filename parameter, even though it will not
2739          modify that string.  So we must cast away const-ness here,
2740          which will cause -Wcast-qual to burp.  */
2741       if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2742         {
2743           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2744             fatal ("%s: not a COFF file", prog_name);
2745
2746           if (GCC_CHECK_HDR (ldptr))
2747             {
2748               sym_count = GCC_SYMBOLS (ldptr);
2749               sym_index = GCC_SYMZERO (ldptr);
2750
2751 #ifdef COLLECT_EXPORT_LIST
2752               /* Is current archive member a shared object?  */
2753               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2754 #endif
2755
2756               while (sym_index < sym_count)
2757                 {
2758                   GCC_SYMENT symbol;
2759
2760                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2761                     break;
2762                   sym_index += GCC_SYMINC (symbol);
2763
2764                   if (GCC_OK_SYMBOL (symbol))
2765                     {
2766                       char *name;
2767
2768                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
2769                         continue;               /* should never happen */
2770
2771 #ifdef XCOFF_DEBUGGING_INFO
2772                       /* All AIX function names have a duplicate entry
2773                          beginning with a dot.  */
2774                       if (*name == '.')
2775                         ++name;
2776 #endif
2777
2778                       switch (is_ctor_dtor (name))
2779                         {
2780                         case 1:
2781                           if (! is_shared)
2782                             add_to_list (&constructors, name);
2783 #ifdef COLLECT_EXPORT_LIST
2784                           if (which_pass == PASS_OBJ)
2785                             add_to_list (&exports, name);
2786 #endif
2787                           break;
2788
2789                         case 2:
2790                           if (! is_shared)
2791                             add_to_list (&destructors, name);
2792 #ifdef COLLECT_EXPORT_LIST
2793                           if (which_pass == PASS_OBJ)
2794                             add_to_list (&exports, name);
2795 #endif
2796                           break;
2797
2798 #ifdef COLLECT_EXPORT_LIST
2799                         case 3:
2800 #ifndef LD_INIT_SWITCH
2801                           if (is_shared)
2802                             add_to_list (&constructors, name);
2803 #endif
2804                           break;
2805
2806                         case 4:
2807 #ifndef LD_INIT_SWITCH
2808                           if (is_shared)
2809                             add_to_list (&destructors, name);
2810 #endif
2811                           break;
2812 #endif
2813
2814                         case 5:
2815                           if (! is_shared)
2816                             add_to_list (&frame_tables, name);
2817 #ifdef COLLECT_EXPORT_LIST
2818                           if (which_pass == PASS_OBJ)
2819                             add_to_list (&exports, name);
2820 #endif
2821                           break;
2822
2823                         default:        /* not a constructor or destructor */
2824 #ifdef COLLECT_EXPORT_LIST
2825                           /* If we are building a shared object on AIX we need
2826                              to explicitly export all global symbols.  */
2827                           if (shared_obj) 
2828                             {
2829                               if (which_pass == PASS_OBJ && (! export_flag))
2830                                 add_to_list (&exports, name);
2831                             }
2832 #endif
2833                           continue;
2834                         }
2835
2836                       if (debug)
2837 #if !defined(EXTENDED_COFF)
2838                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2839                                  symbol.n_scnum, symbol.n_sclass,
2840                                  (symbol.n_type ? "0" : ""), symbol.n_type,
2841                                  name);
2842 #else
2843                         fprintf (stderr,
2844                                  "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2845                                  symbol.iss, (long) symbol.value, symbol.index, name);
2846 #endif
2847                     }
2848                 }
2849             }
2850 #ifdef COLLECT_EXPORT_LIST
2851           else
2852             {
2853               /* If archive contains both 32-bit and 64-bit objects,
2854                  we want to skip objects in other mode so mismatch normal.  */
2855               if (debug)
2856                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2857                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
2858             }
2859 #endif
2860         }
2861       else
2862         {
2863           fatal ("%s: cannot open as COFF file", prog_name);
2864         }
2865 #ifdef COLLECT_EXPORT_LIST
2866       /* On AIX loop continues while there are more members in archive.  */
2867     }
2868   while (ldclose (ldptr) == FAILURE);
2869 #else
2870   /* Otherwise we simply close ldptr.  */
2871   (void) ldclose(ldptr);
2872 #endif
2873 }
2874
2875
2876 #ifdef COLLECT_EXPORT_LIST
2877 /* Given a library name without "lib" prefix, this function
2878    returns a full library name including a path.  */
2879 static char *
2880 resolve_lib_name (name)
2881      const char *name;
2882 {
2883   char *lib_buf;
2884   int i, j, l = 0;
2885
2886   for (i = 0; libpaths[i]; i++)
2887     if (libpaths[i]->max_len > l)
2888       l = libpaths[i]->max_len;
2889
2890   lib_buf = xmalloc (l + strlen(name) + 10);
2891
2892   for (i = 0; libpaths[i]; i++)
2893     {
2894       struct prefix_list *list = libpaths[i]->plist;
2895       for (; list; list = list->next)
2896         {
2897           /* The following lines are needed because path_prefix list
2898              may contain directories both with trailing '/' and
2899              without it.  */
2900           const char *p = "";
2901           if (list->prefix[strlen(list->prefix)-1] != '/')
2902             p = "/";
2903           for (j = 0; libexts[j]; j++)
2904             {
2905               sprintf (lib_buf, "%s%slib%s.%s",
2906                        list->prefix, p, name, libexts[j]);
2907 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2908               if (file_exists (lib_buf))
2909                 {
2910 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2911                   return (lib_buf);
2912                 }
2913             }
2914         }
2915     }
2916   if (debug)
2917     fprintf (stderr, "not found\n");
2918   else
2919     fatal ("Library lib%s not found", name);
2920   return (NULL);
2921 }
2922
2923 /* Array of standard AIX libraries which should not
2924    be scanned for ctors/dtors.  */
2925 static const char *aix_std_libs[] = {
2926   "/unix",
2927   "/lib/libc.a",
2928   "/lib/libm.a",
2929   "/lib/libc_r.a",
2930   "/lib/libm_r.a",
2931   "/usr/lib/libc.a",
2932   "/usr/lib/libm.a",
2933   "/usr/lib/libc_r.a",
2934   "/usr/lib/libm_r.a",
2935   "/usr/lib/threads/libc.a",
2936   "/usr/ccs/lib/libc.a",
2937   "/usr/ccs/lib/libm.a",
2938   "/usr/ccs/lib/libc_r.a",
2939   "/usr/ccs/lib/libm_r.a",
2940   NULL
2941 };
2942
2943 /* This function checks the filename and returns 1
2944    if this name matches the location of a standard AIX library. */
2945 static int
2946 ignore_library (name)
2947      const char *name;
2948 {
2949   const char **p = &aix_std_libs[0];
2950   while (*p++ != NULL)
2951     if (! strcmp (name, *p)) return 1;
2952   return 0;
2953 }
2954 #endif
2955
2956 #endif /* OBJECT_FORMAT_COFF */
2957
2958 \f
2959 /*
2960  * OSF/rose specific stuff.
2961  */
2962
2963 #ifdef OBJECT_FORMAT_ROSE
2964
2965 /* Union of the various load commands */
2966
2967 typedef union load_union
2968 {
2969   ldc_header_t                  hdr;    /* common header */
2970   load_cmd_map_command_t        map;    /* map indexing other load cmds */
2971   interpreter_command_t         iprtr;  /* interpreter pathname */
2972   strings_command_t             str;    /* load commands strings section */
2973   region_command_t              region; /* region load command */
2974   reloc_command_t               reloc;  /* relocation section */
2975   package_command_t             pkg;    /* package load command */
2976   symbols_command_t             sym;    /* symbol sections */
2977   entry_command_t               ent;    /* program start section */
2978   gen_info_command_t            info;   /* object information */
2979   func_table_command_t          func;   /* function constructors/destructors */
2980 } load_union_t;
2981
2982 /* Structure to point to load command and data section in memory.  */
2983
2984 typedef struct load_all
2985 {
2986   load_union_t *load;                   /* load command */
2987   char *section;                        /* pointer to section */
2988 } load_all_t;
2989
2990 /* Structure to contain information about a file mapped into memory.  */
2991
2992 struct file_info
2993 {
2994   char *start;                          /* start of map */
2995   char *name;                           /* filename */
2996   long  size;                           /* size of the file */
2997   long  rounded_size;                   /* size rounded to page boundary */
2998   int   fd;                             /* file descriptor */
2999   int   rw;                             /* != 0 if opened read/write */
3000   int   use_mmap;                       /* != 0 if mmap'ed */
3001 };
3002
3003 extern int decode_mach_o_hdr ();
3004 extern int encode_mach_o_hdr ();
3005
3006 static void add_func_table      PARAMS ((mo_header_t *, load_all_t *,
3007                                        symbol_info_t *, int));
3008 static void print_header        PARAMS ((mo_header_t *));
3009 static void print_load_command  PARAMS ((load_union_t *, size_t, int));
3010 static void bad_header          PARAMS ((int));
3011 static struct file_info *read_file  PARAMS ((const char *, int, int));
3012 static void end_file            PARAMS ((struct file_info *));
3013 \f
3014 /* OSF/rose specific version to scan the name list of the loaded
3015    program for the symbols g++ uses for static constructors and
3016    destructors.
3017
3018    The constructor table begins at __CTOR_LIST__ and contains a count
3019    of the number of pointers (or -1 if the constructors are built in a
3020    separate section by the linker), followed by the pointers to the
3021    constructor functions, terminated with a null pointer.  The
3022    destructor table has the same format, and begins at __DTOR_LIST__.  */
3023
3024 static void
3025 scan_prog_file (prog_name, which_pass)
3026      const char *prog_name;
3027      enum pass which_pass;
3028 {
3029   char *obj;
3030   mo_header_t hdr;
3031   load_all_t *load_array;
3032   load_all_t *load_end;
3033   load_all_t *load_cmd;
3034   int symbol_load_cmds;
3035   off_t offset;
3036   int i;
3037   int num_syms;
3038   int status;
3039   char *str_sect;
3040   struct file_info *obj_file;
3041   int prog_fd;
3042   mo_lcid_t cmd_strings   = -1;
3043   symbol_info_t *main_sym = 0;
3044   int rw                  = (which_pass != PASS_FIRST);
3045
3046   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3047   if (prog_fd < 0)
3048     fatal_perror ("open %s", prog_name);
3049
3050   obj_file = read_file (prog_name, prog_fd, rw);
3051   obj = obj_file->start;
3052
3053   status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3054   if (status != MO_HDR_CONV_SUCCESS)
3055     bad_header (status);
3056
3057
3058   /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
3059      since the hardware will automatically swap bytes for us on loading little endian
3060      integers.  */
3061
3062 #ifndef CROSS_COMPILE
3063   if (hdr.moh_magic != MOH_MAGIC_MSB
3064       || hdr.moh_header_version != MOH_HEADER_VERSION
3065       || hdr.moh_byte_order != OUR_BYTE_ORDER
3066       || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3067       || hdr.moh_cpu_type != OUR_CPU_TYPE
3068       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3069       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3070     {
3071       fatal ("incompatibilities between object file & expected values");
3072     }
3073 #endif
3074
3075   if (debug)
3076     print_header (&hdr);
3077
3078   offset = hdr.moh_first_cmd_off;
3079   load_end = load_array
3080     = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3081
3082   /* Build array of load commands, calculating the offsets */
3083   for (i = 0; i < hdr.moh_n_load_cmds; i++)
3084     {
3085       load_union_t *load_hdr;           /* load command header */
3086
3087       load_cmd = load_end++;
3088       load_hdr = (load_union_t *) (obj + offset);
3089
3090       /* If modifying the program file, copy the header.  */
3091       if (rw)
3092         {
3093           load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3094           memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
3095           load_hdr = ptr;
3096
3097           /* null out old command map, because we will rewrite at the end.  */
3098           if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3099             {
3100               cmd_strings = ptr->map.lcm_ld_cmd_strings;
3101               ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3102             }
3103         }
3104
3105       load_cmd->load = load_hdr;
3106       if (load_hdr->hdr.ldci_section_off > 0)
3107         load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3108
3109       if (debug)
3110         print_load_command (load_hdr, offset, i);
3111
3112       offset += load_hdr->hdr.ldci_cmd_size;
3113     }
3114
3115   /* If the last command is the load command map and is not undefined,
3116      decrement the count of load commands.  */
3117   if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3118     {
3119       load_end--;
3120       hdr.moh_n_load_cmds--;
3121     }
3122
3123   /* Go through and process each symbol table section.  */
3124   symbol_load_cmds = 0;
3125   for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3126     {
3127       load_union_t *load_hdr = load_cmd->load;
3128
3129       if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3130         {
3131           symbol_load_cmds++;
3132
3133           if (debug)
3134             {
3135               const char *kind = "unknown";
3136
3137               switch (load_hdr->sym.symc_kind)
3138                 {
3139                 case SYMC_IMPORTS:         kind = "imports"; break;
3140                 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3141                 case SYMC_STABS:           kind = "stabs";   break;
3142                 }
3143
3144               notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3145                       symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3146             }
3147
3148           if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3149             continue;
3150
3151           str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3152           if (str_sect == (char *) 0)
3153             fatal ("string section missing");
3154
3155           if (load_cmd->section == (char *) 0)
3156             fatal ("section pointer missing");
3157
3158           num_syms = load_hdr->sym.symc_nentries;
3159           for (i = 0; i < num_syms; i++)
3160             {
3161               symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3162               char *name = sym->si_name.symbol_name + str_sect;
3163
3164               if (name[0] != '_')
3165                 continue;
3166
3167               if (rw)
3168                 {
3169                   char *n = name + strlen (name) - strlen (NAME__MAIN);
3170
3171                   if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3172                     continue;
3173                   while (n != name)
3174                     if (*--n != '_')
3175                       continue;
3176
3177                   main_sym = sym;
3178                 }
3179               else
3180                 {
3181                   switch (is_ctor_dtor (name))
3182                     {
3183                     case 1:
3184                       add_to_list (&constructors, name);
3185                       break;
3186
3187                     case 2:
3188                       add_to_list (&destructors, name);
3189                       break;
3190
3191                     default:    /* not a constructor or destructor */
3192                       continue;
3193                     }
3194                 }
3195
3196               if (debug)
3197                 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3198                          sym->si_type, sym->si_sc_type, sym->si_flags, name);
3199             }
3200         }
3201     }
3202
3203   if (symbol_load_cmds == 0)
3204     fatal ("no symbol table found");
3205
3206   /* Update the program file now, rewrite header and load commands.  At present,
3207      we assume that there is enough space after the last load command to insert
3208      one more.  Since the first section written out is page aligned, and the
3209      number of load commands is small, this is ok for the present.  */
3210
3211   if (rw)
3212     {
3213       load_union_t *load_map;
3214       size_t size;
3215
3216       if (cmd_strings == -1)
3217         fatal ("no cmd_strings found");
3218
3219       /* Add __main to initializer list.
3220          If we are building a program instead of a shared library, do not
3221          do anything, since in the current version, you cannot do mallocs
3222          and such in the constructors.  */
3223
3224       if (main_sym != (symbol_info_t *) 0
3225           && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3226         add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3227
3228       if (debug)
3229         notice ("\nUpdating header and load commands.\n\n");
3230
3231       hdr.moh_n_load_cmds++;
3232       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3233
3234       /* Create new load command map.  */
3235       if (debug)
3236         notice ("load command map, %d cmds, new size %ld.\n",
3237                 (int) hdr.moh_n_load_cmds, (long) size);
3238
3239       load_map = (load_union_t *) xcalloc (1, size);
3240       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3241       load_map->map.ldc_header.ldci_cmd_size = size;
3242       load_map->map.lcm_ld_cmd_strings = cmd_strings;
3243       load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3244       load_array[hdr.moh_n_load_cmds-1].load = load_map;
3245
3246       offset = hdr.moh_first_cmd_off;
3247       for (i = 0; i < hdr.moh_n_load_cmds; i++)
3248         {
3249           load_map->map.lcm_map[i] = offset;
3250           if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3251             hdr.moh_load_map_cmd_off = offset;
3252
3253           offset += load_array[i].load->hdr.ldci_cmd_size;
3254         }
3255
3256       hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3257
3258       if (debug)
3259         print_header (&hdr);
3260
3261       /* Write header */
3262       status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3263       if (status != MO_HDR_CONV_SUCCESS)
3264         bad_header (status);
3265
3266       if (debug)
3267         notice ("writing load commands.\n\n");
3268
3269       /* Write load commands */
3270       offset = hdr.moh_first_cmd_off;
3271       for (i = 0; i < hdr.moh_n_load_cmds; i++)
3272         {
3273           load_union_t *load_hdr = load_array[i].load;
3274           size_t size = load_hdr->hdr.ldci_cmd_size;
3275
3276           if (debug)
3277             print_load_command (load_hdr, offset, i);
3278
3279           bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3280           offset += size;
3281         }
3282     }
3283
3284   end_file (obj_file);
3285
3286   if (close (prog_fd))
3287     fatal_perror ("close %s", prog_name);
3288
3289   if (debug)
3290     fprintf (stderr, "\n");
3291 }
3292
3293 \f
3294 /* Add a function table to the load commands to call a function
3295    on initiation or termination of the process.  */
3296
3297 static void
3298 add_func_table (hdr_p, load_array, sym, type)
3299      mo_header_t *hdr_p;                /* pointer to global header */
3300      load_all_t *load_array;            /* array of ptrs to load cmds */
3301      symbol_info_t *sym;                /* pointer to symbol entry */
3302      int type;                          /* fntc_type value */
3303 {
3304   /* Add a new load command.  */
3305   int num_cmds = ++hdr_p->moh_n_load_cmds;
3306   int load_index = num_cmds - 1;
3307   size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3308   load_union_t *ptr = xcalloc (1, size);
3309   load_all_t *load_cmd;
3310   int i;
3311
3312   /* Set the unresolved address bit in the header to force the loader to be
3313      used, since kernel exec does not call the initialization functions.  */
3314   hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3315
3316   load_cmd = &load_array[load_index];
3317   load_cmd->load = ptr;
3318   load_cmd->section = (char *) 0;
3319
3320   /* Fill in func table load command.  */
3321   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3322   ptr->func.ldc_header.ldci_cmd_size = size;
3323   ptr->func.ldc_header.ldci_section_off = 0;
3324   ptr->func.ldc_header.ldci_section_len = 0;
3325   ptr->func.fntc_type = type;
3326   ptr->func.fntc_nentries = 1;
3327
3328   /* copy address, turn it from abs. address to (region,offset) if necessary.  */
3329   /* Is the symbol already expressed as (region, offset)?  */
3330   if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3331     {
3332       ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3333       ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3334     }
3335
3336   /* If not, figure out which region it's in.  */
3337   else
3338     {
3339       mo_vm_addr_t addr = sym->si_value.abs_val;
3340       int found = 0;
3341
3342       for (i = 0; i < load_index; i++)
3343         {
3344           if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3345             {
3346               region_command_t *region_ptr = &load_array[i].load->region;
3347
3348               if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3349                   && addr >= region_ptr->regc_addr.vm_addr
3350                   && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3351                 {
3352                   ptr->func.fntc_entry_loc[0].adr_lcid = i;
3353                   ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3354                   found++;
3355                   break;
3356                 }
3357             }
3358         }
3359
3360       if (!found)
3361         fatal ("could not convert 0x%l.8x into a region", addr);
3362     }
3363
3364   if (debug)
3365     notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3366             type == FNTC_INITIALIZATION ? "init" : "term",
3367             (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3368             (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3369             (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3370
3371 }
3372
3373 \f
3374 /* Print the global header for an OSF/rose object.  */
3375
3376 static void
3377 print_header (hdr_ptr)
3378      mo_header_t *hdr_ptr;
3379 {
3380   fprintf (stderr, "\nglobal header:\n");
3381   fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
3382   fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
3383   fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
3384   fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
3385   fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
3386   fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
3387   fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
3388   fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
3389   fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3390   fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
3391   fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3392   fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3393   fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3394   fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3395   fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
3396
3397   if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3398     fprintf (stderr, ", relocatable");
3399
3400   if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3401     fprintf (stderr, ", linkable");
3402
3403   if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3404     fprintf (stderr, ", execable");
3405
3406   if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3407     fprintf (stderr, ", executable");
3408
3409   if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3410     fprintf (stderr, ", unresolved");
3411
3412   fprintf (stderr, "\n\n");
3413   return;
3414 }
3415
3416 \f
3417 /* Print a short summary of a load command.  */
3418
3419 static void
3420 print_load_command (load_hdr, offset, number)
3421      load_union_t *load_hdr;
3422      size_t offset;
3423      int number;
3424 {
3425   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3426   const char *type_str = (char *) 0;
3427
3428   switch (type)
3429     {
3430     case LDC_UNDEFINED:   type_str = "UNDEFINED";       break;
3431     case LDC_CMD_MAP:     type_str = "CMD_MAP";         break;
3432     case LDC_INTERPRETER: type_str = "INTERPRETER";     break;
3433     case LDC_STRINGS:     type_str = "STRINGS";         break;
3434     case LDC_REGION:      type_str = "REGION";          break;
3435     case LDC_RELOC:       type_str = "RELOC";           break;
3436     case LDC_PACKAGE:     type_str = "PACKAGE";         break;
3437     case LDC_SYMBOLS:     type_str = "SYMBOLS";         break;
3438     case LDC_ENTRY:       type_str = "ENTRY";           break;
3439     case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";      break;
3440     case LDC_GEN_INFO:    type_str = "GEN_INFO";        break;
3441     }
3442
3443   fprintf (stderr,
3444            "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3445            number,
3446            (long) load_hdr->hdr.ldci_cmd_size,
3447            (long) offset,
3448            (long) load_hdr->hdr.ldci_section_off,
3449            (long) load_hdr->hdr.ldci_section_len);
3450
3451   if (type_str == (char *) 0)
3452     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3453
3454   else if (type != LDC_REGION)
3455     fprintf (stderr, ", ty: %s\n", type_str);
3456
3457   else
3458     {
3459       const char *region = "";
3460       switch (load_hdr->region.regc_usage_type)
3461         {
3462         case REG_TEXT_T:        region = ", .text";     break;
3463         case REG_DATA_T:        region = ", .data";     break;
3464         case REG_BSS_T:         region = ", .bss";      break;
3465         case REG_GLUE_T:        region = ", .glue";     break;
3466 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3467         case REG_RDATA_T:       region = ", .rdata";    break;
3468         case REG_SDATA_T:       region = ", .sdata";    break;
3469         case REG_SBSS_T:        region = ", .sbss";     break;
3470 #endif
3471         }
3472
3473       fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3474                type_str,
3475                (long) load_hdr->region.regc_vm_addr,
3476                (long) load_hdr->region.regc_vm_size,
3477                region);
3478     }
3479
3480   return;
3481 }
3482
3483 \f
3484 /* Fatal error when {en,de}code_mach_o_header fails.  */
3485
3486 static void
3487 bad_header (status)
3488      int status;
3489 {
3490   switch (status)
3491     {
3492     case MO_ERROR_BAD_MAGIC:            fatal ("bad magic number");
3493     case MO_ERROR_BAD_HDR_VERS:         fatal ("bad header version");
3494     case MO_ERROR_BAD_RAW_HDR_VERS:     fatal ("bad raw header version");
3495     case MO_ERROR_BUF2SML:              fatal ("raw header buffer too small");
3496     case MO_ERROR_OLD_RAW_HDR_FILE:     fatal ("old raw header file");
3497     case MO_ERROR_UNSUPPORTED_VERS:     fatal ("unsupported version");
3498     default:
3499       fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3500     }
3501 }
3502
3503 \f
3504 /* Read a file into a memory buffer.  */
3505
3506 static struct file_info *
3507 read_file (name, fd, rw)
3508      const char *name;          /* filename */
3509      int fd;                    /* file descriptor */
3510      int rw;                    /* read/write */
3511 {
3512   struct stat stat_pkt;
3513   struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3514 #ifdef USE_MMAP
3515   static int page_size;
3516 #endif
3517
3518   if (fstat (fd, &stat_pkt) < 0)
3519     fatal_perror ("fstat %s", name);
3520
3521   p->name         = name;
3522   p->size         = stat_pkt.st_size;
3523   p->rounded_size = stat_pkt.st_size;
3524   p->fd           = fd;
3525   p->rw           = rw;
3526
3527 #ifdef USE_MMAP
3528   if (debug)
3529     fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3530
3531   if (page_size == 0)
3532     page_size = sysconf (_SC_PAGE_SIZE);
3533
3534   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3535   p->start = mmap ((caddr_t) 0,
3536                    (rw) ? p->rounded_size : p->size,
3537                    (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3538                    MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3539                    fd,
3540                    0L);
3541
3542   if (p->start != (char *) 0 && p->start != (char *) -1)
3543     p->use_mmap = 1;
3544
3545   else
3546 #endif /* USE_MMAP */
3547     {
3548       long len;
3549
3550       if (debug)
3551         fprintf (stderr, "read %s\n", name);
3552
3553       p->use_mmap = 0;
3554       p->start = xmalloc (p->size);
3555       if (lseek (fd, 0L, SEEK_SET) < 0)
3556         fatal_perror ("lseek %s 0", name);
3557
3558       len = read (fd, p->start, p->size);
3559       if (len < 0)
3560         fatal_perror ("read %s", name);
3561
3562       if (len != p->size)
3563         fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3564     }
3565
3566   return p;
3567 }
3568 \f
3569 /* Do anything necessary to write a file back from memory.  */
3570
3571 static void
3572 end_file (ptr)
3573      struct file_info *ptr;     /* file information block */
3574 {
3575 #ifdef USE_MMAP
3576   if (ptr->use_mmap)
3577     {
3578       if (ptr->rw)
3579         {
3580           if (debug)
3581             fprintf (stderr, "msync %s\n", ptr->name);
3582
3583           if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3584             fatal_perror ("msync %s", ptr->name);
3585         }
3586
3587       if (debug)
3588         fprintf (stderr, "munmap %s\n", ptr->name);
3589
3590       if (munmap (ptr->start, ptr->size))
3591         fatal_perror ("munmap %s", ptr->name);
3592     }
3593   else
3594 #endif /* USE_MMAP */
3595     {
3596       if (ptr->rw)
3597         {
3598           long len;
3599
3600           if (debug)
3601             fprintf (stderr, "write %s\n", ptr->name);
3602
3603           if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3604             fatal_perror ("lseek %s 0", ptr->name);
3605
3606           len = write (ptr->fd, ptr->start, ptr->size);
3607           if (len < 0)
3608             fatal_perror ("write %s", ptr->name);
3609
3610           if (len != ptr->size)
3611             fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3612         }
3613
3614       free (ptr->start);
3615     }
3616
3617   free (ptr);
3618 }
3619
3620 #endif /* OBJECT_FORMAT_ROSE */