OSDN Git Service

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