OSDN Git Service

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