OSDN Git Service

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