OSDN Git Service

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