OSDN Git Service

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