OSDN Git Service

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