OSDN Git Service

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