Annotation of GNUtools/cc/collect2.c, revision 1.1.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.