Annotation of gcc/collect2.c, revision 1.1.1.1

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