OSDN Git Service

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