OSDN Git Service

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