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

unix.superglobalmegacorp.com

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