Annotation of gcc/collect2.c, revision 1.1.1.3

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