OSDN Git Service

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