Annotation of gcc/collect2.c, revision 1.1.1.4

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