OSDN Git Service

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