OSDN Git Service

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