OSDN Git Service

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