OSDN Git Service

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