OSDN Git Service

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