OSDN Git Service

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