OSDN Git Service

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