OSDN Git Service

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