OSDN Git Service

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