OSDN Git Service

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