OSDN Git Service

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