OSDN Git Service

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