Annotation of gcc/collect2.c, revision 1.1.1.5

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