OSDN Git Service

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