OSDN Git Service

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