OSDN Git Service

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