OSDN Git Service

(find_a_file): Always reject "./ld".
[pf3gnuchains/gcc-fork.git] / gcc / collect2.c
1 /* Collect static initialization info into data structures
2    that can be traversed by C++ initialization and finalization
3    routines.
4
5    Copyright (C) 1992 Free Software Foundation, Inc.
6    Contributed by Chris Smith (csmith@convex.com).
7    Heavily modified by Michael Meissner (meissner@osf.org),
8    Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
9
10 This file is part of GNU CC.
11
12 GNU CC is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GNU CC is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GNU CC; see the file COPYING.  If not, write to
24 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
25
26
27 /* Build tables of static constructors and destructors and run ld. */
28
29 #include <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 #ifdef NO_WAIT_H
37 #include <sys/wait.h>
38 #endif
39
40 #ifndef errno
41 extern int errno;
42 #endif
43
44 #define COLLECT
45
46 #include "config.h"
47
48 #ifndef __STDC__
49 #define generic char
50 #define const
51
52 #else
53 #define generic void
54 #endif
55
56 #ifdef USG
57 #define vfork fork
58 #endif
59
60 #ifndef R_OK
61 #define R_OK 4
62 #define W_OK 2
63 #define X_OK 1
64 #endif
65
66 /* On MSDOS, write temp files in current dir
67    because there's no place else we can expect to use.  */
68 #if __MSDOS__
69 #ifndef P_tmpdir
70 #define P_tmpdir "./"
71 #endif
72 #endif
73 \f
74 /* On certain systems, we have code that works by scanning the object file
75    directly.  But this code uses system-specific header files and library
76    functions, so turn it off in a cross-compiler.  Likewise, the names of
77    the utilities aren't correct for a cross-compiler; we have to hope that
78    cross-versions are in the proper directories.  */
79
80 #ifdef CROSS_COMPILE
81 #undef OBJECT_FORMAT_COFF
82 #undef OBJECT_FORMAT_ROSE
83 #undef MD_EXEC_PREFIX
84 #undef REAL_LD_FILE_NAME
85 #undef REAL_NM_FILE_NAME
86 #undef REAL_STRIP_FILE_NAME
87 #endif
88
89 /* If we can't use a special method, use the ordinary one:
90    run nm to find what symbols are present.
91    In a cross-compiler, this means you need a cross nm,
92    but that isn't quite as unpleasant as special headers.  */
93
94 #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
95 #define OBJECT_FORMAT_NONE
96 #endif
97
98 #ifdef OBJECT_FORMAT_COFF
99
100 #include <a.out.h>
101 #include <ar.h>
102
103 #ifdef UMAX
104 #include <sgs.h>
105 #endif
106
107 /* Many versions of ldfcn.h define these.  */
108 #ifdef FREAD
109 #undef FREAD
110 #undef FWRITE
111 #endif
112
113 #include <ldfcn.h>
114
115 /* Some systems have an ISCOFF macro, but others do not.  In some cases
116    the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
117    that either do not have an ISCOFF macro in /usr/include or for those 
118    where it is wrong.  */
119
120 #ifndef MY_ISCOFF
121 #define MY_ISCOFF(X) ISCOFF (X)
122 #endif
123
124 #endif /* OBJECT_FORMAT_COFF */
125
126 #ifdef OBJECT_FORMAT_ROSE
127
128 #ifdef _OSF_SOURCE
129 #define USE_MMAP
130 #endif
131
132 #ifdef USE_MMAP
133 #include <sys/mman.h>
134 #endif
135
136 #include <unistd.h>
137 #include <mach_o_format.h>
138 #include <mach_o_header.h>
139 #include <mach_o_vals.h>
140 #include <mach_o_types.h>
141
142 #endif /* OBJECT_FORMAT_ROSE */
143
144 #ifdef OBJECT_FORMAT_NONE
145
146 /* Default flags to pass to nm.  */
147 #ifndef NM_FLAGS
148 #define NM_FLAGS "-p"
149 #endif
150
151 #endif /* OBJECT_FORMAT_NONE */
152 \f
153 /* Linked lists of constructor and destructor names. */
154
155 struct id 
156 {
157   struct id *next;
158   int sequence;
159   char name[1];
160 };
161
162 struct head
163 {
164   struct id *first;
165   struct id *last;
166   int number;
167 };
168
169 /* Enumeration giving which pass this is for scanning the program file.  */
170
171 enum pass {
172   PASS_FIRST,                           /* without constructors */
173   PASS_SECOND                           /* with constructors linked in */
174 };
175
176 #ifndef NO_SYS_SIGLIST
177 extern char *sys_siglist[];
178 #endif
179 extern char *version_string;
180
181 static int vflag;                       /* true if -v */
182 static int rflag;                       /* true if -r */
183 static int strip_flag;                  /* true if -s */
184
185 static int debug;                       /* true if -debug */
186
187 static int   temp_filename_length;      /* Length of temp_filename */
188 static char *temp_filename;             /* Base of temp filenames */
189 static char *c_file;                    /* <xxx>.c for constructor/destructor list. */
190 static char *o_file;                    /* <xxx>.o for constructor/destructor list. */
191 static char *nm_file_name;              /* pathname of nm */
192 static char *strip_file_name;           /* pathname of strip */
193
194 static struct head constructors;        /* list of constructors found */
195 static struct head destructors;         /* list of destructors found */
196
197 extern char *getenv ();
198 extern char *mktemp ();
199 static void  add_to_list ();
200 static void  scan_prog_file ();
201 static void  fork_execute ();
202 static void  do_wait ();
203 static void  write_c_file ();
204 static void  my_exit ();
205 static void  handler ();
206 static void  maybe_unlink ();
207 static void  choose_temp_base ();
208
209 generic *xcalloc ();
210 generic *xmalloc ();
211
212 extern char *index ();
213 extern char *rindex ();
214 \f
215 #ifdef NO_DUP2
216 dup2 (oldfd, newfd)
217      int oldfd;
218      int newfd;
219 {
220   int fdtmp[256];
221   int fdx = 0;
222   int fd;
223  
224   if (oldfd == newfd)
225     return 0;
226   close (newfd);
227   while ((fd = dup (oldfd)) != newfd) /* good enough for low fd's */
228     fdtmp[fdx++] = fd;
229   while (fdx > 0)
230     close (fdtmp[--fdx]);
231 }
232 #endif
233
234 char *
235 my_strerror (e)
236      int e;
237 {
238   extern char *sys_errlist[];
239   extern int sys_nerr;
240   static char buffer[30];
241
242   if (!e)
243     return "";
244
245   if (e > 0 && e < sys_nerr)
246     return sys_errlist[e];
247
248   sprintf (buffer, "Unknown error %d", e);
249   return buffer;
250 }
251 \f
252 /* Delete tempfiles and exit function.  */
253
254 static void
255 my_exit (status)
256      int status;
257 {
258   if (c_file != 0 && c_file[0])
259     maybe_unlink (c_file);
260
261   if (o_file != 0 && o_file[0])
262     maybe_unlink (o_file);
263
264   exit (status);
265 }
266
267 \f
268 /* Die when sys call fails. */
269
270 static void
271 fatal_perror (string, arg1, arg2, arg3)
272      char *string;
273 {
274   int e = errno;
275
276   fprintf (stderr, "collect: ");
277   fprintf (stderr, string, arg1, arg2, arg3);
278   fprintf (stderr, ": %s\n", my_strerror (e));
279   my_exit (1);
280 }
281
282 /* Just die. */
283
284 static void
285 fatal (string, arg1, arg2, arg3)
286      char *string;
287 {
288   fprintf (stderr, "collect: ");
289   fprintf (stderr, string, arg1, arg2, arg3);
290   fprintf (stderr, "\n");
291   my_exit (1);
292 }
293
294 /* Write error message.  */
295
296 static void
297 error (string, arg1, arg2, arg3, arg4)
298      char *string;
299 {
300   fprintf (stderr, "collect: ");
301   fprintf (stderr, string, arg1, arg2, arg3, arg4);
302   fprintf (stderr, "\n");
303 }
304
305 /* In case obstack is linked in, and abort is defined to fancy_abort,
306    provide a default entry.  */
307
308 void
309 fancy_abort ()
310 {
311   fatal ("internal error");
312 }
313
314 \f
315 static void
316 handler (signo)
317      int signo;
318 {
319   if (c_file[0])
320     maybe_unlink (c_file);
321
322   if (o_file[0])
323     maybe_unlink (o_file);
324
325   signal (signo, SIG_DFL);
326   kill (getpid (), signo);
327 }
328
329 \f
330 generic *
331 xcalloc (size1, size2)
332      int size1, size2;
333 {
334   generic *ptr = (generic *) calloc (size1, size2);
335   if (ptr)
336     return ptr;
337
338   fatal ("out of memory");
339   return (generic *)0;
340 }
341
342 generic *
343 xmalloc (size)
344      int size;
345 {
346   generic *ptr = (generic *) malloc (size);
347   if (ptr)
348     return ptr;
349
350   fatal ("out of memory");
351   return (generic *)0;
352 }
353
354 /* Make a copy of a string INPUT with size SIZE.  */
355
356 char *
357 savestring (input, size)
358      char *input;
359      int size;
360 {
361   char *output = (char *) xmalloc (size + 1);
362   bcopy (input, output, size);
363   output[size] = 0;
364   return output;
365 }
366 \f
367 /* Decide whether the given symbol is:
368    a constructor (1), a destructor (2), or neither (0).  */
369
370 static int
371 is_ctor_dtor (s)
372      char *s;
373 {
374   struct names { char *name; int len; int ret; int two_underscores; };
375
376   register struct names *p;
377   register int ch;
378   register char *orig_s = s;
379
380   static struct names special[] = {
381 #ifdef NO_DOLLAR_IN_LABEL
382     { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
383     { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
384 #else
385     { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
386     { "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 },
387 #endif
388 #ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
389                          cfront has its own linker procedure to collect them;
390                          if collect2 gets them too, they get collected twice
391                          when the cfront procedure is run and the compiler used
392                          for linking happens to be GCC.  */
393     { "sti__", sizeof ("sti__")-1, 1, 1 },
394     { "std__", sizeof ("std__")-1, 2, 1 },
395 #endif /* CFRONT_LOSSAGE */
396     { NULL, 0, 0, 0 }
397   };
398
399   while ((ch = *s) == '_')
400     ++s;
401
402   if (s == orig_s)
403     return 0;
404
405   for (p = &special[0]; p->len > 0; p++)
406     {
407       if (ch == p->name[0]
408           && (!p->two_underscores || ((s - orig_s) >= 2))
409           && strncmp(s, p->name, p->len) == 0)
410         {
411           return p->ret;
412         }
413     }
414   return 0;
415 }
416
417 \f
418 /* Compute a string to use as the base of all temporary file names.
419    It is substituted for %g.  */
420
421 static void
422 choose_temp_base ()
423 {
424   char *base = getenv ("TMPDIR");
425   int len;
426
427   if (base == (char *)0)
428     {
429 #ifdef P_tmpdir
430       if (access (P_tmpdir, R_OK | W_OK) == 0)
431         base = P_tmpdir;
432 #endif
433       if (base == (char *)0)
434         {
435           if (access ("/usr/tmp", R_OK | W_OK) == 0)
436             base = "/usr/tmp/";
437           else
438             base = "/tmp/";
439         }
440     }
441
442   len = strlen (base);
443   temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
444   strcpy (temp_filename, base);
445   if (len > 0 && temp_filename[len-1] != '/')
446     temp_filename[len++] = '/';
447   strcpy (temp_filename + len, "ccXXXXXX");
448
449   mktemp (temp_filename);
450   temp_filename_length = strlen (temp_filename);
451 }
452 \f
453 /* Routine to add variables to the environment.  */
454
455 #ifndef HAVE_PUTENV
456
457 putenv (str)
458      char *str;
459 {
460 #ifndef VMS                     /* nor about VMS */
461
462   extern char **environ;
463   char **old_environ = environ;
464   char **envp;
465   int num_envs = 0;
466   int name_len = 1;
467   int str_len = strlen (str);
468   char *p = str;
469   int ch;
470
471   while ((ch = *p++) != '\0' && ch != '=')
472     name_len++;
473
474   if (!ch)
475     abort ();
476
477   /* Search for replacing an existing environment variable, and
478      count the number of total environment variables.  */
479   for (envp = old_environ; *envp; envp++)
480     {
481       num_envs++;
482       if (!strncmp (str, *envp, name_len))
483         {
484           *envp = str;
485           return;
486         }
487     }
488
489   /* Add a new environment variable */
490   environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
491   *environ = str;
492   bcopy (old_environ, environ+1, sizeof (char *) * (num_envs+1));
493
494 #endif  /* VMS */
495 }
496
497 #endif  /* HAVE_PUTENV */
498 \f
499 /* By default, colon separates directories in a path.  */
500 #ifndef PATH_SEPARATOR
501 #define PATH_SEPARATOR ':'
502 #endif
503
504 /* Structure to hold all the directories in which to search for files to
505    execute.  */
506
507 struct prefix_list
508 {
509   char *prefix;               /* String to prepend to the path. */
510   struct prefix_list *next;   /* Next in linked list. */
511 };
512
513 struct path_prefix
514 {
515   struct prefix_list *plist;  /* List of prefixes to try */
516   int max_len;                /* Max length of a prefix in PLIST */
517   char *name;                 /* Name of this list (used in config stuff) */
518 };
519
520 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
521    and one from the PATH variable.  */
522
523 static struct path_prefix cpath, path;
524
525 #ifdef CROSS_COMPILE
526 /* This is the name of the target machine.  We use it to form the name
527    of the files to execute.  */
528
529 static char *target_machine = TARGET_MACHINE;
530 #endif
531
532 /* Names under which we were executed.  Never return one of those files in our
533    searches.  */
534
535 static char *our_file_name, *last_file_name;
536 \f
537 /* Search for NAME using prefix list PPREFIX.  We only look for executable
538    files. 
539
540    Return 0 if not found, otherwise return its name, allocated with malloc. */
541
542 static char *
543 find_a_file (pprefix, name)
544      struct path_prefix *pprefix;
545      char *name;
546 {
547   char *temp;
548   struct prefix_list *pl;
549   int len = pprefix->max_len + strlen (name) + 1;
550
551 #ifdef EXECUTABLE_SUFFIX
552   len += strlen (EXECUTABLE_SUFFIX);
553 #endif
554
555   temp = xmalloc (len);
556
557   /* Determine the filename to execute (special case for absolute paths).  */
558
559   if (*name == '/')
560     {
561       if (access (name, X_OK) == 0)
562         {
563           strcpy (temp, name);
564           return temp;
565         }
566     }
567   else
568     for (pl = pprefix->plist; pl; pl = pl->next)
569       {
570         strcpy (temp, pl->prefix);
571         strcat (temp, name);
572         if (strcmp (temp, our_file_name) != 0
573             && ! (last_file_name != 0 && strcmp (temp, last_file_name) == 0)
574             /* This is a kludge, but there seems no way around it.  */
575             && strcmp (temp, "./ld") != 0
576             && access (temp, X_OK) == 0)
577           return temp;
578
579 #ifdef EXECUTABLE_SUFFIX
580         /* Some systems have a suffix for executable files.
581            So try appending that.  */
582         strcat (temp, EXECUTABLE_SUFFIX);
583         if (strcmp (temp, our_file_name) != 0
584             && ! (last_file_name != 0 && strcmp (temp, last_file_name) == 0)
585             && access (temp, X_OK) == 0)
586           return temp;
587 #endif
588       }
589
590   free (temp);
591   return 0;
592 }
593
594 /* Add an entry for PREFIX to prefix list PPREFIX.  */
595
596 static void
597 add_prefix (pprefix, prefix)
598      struct path_prefix *pprefix;
599      char *prefix;
600 {
601   struct prefix_list *pl, **prev;
602   int len;
603
604   if (pprefix->plist)
605     {
606       for (pl = pprefix->plist; pl->next; pl = pl->next)
607         ;
608       prev = &pl->next;
609     }
610   else
611     prev = &pprefix->plist;
612
613   /* Keep track of the longest prefix */
614
615   len = strlen (prefix);
616   if (len > pprefix->max_len)
617     pprefix->max_len = len;
618
619   pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
620   pl->prefix = savestring (prefix, len);
621
622   if (*prev)
623     pl->next = *prev;
624   else
625     pl->next = (struct prefix_list *) 0;
626   *prev = pl;
627 }
628 \f
629 /* Take the value of the environment variable ENV, break it into a path, and
630    add of the entries to PPREFIX.  */
631
632 static void
633 prefix_from_env (env, pprefix)
634      char *env;
635      struct path_prefix *pprefix;
636 {
637   char *p = getenv (env);
638
639   if (p)
640     {
641       char *startp, *endp;
642       char *nstore = (char *) xmalloc (strlen (p) + 3);
643
644       startp = endp = p;
645       while (1)
646         {
647           if (*endp == PATH_SEPARATOR || *endp == 0)
648             {
649               strncpy (nstore, startp, endp-startp);
650               if (endp == startp)
651                 {
652                   strcpy (nstore, "./");
653                 }
654               else if (endp[-1] != '/')
655                 {
656                   nstore[endp-startp] = '/';
657                   nstore[endp-startp+1] = 0;
658                 }
659               else
660                 nstore[endp-startp] = 0;
661
662               add_prefix (pprefix, nstore);
663               if (*endp == 0)
664                 break;
665               endp = startp = endp + 1;
666             }
667           else
668             endp++;
669         }
670     }
671 }
672 \f
673 /* Main program. */
674
675 int
676 main (argc, argv)
677      int argc;
678      char *argv[];
679 {
680   char *ld_suffix       = "ld";
681   char *full_ld_suffix  = ld_suffix;
682   char *real_ld_suffix  = "real-ld";
683   char *full_real_ld_suffix = real_ld_suffix;
684   char *gld_suffix      = "gld";
685   char *full_gld_suffix = gld_suffix;
686   char *nm_suffix       = "nm";
687   char *full_nm_suffix  = nm_suffix;
688   char *gnm_suffix      = "gnm";
689   char *full_gnm_suffix = gnm_suffix;
690   char *strip_suffix    = "strip";
691   char *full_strip_suffix = strip_suffix;
692   char *gstrip_suffix   = "gstrip";
693   char *full_gstrip_suffix = gstrip_suffix;
694   char *outfile         = "a.out";
695   char *arg;
696   FILE *outf;
697   char *ld_file_name;
698   char *c_file_name;
699   char *p;
700   char **c_argv;
701   char **c_ptr;
702   char **ld1_argv       = (char **) xcalloc (sizeof (char *), argc+2);
703   char **ld1            = ld1_argv;
704   char **ld2_argv       = (char **) xcalloc (sizeof (char *), argc+5);
705   char **ld2            = ld2_argv;
706   int first_file;
707   int num_c_args        = argc+7;
708   int len;
709   int clen;
710
711 #ifdef DEBUG
712   debug = 1;
713   vflag = 1;
714 #endif
715
716   our_file_name = argv[0];
717
718   /* We must check that we do not call ourselves in an infinite
719      recursion loop. We save the name used for us in the COLLECT_NAME
720      environment variable, first getting the previous value.
721
722      To be fully safe, we need to maintain a list of names that name
723      been used, but, in practice, two names are enough.  */
724
725   last_file_name = getenv ("COLLECT_NAME");
726
727   p = (char *) xcalloc (sizeof (char *),
728                         sizeof (our_file_name) + strlen ("COLLECT_NAME=") + 1);
729   sprintf (p, "COLLECT_NAME=%s", our_file_name);
730   putenv (p);
731
732   p = (char *) getenv ("COLLECT_GCC_OPTIONS");
733   if (p)
734     while (*p)
735       {
736         char *q = p;
737         while (*q && *q != ' ') q++;
738         if (*p == '-' && p[1] == 'm')
739           num_c_args++;
740
741         if (*q) q++;
742         p = q;
743       }
744
745   c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
746
747   if (argc < 2)
748     fatal ("no arguments");
749
750   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
751     signal (SIGQUIT, handler);
752   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
753     signal (SIGINT, handler);
754   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
755     signal (SIGALRM, handler);
756   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
757     signal (SIGHUP, handler);
758   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
759     signal (SIGSEGV, handler);
760   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
761     signal (SIGBUS, handler);
762
763   /* Extract COMPILER_PATH and PATH into our prefix list.  */
764   prefix_from_env ("COMPILER_PATH", &cpath);
765   prefix_from_env ("PATH", &path);
766
767 #ifdef CROSS_COMPILE
768   /* If we look for a program in the compiler directories, we just use
769      the short name, since these directories are already system-specific.
770      But it we look for a took in the system directories, we need to
771      qualify the program name with the target machine.  */
772
773   full_ld_suffix
774     = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
775   strcpy (full_ld_suffix, ld_suffix);
776   strcat (full_ld_suffix, "-");
777   strcat (full_ld_suffix, target_machine);
778
779   full_real_ld_suffix
780     = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1);
781   strcpy (full_real_ld_suffix, real_ld_suffix);
782   strcat (full_real_ld_suffix, "-");
783   strcat (full_real_ld_suffix, target_machine);
784
785   full_gld_suffix
786     = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
787   strcpy (full_gld_suffix, gld_suffix);
788   strcat (full_gld_suffix, "-");
789   strcat (full_gld_suffix, target_machine);
790
791   full_nm_suffix
792     = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
793   strcpy (full_nm_suffix, nm_suffix);
794   strcat (full_nm_suffix, "-");
795   strcat (full_nm_suffix, target_machine);
796
797   full_gnm_suffix
798     = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
799   strcpy (full_gnm_suffix, gnm_suffix);
800   strcat (full_gnm_suffix, "-");
801   strcat (full_gnm_suffix, target_machine);
802
803   full_strip_suffix
804     = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
805   strcpy (full_strip_suffix, strip_suffix);
806   strcat (full_strip_suffix, "-");
807   strcat (full_strip_suffix, target_machine);
808   
809   full_gstrip_suffix
810     = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
811   strcpy (full_gstrip_suffix, gstrip_suffix);
812   strcat (full_gstrip_suffix, "-");
813   strcat (full_gstrip_suffix, target_machine);
814 #endif /* CROSS_COMPILE */
815
816   /* Try to discover a valid linker/nm/strip to use.  */
817
818   /* Search the (target-specific) compiler dirs for `gld'.  */
819   ld_file_name = find_a_file (&cpath, gld_suffix);
820   /* Search the ordinary system bin directories
821      for `gld' (if native linking) or `gld-TARGET' (if cross).  */
822   if (ld_file_name == 0)
823     ld_file_name = find_a_file (&path, full_gld_suffix);
824   /* Likewise for `real-ld'.  */
825   if (ld_file_name == 0)
826     ld_file_name = find_a_file (&cpath, real_ld_suffix);
827   if (ld_file_name == 0)
828     ld_file_name = find_a_file (&path, full_real_ld_suffix);
829   /* Maybe we know the right file to use (if not cross).  */
830 #ifdef REAL_LD_FILE_NAME
831   if (ld_file_name == 0)
832     ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
833 #endif
834   /* This would be the right place to search the compiler dirs
835      for `ld', but we don't do that, since this program is installed
836      there as `ld'.  */
837   /* Search the ordinary system bin directories
838      for `ld' (if native linking) or `ld-TARGET' (if cross).  */
839   if (ld_file_name == 0)
840     ld_file_name = find_a_file (&path, full_ld_suffix);
841
842   nm_file_name = find_a_file (&cpath, gnm_suffix);
843   if (nm_file_name == 0)
844     nm_file_name = find_a_file (&path, full_gnm_suffix);
845   if (nm_file_name == 0)
846     nm_file_name = find_a_file (&cpath, nm_suffix);
847 #ifdef REAL_NM_FILE_NAME
848   if (nm_file_name == 0)
849     nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
850 #endif
851   if (nm_file_name == 0)
852     nm_file_name = find_a_file (&path, full_nm_suffix);
853
854   strip_file_name = find_a_file (&cpath, gstrip_suffix);
855   if (strip_file_name == 0)
856     strip_file_name = find_a_file (&path, full_gstrip_suffix);
857   if (strip_file_name == 0)
858     strip_file_name = find_a_file (&cpath, strip_suffix);
859 #ifdef REAL_STRIP_FILE_NAME
860   if (strip_file_name == 0)
861     strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
862 #endif
863   if (strip_file_name == 0)
864     strip_file_name = find_a_file (&path, full_strip_suffix);
865
866   /* Determine the full path name of the C compiler to use.  */
867   c_file_name = getenv ("COLLECT_GCC");
868   if (c_file_name == 0)
869     {
870 #ifdef CROSS_COMPILE
871       c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
872       strcpy (c_file_name, "gcc-");
873       strcat (c_file_name, target_machine);
874 #else
875       c_file_name = "gcc";
876 #endif
877     }
878
879   p = find_a_file (&cpath, c_file_name);
880
881   /* Here it should be safe to use the system search path since we should have
882      already qualified the name of the compiler when it is needed.  */
883   if (p == 0)
884     p = find_a_file (&path, c_file_name);
885
886   if (p)
887     c_file_name = p;
888
889   *ld1++ = *ld2++ = ld_file_name;
890
891   /* Make temp file names. */
892   choose_temp_base ();
893   c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
894   o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
895   sprintf (c_file, "%s.c", temp_filename);
896   sprintf (o_file, "%s.o", temp_filename);
897   *c_ptr++ = c_file_name;
898   *c_ptr++ = "-c";
899   *c_ptr++ = "-o";
900   *c_ptr++ = o_file;
901
902   /* !!! When GCC calls collect2,
903      it does not know whether it is calling collect2 or ld.
904      So collect2 cannot meaningfully understand any options
905      except those ld understands.
906      If you propose to make GCC pass some other option,
907      just imagine what will happen if ld is really ld!!!  */
908
909   /* Parse arguments.  Remember output file spec, pass the rest to ld. */
910   /* After the first file, put in the c++ rt0.  */
911
912   first_file = 1;
913   while ((arg = *++argv) != (char *)0)
914     {
915       *ld1++ = *ld2++ = arg;
916
917       if (arg[0] == '-')
918           switch (arg[1])
919             {
920             case 'd':
921               if (!strcmp (arg, "-debug"))
922                 {
923                   debug = 1;
924                   vflag = 1;
925                   ld1--;
926                   ld2--;
927                 }
928               break;
929
930             case 'o':
931               outfile = (arg[2] == '\0') ? argv[1] : &arg[2];
932               break;
933
934             case 'r':
935               if (arg[2] == '\0')
936                 rflag = 1;
937               break;
938
939             case 's':
940               if (arg[2] == '\0')
941                 {
942                   /* We must strip after the nm run, otherwise C++ linking
943                      won't work.  Thus we strip in the second ld run, or
944                      else with strip if there is no second ld run.  */
945                   strip_flag = 1;
946                   ld1--;
947                 }
948               break;
949
950             case 'v':
951               if (arg[2] == '\0')
952                 vflag = 1;
953               break;
954             }
955
956       else if (first_file
957                && (p = rindex (arg, '.')) != (char *)0
958                && strcmp (p, ".o") == 0)
959         {
960           first_file = 0;
961           *ld2++ = o_file;
962         }
963     }
964
965   /* Get any options that the upper GCC wants to pass to the sub-GCC.  */
966   p = (char *) getenv ("COLLECT_GCC_OPTIONS");
967   if (p)
968     while (*p)
969       {
970         char *q = p;
971         while (*q && *q != ' ') q++;
972         if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
973           *c_ptr++ = savestring (p, q - p);
974
975         if (*q) q++;
976         p = q;
977       }
978
979   *c_ptr++ = c_file;
980   *c_ptr = *ld1 = *ld2 = (char *)0;
981
982   if (vflag)
983     {
984       fprintf (stderr, "collect2 version %s", version_string);
985 #ifdef TARGET_VERSION
986       TARGET_VERSION;
987 #endif
988       fprintf (stderr, "\n");
989     }
990
991   if (debug)
992     {
993       char *ptr;
994       fprintf (stderr, "ld_file_name        = %s\n", ld_file_name);
995       fprintf (stderr, "c_file_name         = %s\n", c_file_name);
996       fprintf (stderr, "nm_file_name        = %s\n", nm_file_name);
997       fprintf (stderr, "strip_file_name     = %s\n", strip_file_name);
998       fprintf (stderr, "c_file              = %s\n", c_file);
999       fprintf (stderr, "o_file              = %s\n", o_file);
1000
1001       ptr = getenv ("COLLECT_GCC_OPTIONS");
1002       if (ptr)
1003         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1004
1005       ptr = getenv ("COLLECT_GCC");
1006       if (ptr)
1007         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
1008
1009       ptr = getenv ("COMPILER_PATH");
1010       if (ptr)
1011         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
1012
1013       ptr = getenv ("LIBRARY_PATH");
1014       if (ptr)
1015         fprintf (stderr, "LIBRARY_PATH        = %s\n", ptr);
1016
1017       fprintf (stderr, "\n");
1018     }
1019
1020   /* Load the program, searching all libraries.
1021      Examine the namelist with nm and search it for static constructors
1022      and destructors to call.
1023      Write the constructor and destructor tables to a .s file and reload. */
1024
1025   fork_execute ("ld", ld1_argv);
1026
1027   /* If -r, don't build the constructor or destructor list, just return now.  */
1028   if (rflag)
1029     return 0;
1030
1031   scan_prog_file (outfile, PASS_FIRST);
1032
1033   if (debug)
1034     {
1035       fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1036       fprintf (stderr, "%d destructor(s)  found\n", destructors.number);
1037     }
1038
1039   if (constructors.number == 0 && destructors.number == 0)
1040     {
1041       /* Strip now if it was requested on the command line.  */
1042       if (strip_flag)
1043         {
1044           char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
1045           strip_argv[0] = strip_file_name;
1046           strip_argv[1] = outfile;
1047           strip_argv[2] = (char *) 0;
1048           fork_execute ("strip", strip_argv);
1049         }
1050       return 0;
1051     }
1052
1053   outf = fopen (c_file, "w");
1054   if (outf == (FILE *)0)
1055     fatal_perror ("%s", c_file);
1056
1057   write_c_file (outf, c_file);
1058
1059   if (fclose (outf))
1060     fatal_perror ("closing %s", c_file);
1061
1062   if (debug)
1063     {
1064       fprintf (stderr, "\n========== outfile = %s, c_file = %s\n", outfile, c_file);
1065       write_c_file (stderr, "stderr");
1066       fprintf (stderr, "========== end of c_file\n\n");
1067     }
1068
1069   /* Assemble the constructor and destructor tables.
1070      Link the tables in with the rest of the program. */
1071
1072   fork_execute ("gcc",  c_argv);
1073   fork_execute ("ld", ld2_argv);
1074
1075   /* Let scan_prog_file do any final mods (OSF/rose needs this for
1076      constructors/destructors in shared libraries.  */
1077   scan_prog_file (outfile, PASS_SECOND);
1078
1079   maybe_unlink (c_file);
1080   maybe_unlink (o_file);
1081   return 0;
1082 }
1083
1084 \f
1085 /* Wait for a process to finish, and exit if a non-zero status is found. */
1086
1087 static void
1088 do_wait (prog)
1089      char *prog;
1090 {
1091   int status;
1092
1093   wait (&status);
1094   if (status)
1095     {
1096       int sig = status & 0x7F;
1097       int ret;
1098
1099       if (sig != -1 && sig != 0)
1100         {
1101 #ifdef NO_SYS_SIGLIST
1102           error ("%s terminated with signal %d %s",
1103                  prog,
1104                  sig,
1105                  (status & 0200) ? ", core dumped" : "");
1106 #else
1107           error ("%s terminated with signal %d [%s]%s",
1108                  prog,
1109                  sig,
1110                  sys_siglist[sig],
1111                  (status & 0200) ? ", core dumped" : "");
1112 #endif
1113
1114           my_exit (127);
1115         }
1116
1117       ret = ((status & 0xFF00) >> 8);
1118       if (ret != -1 && ret != 0)
1119         {
1120           error ("%s returned %d exit status", prog, ret);
1121           my_exit (ret);
1122         }
1123     }
1124 }
1125
1126 \f
1127 /* Fork and execute a program, and wait for the reply.  */
1128
1129 static void
1130 fork_execute (prog, argv)
1131      char *prog;
1132      char **argv;
1133 {
1134   int pid;
1135
1136   if (vflag || debug)
1137     {
1138       char **p_argv;
1139       char *str;
1140
1141       if (argv[0])
1142         fprintf (stderr, "%s", argv[0]);
1143       else
1144         fprintf (stderr, "[cannot find %s]", prog);
1145
1146       for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1147         fprintf (stderr, " %s", str);
1148
1149       fprintf (stderr, "\n");
1150     }
1151
1152   fflush (stdout);
1153   fflush (stderr);
1154
1155   /* If we can't find a program we need, complain error.  Do this here
1156      since we might not end up needing something that we couldn't find.  */
1157
1158   if (argv[0] == 0)
1159     fatal ("cannot find `%s'", prog);
1160
1161   pid = vfork ();
1162   if (pid == -1)
1163     fatal_perror ("vfork");
1164
1165   if (pid == 0)                 /* child context */
1166     {
1167       execvp (argv[0], argv);
1168       fatal_perror ("executing %s", prog);
1169     }
1170
1171   do_wait (prog);
1172 }
1173
1174 \f
1175 /* Unlink a file unless we are debugging.  */
1176
1177 static void
1178 maybe_unlink (file)
1179      char *file;
1180 {
1181   if (!debug)
1182     unlink (file);
1183   else
1184     fprintf (stderr, "[Leaving %s]\n", file);
1185 }
1186
1187 \f
1188 /* Add a name to a linked list.  */
1189
1190 static void
1191 add_to_list (head_ptr, name)
1192      struct head *head_ptr;
1193      char *name;
1194 {
1195   struct id *newid = (struct id *) xcalloc (sizeof (*newid) + strlen (name), 1);
1196   static long sequence_number = 0;
1197   newid->sequence = ++sequence_number;
1198   strcpy (newid->name, name);
1199
1200   if (head_ptr->first)
1201     head_ptr->last->next = newid;
1202   else
1203     head_ptr->first = newid;
1204
1205   head_ptr->last = newid;
1206   head_ptr->number++;
1207 }
1208
1209 /* Write: `prefix', the names on list LIST, `suffix'.  */
1210
1211 static void
1212 write_list (stream, prefix, list)
1213      FILE *stream;
1214      char *prefix;
1215      struct id *list;
1216 {
1217   while (list)
1218     {
1219       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1220       list = list->next;
1221     }
1222 }
1223
1224 static void
1225 write_list_with_asm (stream, prefix, list)
1226      FILE *stream;
1227      char *prefix;
1228      struct id *list;
1229 {
1230   while (list)
1231     {
1232       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1233                prefix, list->sequence, list->name);
1234       list = list->next;
1235     }
1236 }
1237
1238 /* Write the constructor/destructor tables. */
1239
1240 static void
1241 write_c_file (stream, name)
1242      FILE *stream;
1243      char *name;
1244 {
1245   /* Write the tables as C code  */
1246
1247   fprintf (stream, "typedef void entry_pt();\n\n");
1248     
1249   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1250     
1251   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1252   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
1253   write_list (stream, "\t", constructors.first);
1254   fprintf (stream, "\t0\n};\n\n");
1255
1256   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1257
1258   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1259   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
1260   write_list (stream, "\t", destructors.first);
1261   fprintf (stream, "\t0\n};\n\n");
1262
1263   fprintf (stream, "extern entry_pt __main;\n");
1264   fprintf (stream, "entry_pt *__main_reference = __main;\n\n");
1265 }
1266
1267 \f
1268 #ifdef OBJECT_FORMAT_NONE
1269
1270 /* Generic version to scan the name list of the loaded program for
1271    the symbols g++ uses for static constructors and destructors.
1272
1273    The constructor table begins at __CTOR_LIST__ and contains a count
1274    of the number of pointers (or -1 if the constructors are built in a
1275    separate section by the linker), followed by the pointers to the
1276    constructor functions, terminated with a null pointer.  The
1277    destructor table has the same format, and begins at __DTOR_LIST__.  */
1278
1279 static void
1280 scan_prog_file (prog_name, which_pass)
1281      char *prog_name;
1282      enum pass which_pass;
1283 {
1284   void (*int_handler) ();
1285   void (*quit_handler) ();
1286   char *nm_argv[4];
1287   int pid;
1288   int argc = 0;
1289   int pipe_fd[2];
1290   char *p, buf[1024];
1291   FILE *inf;
1292
1293   if (which_pass != PASS_FIRST)
1294     return;
1295
1296   /* If we don't have an `nm', complain.  */
1297   if (nm_file_name == 0)
1298     fatal ("cannot find `nm'");
1299
1300   nm_argv[argc++] = "nm";
1301   if (NM_FLAGS[0] != '\0')
1302     nm_argv[argc++] = NM_FLAGS;
1303
1304   nm_argv[argc++] = prog_name;
1305   nm_argv[argc++] = (char *)0;
1306
1307   if (pipe (pipe_fd) < 0)
1308     fatal_perror ("pipe");
1309
1310   inf = fdopen (pipe_fd[0], "r");
1311   if (inf == (FILE *)0)
1312     fatal_perror ("fdopen");
1313
1314   /* Trace if needed.  */
1315   if (vflag)
1316     {
1317       char **p_argv;
1318       char *str;
1319
1320       fprintf (stderr, "%s", nm_file_name);
1321       for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1322         fprintf (stderr, " %s", str);
1323
1324       fprintf (stderr, "\n");
1325     }
1326
1327   fflush (stdout);
1328   fflush (stderr);
1329
1330   /* Spawn child nm on pipe */
1331   pid = vfork ();
1332   if (pid == -1)
1333     fatal_perror ("vfork");
1334
1335   if (pid == 0)                 /* child context */
1336     {
1337       /* setup stdout */
1338       if (dup2 (pipe_fd[1], 1) < 0)
1339         fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
1340
1341       if (close (pipe_fd[0]) < 0)
1342         fatal_perror ("close (%d)", pipe_fd[0]);
1343
1344       if (close (pipe_fd[1]) < 0)
1345         fatal_perror ("close (%d)", pipe_fd[1]);
1346
1347       execv (nm_file_name, nm_argv);
1348       fatal_perror ("executing %s", nm_file_name);
1349     }
1350
1351   /* Parent context from here on.  */
1352   int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
1353   quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
1354
1355   if (close (pipe_fd[1]) < 0)
1356     fatal_perror ("close (%d)", pipe_fd[1]);
1357
1358   if (debug)
1359     fprintf (stderr, "\nnm output with constructors/destructors.\n");
1360
1361   /* Read each line of nm output.  */
1362   while (fgets (buf, sizeof buf, inf) != (char *)0)
1363     {
1364       int ch, ch2;
1365       char *name, *end;
1366
1367       /* If it contains a constructor or destructor name, add the name
1368          to the appropriate list. */
1369
1370       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1371         ;
1372
1373       if (ch == '\0' || ch == '\n')
1374         continue;
1375   
1376       name = p;
1377       /* Find the end of the symbol name.
1378          Don't include `|', because Encore nm can tack that on the end.  */
1379       for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1380            end++)
1381         continue;
1382
1383       *end = '\0';
1384       switch (is_ctor_dtor (name))
1385         {
1386         case 1:
1387           add_to_list (&constructors, name);
1388           break;
1389
1390         case 2:
1391           add_to_list (&destructors, name);
1392           break;
1393
1394         default:                /* not a constructor or destructor */
1395           continue;
1396         }
1397
1398       if (debug)
1399         fprintf (stderr, "\t%s\n", buf);
1400     }
1401
1402   if (debug)
1403     fprintf (stderr, "\n");
1404
1405   if (fclose (inf) != 0)
1406     fatal_perror ("fclose of pipe");
1407
1408   do_wait (nm_file_name);
1409
1410   signal (SIGINT,  int_handler);
1411   signal (SIGQUIT, quit_handler);
1412 }
1413
1414 #endif /* OBJECT_FORMAT_NONE */
1415
1416 \f
1417 /*
1418  * COFF specific stuff.
1419  */
1420
1421 #ifdef OBJECT_FORMAT_COFF
1422
1423 #if defined(EXTENDED_COFF)
1424 #   define GCC_SYMBOLS(X)       (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
1425 #   define GCC_SYMENT           SYMR
1426 #   define GCC_OK_SYMBOL(X)     ((X).st == stProc && (X).sc == scText)
1427 #   define GCC_SYMINC(X)        (1)
1428 #   define GCC_SYMZERO(X)       (SYMHEADER(X).isymMax)
1429 #   define GCC_CHECK_HDR(X)     (PSYMTAB(X) != 0)
1430 #else
1431 #   define GCC_SYMBOLS(X)       (HEADER(ldptr).f_nsyms)
1432 #   define GCC_SYMENT           SYMENT
1433 #   define GCC_OK_SYMBOL(X) \
1434      (((X).n_sclass == C_EXT) && \
1435         (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
1436          ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
1437 #   define GCC_SYMINC(X)        ((X).n_numaux+1)
1438 #   define GCC_SYMZERO(X)       0
1439 #   define GCC_CHECK_HDR(X)     (1)
1440 #endif
1441
1442 extern char *ldgetname ();
1443
1444 /* COFF version to scan the name list of the loaded program for
1445    the symbols g++ uses for static constructors and destructors.
1446
1447    The constructor table begins at __CTOR_LIST__ and contains a count
1448    of the number of pointers (or -1 if the constructors are built in a
1449    separate section by the linker), followed by the pointers to the
1450    constructor functions, terminated with a null pointer.  The
1451    destructor table has the same format, and begins at __DTOR_LIST__.  */
1452
1453 static void
1454 scan_prog_file (prog_name, which_pass)
1455      char *prog_name;
1456      enum pass which_pass;
1457 {
1458   LDFILE *ldptr = NULL;
1459   int sym_index, sym_count;
1460
1461   if (which_pass != PASS_FIRST)
1462     return;
1463
1464   if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
1465     fatal ("%s: can't open as COFF file", prog_name);
1466       
1467   if (!MY_ISCOFF (HEADER (ldptr).f_magic))
1468     fatal ("%s: not a COFF file", prog_name);
1469
1470   if (GCC_CHECK_HDR (ldptr))
1471     {
1472       sym_count = GCC_SYMBOLS (ldptr);
1473       sym_index = GCC_SYMZERO (ldptr);
1474       while (sym_index < sym_count)
1475         {
1476           GCC_SYMENT symbol;
1477
1478           if (ldtbread (ldptr, sym_index, &symbol) <= 0)
1479             break;
1480           sym_index += GCC_SYMINC (symbol);
1481
1482           if (GCC_OK_SYMBOL (symbol))
1483             {
1484               char *name;
1485
1486               if ((name = ldgetname (ldptr, &symbol)) == NULL)
1487                 continue;               /* should never happen */
1488
1489 #ifdef _AIX
1490               /* All AIX function names begin with a dot. */
1491               if (*name++ != '.')
1492                 continue;
1493 #endif
1494
1495               switch (is_ctor_dtor (name))
1496                 {
1497                 case 1:
1498                   add_to_list (&constructors, name);
1499                   break;
1500
1501                 case 2:
1502                   add_to_list (&destructors, name);
1503                   break;
1504
1505                 default:                /* not a constructor or destructor */
1506                   continue;
1507                 }
1508
1509 #if !defined(EXTENDED_COFF)
1510               if (debug)
1511                 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
1512                          symbol.n_scnum, symbol.n_sclass,
1513                          (symbol.n_type ? "0" : ""), symbol.n_type,
1514                          name);
1515 #else
1516               if (debug)
1517                 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
1518                          symbol.iss, symbol.value, symbol.index, name);
1519 #endif
1520             }
1521         }
1522     }
1523
1524   (void) ldclose(ldptr);
1525 }
1526
1527 #endif /* OBJECT_FORMAT_COFF */
1528
1529 \f
1530 /*
1531  * OSF/rose specific stuff.
1532  */
1533
1534 #ifdef OBJECT_FORMAT_ROSE
1535
1536 /* Union of the various load commands */
1537
1538 typedef union load_union
1539 {
1540   ldc_header_t                  hdr;    /* common header */
1541   load_cmd_map_command_t        map;    /* map indexing other load cmds */
1542   interpreter_command_t         iprtr;  /* interpreter pathname */
1543   strings_command_t             str;    /* load commands strings section */
1544   region_command_t              region; /* region load command */
1545   reloc_command_t               reloc;  /* relocation section */
1546   package_command_t             pkg;    /* package load command */
1547   symbols_command_t             sym;    /* symbol sections */
1548   entry_command_t               ent;    /* program start section */
1549   gen_info_command_t            info;   /* object information */
1550   func_table_command_t          func;   /* function constructors/destructors */
1551 } load_union_t;
1552
1553 /* Structure to point to load command and data section in memory.  */
1554
1555 typedef struct load_all
1556 {
1557   load_union_t *load;                   /* load command */
1558   char *section;                        /* pointer to section */
1559 } load_all_t;
1560
1561 /* Structure to contain information about a file mapped into memory.  */
1562
1563 struct file_info
1564 {
1565   char *start;                          /* start of map */
1566   char *name;                           /* filename */
1567   long  size;                           /* size of the file */
1568   long  rounded_size;                   /* size rounded to page boundary */
1569   int   fd;                             /* file descriptor */
1570   int   rw;                             /* != 0 if opened read/write */
1571   int   use_mmap;                       /* != 0 if mmap'ed */
1572 };
1573
1574 extern int decode_mach_o_hdr ();
1575
1576 extern int encode_mach_o_hdr ();
1577
1578 static void bad_header ();
1579
1580 static void print_header ();
1581
1582 static void print_load_command ();
1583
1584 static void add_func_table ();
1585
1586 static struct file_info *read_file ();
1587
1588 static void end_file ();
1589
1590 \f
1591 /* OSF/rose specific version to scan the name list of the loaded
1592    program for the symbols g++ uses for static constructors and
1593    destructors.
1594
1595    The constructor table begins at __CTOR_LIST__ and contains a count
1596    of the number of pointers (or -1 if the constructors are built in a
1597    separate section by the linker), followed by the pointers to the
1598    constructor functions, terminated with a null pointer.  The
1599    destructor table has the same format, and begins at __DTOR_LIST__.  */
1600
1601 static void
1602 scan_prog_file (prog_name, which_pass)
1603      char *prog_name;
1604      enum pass which_pass;
1605 {
1606   char *obj;
1607   mo_header_t hdr;
1608   load_all_t *load_array;
1609   load_all_t *load_end;
1610   load_all_t *load_cmd;
1611   int symbol_load_cmds;
1612   off_t offset;
1613   int i;
1614   int num_syms;
1615   int status;
1616   char *str_sect;
1617   struct file_info *obj_file;
1618   int prog_fd;
1619   mo_lcid_t cmd_strings   = -1;
1620   symbol_info_t *main_sym = 0;
1621   int rw                  = (which_pass != PASS_FIRST);
1622
1623   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1624   if (prog_fd < 0)
1625     fatal_perror ("can't read %s", prog_name);
1626
1627   obj_file = read_file (prog_name, prog_fd, rw);
1628   obj = obj_file->start;
1629
1630   status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
1631   if (status != MO_HDR_CONV_SUCCESS)
1632     bad_header (status);
1633
1634
1635   /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
1636      since the hardware will automatically swap bytes for us on loading little endian
1637      integers.  */
1638
1639 #ifndef CROSS_COMPILE
1640   if (hdr.moh_magic != MOH_MAGIC_MSB
1641       || hdr.moh_header_version != MOH_HEADER_VERSION
1642       || hdr.moh_byte_order != OUR_BYTE_ORDER
1643       || hdr.moh_data_rep_id != OUR_DATA_REP_ID
1644       || hdr.moh_cpu_type != OUR_CPU_TYPE
1645       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
1646       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
1647     {
1648       fatal ("incompatibilities between object file & expected values");
1649     }
1650 #endif
1651
1652   if (debug)
1653     print_header (&hdr);
1654
1655   offset = hdr.moh_first_cmd_off;
1656   load_end = load_array
1657     = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
1658
1659   /* Build array of load commands, calculating the offsets */
1660   for (i = 0; i < hdr.moh_n_load_cmds; i++)
1661     {
1662       load_union_t *load_hdr;           /* load command header */
1663
1664       load_cmd = load_end++;
1665       load_hdr = (load_union_t *) (obj + offset);
1666
1667       /* If modifying the program file, copy the header.  */
1668       if (rw)
1669         {
1670           load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
1671           bcopy ((generic *)load_hdr, (generic *)ptr, load_hdr->hdr.ldci_cmd_size);
1672           load_hdr = ptr;
1673
1674           /* null out old command map, because we will rewrite at the end.  */
1675           if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1676             {
1677               cmd_strings = ptr->map.lcm_ld_cmd_strings;
1678               ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
1679             }
1680         }
1681
1682       load_cmd->load = load_hdr;
1683       if (load_hdr->hdr.ldci_section_off > 0)
1684         load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
1685
1686       if (debug)
1687         print_load_command (load_hdr, offset, i);
1688
1689       offset += load_hdr->hdr.ldci_cmd_size;
1690     }
1691
1692   /* If the last command is the load command map and is not undefined,
1693      decrement the count of load commands.  */
1694   if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
1695     {
1696       load_end--;
1697       hdr.moh_n_load_cmds--;
1698     }
1699
1700   /* Go through and process each symbol table section.  */
1701   symbol_load_cmds = 0;
1702   for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
1703     {
1704       load_union_t *load_hdr = load_cmd->load;
1705
1706       if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1707         {
1708           symbol_load_cmds++;
1709
1710           if (debug)
1711             {
1712               char *kind = "unknown";
1713
1714               switch (load_hdr->sym.symc_kind)
1715                 {
1716                 case SYMC_IMPORTS:         kind = "imports"; break;
1717                 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1718                 case SYMC_STABS:           kind = "stabs";   break;
1719                 }
1720
1721               fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1722                        symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1723             }
1724
1725           if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1726             continue;
1727
1728           str_sect = load_array[load_hdr->sym.symc_strings_section].section;
1729           if (str_sect == (char *)0)
1730             fatal ("string section missing");
1731
1732           if (load_cmd->section == (char *)0)
1733             fatal ("section pointer missing");
1734
1735           num_syms = load_hdr->sym.symc_nentries;
1736           for (i = 0; i < num_syms; i++)
1737             {
1738               symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
1739               char *name = sym->si_name.symbol_name + str_sect;
1740
1741               if (name[0] != '_')
1742                 continue;
1743
1744               if (rw)
1745                 {
1746                   char *n = name;
1747                   while (*n == '_')
1748                     ++n;
1749                   if (*n != 'm' || (n - name) < 2 || strcmp (n, "main"))
1750                     continue;
1751
1752                   main_sym = sym;
1753                 }
1754               else
1755                 {
1756                   switch (is_ctor_dtor (name))
1757                     {
1758                     case 1:
1759                       add_to_list (&constructors, name);
1760                       break;
1761
1762                     case 2:
1763                       add_to_list (&destructors, name);
1764                       break;
1765
1766                     default:    /* not a constructor or destructor */
1767                       continue;
1768                     }
1769                 }
1770
1771               if (debug)
1772                 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
1773                          sym->si_type, sym->si_sc_type, sym->si_flags, name);
1774             }
1775         }
1776     }
1777
1778   if (symbol_load_cmds == 0)
1779     fatal ("no symbol table found");
1780
1781   /* Update the program file now, rewrite header and load commands.  At present,
1782      we assume that there is enough space after the last load command to insert
1783      one more.  Since the first section written out is page aligned, and the
1784      number of load commands is small, this is ok for the present.  */
1785
1786   if (rw)
1787     {
1788       load_union_t *load_map;
1789       size_t size;
1790
1791       if (cmd_strings == -1)
1792         fatal ("no cmd_strings found");
1793
1794       /* Add __main to initializer list.
1795          If we are building a program instead of a shared library, don't
1796          do anything, since in the current version, you cannot do mallocs
1797          and such in the constructors.  */
1798
1799       if (main_sym != (symbol_info_t *)0
1800           && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
1801         add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
1802
1803       if (debug)
1804         fprintf (stderr, "\nUpdating header and load commands.\n\n");
1805
1806       hdr.moh_n_load_cmds++;
1807       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1808
1809       /* Create new load command map.  */
1810       if (debug)
1811         fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
1812                  (int)hdr.moh_n_load_cmds, (long)size);
1813
1814       load_map = (load_union_t *) xcalloc (1, size);
1815       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
1816       load_map->map.ldc_header.ldci_cmd_size = size;
1817       load_map->map.lcm_ld_cmd_strings = cmd_strings;
1818       load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
1819       load_array[hdr.moh_n_load_cmds-1].load = load_map;
1820
1821       offset = hdr.moh_first_cmd_off;
1822       for (i = 0; i < hdr.moh_n_load_cmds; i++)
1823         {
1824           load_map->map.lcm_map[i] = offset;
1825           if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
1826             hdr.moh_load_map_cmd_off = offset;
1827
1828           offset += load_array[i].load->hdr.ldci_cmd_size;
1829         }
1830
1831       hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
1832
1833       if (debug)
1834         print_header (&hdr);
1835
1836       /* Write header */
1837       status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
1838       if (status != MO_HDR_CONV_SUCCESS)
1839         bad_header (status);
1840
1841       if (debug)
1842         fprintf (stderr, "writing load commands.\n\n");
1843
1844       /* Write load commands */
1845       offset = hdr.moh_first_cmd_off;
1846       for (i = 0; i < hdr.moh_n_load_cmds; i++)
1847         {
1848           load_union_t *load_hdr = load_array[i].load;
1849           size_t size = load_hdr->hdr.ldci_cmd_size;
1850
1851           if (debug)
1852             print_load_command (load_hdr, offset, i);
1853
1854           bcopy ((generic *)load_hdr, (generic *)(obj + offset), size);
1855           offset += size;
1856         }
1857     }
1858
1859   end_file (obj_file);
1860
1861   if (close (prog_fd))
1862     fatal_perror ("closing %s", prog_name);
1863
1864   if (debug)
1865     fprintf (stderr, "\n");
1866 }
1867
1868 \f
1869 /* Add a function table to the load commands to call a function
1870    on initiation or termination of the process.  */
1871
1872 static void
1873 add_func_table (hdr_p, load_array, sym, type)
1874      mo_header_t *hdr_p;                /* pointer to global header */
1875      load_all_t *load_array;            /* array of ptrs to load cmds */
1876      symbol_info_t *sym;                /* pointer to symbol entry */
1877      int type;                          /* fntc_type value */
1878 {
1879   /* Add a new load command.  */
1880   int num_cmds = ++hdr_p->moh_n_load_cmds;
1881   int load_index = num_cmds - 1;
1882   size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
1883   load_union_t *ptr = xcalloc (1, size);
1884   load_all_t *load_cmd;
1885   int i;
1886
1887   /* Set the unresolved address bit in the header to force the loader to be
1888      used, since kernel exec does not call the initialization functions.  */
1889   hdr_p->moh_flags |= MOH_UNRESOLVED_F;
1890
1891   load_cmd = &load_array[load_index];
1892   load_cmd->load = ptr;
1893   load_cmd->section = (char *)0;
1894
1895   /* Fill in func table load command.  */
1896   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
1897   ptr->func.ldc_header.ldci_cmd_size = size;
1898   ptr->func.ldc_header.ldci_section_off = 0;
1899   ptr->func.ldc_header.ldci_section_len = 0;
1900   ptr->func.fntc_type = type;
1901   ptr->func.fntc_nentries = 1;
1902
1903   /* copy address, turn it from abs. address to (region,offset) if necessary.  */
1904   /* Is the symbol already expressed as (region, offset)?  */
1905   if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
1906     {
1907       ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
1908       ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
1909     }
1910
1911   /* If not, figure out which region it's in.  */
1912   else
1913     {
1914       mo_vm_addr_t addr = sym->si_value.abs_val;
1915       int found = 0;
1916
1917       for (i = 0; i < load_index; i++)
1918         {
1919           if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
1920             {
1921               region_command_t *region_ptr = &load_array[i].load->region;
1922
1923               if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
1924                   && addr >= region_ptr->regc_addr.vm_addr
1925                   && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
1926                 {
1927                   ptr->func.fntc_entry_loc[0].adr_lcid = i;
1928                   ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
1929                   found++;
1930                   break;
1931                 }
1932             }
1933         }
1934
1935       if (!found)
1936         fatal ("could not convert 0x%l.8x into a region", addr);
1937     }
1938
1939   if (debug)
1940     fprintf (stderr,
1941              "%s function, region %d, offset = %ld (0x%.8lx)\n",
1942              (type == FNTC_INITIALIZATION) ? "init" : "term",
1943              (int)ptr->func.fntc_entry_loc[i].adr_lcid,
1944              (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
1945              (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
1946
1947 }
1948
1949 \f
1950 /* Print the global header for an OSF/rose object.  */
1951
1952 static void
1953 print_header (hdr_ptr)
1954      mo_header_t *hdr_ptr;
1955 {
1956   fprintf (stderr, "\nglobal header:\n");
1957   fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
1958   fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
1959   fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
1960   fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
1961   fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
1962   fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
1963   fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
1964   fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
1965   fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
1966   fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
1967   fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
1968   fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
1969   fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
1970   fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
1971   fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
1972
1973   if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
1974     fprintf (stderr, ", relocatable");
1975
1976   if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
1977     fprintf (stderr, ", linkable");
1978
1979   if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
1980     fprintf (stderr, ", execable");
1981
1982   if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
1983     fprintf (stderr, ", executable");
1984
1985   if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
1986     fprintf (stderr, ", unresolved");
1987
1988   fprintf (stderr, "\n\n");
1989   return;
1990 }
1991
1992 \f
1993 /* Print a short summary of a load command.  */
1994
1995 static void
1996 print_load_command (load_hdr, offset, number)
1997      load_union_t *load_hdr;
1998      size_t offset;
1999      int number;
2000 {
2001   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
2002   char *type_str = (char *)0;
2003
2004   switch (type)
2005     {
2006     case LDC_UNDEFINED:   type_str = "UNDEFINED";       break;
2007     case LDC_CMD_MAP:     type_str = "CMD_MAP";         break;
2008     case LDC_INTERPRETER: type_str = "INTERPRETER";     break;
2009     case LDC_STRINGS:     type_str = "STRINGS";         break;
2010     case LDC_REGION:      type_str = "REGION";          break;
2011     case LDC_RELOC:       type_str = "RELOC";           break;
2012     case LDC_PACKAGE:     type_str = "PACKAGE";         break;
2013     case LDC_SYMBOLS:     type_str = "SYMBOLS";         break;
2014     case LDC_ENTRY:       type_str = "ENTRY";           break;
2015     case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";      break;
2016     case LDC_GEN_INFO:    type_str = "GEN_INFO";        break;
2017     }
2018
2019   fprintf (stderr,
2020            "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
2021            number,
2022            (long) load_hdr->hdr.ldci_cmd_size,
2023            (long) offset,
2024            (long) load_hdr->hdr.ldci_section_off,
2025            (long) load_hdr->hdr.ldci_section_len);
2026
2027   if (type_str == (char *)0)
2028     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
2029
2030   else if (type != LDC_REGION)
2031     fprintf (stderr, ", ty: %s\n", type_str);
2032
2033   else
2034     {
2035       char *region = "";
2036       switch (load_hdr->region.regc_usage_type)
2037         {
2038         case REG_TEXT_T:        region = ", .text";     break;
2039         case REG_DATA_T:        region = ", .data";     break;
2040         case REG_BSS_T:         region = ", .bss";      break;
2041         case REG_GLUE_T:        region = ", .glue";     break;
2042 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
2043         case REG_RDATA_T:       region = ", .rdata";    break;
2044         case REG_SDATA_T:       region = ", .sdata";    break;
2045         case REG_SBSS_T:        region = ", .sbss";     break;
2046 #endif
2047         }
2048
2049       fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
2050                type_str,
2051                (long) load_hdr->region.regc_vm_addr,
2052                (long) load_hdr->region.regc_vm_size,
2053                region);
2054     }
2055
2056   return;
2057 }
2058
2059 \f
2060 /* Fatal error when {en,de}code_mach_o_header fails.  */
2061
2062 static void
2063 bad_header (status)
2064      int status;
2065 {
2066   char *msg = (char *)0;
2067
2068   switch (status)
2069     {
2070     case MO_ERROR_BAD_MAGIC:            msg = "bad magic number";               break;
2071     case MO_ERROR_BAD_HDR_VERS:         msg = "bad header version";             break;
2072     case MO_ERROR_BAD_RAW_HDR_VERS:     msg = "bad raw header version";         break;
2073     case MO_ERROR_BUF2SML:              msg = "raw header buffer too small";    break;
2074     case MO_ERROR_OLD_RAW_HDR_FILE:     msg = "old raw header file";            break;
2075     case MO_ERROR_UNSUPPORTED_VERS:     msg = "unsupported version";            break;
2076     }
2077
2078   if (msg == (char *)0)
2079     fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
2080   else
2081     fatal ("%s", msg);
2082 }
2083
2084 \f
2085 /* Read a file into a memory buffer.  */
2086
2087 static struct file_info *
2088 read_file (name, fd, rw)
2089      char *name;                /* filename */
2090      int fd;                    /* file descriptor */
2091      int rw;                    /* read/write */
2092 {
2093   struct stat stat_pkt;
2094   struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
2095 #ifdef USE_MMAP
2096   static int page_size;
2097 #endif
2098
2099   if (fstat (fd, &stat_pkt) < 0)
2100     fatal_perror ("fstat %s", name);
2101
2102   p->name         = name;
2103   p->size         = stat_pkt.st_size;
2104   p->rounded_size = stat_pkt.st_size;
2105   p->fd           = fd;
2106   p->rw           = rw;
2107
2108 #ifdef USE_MMAP
2109   if (debug)
2110     fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
2111
2112   if (page_size == 0)
2113     page_size = sysconf (_SC_PAGE_SIZE);
2114
2115   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
2116   p->start = mmap ((caddr_t)0,
2117                    (rw) ? p->rounded_size : p->size,
2118                    (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
2119                    MAP_FILE | MAP_VARIABLE | MAP_SHARED,
2120                    fd,
2121                    0L);
2122
2123   if (p->start != (char *)0 && p->start != (char *)-1)
2124     p->use_mmap = 1;
2125
2126   else
2127 #endif /* USE_MMAP */
2128     {
2129       long len;
2130
2131       if (debug)
2132         fprintf (stderr, "read %s\n", name);
2133
2134       p->use_mmap = 0;
2135       p->start = xmalloc (p->size);
2136       if (lseek (fd, 0L, SEEK_SET) < 0)
2137         fatal_perror ("lseek to 0 on %s", name);
2138
2139       len = read (fd, p->start, p->size);
2140       if (len < 0)
2141         fatal_perror ("read %s", name);
2142
2143       if (len != p->size)
2144         fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
2145     }
2146
2147   return p;
2148 }
2149
2150 \f
2151 /* Do anything necessary to write a file back from memory.  */
2152
2153 static void
2154 end_file (ptr)
2155      struct file_info *ptr;     /* file information block */
2156 {
2157 #ifdef USE_MMAP
2158   if (ptr->use_mmap)
2159     {
2160       if (ptr->rw)
2161         {
2162           if (debug)
2163             fprintf (stderr, "msync %s\n", ptr->name);
2164
2165           if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
2166             fatal_perror ("msync %s", ptr->name);
2167         }
2168
2169       if (debug)
2170         fprintf (stderr, "munmap %s\n", ptr->name);
2171
2172       if (munmap (ptr->start, ptr->size))
2173         fatal_perror ("munmap %s", ptr->name);
2174     }
2175   else
2176 #endif /* USE_MMAP */
2177     {
2178       if (ptr->rw)
2179         {
2180           long len;
2181
2182           if (debug)
2183             fprintf (stderr, "write %s\n", ptr->name);
2184
2185           if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
2186             fatal_perror ("lseek to 0 on %s", ptr->name);
2187
2188           len = write (ptr->fd, ptr->start, ptr->size);
2189           if (len < 0)
2190             fatal_perror ("read %s", ptr->name);
2191
2192           if (len != ptr->size)
2193             fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
2194         }
2195
2196       free ((generic *)ptr->start);
2197     }
2198
2199   free ((generic *)ptr);
2200 }
2201
2202 #endif /* OBJECT_FORMAT_ROSE */