Annotation of gcc/collect2.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.