OSDN Git Service

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