Annotation of gcc/collect2.c, revision 1.1.1.7

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