OSDN Git Service

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