OSDN Git Service

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