OSDN Git Service

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