OSDN Git Service

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