OSDN Git Service

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