OSDN Git Service

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