OSDN Git Service

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