OSDN Git Service

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