OSDN Git Service

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