OSDN Git Service

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