OSDN Git Service

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