OSDN Git Service

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