OSDN Git Service

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