OSDN Git Service

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