OSDN Git Service

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