OSDN Git Service

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