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