OSDN Git Service

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