Annotation of gcc/collect2.c, revision 1.1.1.9

1.1       root        1: /* Collect static initialization info into data structures
                      2:    that can be traversed by C++ initialization and finalization
                      3:    routines.
                      4: 
1.1.1.8   root        5:    Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1.1       root        6:    Contributed by Chris Smith ([email protected]).
1.1.1.8   root        7:    Heavily modified by Michael Meissner ([email protected]),
1.1       root        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
1.1.1.8   root       24: the Free Software Foundation, 59 Temple Place - Suite 330,
                     25: Boston, MA 02111-1307, USA.  */
1.1       root       26: 
                     27: 
                     28: /* Build tables of static constructors and destructors and run ld. */
                     29: 
1.1.1.8   root       30: #include "config.h"
1.1       root       31: #include <sys/types.h>
                     32: #include <stdio.h>
                     33: #include <ctype.h>
                     34: #include <errno.h>
                     35: #include <signal.h>
                     36: #include <sys/file.h>
                     37: #include <sys/stat.h>
1.1.1.3   root       38: #ifdef NO_WAIT_H
1.1       root       39: #include <sys/wait.h>
1.1.1.3   root       40: #endif
1.1       root       41: 
1.1.1.8   root       42: #define COLLECT
                     43: 
                     44: #include "demangle.h"
                     45: #include "obstack.h"
                     46: 
1.1       root       47: #ifndef errno
                     48: extern int errno;
                     49: #endif
                     50: 
1.1.1.8   root       51: #ifndef HAVE_STRERROR
                     52: #if defined(bsd4_4) 
1.1.1.6   root       53: extern const char *const sys_errlist[];
                     54: #else
                     55: extern char *sys_errlist[];
                     56: #endif
                     57: extern int sys_nerr;
1.1.1.8   root       58: #else
                     59: char *strerror();
                     60: #endif
1.1.1.6   root       61: 
1.1.1.8   root       62: /* Obstack allocation and deallocation routines.  */
                     63: #define obstack_chunk_alloc xmalloc
                     64: #define obstack_chunk_free free
1.1       root       65: 
1.1.1.8   root       66: #if !defined (__STDC__) && !defined (const)
1.1       root       67: #define const
                     68: #endif
                     69: 
1.1.1.2   root       70: #ifdef USG
                     71: #define vfork fork
                     72: #endif
                     73: 
1.1.1.6   root       74: /* Add prototype support.  */
                     75: #ifndef PROTO
                     76: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
                     77: #define PROTO(ARGS) ARGS
                     78: #else
                     79: #define PROTO(ARGS) ()
                     80: #endif
                     81: #endif
                     82: 
1.1.1.2   root       83: #ifndef R_OK
                     84: #define R_OK 4
                     85: #define W_OK 2
                     86: #define X_OK 1
                     87: #endif
                     88: 
1.1.1.7   root       89: #ifndef WIFSIGNALED
                     90: #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
                     91: #endif
                     92: #ifndef WTERMSIG
                     93: #define WTERMSIG(S) ((S) & 0x7f)
                     94: #endif
                     95: #ifndef WIFEXITED
                     96: #define WIFEXITED(S) (((S) & 0xff) == 0)
                     97: #endif
                     98: #ifndef WEXITSTATUS
                     99: #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
                    100: #endif
                    101: 
1.1.1.2   root      102: /* On MSDOS, write temp files in current dir
                    103:    because there's no place else we can expect to use.  */
1.1.1.7   root      104: #ifdef __MSDOS__
1.1.1.2   root      105: #ifndef P_tmpdir
                    106: #define P_tmpdir "./"
                    107: #endif
                    108: #endif
                    109: 
                    110: /* On certain systems, we have code that works by scanning the object file
                    111:    directly.  But this code uses system-specific header files and library
1.1.1.5   root      112:    functions, so turn it off in a cross-compiler.  Likewise, the names of
                    113:    the utilities aren't correct for a cross-compiler; we have to hope that
                    114:    cross-versions are in the proper directories.  */
1.1.1.2   root      115: 
                    116: #ifdef CROSS_COMPILE
1.1.1.8   root      117: #undef SUNOS4_SHARED_LIBRARIES
1.1.1.2   root      118: #undef OBJECT_FORMAT_COFF
                    119: #undef OBJECT_FORMAT_ROSE
1.1.1.5   root      120: #undef MD_EXEC_PREFIX
                    121: #undef REAL_LD_FILE_NAME
                    122: #undef REAL_NM_FILE_NAME
                    123: #undef REAL_STRIP_FILE_NAME
1.1.1.2   root      124: #endif
                    125: 
                    126: /* If we can't use a special method, use the ordinary one:
                    127:    run nm to find what symbols are present.
                    128:    In a cross-compiler, this means you need a cross nm,
                    129:    but that isn't quite as unpleasant as special headers.  */
                    130: 
                    131: #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
                    132: #define OBJECT_FORMAT_NONE
                    133: #endif
                    134: 
                    135: #ifdef OBJECT_FORMAT_COFF
                    136: 
                    137: #include <a.out.h>
                    138: #include <ar.h>
                    139: 
                    140: #ifdef UMAX
                    141: #include <sgs.h>
                    142: #endif
                    143: 
1.1.1.4   root      144: /* Many versions of ldfcn.h define these.  */
                    145: #ifdef FREAD
1.1.1.2   root      146: #undef FREAD
                    147: #undef FWRITE
                    148: #endif
                    149: 
                    150: #include <ldfcn.h>
                    151: 
1.1.1.5   root      152: /* Some systems have an ISCOFF macro, but others do not.  In some cases
                    153:    the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
                    154:    that either do not have an ISCOFF macro in /usr/include or for those 
                    155:    where it is wrong.  */
                    156: 
1.1.1.4   root      157: #ifndef MY_ISCOFF
                    158: #define MY_ISCOFF(X) ISCOFF (X)
                    159: #endif
                    160: 
1.1.1.8   root      161: #ifdef XCOFF_DEBUGGING_INFO
                    162: #define XCOFF_SCAN_LIBS
                    163: #endif
                    164: 
1.1.1.2   root      165: #endif /* OBJECT_FORMAT_COFF */
                    166: 
1.1       root      167: #ifdef OBJECT_FORMAT_ROSE
                    168: 
                    169: #ifdef _OSF_SOURCE
                    170: #define USE_MMAP
                    171: #endif
                    172: 
                    173: #ifdef USE_MMAP
                    174: #include <sys/mman.h>
                    175: #endif
                    176: 
                    177: #include <unistd.h>
                    178: #include <mach_o_format.h>
                    179: #include <mach_o_header.h>
                    180: #include <mach_o_vals.h>
                    181: #include <mach_o_types.h>
1.1.1.2   root      182: 
1.1       root      183: #endif /* OBJECT_FORMAT_ROSE */
                    184: 
1.1.1.2   root      185: #ifdef OBJECT_FORMAT_NONE
                    186: 
1.1       root      187: /* Default flags to pass to nm.  */
                    188: #ifndef NM_FLAGS
                    189: #define NM_FLAGS "-p"
                    190: #endif
                    191: 
1.1.1.2   root      192: #endif /* OBJECT_FORMAT_NONE */
1.1.1.6   root      193: 
                    194: /* Some systems use __main in a way incompatible with its use in gcc, in these
                    195:    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
                    196:    give the same symbol without quotes for an alternative entry point.  You
1.1.1.8   root      197:    must define both, or neither.  */
1.1.1.6   root      198: #ifndef NAME__MAIN
                    199: #define NAME__MAIN "__main"
                    200: #define SYMBOL__MAIN __main
                    201: #endif
                    202: 
1.1.1.8   root      203: #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES || defined(XCOFF_SCAN_LIBS)
                    204: #define SCAN_LIBRARIES
                    205: #endif
                    206: 
                    207: #ifdef USE_COLLECT2
                    208: int do_collecting = 1;
                    209: #else
                    210: int do_collecting = 0;
                    211: #endif
1.1       root      212: 
                    213: /* Linked lists of constructor and destructor names. */
                    214: 
                    215: struct id 
                    216: {
                    217:   struct id *next;
                    218:   int sequence;
                    219:   char name[1];
                    220: };
                    221: 
                    222: struct head
                    223: {
                    224:   struct id *first;
                    225:   struct id *last;
                    226:   int number;
                    227: };
                    228: 
                    229: /* Enumeration giving which pass this is for scanning the program file.  */
                    230: 
                    231: enum pass {
                    232:   PASS_FIRST,                          /* without constructors */
1.1.1.8   root      233:   PASS_OBJ,                            /* individual objects */
                    234:   PASS_LIB,                            /* looking for shared libraries */
1.1       root      235:   PASS_SECOND                          /* with constructors linked in */
                    236: };
                    237: 
1.1.1.2   root      238: #ifndef NO_SYS_SIGLIST
1.1.1.7   root      239: #ifndef DONT_DECLARE_SYS_SIGLIST
1.1       root      240: extern char *sys_siglist[];
1.1.1.2   root      241: #endif
1.1.1.7   root      242: #endif
1.1       root      243: extern char *version_string;
                    244: 
1.1.1.8   root      245: int vflag;                             /* true if -v */
1.1       root      246: static int rflag;                      /* true if -r */
1.1.1.3   root      247: static int strip_flag;                 /* true if -s */
1.1       root      248: 
1.1.1.8   root      249: int debug;                             /* true if -debug */
                    250: 
                    251: static int shared_obj;                 /* true if -shared */
1.1       root      252: 
                    253: static int   temp_filename_length;     /* Length of temp_filename */
                    254: static char *temp_filename;            /* Base of temp filenames */
                    255: static char *c_file;                   /* <xxx>.c for constructor/destructor list. */
                    256: static char *o_file;                   /* <xxx>.o for constructor/destructor list. */
1.1.1.8   root      257: static char *export_file;              /* <xxx>.x for AIX export list. */
                    258: char *ldout;                           /* File for ld errors.  */
1.1.1.5   root      259: static char *output_file;              /* Output file for ld.  */
1.1       root      260: static char *nm_file_name;             /* pathname of nm */
1.1.1.8   root      261: static char *ldd_file_name;            /* pathname of ldd (or equivalent) */
1.1.1.3   root      262: static char *strip_file_name;          /* pathname of strip */
1.1.1.8   root      263: char *c_file_name;                     /* pathname of gcc */
                    264: static char *initname, *fininame;      /* names of init and fini funcs */
1.1       root      265: 
                    266: static struct head constructors;       /* list of constructors found */
                    267: static struct head destructors;                /* list of destructors found */
1.1.1.8   root      268: static struct head exports;            /* list of exported symbols */
                    269: 
                    270: struct obstack temporary_obstack;
                    271: struct obstack permanent_obstack;
                    272: char * temporary_firstobj;
                    273: 
                    274: /* Defined in the automatically-generated underscore.c.  */
                    275: extern int prepends_underscore;
1.1       root      276: 
                    277: extern char *getenv ();
                    278: extern char *mktemp ();
1.1.1.6   root      279: extern FILE *fdopen ();
                    280: 
                    281: /* Structure to hold all the directories in which to search for files to
                    282:    execute.  */
                    283: 
                    284: struct prefix_list
                    285: {
                    286:   char *prefix;               /* String to prepend to the path. */
                    287:   struct prefix_list *next;   /* Next in linked list. */
                    288: };
                    289: 
                    290: struct path_prefix
                    291: {
                    292:   struct prefix_list *plist;  /* List of prefixes to try */
                    293:   int max_len;                /* Max length of a prefix in PLIST */
                    294:   char *name;                 /* Name of this list (used in config stuff) */
                    295: };
                    296: 
1.1.1.8   root      297: void collect_exit              PROTO((int));
                    298: void collect_execute           PROTO((char *, char **, char *));
                    299: void dump_file                 PROTO((char *));
1.1.1.6   root      300: static void handler            PROTO((int));
                    301: static int is_ctor_dtor                PROTO((char *));
                    302: static void choose_temp_base   PROTO((void));
                    303: static int is_in_prefix_list   PROTO((struct path_prefix *, char *, int));
                    304: static char *find_a_file       PROTO((struct path_prefix *, char *));
                    305: static void add_prefix         PROTO((struct path_prefix *, char *));
                    306: static void prefix_from_env    PROTO((char *, struct path_prefix *));
1.1.1.8   root      307: static void prefix_from_string PROTO((char *, struct path_prefix *));
1.1.1.6   root      308: static void do_wait            PROTO((char *));
                    309: static void fork_execute       PROTO((char *, char **));
                    310: static void maybe_unlink       PROTO((char *));
                    311: static void add_to_list                PROTO((struct head *, char *));
                    312: static void write_list         PROTO((FILE *, char *, struct id *));
                    313: static void write_list_with_asm PROTO((FILE *, char *, struct id *));
                    314: static void write_c_file       PROTO((FILE *, char *));
1.1.1.8   root      315: static void write_export_file  PROTO((FILE *));
1.1.1.6   root      316: static void scan_prog_file     PROTO((char *, enum pass));
1.1.1.8   root      317: static void scan_libraries     PROTO((char *));
1.1       root      318: 
1.1.1.8   root      319: char *xcalloc ();
                    320: char *xmalloc ();
1.1.1.4   root      321: 
                    322: extern char *index ();
                    323: extern char *rindex ();
1.1.1.8   root      324: extern void free ();
1.1       root      325: 
1.1.1.4   root      326: #ifdef NO_DUP2
1.1.1.6   root      327: int
1.1.1.4   root      328: dup2 (oldfd, newfd)
                    329:      int oldfd;
                    330:      int newfd;
                    331: {
                    332:   int fdtmp[256];
                    333:   int fdx = 0;
                    334:   int fd;
                    335:  
                    336:   if (oldfd == newfd)
1.1.1.7   root      337:     return oldfd;
1.1.1.4   root      338:   close (newfd);
1.1.1.7   root      339:   while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
1.1.1.4   root      340:     fdtmp[fdx++] = fd;
                    341:   while (fdx > 0)
                    342:     close (fdtmp[--fdx]);
1.1.1.6   root      343: 
1.1.1.7   root      344:   return fd;
1.1.1.4   root      345: }
                    346: #endif
                    347: 
1.1.1.2   root      348: char *
1.1.1.3   root      349: my_strerror (e)
1.1       root      350:      int e;
                    351: {
                    352: 
1.1.1.7   root      353: #ifdef HAVE_STRERROR
                    354:   return strerror (e);
                    355: 
                    356: #else
                    357: 
                    358:   static char buffer[30];
1.1       root      359:   if (!e)
                    360:     return "";
                    361: 
                    362:   if (e > 0 && e < sys_nerr)
                    363:     return sys_errlist[e];
                    364: 
                    365:   sprintf (buffer, "Unknown error %d", e);
                    366:   return buffer;
1.1.1.7   root      367: #endif
1.1       root      368: }
                    369: 
                    370: /* Delete tempfiles and exit function.  */
                    371: 
1.1.1.8   root      372: void
                    373: collect_exit (status)
1.1       root      374:      int status;
                    375: {
1.1.1.2   root      376:   if (c_file != 0 && c_file[0])
1.1       root      377:     maybe_unlink (c_file);
                    378: 
1.1.1.2   root      379:   if (o_file != 0 && o_file[0])
1.1       root      380:     maybe_unlink (o_file);
                    381: 
1.1.1.8   root      382:   if (export_file != 0 && export_file[0])
                    383:     maybe_unlink (export_file);
                    384: 
                    385:   if (ldout != 0 && ldout[0])
                    386:     {
                    387:       dump_file (ldout);
                    388:       maybe_unlink (ldout);
                    389:     }
                    390: 
1.1.1.5   root      391:   if (status != 0 && output_file != 0 && output_file[0])
                    392:     maybe_unlink (output_file);
                    393: 
1.1       root      394:   exit (status);
                    395: }
                    396: 
                    397: 
                    398: /* Die when sys call fails. */
                    399: 
1.1.1.8   root      400: void
1.1.1.3   root      401: fatal_perror (string, arg1, arg2, arg3)
1.1.1.7   root      402:      char *string, *arg1, *arg2, *arg3;
1.1       root      403: {
                    404:   int e = errno;
                    405: 
1.1.1.6   root      406:   fprintf (stderr, "collect2: ");
1.1.1.3   root      407:   fprintf (stderr, string, arg1, arg2, arg3);
                    408:   fprintf (stderr, ": %s\n", my_strerror (e));
1.1.1.8   root      409:   collect_exit (1);
1.1       root      410: }
                    411: 
                    412: /* Just die. */
                    413: 
1.1.1.8   root      414: void
1.1.1.3   root      415: fatal (string, arg1, arg2, arg3)
1.1.1.7   root      416:      char *string, *arg1, *arg2, *arg3;
1.1       root      417: {
1.1.1.6   root      418:   fprintf (stderr, "collect2: ");
1.1.1.3   root      419:   fprintf (stderr, string, arg1, arg2, arg3);
1.1       root      420:   fprintf (stderr, "\n");
1.1.1.8   root      421:   collect_exit (1);
1.1       root      422: }
                    423: 
                    424: /* Write error message.  */
                    425: 
1.1.1.8   root      426: void
1.1.1.3   root      427: error (string, arg1, arg2, arg3, arg4)
1.1.1.7   root      428:      char *string, *arg1, *arg2, *arg3, *arg4;
1.1       root      429: {
1.1.1.6   root      430:   fprintf (stderr, "collect2: ");
1.1.1.3   root      431:   fprintf (stderr, string, arg1, arg2, arg3, arg4);
1.1       root      432:   fprintf (stderr, "\n");
                    433: }
                    434: 
                    435: /* In case obstack is linked in, and abort is defined to fancy_abort,
                    436:    provide a default entry.  */
                    437: 
                    438: void
                    439: fancy_abort ()
                    440: {
                    441:   fatal ("internal error");
                    442: }
                    443: 
                    444: 
                    445: static void
                    446: handler (signo)
                    447:      int signo;
                    448: {
1.1.1.6   root      449:   if (c_file != 0 && c_file[0])
1.1       root      450:     maybe_unlink (c_file);
                    451: 
1.1.1.6   root      452:   if (o_file != 0 && o_file[0])
1.1       root      453:     maybe_unlink (o_file);
                    454: 
1.1.1.8   root      455:   if (ldout != 0 && ldout[0])
                    456:     maybe_unlink (ldout);
                    457: 
1.1       root      458:   signal (signo, SIG_DFL);
                    459:   kill (getpid (), signo);
                    460: }
                    461: 
                    462: 
1.1.1.8   root      463: char *
1.1       root      464: xcalloc (size1, size2)
                    465:      int size1, size2;
                    466: {
1.1.1.8   root      467:   char *ptr = (char *) calloc (size1, size2);
1.1       root      468:   if (ptr)
                    469:     return ptr;
                    470: 
1.1.1.3   root      471:   fatal ("out of memory");
1.1.1.8   root      472:   return (char *)0;
1.1       root      473: }
                    474: 
1.1.1.8   root      475: char *
1.1       root      476: xmalloc (size)
1.1.1.8   root      477:      unsigned size;
1.1       root      478: {
1.1.1.8   root      479:   char *ptr = (char *) malloc (size);
1.1       root      480:   if (ptr)
                    481:     return ptr;
                    482: 
1.1.1.3   root      483:   fatal ("out of memory");
1.1.1.8   root      484:   return (char *)0;
                    485: }
                    486: 
                    487: char *
                    488: xrealloc (ptr, size)
                    489:      char *ptr;
                    490:      unsigned size;
                    491: {
                    492:   register char *value = (char *) realloc (ptr, size);
                    493:   if (value == 0)
                    494:     fatal ("virtual memory exhausted");
                    495:   return value;
                    496: }
                    497: 
                    498: int
                    499: file_exists (name)
                    500:      char *name;
                    501: {
                    502:   return access (name, R_OK) == 0;
1.1       root      503: }
                    504: 
1.1.1.2   root      505: /* Make a copy of a string INPUT with size SIZE.  */
                    506: 
                    507: char *
                    508: savestring (input, size)
                    509:      char *input;
                    510:      int size;
                    511: {
                    512:   char *output = (char *) xmalloc (size + 1);
1.1.1.3   root      513:   bcopy (input, output, size);
                    514:   output[size] = 0;
1.1.1.2   root      515:   return output;
                    516: }
                    517: 
1.1.1.8   root      518: void
                    519: dump_file (name)
                    520:      char *name;
                    521: {
                    522:   FILE *stream = fopen (name, "r");
                    523:   int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
                    524: 
                    525:   if (stream == 0)
                    526:     return;
                    527:   while (1)
                    528:     {
                    529:       int c;
                    530:       while (c = getc (stream),
                    531:             c != EOF && (isalnum (c) || c == '_' || c == '$' || c == '.'))
                    532:        obstack_1grow (&temporary_obstack, c);
                    533:       if (obstack_object_size (&temporary_obstack) > 0)
                    534:        {
                    535:          char *word, *p, *result;
                    536:          obstack_1grow (&temporary_obstack, '\0');
                    537:          word = obstack_finish (&temporary_obstack);
                    538: 
                    539:          if (*word == '.')
                    540:            ++word, putc ('.', stderr);
                    541:          p = word;
                    542:          if (*p == '_' && prepends_underscore)
                    543:            ++p;
                    544: 
                    545:          if (no_demangle)
                    546:            result = 0;
                    547:          else
                    548:            result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI);
                    549: 
                    550:          if (result)
                    551:            {
                    552:              int diff;
                    553:              fputs (result, stderr);
                    554: 
                    555:              diff = strlen (word) - strlen (result);
                    556:              while (diff > 0)
                    557:                --diff, putc (' ', stderr);
                    558:              while (diff < 0 && c == ' ')
                    559:                ++diff, c = getc (stream);
                    560: 
                    561:              free (result);
                    562:            }
                    563:          else
                    564:            fputs (word, stderr);
                    565: 
                    566:          fflush (stderr);
                    567:          obstack_free (&temporary_obstack, temporary_firstobj);
                    568:        }
                    569:       if (c == EOF)
                    570:        break;
                    571:       putc (c, stderr);
                    572:     }
                    573: }
                    574: 
1.1.1.2   root      575: /* Decide whether the given symbol is:
                    576:    a constructor (1), a destructor (2), or neither (0).  */
                    577: 
                    578: static int
                    579: is_ctor_dtor (s)
                    580:      char *s;
                    581: {
                    582:   struct names { char *name; int len; int ret; int two_underscores; };
                    583: 
                    584:   register struct names *p;
                    585:   register int ch;
                    586:   register char *orig_s = s;
                    587: 
                    588:   static struct names special[] = {
                    589: #ifdef NO_DOLLAR_IN_LABEL
1.1.1.5   root      590: #ifdef NO_DOT_IN_LABEL
1.1.1.6   root      591:     { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
                    592:     { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
1.1.1.5   root      593: #else
1.1.1.2   root      594:     { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
                    595:     { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
1.1.1.5   root      596: #endif
1.1.1.2   root      597: #else
                    598:     { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
1.1.1.6   root      599:     { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
1.1.1.2   root      600: #endif
1.1.1.8   root      601:     { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
                    602:     { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
1.1.1.4   root      603: #ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
                    604:                         cfront has its own linker procedure to collect them;
                    605:                         if collect2 gets them too, they get collected twice
                    606:                         when the cfront procedure is run and the compiler used
                    607:                         for linking happens to be GCC.  */
1.1.1.2   root      608:     { "sti__", sizeof ("sti__")-1, 1, 1 },
                    609:     { "std__", sizeof ("std__")-1, 2, 1 },
1.1.1.4   root      610: #endif /* CFRONT_LOSSAGE */
1.1.1.2   root      611:     { NULL, 0, 0, 0 }
                    612:   };
                    613: 
                    614:   while ((ch = *s) == '_')
                    615:     ++s;
                    616: 
                    617:   if (s == orig_s)
                    618:     return 0;
                    619: 
                    620:   for (p = &special[0]; p->len > 0; p++)
                    621:     {
                    622:       if (ch == p->name[0]
                    623:          && (!p->two_underscores || ((s - orig_s) >= 2))
                    624:          && strncmp(s, p->name, p->len) == 0)
                    625:        {
                    626:          return p->ret;
                    627:        }
                    628:     }
                    629:   return 0;
                    630: }
                    631: 
1.1       root      632: 
                    633: /* Compute a string to use as the base of all temporary file names.
                    634:    It is substituted for %g.  */
                    635: 
                    636: static void
                    637: choose_temp_base ()
                    638: {
                    639:   char *base = getenv ("TMPDIR");
                    640:   int len;
                    641: 
                    642:   if (base == (char *)0)
                    643:     {
                    644: #ifdef P_tmpdir
                    645:       if (access (P_tmpdir, R_OK | W_OK) == 0)
                    646:        base = P_tmpdir;
                    647: #endif
                    648:       if (base == (char *)0)
                    649:        {
                    650:          if (access ("/usr/tmp", R_OK | W_OK) == 0)
                    651:            base = "/usr/tmp/";
                    652:          else
                    653:            base = "/tmp/";
                    654:        }
                    655:     }
                    656: 
                    657:   len = strlen (base);
1.1.1.5   root      658:   temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
1.1       root      659:   strcpy (temp_filename, base);
                    660:   if (len > 0 && temp_filename[len-1] != '/')
                    661:     temp_filename[len++] = '/';
                    662:   strcpy (temp_filename + len, "ccXXXXXX");
                    663: 
                    664:   mktemp (temp_filename);
                    665:   temp_filename_length = strlen (temp_filename);
                    666: }
1.1.1.5   root      667: 
                    668: /* Routine to add variables to the environment.  */
                    669: 
                    670: #ifndef HAVE_PUTENV
                    671: 
1.1.1.6   root      672: int
1.1.1.5   root      673: putenv (str)
                    674:      char *str;
                    675: {
                    676: #ifndef VMS                    /* nor about VMS */
                    677: 
                    678:   extern char **environ;
                    679:   char **old_environ = environ;
                    680:   char **envp;
                    681:   int num_envs = 0;
                    682:   int name_len = 1;
                    683:   char *p = str;
                    684:   int ch;
                    685: 
                    686:   while ((ch = *p++) != '\0' && ch != '=')
                    687:     name_len++;
                    688: 
                    689:   if (!ch)
                    690:     abort ();
                    691: 
                    692:   /* Search for replacing an existing environment variable, and
                    693:      count the number of total environment variables.  */
                    694:   for (envp = old_environ; *envp; envp++)
                    695:     {
                    696:       num_envs++;
                    697:       if (!strncmp (str, *envp, name_len))
                    698:        {
                    699:          *envp = str;
1.1.1.6   root      700:          return 0;
1.1.1.5   root      701:        }
                    702:     }
                    703: 
                    704:   /* Add a new environment variable */
                    705:   environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
                    706:   *environ = str;
1.1.1.7   root      707:   bcopy ((char *) old_environ, (char *) (environ + 1),
                    708:         sizeof (char *) * (num_envs+1));
                    709: 
1.1.1.6   root      710:   return 0;
1.1.1.5   root      711: #endif /* VMS */
                    712: }
1.1       root      713: 
1.1.1.5   root      714: #endif /* HAVE_PUTENV */
                    715: 
                    716: /* By default, colon separates directories in a path.  */
                    717: #ifndef PATH_SEPARATOR
                    718: #define PATH_SEPARATOR ':'
                    719: #endif
                    720: 
                    721: /* We maintain two prefix lists: one from COMPILER_PATH environment variable
                    722:    and one from the PATH variable.  */
                    723: 
                    724: static struct path_prefix cpath, path;
                    725: 
                    726: #ifdef CROSS_COMPILE
                    727: /* This is the name of the target machine.  We use it to form the name
                    728:    of the files to execute.  */
                    729: 
                    730: static char *target_machine = TARGET_MACHINE;
                    731: #endif
                    732: 
                    733: /* Names under which we were executed.  Never return one of those files in our
                    734:    searches.  */
                    735: 
1.1.1.6   root      736: static struct path_prefix our_file_names;
1.1.1.5   root      737: 
1.1.1.6   root      738: /* Determine if STRING is in PPREFIX.
                    739: 
                    740:    This utility is currently only used to look up file names.  Prefix lists
                    741:    record directory names.  This matters to us because the latter has a 
                    742:    trailing slash, so I've added a flag to handle both.  */
                    743: 
                    744: static int
                    745: is_in_prefix_list (pprefix, string, filep)
                    746:      struct path_prefix *pprefix;
                    747:      char *string;
                    748:      int filep;
                    749: {
                    750:   struct prefix_list *pl;
                    751: 
                    752:   if (filep)
                    753:     {
                    754:       int len = strlen (string);
                    755: 
                    756:       for (pl = pprefix->plist; pl; pl = pl->next)
                    757:        {
                    758:          if (strncmp (pl->prefix, string, len) == 0
                    759:              && strcmp (pl->prefix + len, "/") == 0)
                    760:            return 1;
                    761:        }
                    762:     }
                    763:   else
                    764:     {
                    765:       for (pl = pprefix->plist; pl; pl = pl->next)
                    766:        {
                    767:          if (strcmp (pl->prefix, string) == 0)
                    768:            return 1;
                    769:        }
                    770:     }
                    771: 
                    772:   return 0;
                    773: }
                    774: 
1.1.1.5   root      775: /* Search for NAME using prefix list PPREFIX.  We only look for executable
                    776:    files. 
                    777: 
                    778:    Return 0 if not found, otherwise return its name, allocated with malloc. */
                    779: 
                    780: static char *
                    781: find_a_file (pprefix, name)
                    782:      struct path_prefix *pprefix;
                    783:      char *name;
                    784: {
                    785:   char *temp;
                    786:   struct prefix_list *pl;
                    787:   int len = pprefix->max_len + strlen (name) + 1;
                    788: 
                    789: #ifdef EXECUTABLE_SUFFIX
                    790:   len += strlen (EXECUTABLE_SUFFIX);
                    791: #endif
                    792: 
                    793:   temp = xmalloc (len);
                    794: 
                    795:   /* Determine the filename to execute (special case for absolute paths).  */
                    796: 
                    797:   if (*name == '/')
                    798:     {
                    799:       if (access (name, X_OK) == 0)
                    800:        {
                    801:          strcpy (temp, name);
                    802:          return temp;
                    803:        }
                    804:     }
                    805:   else
                    806:     for (pl = pprefix->plist; pl; pl = pl->next)
                    807:       {
                    808:        strcpy (temp, pl->prefix);
                    809:        strcat (temp, name);
1.1.1.6   root      810:        if (! is_in_prefix_list (&our_file_names, temp, 1)
1.1.1.5   root      811:            /* This is a kludge, but there seems no way around it.  */
                    812:            && strcmp (temp, "./ld") != 0
                    813:            && access (temp, X_OK) == 0)
                    814:          return temp;
                    815: 
                    816: #ifdef EXECUTABLE_SUFFIX
                    817:        /* Some systems have a suffix for executable files.
                    818:           So try appending that.  */
                    819:        strcat (temp, EXECUTABLE_SUFFIX);
1.1.1.6   root      820:        if (! is_in_prefix_list (&our_file_names, temp, 1)
1.1.1.5   root      821:            && access (temp, X_OK) == 0)
                    822:          return temp;
                    823: #endif
                    824:       }
                    825: 
                    826:   free (temp);
                    827:   return 0;
                    828: }
                    829: 
                    830: /* Add an entry for PREFIX to prefix list PPREFIX.  */
                    831: 
                    832: static void
                    833: add_prefix (pprefix, prefix)
                    834:      struct path_prefix *pprefix;
                    835:      char *prefix;
                    836: {
                    837:   struct prefix_list *pl, **prev;
                    838:   int len;
                    839: 
                    840:   if (pprefix->plist)
                    841:     {
                    842:       for (pl = pprefix->plist; pl->next; pl = pl->next)
                    843:        ;
                    844:       prev = &pl->next;
                    845:     }
                    846:   else
                    847:     prev = &pprefix->plist;
                    848: 
                    849:   /* Keep track of the longest prefix */
                    850: 
                    851:   len = strlen (prefix);
                    852:   if (len > pprefix->max_len)
                    853:     pprefix->max_len = len;
                    854: 
                    855:   pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
                    856:   pl->prefix = savestring (prefix, len);
                    857: 
                    858:   if (*prev)
                    859:     pl->next = *prev;
                    860:   else
                    861:     pl->next = (struct prefix_list *) 0;
                    862:   *prev = pl;
                    863: }
                    864: 
                    865: /* Take the value of the environment variable ENV, break it into a path, and
                    866:    add of the entries to PPREFIX.  */
                    867: 
                    868: static void
                    869: prefix_from_env (env, pprefix)
                    870:      char *env;
                    871:      struct path_prefix *pprefix;
                    872: {
                    873:   char *p = getenv (env);
                    874: 
                    875:   if (p)
1.1.1.8   root      876:     prefix_from_string (p, pprefix);
                    877: }
                    878: 
                    879: static void
                    880: prefix_from_string (p, pprefix)
                    881:      char *p;
                    882:      struct path_prefix *pprefix;
                    883: {
                    884:   char *startp, *endp;
                    885:   char *nstore = (char *) xmalloc (strlen (p) + 3);
1.1.1.5   root      886: 
1.1.1.8   root      887:   startp = endp = p;
                    888:   while (1)
                    889:     {
                    890:       if (*endp == PATH_SEPARATOR || *endp == 0)
1.1.1.5   root      891:        {
1.1.1.8   root      892:          strncpy (nstore, startp, endp-startp);
                    893:          if (endp == startp)
1.1.1.5   root      894:            {
1.1.1.8   root      895:              strcpy (nstore, "./");
                    896:            }
                    897:          else if (endp[-1] != '/')
                    898:            {
                    899:              nstore[endp-startp] = '/';
                    900:              nstore[endp-startp+1] = 0;
1.1.1.5   root      901:            }
                    902:          else
1.1.1.8   root      903:            nstore[endp-startp] = 0;
                    904: 
                    905:          add_prefix (pprefix, nstore);
                    906:          if (*endp == 0)
                    907:            break;
                    908:          endp = startp = endp + 1;
1.1.1.5   root      909:        }
1.1.1.8   root      910:       else
                    911:        endp++;
1.1.1.5   root      912:     }
                    913: }
1.1       root      914: 
                    915: /* Main program. */
                    916: 
                    917: int
                    918: main (argc, argv)
                    919:      int argc;
                    920:      char *argv[];
                    921: {
1.1.1.5   root      922:   char *ld_suffix      = "ld";
                    923:   char *full_ld_suffix = ld_suffix;
                    924:   char *real_ld_suffix = "real-ld";
                    925:   char *full_real_ld_suffix = real_ld_suffix;
1.1.1.8   root      926:   char *collect_ld_suffix = "collect-ld";
1.1.1.5   root      927:   char *nm_suffix      = "nm";
                    928:   char *full_nm_suffix = nm_suffix;
                    929:   char *gnm_suffix     = "gnm";
                    930:   char *full_gnm_suffix        = gnm_suffix;
1.1.1.8   root      931: #ifdef LDD_SUFFIX
                    932:   char *ldd_suffix     = LDD_SUFFIX;
                    933:   char *full_ldd_suffix        = ldd_suffix;
                    934: #endif
1.1.1.5   root      935:   char *strip_suffix   = "strip";
                    936:   char *full_strip_suffix = strip_suffix;
                    937:   char *gstrip_suffix  = "gstrip";
                    938:   char *full_gstrip_suffix = gstrip_suffix;
1.1       root      939:   char *arg;
1.1.1.8   root      940:   FILE *outf, *exportf;
1.1       root      941:   char *ld_file_name;
1.1.1.6   root      942:   char *collect_name;
                    943:   char *collect_names;
1.1       root      944:   char *p;
1.1.1.2   root      945:   char **c_argv;
                    946:   char **c_ptr;
1.1.1.8   root      947:   char **ld1_argv      = (char **) xcalloc (sizeof (char *), argc+3);
1.1       root      948:   char **ld1           = ld1_argv;
1.1.1.8   root      949:   char **ld2_argv      = (char **) xcalloc (sizeof (char *), argc+6);
1.1       root      950:   char **ld2           = ld2_argv;
1.1.1.8   root      951:   char **object_lst    = (char **) xcalloc (sizeof (char *), argc);
                    952:   char **object                = object_lst;
1.1       root      953:   int first_file;
1.1.1.2   root      954:   int num_c_args       = argc+7;
1.1       root      955: 
                    956: #ifdef DEBUG
                    957:   debug = 1;
                    958:   vflag = 1;
                    959: #endif
                    960: 
1.1.1.5   root      961:   output_file = "a.out";
                    962: 
1.1.1.8   root      963:   obstack_begin (&temporary_obstack, 0);
                    964:   obstack_begin (&permanent_obstack, 0);
                    965:   temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
                    966:   current_demangling_style = gnu_demangling;
                    967: 
1.1.1.5   root      968:   /* We must check that we do not call ourselves in an infinite
1.1.1.6   root      969:      recursion loop. We append the name used for us to the COLLECT_NAMES
                    970:      environment variable.
1.1.1.5   root      971: 
1.1.1.6   root      972:      In practice, collect will rarely invoke itself.  This can happen now
                    973:      that we are no longer called gld.  A perfect example is when running
                    974:      gcc in a build directory that has been installed.  When looking for 
                    975:      ld's, we'll find our installed version and believe that's the real ld.  */
                    976: 
                    977:   /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the
                    978:      previous version of collect (the one that used COLLECT_NAME and only
                    979:      handled two levels of recursion).  If we don't we may mutually recurse
                    980:      forever.  This can happen (I think) when bootstrapping the old version
                    981:      and a new one is installed (rare, but we should handle it).
                    982:      ??? Hopefully references to COLLECT_NAME can be removed at some point.  */
                    983: 
                    984:   collect_name = (char *) getenv ("COLLECT_NAME");
                    985:   collect_names = (char *) getenv ("COLLECT_NAMES");
                    986: 
                    987:   p = (char *) xmalloc (strlen ("COLLECT_NAMES=")
                    988:                        + (collect_name ? strlen (collect_name) + 1 : 0)
                    989:                        + (collect_names ? strlen (collect_names) + 1 : 0)
                    990:                        + strlen (argv[0]) + 1);
                    991:   strcpy (p, "COLLECT_NAMES=");
                    992:   if (collect_name != 0)
                    993:     sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR);
                    994:   if (collect_names != 0)
                    995:     sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR);
                    996:   strcat (p, argv[0]);
                    997:   putenv (p);
                    998: 
                    999:   prefix_from_env ("COLLECT_NAMES", &our_file_names);
1.1.1.5   root     1000: 
1.1.1.6   root     1001:   /* Set environment variable COLLECT_NAME to our name so the previous version
                   1002:      of collect won't find us.  If it does we'll mutually recurse forever.
                   1003:      This can happen when bootstrapping the new version and an old version is
                   1004:      installed.
                   1005:      ??? Hopefully this bit of code can be removed at some point.  */
1.1.1.5   root     1006: 
1.1.1.6   root     1007:   p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1);
                   1008:   sprintf (p, "COLLECT_NAME=%s", argv[0]);
1.1.1.5   root     1009:   putenv (p);
                   1010: 
1.1.1.2   root     1011:   p = (char *) getenv ("COLLECT_GCC_OPTIONS");
                   1012:   if (p)
                   1013:     while (*p)
                   1014:       {
                   1015:        char *q = p;
                   1016:        while (*q && *q != ' ') q++;
1.1.1.3   root     1017:        if (*p == '-' && p[1] == 'm')
1.1.1.2   root     1018:          num_c_args++;
                   1019: 
                   1020:        if (*q) q++;
                   1021:        p = q;
                   1022:       }
                   1023: 
                   1024:   c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
                   1025: 
1.1       root     1026:   if (argc < 2)
                   1027:     fatal ("no arguments");
                   1028: 
1.1.1.5   root     1029: #ifdef SIGQUIT
1.1.1.4   root     1030:   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
                   1031:     signal (SIGQUIT, handler);
1.1.1.5   root     1032: #endif
1.1.1.4   root     1033:   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
                   1034:     signal (SIGINT, handler);
1.1.1.5   root     1035: #ifdef SIGALRM
1.1.1.4   root     1036:   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
                   1037:     signal (SIGALRM, handler);
1.1.1.5   root     1038: #endif
                   1039: #ifdef SIGHUP
1.1.1.4   root     1040:   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
                   1041:     signal (SIGHUP, handler);
1.1.1.5   root     1042: #endif
1.1.1.4   root     1043:   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
                   1044:     signal (SIGSEGV, handler);
1.1.1.5   root     1045: #ifdef SIGBUS
1.1.1.4   root     1046:   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
                   1047:     signal (SIGBUS, handler);
1.1       root     1048: #endif
                   1049: 
1.1.1.5   root     1050:   /* Extract COMPILER_PATH and PATH into our prefix list.  */
                   1051:   prefix_from_env ("COMPILER_PATH", &cpath);
                   1052:   prefix_from_env ("PATH", &path);
1.1       root     1053: 
1.1.1.5   root     1054: #ifdef CROSS_COMPILE
                   1055:   /* If we look for a program in the compiler directories, we just use
                   1056:      the short name, since these directories are already system-specific.
                   1057:      But it we look for a took in the system directories, we need to
                   1058:      qualify the program name with the target machine.  */
                   1059: 
                   1060:   full_ld_suffix
                   1061:     = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
                   1062:   strcpy (full_ld_suffix, target_machine);
                   1063:   strcat (full_ld_suffix, "-");
                   1064:   strcat (full_ld_suffix, ld_suffix);
                   1065: 
                   1066:   full_real_ld_suffix
                   1067:     = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1);
                   1068:   strcpy (full_real_ld_suffix, target_machine);
                   1069:   strcat (full_real_ld_suffix, "-");
                   1070:   strcat (full_real_ld_suffix, real_ld_suffix);
                   1071: 
1.1.1.6   root     1072: #if 0
1.1.1.5   root     1073:   full_gld_suffix
                   1074:     = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
                   1075:   strcpy (full_gld_suffix, target_machine);
                   1076:   strcat (full_gld_suffix, "-");
                   1077:   strcat (full_gld_suffix, gld_suffix);
1.1.1.6   root     1078: #endif
1.1.1.5   root     1079: 
                   1080:   full_nm_suffix
                   1081:     = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
                   1082:   strcpy (full_nm_suffix, target_machine);
                   1083:   strcat (full_nm_suffix, "-");
                   1084:   strcat (full_nm_suffix, nm_suffix);
                   1085: 
                   1086:   full_gnm_suffix
                   1087:     = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
                   1088:   strcpy (full_gnm_suffix, target_machine);
                   1089:   strcat (full_gnm_suffix, "-");
                   1090:   strcat (full_gnm_suffix, gnm_suffix);
                   1091: 
1.1.1.8   root     1092: #ifdef LDD_SUFFIX
                   1093:   full_ldd_suffix
                   1094:     = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1);
                   1095:   strcpy (full_ldd_suffix, target_machine);
                   1096:   strcat (full_ldd_suffix, "-");
                   1097:   strcat (full_ldd_suffix, ldd_suffix);
                   1098: #endif
                   1099: 
1.1.1.5   root     1100:   full_strip_suffix
                   1101:     = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
                   1102:   strcpy (full_strip_suffix, target_machine);
                   1103:   strcat (full_strip_suffix, "-");
                   1104:   strcat (full_strip_suffix, strip_suffix);
                   1105:   
                   1106:   full_gstrip_suffix
                   1107:     = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
                   1108:   strcpy (full_gstrip_suffix, target_machine);
                   1109:   strcat (full_gstrip_suffix, "-");
                   1110:   strcat (full_gstrip_suffix, gstrip_suffix);
                   1111: #endif /* CROSS_COMPILE */
                   1112: 
                   1113:   /* Try to discover a valid linker/nm/strip to use.  */
                   1114: 
1.1.1.7   root     1115:   /* Maybe we know the right file to use (if not cross).  */
                   1116: #ifdef REAL_LD_FILE_NAME
                   1117:   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
                   1118:   if (ld_file_name == 0)
                   1119: #endif
1.1.1.8   root     1120:   /* Search the (target-specific) compiler dirs for ld'.  */
                   1121:   ld_file_name = find_a_file (&cpath, real_ld_suffix);
                   1122:   /* Likewise for `collect-ld'.  */
1.1.1.5   root     1123:   if (ld_file_name == 0)
1.1.1.8   root     1124:     ld_file_name = find_a_file (&cpath, collect_ld_suffix);
1.1.1.7   root     1125:   /* Search the compiler directories for `ld'.  We have protection against
                   1126:      recursive calls in find_a_file.  */
1.1.1.5   root     1127:   if (ld_file_name == 0)
1.1.1.7   root     1128:     ld_file_name = find_a_file (&cpath, ld_suffix);
1.1.1.5   root     1129:   /* Search the ordinary system bin directories
                   1130:      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
                   1131:   if (ld_file_name == 0)
                   1132:     ld_file_name = find_a_file (&path, full_ld_suffix);
                   1133: 
1.1.1.6   root     1134:   /* If we've invoked ourselves, try again with LD_FILE_NAME.  */
                   1135: 
                   1136:   if (collect_names != 0)
                   1137:     {
                   1138:       if (ld_file_name != 0)
                   1139:        {
                   1140:          argv[0] = ld_file_name;
                   1141:          execvp (argv[0], argv);
                   1142:        }
                   1143:       fatal ("cannot find `ld'");
                   1144:     }
                   1145: 
1.1.1.7   root     1146: #ifdef REAL_NM_FILE_NAME
                   1147:   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
                   1148:   if (nm_file_name == 0)
                   1149: #endif
1.1.1.5   root     1150:   nm_file_name = find_a_file (&cpath, gnm_suffix);
                   1151:   if (nm_file_name == 0)
                   1152:     nm_file_name = find_a_file (&path, full_gnm_suffix);
                   1153:   if (nm_file_name == 0)
                   1154:     nm_file_name = find_a_file (&cpath, nm_suffix);
                   1155:   if (nm_file_name == 0)
                   1156:     nm_file_name = find_a_file (&path, full_nm_suffix);
1.1.1.3   root     1157: 
1.1.1.8   root     1158: #ifdef LDD_SUFFIX
                   1159:   ldd_file_name = find_a_file (&cpath, ldd_suffix);
                   1160:   if (ldd_file_name == 0)
                   1161:     ldd_file_name = find_a_file (&path, full_ldd_suffix);
                   1162: #endif
                   1163: 
1.1.1.7   root     1164: #ifdef REAL_STRIP_FILE_NAME
                   1165:   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
                   1166:   if (strip_file_name == 0)
                   1167: #endif
1.1.1.5   root     1168:   strip_file_name = find_a_file (&cpath, gstrip_suffix);
                   1169:   if (strip_file_name == 0)
                   1170:     strip_file_name = find_a_file (&path, full_gstrip_suffix);
                   1171:   if (strip_file_name == 0)
                   1172:     strip_file_name = find_a_file (&cpath, strip_suffix);
                   1173:   if (strip_file_name == 0)
                   1174:     strip_file_name = find_a_file (&path, full_strip_suffix);
1.1       root     1175: 
1.1.1.3   root     1176:   /* Determine the full path name of the C compiler to use.  */
1.1.1.2   root     1177:   c_file_name = getenv ("COLLECT_GCC");
1.1.1.4   root     1178:   if (c_file_name == 0)
1.1       root     1179:     {
1.1.1.5   root     1180: #ifdef CROSS_COMPILE
                   1181:       c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
                   1182:       strcpy (c_file_name, target_machine);
                   1183:       strcat (c_file_name, "-gcc");
1.1       root     1184: #else
1.1.1.5   root     1185:       c_file_name = "gcc";
1.1.1.3   root     1186: #endif
                   1187:     }
                   1188: 
1.1.1.5   root     1189:   p = find_a_file (&cpath, c_file_name);
1.1       root     1190: 
1.1.1.5   root     1191:   /* Here it should be safe to use the system search path since we should have
                   1192:      already qualified the name of the compiler when it is needed.  */
                   1193:   if (p == 0)
                   1194:     p = find_a_file (&path, c_file_name);
                   1195: 
                   1196:   if (p)
                   1197:     c_file_name = p;
                   1198: 
                   1199:   *ld1++ = *ld2++ = ld_file_name;
1.1       root     1200: 
                   1201:   /* Make temp file names. */
                   1202:   choose_temp_base ();
                   1203:   c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
                   1204:   o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
1.1.1.8   root     1205:   export_file = xmalloc (temp_filename_length + sizeof (".x"));
                   1206:   ldout = xmalloc (temp_filename_length + sizeof (".ld"));
                   1207:   sprintf (ldout, "%s.ld", temp_filename);
1.1       root     1208:   sprintf (c_file, "%s.c", temp_filename);
                   1209:   sprintf (o_file, "%s.o", temp_filename);
1.1.1.8   root     1210:   sprintf (export_file, "%s.x", temp_filename);
1.1.1.2   root     1211:   *c_ptr++ = c_file_name;
1.1       root     1212:   *c_ptr++ = "-c";
                   1213:   *c_ptr++ = "-o";
                   1214:   *c_ptr++ = o_file;
                   1215: 
1.1.1.2   root     1216:   /* !!! When GCC calls collect2,
                   1217:      it does not know whether it is calling collect2 or ld.
                   1218:      So collect2 cannot meaningfully understand any options
                   1219:      except those ld understands.
                   1220:      If you propose to make GCC pass some other option,
                   1221:      just imagine what will happen if ld is really ld!!!  */
                   1222: 
1.1       root     1223:   /* Parse arguments.  Remember output file spec, pass the rest to ld. */
1.1.1.2   root     1224:   /* After the first file, put in the c++ rt0.  */
                   1225: 
1.1       root     1226:   first_file = 1;
                   1227:   while ((arg = *++argv) != (char *)0)
                   1228:     {
                   1229:       *ld1++ = *ld2++ = arg;
                   1230: 
                   1231:       if (arg[0] == '-')
1.1.1.7   root     1232:        {
1.1       root     1233:          switch (arg[1])
                   1234:            {
                   1235:            case 'd':
                   1236:              if (!strcmp (arg, "-debug"))
                   1237:                {
                   1238:                  debug = 1;
                   1239:                  vflag = 1;
                   1240:                  ld1--;
                   1241:                  ld2--;
                   1242:                }
                   1243:              break;
                   1244: 
1.1.1.8   root     1245:            case 'l':
                   1246:              if (first_file)
                   1247:                {
                   1248:                  /* place o_file BEFORE this argument! */
                   1249:                  first_file = 0;
                   1250:                  ld2--;
                   1251:                  *ld2++ = o_file;
                   1252:                  *ld2++ = arg;
                   1253:                }
                   1254:              break;
                   1255: 
1.1       root     1256:            case 'o':
1.1.1.8   root     1257:              if (arg[2] == '\0')
                   1258:                output_file = *ld1++ = *ld2++ = *++argv;
                   1259:              else
                   1260:                output_file = &arg[2];
1.1       root     1261:              break;
                   1262: 
                   1263:            case 'r':
                   1264:              if (arg[2] == '\0')
                   1265:                rflag = 1;
                   1266:              break;
                   1267: 
1.1.1.3   root     1268:            case 's':
1.1.1.8   root     1269:              if (arg[2] == '\0' && do_collecting)
1.1.1.3   root     1270:                {
                   1271:                  /* We must strip after the nm run, otherwise C++ linking
                   1272:                     won't work.  Thus we strip in the second ld run, or
                   1273:                     else with strip if there is no second ld run.  */
                   1274:                  strip_flag = 1;
                   1275:                  ld1--;
                   1276:                }
                   1277:              break;
                   1278: 
1.1       root     1279:            case 'v':
                   1280:              if (arg[2] == '\0')
                   1281:                vflag = 1;
                   1282:              break;
                   1283:            }
1.1.1.7   root     1284:        }
1.1.1.8   root     1285:       else if ((p = rindex (arg, '.')) != (char *)0
                   1286:               && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0))
1.1       root     1287:        {
1.1.1.8   root     1288:          if (first_file)
                   1289:            {
                   1290:              first_file = 0;
                   1291:              if (p[1] == 'o')
                   1292:                *ld2++ = o_file;
                   1293:              else
                   1294:                {
                   1295:                  /* place o_file BEFORE this argument! */
                   1296:                  ld2--;
                   1297:                  *ld2++ = o_file;
                   1298:                  *ld2++ = arg;
                   1299:                }
                   1300:            }
                   1301:          if (p[1] == 'o')
                   1302:            *object++ = arg;
1.1       root     1303:        }
                   1304:     }
                   1305: 
1.1.1.2   root     1306:   /* Get any options that the upper GCC wants to pass to the sub-GCC.  */
                   1307:   p = (char *) getenv ("COLLECT_GCC_OPTIONS");
                   1308:   if (p)
                   1309:     while (*p)
                   1310:       {
                   1311:        char *q = p;
                   1312:        while (*q && *q != ' ') q++;
                   1313:        if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
                   1314:          *c_ptr++ = savestring (p, q - p);
1.1.1.8   root     1315:        if (strncmp (p, "-shared", sizeof ("shared") - 1) == 0)
                   1316:          shared_obj = 1;
1.1.1.2   root     1317: 
                   1318:        if (*q) q++;
                   1319:        p = q;
                   1320:       }
                   1321: 
1.1.1.8   root     1322: #ifdef COLLECT_EXPORT_LIST
                   1323:   /* The AIX linker will discard static constructors in object files if
                   1324:      nothing else in the file is referenced, so look at them first.  */
                   1325:   while (object_lst < object)
                   1326:     scan_prog_file (*object_lst++, PASS_OBJ);
                   1327: 
                   1328:   {
                   1329:     char *buf = alloca (strlen (export_file) + 5);
                   1330:     sprintf (buf, "-bE:%s", export_file);
                   1331:     *ld1++ = buf;
                   1332:     *ld2++ = buf;
                   1333:     exportf = fopen (export_file, "w");
                   1334:     if (exportf == (FILE *)0)
                   1335:       fatal_perror ("%s", export_file);
                   1336:     write_export_file (exportf);
                   1337:     if (fclose (exportf))
                   1338:       fatal_perror ("closing %s", export_file);
                   1339:   }
                   1340: #endif
                   1341: 
1.1       root     1342:   *c_ptr++ = c_file;
1.1.1.8   root     1343:   *object = *c_ptr = *ld1 = (char *)0;
1.1       root     1344: 
                   1345:   if (vflag)
                   1346:     {
1.1.1.2   root     1347:       fprintf (stderr, "collect2 version %s", version_string);
1.1       root     1348: #ifdef TARGET_VERSION
                   1349:       TARGET_VERSION;
                   1350: #endif
                   1351:       fprintf (stderr, "\n");
                   1352:     }
                   1353: 
                   1354:   if (debug)
                   1355:     {
1.1.1.2   root     1356:       char *ptr;
1.1.1.5   root     1357:       fprintf (stderr, "ld_file_name        = %s\n",
                   1358:               (ld_file_name ? ld_file_name : "not found"));
                   1359:       fprintf (stderr, "c_file_name         = %s\n",
                   1360:               (c_file_name ? c_file_name : "not found"));
                   1361:       fprintf (stderr, "nm_file_name        = %s\n",
                   1362:               (nm_file_name ? nm_file_name : "not found"));
1.1.1.8   root     1363: #ifdef LDD_SUFFIX
                   1364:       fprintf (stderr, "ldd_file_name       = %s\n",
                   1365:               (ldd_file_name ? ldd_file_name : "not found"));
                   1366: #endif
1.1.1.5   root     1367:       fprintf (stderr, "strip_file_name     = %s\n",
                   1368:               (strip_file_name ? strip_file_name : "not found"));
                   1369:       fprintf (stderr, "c_file              = %s\n",
                   1370:               (c_file ? c_file : "not found"));
                   1371:       fprintf (stderr, "o_file              = %s\n",
                   1372:               (o_file ? o_file : "not found"));
1.1.1.2   root     1373: 
1.1.1.6   root     1374:       ptr = getenv ("COLLECT_NAMES");
                   1375:       if (ptr)
                   1376:        fprintf (stderr, "COLLECT_NAMES       = %s\n", ptr);
                   1377: 
1.1.1.2   root     1378:       ptr = getenv ("COLLECT_GCC_OPTIONS");
                   1379:       if (ptr)
                   1380:        fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
                   1381: 
                   1382:       ptr = getenv ("COLLECT_GCC");
                   1383:       if (ptr)
                   1384:        fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
                   1385: 
                   1386:       ptr = getenv ("COMPILER_PATH");
                   1387:       if (ptr)
                   1388:        fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
                   1389: 
                   1390:       ptr = getenv ("LIBRARY_PATH");
                   1391:       if (ptr)
                   1392:        fprintf (stderr, "LIBRARY_PATH        = %s\n", ptr);
                   1393: 
                   1394:       fprintf (stderr, "\n");
1.1       root     1395:     }
                   1396: 
1.1.1.8   root     1397:   /* Load the program, searching all libraries.  */
1.1       root     1398: 
1.1.1.8   root     1399:   collect_execute ("ld", ld1_argv, ldout);
                   1400:   do_wait ("ld");
                   1401:   dump_file (ldout);
                   1402:   unlink (ldout);
                   1403: 
                   1404:   /* If -r or they'll be run via some other method, don't build the
                   1405:      constructor or destructor list, just return now. */
                   1406:   if (rflag || ! do_collecting)
1.1       root     1407:     return 0;
                   1408: 
1.1.1.8   root     1409:   /* Examine the namelist with nm and search it for static constructors
                   1410:      and destructors to call.
                   1411:      Write the constructor and destructor tables to a .s file and reload. */
                   1412: 
1.1.1.5   root     1413:   scan_prog_file (output_file, PASS_FIRST);
1.1       root     1414: 
1.1.1.8   root     1415: #ifdef SCAN_LIBRARIES
                   1416:   scan_libraries (output_file);
                   1417: #endif
                   1418: 
1.1       root     1419:   if (debug)
                   1420:     {
                   1421:       fprintf (stderr, "%d constructor(s) found\n", constructors.number);
                   1422:       fprintf (stderr, "%d destructor(s)  found\n", destructors.number);
                   1423:     }
                   1424: 
1.1.1.8   root     1425:   if (constructors.number == 0 && destructors.number == 0
                   1426: #ifdef LDD_SUFFIX
                   1427:       /* If we will be running these functions ourselves, we want to emit
                   1428:         stubs into the shared library so that we don't have to relink
                   1429:         dependent programs when we add static objects.  */
                   1430:       && ! shared_obj
                   1431: #endif
                   1432:       )
1.1.1.3   root     1433:     {
                   1434:       /* Strip now if it was requested on the command line.  */
                   1435:       if (strip_flag)
                   1436:        {
                   1437:          char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
1.1.1.5   root     1438:          strip_argv[0] = strip_file_name;
                   1439:          strip_argv[1] = output_file;
1.1.1.3   root     1440:          strip_argv[2] = (char *) 0;
1.1.1.5   root     1441:          fork_execute ("strip", strip_argv);
1.1.1.3   root     1442:        }
1.1.1.8   root     1443: 
                   1444: #ifdef COLLECT_EXPORT_LIST
                   1445:       maybe_unlink (export_file);
                   1446: #endif
1.1.1.3   root     1447:       return 0;
                   1448:     }
1.1       root     1449: 
1.1.1.7   root     1450:   maybe_unlink(output_file);
1.1       root     1451:   outf = fopen (c_file, "w");
                   1452:   if (outf == (FILE *)0)
1.1.1.3   root     1453:     fatal_perror ("%s", c_file);
1.1       root     1454: 
                   1455:   write_c_file (outf, c_file);
                   1456: 
                   1457:   if (fclose (outf))
1.1.1.3   root     1458:     fatal_perror ("closing %s", c_file);
1.1       root     1459: 
1.1.1.8   root     1460:   /* Tell the linker that we have initializer and finalizer functions.  */
                   1461: #ifdef LD_INIT_SWITCH
                   1462:   *ld2++ = LD_INIT_SWITCH;
                   1463:   *ld2++ = initname;
                   1464:   *ld2++ = LD_FINI_SWITCH;
                   1465:   *ld2++ = fininame;
                   1466: #endif
                   1467:   *ld2 = (char*)0;
                   1468: 
                   1469: #ifdef COLLECT_EXPORT_LIST
                   1470:   if (shared_obj)
                   1471:     {
                   1472:       add_to_list (&exports, initname);
                   1473:       add_to_list (&exports, fininame);
                   1474:       add_to_list (&exports, "_GLOBAL__DI");
                   1475:       add_to_list (&exports, "_GLOBAL__DD");
                   1476:       exportf = fopen (export_file, "w");
                   1477:       if (exportf == (FILE *)0)
                   1478:        fatal_perror ("%s", export_file);
                   1479:       write_export_file (exportf);
                   1480:       if (fclose (exportf))
                   1481:        fatal_perror ("closing %s", export_file);
                   1482:     }
                   1483: #endif
                   1484: 
1.1       root     1485:   if (debug)
                   1486:     {
1.1.1.5   root     1487:       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
                   1488:               output_file, c_file);
1.1       root     1489:       write_c_file (stderr, "stderr");
                   1490:       fprintf (stderr, "========== end of c_file\n\n");
1.1.1.8   root     1491: #ifdef COLLECT_EXPORT_LIST
                   1492:       fprintf (stderr, "\n========== export_file = %s\n", export_file);
                   1493:       write_export_file (stderr);
                   1494:       fprintf (stderr, "========== end of export_file\n\n");
                   1495: #endif
1.1       root     1496:     }
                   1497: 
                   1498:   /* Assemble the constructor and destructor tables.
                   1499:      Link the tables in with the rest of the program. */
                   1500: 
1.1.1.5   root     1501:   fork_execute ("gcc",  c_argv);
                   1502:   fork_execute ("ld", ld2_argv);
1.1       root     1503: 
                   1504:   /* Let scan_prog_file do any final mods (OSF/rose needs this for
                   1505:      constructors/destructors in shared libraries.  */
1.1.1.5   root     1506:   scan_prog_file (output_file, PASS_SECOND);
1.1       root     1507: 
                   1508:   maybe_unlink (c_file);
                   1509:   maybe_unlink (o_file);
1.1.1.8   root     1510:   maybe_unlink (export_file);
1.1       root     1511:   return 0;
                   1512: }
                   1513: 
                   1514: 
                   1515: /* Wait for a process to finish, and exit if a non-zero status is found. */
                   1516: 
1.1.1.8   root     1517: int
                   1518: collect_wait (prog)
1.1       root     1519:      char *prog;
                   1520: {
                   1521:   int status;
                   1522: 
                   1523:   wait (&status);
                   1524:   if (status)
                   1525:     {
1.1.1.7   root     1526:       if (WIFSIGNALED (status))
1.1       root     1527:        {
1.1.1.7   root     1528:          int sig = WTERMSIG (status);
1.1.1.2   root     1529: #ifdef NO_SYS_SIGLIST
                   1530:          error ("%s terminated with signal %d %s",
                   1531:                 prog,
                   1532:                 sig,
                   1533:                 (status & 0200) ? ", core dumped" : "");
                   1534: #else
1.1       root     1535:          error ("%s terminated with signal %d [%s]%s",
                   1536:                 prog,
                   1537:                 sig,
                   1538:                 sys_siglist[sig],
                   1539:                 (status & 0200) ? ", core dumped" : "");
1.1.1.2   root     1540: #endif
1.1       root     1541: 
1.1.1.8   root     1542:          collect_exit (127);
1.1       root     1543:        }
                   1544: 
1.1.1.7   root     1545:       if (WIFEXITED (status))
1.1.1.8   root     1546:        return WEXITSTATUS (status);
                   1547:     }
                   1548:   return 0;
                   1549: }
                   1550: 
                   1551: static void
                   1552: do_wait (prog)
                   1553:      char *prog;
                   1554: {
                   1555:   int ret = collect_wait (prog);
                   1556:   if (ret != 0)
                   1557:     {
                   1558:       error ("%s returned %d exit status", prog, ret);
                   1559:       collect_exit (ret);
1.1       root     1560:     }
                   1561: }
                   1562: 
                   1563: 
                   1564: /* Fork and execute a program, and wait for the reply.  */
                   1565: 
1.1.1.8   root     1566: void
                   1567: collect_execute (prog, argv, redir)
1.1       root     1568:      char *prog;
                   1569:      char **argv;
1.1.1.8   root     1570:      char *redir;
1.1       root     1571: {
                   1572:   int pid;
                   1573: 
                   1574:   if (vflag || debug)
                   1575:     {
                   1576:       char **p_argv;
                   1577:       char *str;
                   1578: 
1.1.1.5   root     1579:       if (argv[0])
                   1580:        fprintf (stderr, "%s", argv[0]);
                   1581:       else
                   1582:        fprintf (stderr, "[cannot find %s]", prog);
                   1583: 
1.1       root     1584:       for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
                   1585:        fprintf (stderr, " %s", str);
                   1586: 
                   1587:       fprintf (stderr, "\n");
                   1588:     }
                   1589: 
                   1590:   fflush (stdout);
                   1591:   fflush (stderr);
                   1592: 
1.1.1.5   root     1593:   /* If we can't find a program we need, complain error.  Do this here
                   1594:      since we might not end up needing something that we couldn't find.  */
                   1595: 
                   1596:   if (argv[0] == 0)
                   1597:     fatal ("cannot find `%s'", prog);
                   1598: 
1.1       root     1599:   pid = vfork ();
                   1600:   if (pid == -1)
1.1.1.6   root     1601:     {
                   1602: #ifdef vfork
                   1603:       fatal_perror ("fork");
                   1604: #else
                   1605:       fatal_perror ("vfork");
                   1606: #endif
                   1607:     }
1.1       root     1608: 
                   1609:   if (pid == 0)                        /* child context */
                   1610:     {
1.1.1.8   root     1611:       if (redir)
                   1612:        {
                   1613:          unlink (redir);
                   1614:          if (freopen (redir, "a", stdout) == NULL)
                   1615:            fatal_perror ("redirecting stdout");
                   1616:          if (freopen (redir, "a", stderr) == NULL)
                   1617:            fatal_perror ("redirecting stderr");
                   1618:        }
                   1619: 
1.1.1.5   root     1620:       execvp (argv[0], argv);
1.1.1.3   root     1621:       fatal_perror ("executing %s", prog);
1.1       root     1622:     }
1.1.1.8   root     1623: }
1.1       root     1624: 
1.1.1.8   root     1625: static void
                   1626: fork_execute (prog, argv)
                   1627:      char *prog;
                   1628:      char **argv;
                   1629: {
                   1630:   collect_execute (prog, argv, NULL);
1.1       root     1631:   do_wait (prog);
                   1632: }
                   1633: 
                   1634: /* Unlink a file unless we are debugging.  */
                   1635: 
                   1636: static void
                   1637: maybe_unlink (file)
                   1638:      char *file;
                   1639: {
                   1640:   if (!debug)
                   1641:     unlink (file);
                   1642:   else
                   1643:     fprintf (stderr, "[Leaving %s]\n", file);
                   1644: }
                   1645: 
                   1646: 
                   1647: /* Add a name to a linked list.  */
                   1648: 
                   1649: static void
                   1650: add_to_list (head_ptr, name)
                   1651:      struct head *head_ptr;
                   1652:      char *name;
                   1653: {
1.1.1.7   root     1654:   struct id *newid
                   1655:     = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
                   1656:   struct id *p;
1.1       root     1657:   static long sequence_number = 0;
                   1658:   strcpy (newid->name, name);
                   1659: 
                   1660:   if (head_ptr->first)
                   1661:     head_ptr->last->next = newid;
                   1662:   else
                   1663:     head_ptr->first = newid;
                   1664: 
1.1.1.7   root     1665:   /* Check for duplicate symbols.  */
                   1666:   for (p = head_ptr->first;
                   1667:        strcmp (name, p->name) != 0;
                   1668:        p = p->next)
                   1669:     ;
                   1670:   if (p != newid)
                   1671:     {
                   1672:       head_ptr->last->next = 0;
                   1673:       free (newid);
                   1674:       return;
                   1675:     }
                   1676: 
                   1677:   newid->sequence = ++sequence_number;
1.1       root     1678:   head_ptr->last = newid;
                   1679:   head_ptr->number++;
                   1680: }
                   1681: 
                   1682: /* Write: `prefix', the names on list LIST, `suffix'.  */
                   1683: 
                   1684: static void
                   1685: write_list (stream, prefix, list)
                   1686:      FILE *stream;
                   1687:      char *prefix;
                   1688:      struct id *list;
                   1689: {
                   1690:   while (list)
                   1691:     {
                   1692:       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
                   1693:       list = list->next;
                   1694:     }
                   1695: }
                   1696: 
                   1697: static void
                   1698: write_list_with_asm (stream, prefix, list)
                   1699:      FILE *stream;
                   1700:      char *prefix;
                   1701:      struct id *list;
                   1702: {
                   1703:   while (list)
                   1704:     {
1.1.1.5   root     1705:       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1.1       root     1706:               prefix, list->sequence, list->name);
                   1707:       list = list->next;
                   1708:     }
                   1709: }
                   1710: 
1.1.1.8   root     1711: /* Write out the constructor and destructor tables statically (for a shared
                   1712:    object), along with the functions to execute them.  */
                   1713: 
                   1714: static void
                   1715: write_c_file_stat (stream, name)
                   1716:      FILE *stream;
                   1717:      char *name;
                   1718: {
                   1719:   char *prefix, *p, *q;
                   1720: 
                   1721:   /* Figure out name of output_file, stripping off .so version.  */
                   1722:   p = rindex (output_file, '/');
                   1723:   if (p == 0)
                   1724:     p = (char *) output_file;
                   1725:   else
                   1726:     p++;
                   1727:   q = p;
                   1728:   while (q)
                   1729:     {
                   1730:       q = index (q,'.');
                   1731:       if (q == 0)
                   1732:        {
                   1733:          q = p + strlen (p);
                   1734:          break;
                   1735:        }
                   1736:       else
                   1737:        {
                   1738:          if (strncmp (q, ".so", 3) == 0)
                   1739:            {
                   1740:              q += 3;
                   1741:              break;
                   1742:            }
                   1743:          else
                   1744:            q++;
                   1745:        }
                   1746:     }
                   1747:   /* q points to null at end of the string (or . of the .so version) */
                   1748:   prefix = xmalloc (q - p + 1);
                   1749:   strncpy (prefix, p, q - p);
                   1750:   prefix[q - p] = 0;
                   1751:   for (q = prefix; *q; q++)
                   1752:     if (!isalnum (*q))
                   1753:       *q = '_';
                   1754:   if (debug)
                   1755:     fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n",
                   1756:             output_file, prefix);
                   1757: 
                   1758: #define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
                   1759:   initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
                   1760:   sprintf (initname, INIT_NAME_FORMAT, prefix);
                   1761: 
                   1762: #define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
                   1763:   fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
                   1764:   sprintf (fininame, FINI_NAME_FORMAT, prefix);
                   1765: 
                   1766:   free (prefix);
                   1767: 
                   1768:   /* Write the tables as C code  */
                   1769: 
                   1770:   fprintf (stream, "static int count;\n");
                   1771:   fprintf (stream, "typedef void entry_pt();\n");
                   1772:   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
                   1773:   fprintf (stream, "void %s() {\n", initname);
                   1774:   if (constructors.number > 0)
                   1775:     {
                   1776:       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
                   1777:       write_list (stream, "\t\t", constructors.first);
                   1778:       fprintf (stream, "\t};\n");
                   1779:       fprintf (stream, "\tentry_pt **p;\n");
                   1780:       fprintf (stream, "\tif (count++ != 0) return;\n");
                   1781:       fprintf (stream, "\tp = ctors + %d;\n", constructors.number);
                   1782:       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
                   1783:     }
                   1784:   else
                   1785:     fprintf (stream, "\t++count;\n");
                   1786:   fprintf (stream, "}\n");
                   1787:   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
                   1788:   fprintf (stream, "void %s() {\n", fininame);
                   1789:   if (destructors.number > 0)
                   1790:     {
                   1791:       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
                   1792:       write_list (stream, "\t\t", destructors.first);
                   1793:       fprintf (stream, "\t};\n");
                   1794:       fprintf (stream, "\tentry_pt **p;\n");
                   1795:       fprintf (stream, "\tif (--count != 0) return;\n");
                   1796:       fprintf (stream, "\tp = dtors;\n");
                   1797:       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
                   1798:               destructors.number);
                   1799:     }
                   1800:   fprintf (stream, "}\n");
                   1801: 
                   1802:   if (shared_obj)
                   1803:     {
                   1804:       fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
                   1805:       fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
                   1806:     }
                   1807: }
                   1808: 
1.1       root     1809: /* Write the constructor/destructor tables. */
                   1810: 
                   1811: static void
1.1.1.8   root     1812: write_c_file_glob (stream, name)
1.1       root     1813:      FILE *stream;
                   1814:      char *name;
                   1815: {
                   1816:   /* Write the tables as C code  */
                   1817: 
                   1818:   fprintf (stream, "typedef void entry_pt();\n\n");
                   1819:     
1.1.1.3   root     1820:   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1.1       root     1821:     
                   1822:   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
                   1823:   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
                   1824:   write_list (stream, "\t", constructors.first);
                   1825:   fprintf (stream, "\t0\n};\n\n");
                   1826: 
1.1.1.3   root     1827:   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1.1       root     1828: 
                   1829:   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
                   1830:   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
                   1831:   write_list (stream, "\t", destructors.first);
                   1832:   fprintf (stream, "\t0\n};\n\n");
                   1833: 
1.1.1.6   root     1834:   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
                   1835:   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
1.1       root     1836: }
                   1837: 
1.1.1.8   root     1838: static void
                   1839: write_c_file (stream, name)
                   1840:      FILE *stream;
                   1841:      char *name;
                   1842: {
                   1843: #ifndef LD_INIT_SWITCH
                   1844:   if (! shared_obj)
                   1845:     write_c_file_glob (stream, name);
                   1846:   else
                   1847: #endif
                   1848:     write_c_file_stat (stream, name);
                   1849: }
                   1850: 
                   1851: static void
                   1852: write_export_file (stream)
                   1853:      FILE *stream;
                   1854: {
                   1855:   struct id *list = exports.first;
                   1856:   for (; list; list = list->next)
                   1857:     fprintf (stream, "%s\n", list->name);
                   1858: }
1.1       root     1859: 
1.1.1.2   root     1860: #ifdef OBJECT_FORMAT_NONE
1.1       root     1861: 
1.1.1.2   root     1862: /* Generic version to scan the name list of the loaded program for
                   1863:    the symbols g++ uses for static constructors and destructors.
1.1       root     1864: 
                   1865:    The constructor table begins at __CTOR_LIST__ and contains a count
                   1866:    of the number of pointers (or -1 if the constructors are built in a
                   1867:    separate section by the linker), followed by the pointers to the
                   1868:    constructor functions, terminated with a null pointer.  The
                   1869:    destructor table has the same format, and begins at __DTOR_LIST__.  */
                   1870: 
                   1871: static void
                   1872: scan_prog_file (prog_name, which_pass)
                   1873:      char *prog_name;
                   1874:      enum pass which_pass;
                   1875: {
                   1876:   void (*int_handler) ();
                   1877:   void (*quit_handler) ();
                   1878:   char *nm_argv[4];
                   1879:   int pid;
                   1880:   int argc = 0;
                   1881:   int pipe_fd[2];
                   1882:   char *p, buf[1024];
                   1883:   FILE *inf;
                   1884: 
1.1.1.8   root     1885:   if (which_pass == PASS_SECOND)
1.1       root     1886:     return;
                   1887: 
1.1.1.5   root     1888:   /* If we don't have an `nm', complain.  */
                   1889:   if (nm_file_name == 0)
                   1890:     fatal ("cannot find `nm'");
                   1891: 
1.1.1.8   root     1892:   nm_argv[argc++] = nm_file_name;
1.1       root     1893:   if (NM_FLAGS[0] != '\0')
                   1894:     nm_argv[argc++] = NM_FLAGS;
                   1895: 
                   1896:   nm_argv[argc++] = prog_name;
                   1897:   nm_argv[argc++] = (char *)0;
                   1898: 
                   1899:   if (pipe (pipe_fd) < 0)
                   1900:     fatal_perror ("pipe");
                   1901: 
                   1902:   inf = fdopen (pipe_fd[0], "r");
                   1903:   if (inf == (FILE *)0)
                   1904:     fatal_perror ("fdopen");
                   1905: 
                   1906:   /* Trace if needed.  */
                   1907:   if (vflag)
                   1908:     {
                   1909:       char **p_argv;
                   1910:       char *str;
                   1911: 
1.1.1.8   root     1912:       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++)
1.1       root     1913:        fprintf (stderr, " %s", str);
                   1914: 
                   1915:       fprintf (stderr, "\n");
                   1916:     }
                   1917: 
                   1918:   fflush (stdout);
                   1919:   fflush (stderr);
                   1920: 
                   1921:   /* Spawn child nm on pipe */
                   1922:   pid = vfork ();
                   1923:   if (pid == -1)
1.1.1.6   root     1924:     {
                   1925: #ifdef vfork
                   1926:       fatal_perror ("fork");
                   1927: #else
                   1928:       fatal_perror ("vfork");
                   1929: #endif
                   1930:     }
1.1       root     1931: 
                   1932:   if (pid == 0)                        /* child context */
                   1933:     {
                   1934:       /* setup stdout */
                   1935:       if (dup2 (pipe_fd[1], 1) < 0)
1.1.1.3   root     1936:        fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
1.1       root     1937: 
                   1938:       if (close (pipe_fd[0]) < 0)
1.1.1.3   root     1939:        fatal_perror ("close (%d)", pipe_fd[0]);
1.1       root     1940: 
                   1941:       if (close (pipe_fd[1]) < 0)
1.1.1.3   root     1942:        fatal_perror ("close (%d)", pipe_fd[1]);
1.1       root     1943: 
                   1944:       execv (nm_file_name, nm_argv);
1.1.1.3   root     1945:       fatal_perror ("executing %s", nm_file_name);
1.1       root     1946:     }
                   1947: 
                   1948:   /* Parent context from here on.  */
                   1949:   int_handler  = (void (*) ())signal (SIGINT,  SIG_IGN);
1.1.1.5   root     1950: #ifdef SIGQUIT
1.1       root     1951:   quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
1.1.1.5   root     1952: #endif
1.1       root     1953: 
                   1954:   if (close (pipe_fd[1]) < 0)
1.1.1.3   root     1955:     fatal_perror ("close (%d)", pipe_fd[1]);
1.1       root     1956: 
                   1957:   if (debug)
                   1958:     fprintf (stderr, "\nnm output with constructors/destructors.\n");
                   1959: 
                   1960:   /* Read each line of nm output.  */
                   1961:   while (fgets (buf, sizeof buf, inf) != (char *)0)
                   1962:     {
                   1963:       int ch, ch2;
1.1.1.2   root     1964:       char *name, *end;
1.1       root     1965: 
                   1966:       /* If it contains a constructor or destructor name, add the name
                   1967:         to the appropriate list. */
                   1968: 
                   1969:       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1.1.1.8   root     1970:        if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
                   1971:          break;
1.1       root     1972: 
1.1.1.8   root     1973:       if (ch != '_')
1.1       root     1974:        continue;
1.1.1.2   root     1975:   
                   1976:       name = p;
                   1977:       /* Find the end of the symbol name.
                   1978:         Don't include `|', because Encore nm can tack that on the end.  */
                   1979:       for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
                   1980:           end++)
                   1981:        continue;
1.1       root     1982: 
1.1.1.7   root     1983: 
1.1       root     1984:       *end = '\0';
1.1.1.2   root     1985:       switch (is_ctor_dtor (name))
1.1       root     1986:        {
1.1.1.2   root     1987:        case 1:
1.1.1.8   root     1988:          if (which_pass != PASS_LIB)
                   1989:            add_to_list (&constructors, name);
1.1.1.2   root     1990:          break;
                   1991: 
                   1992:        case 2:
1.1.1.8   root     1993:          if (which_pass != PASS_LIB)
                   1994:            add_to_list (&destructors, name);
                   1995:          break;
                   1996: 
                   1997:        case 3:
                   1998:          if (which_pass != PASS_LIB)
                   1999:            fatal ("init function found in object %s", prog_name);
                   2000: #ifndef LD_INIT_SWITCH
                   2001:          add_to_list (&constructors, name);
                   2002: #endif
                   2003:          break;
                   2004: 
                   2005:        case 4:
                   2006:          if (which_pass != PASS_LIB)
                   2007:            fatal ("fini function found in object %s", prog_name);
                   2008: #ifndef LD_FINI_SWITCH
1.1.1.2   root     2009:          add_to_list (&destructors, name);
1.1.1.8   root     2010: #endif
1.1.1.2   root     2011:          break;
1.1       root     2012: 
1.1.1.2   root     2013:        default:                /* not a constructor or destructor */
                   2014:          continue;
1.1       root     2015:        }
                   2016: 
                   2017:       if (debug)
                   2018:        fprintf (stderr, "\t%s\n", buf);
                   2019:     }
                   2020: 
                   2021:   if (debug)
                   2022:     fprintf (stderr, "\n");
                   2023: 
                   2024:   if (fclose (inf) != 0)
                   2025:     fatal_perror ("fclose of pipe");
                   2026: 
                   2027:   do_wait (nm_file_name);
                   2028: 
                   2029:   signal (SIGINT,  int_handler);
1.1.1.5   root     2030: #ifdef SIGQUIT
1.1       root     2031:   signal (SIGQUIT, quit_handler);
1.1.1.5   root     2032: #endif
1.1       root     2033: }
                   2034: 
1.1.1.8   root     2035: #if SUNOS4_SHARED_LIBRARIES
                   2036: 
                   2037: /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
                   2038:    that the output file depends upon and their initialization/finalization
                   2039:    routines, if any.  */
                   2040: 
                   2041: #include <a.out.h>
                   2042: #include <fcntl.h>
                   2043: #include <link.h>
                   2044: #include <sys/mman.h>
                   2045: #include <sys/param.h>
                   2046: #include <sys/unistd.h>
                   2047: #include <sys/dir.h>
                   2048: 
                   2049: /* pointers to the object file */
                   2050: unsigned object;       /* address of memory mapped file */
                   2051: unsigned objsize;      /* size of memory mapped to file */
                   2052: char * code;           /* pointer to code segment */
                   2053: char * data;           /* pointer to data segment */
                   2054: struct nlist *symtab;  /* pointer to symbol table */
                   2055: struct link_dynamic *ld;
                   2056: struct link_dynamic_2 *ld_2;
                   2057: struct head libraries;
                   2058: 
                   2059: /* Map the file indicated by NAME into memory and store its address.  */
                   2060: 
                   2061: static void
                   2062: mapfile (name)
                   2063:      char *name;
                   2064: {
                   2065:   int fp;
                   2066:   struct stat s;
                   2067:   if ((fp = open (name, O_RDONLY)) == -1)
                   2068:     fatal ("unable to open file '%s'", name);
                   2069:   if (fstat (fp, &s) == -1)
                   2070:     fatal ("unable to stat file '%s'", name);
                   2071: 
                   2072:   objsize = s.st_size;
                   2073:   object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
                   2074:                            fp, 0);
                   2075:   if (object == -1)
                   2076:     fatal ("unable to mmap file '%s'", name);
                   2077: 
                   2078:   close (fp);
                   2079: }
                   2080: 
                   2081: /* Helpers for locatelib.  */
                   2082: 
                   2083: static char *libname;
                   2084: 
                   2085: static int
                   2086: libselect (d)
                   2087:      struct direct *d;
                   2088: {
                   2089:   return (strncmp (libname, d->d_name, strlen (libname)) == 0);
                   2090: }
                   2091: 
                   2092: /* If one file has an additional numeric extension past LIBNAME, then put
                   2093:    that one first in the sort.  If both files have additional numeric
                   2094:    extensions, then put the one with the higher number first in the sort.
                   2095: 
                   2096:    We must verify that the extension is numeric, because Sun saves the
                   2097:    original versions of patched libraries with a .FCS extension.  Files with
                   2098:    invalid extensions must go last in the sort, so that they won't be used.  */
                   2099: 
                   2100: static int
                   2101: libcompare (d1, d2)
                   2102:      struct direct **d1, **d2;
                   2103: {
                   2104:   int i1, i2 = strlen (libname);
                   2105:   char *e1 = (*d1)->d_name + i2;
                   2106:   char *e2 = (*d2)->d_name + i2;
                   2107: 
                   2108:   while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
                   2109:         && e1[1] && isdigit (e1[1]) && e2[1] && isdigit (e2[1]))
                   2110:     {
                   2111:       ++e1;
                   2112:       ++e2;
                   2113:       i1 = strtol (e1, &e1, 10);
                   2114:       i2 = strtol (e2, &e2, 10);
                   2115:       if (i1 != i2)
                   2116:        return i1 - i2;
                   2117:     }
                   2118: 
                   2119:   if (*e1)
                   2120:     {
                   2121:       /* It has a valid numeric extension, prefer this one.  */
                   2122:       if (*e1 == '.' && e1[1] && isdigit (e1[1]))
                   2123:        return 1;
                   2124:       /* It has a invalid numeric extension, must prefer the other one.  */
                   2125:       else
                   2126:        return -1;
                   2127:     }
                   2128:   else if (*e2)
                   2129:     {
                   2130:       /* It has a valid numeric extension, prefer this one.  */
                   2131:       if (*e2 == '.' && e2[1] && isdigit (e2[1]))
                   2132:        return -1;
                   2133:       /* It has a invalid numeric extension, must prefer the other one.  */
                   2134:       else
                   2135:        return 1;
                   2136:     }
                   2137:   else
                   2138:     return 0;
                   2139: }
                   2140: 
                   2141: /* Given the name NAME of a dynamic dependency, find its pathname and add
                   2142:    it to the list of libraries.  */
                   2143: 
                   2144: static void
                   2145: locatelib (name)
                   2146:      char *name;
                   2147: {
                   2148:   static char **l;
                   2149:   static int cnt;
                   2150:   char buf[MAXPATHLEN];
                   2151:   char *p, *q;
                   2152:   char **pp;
                   2153: 
                   2154:   if (l == 0)
                   2155:     {
                   2156:       char *ld_rules;
                   2157:       char *ldr = 0;
                   2158:       /* counting elements in array, need 1 extra for null */
                   2159:       cnt = 1;  
                   2160:       ld_rules = (char *) (ld_2->ld_rules + code);
                   2161:       if (ld_rules)
                   2162:        {
                   2163:          cnt++;
                   2164:          for (; *ld_rules != 0; ld_rules++)
                   2165:            if (*ld_rules == ':')
                   2166:              cnt++;
                   2167:          ld_rules = (char *) (ld_2->ld_rules + code);
                   2168:          ldr = (char *) malloc (strlen (ld_rules) + 1);
                   2169:          strcpy (ldr, ld_rules);
                   2170:        }
                   2171:       p = getenv ("LD_LIBRARY_PATH");
                   2172:       q = 0;
                   2173:       if (p)
                   2174:        {
                   2175:          cnt++;
                   2176:          for (q = p ; *q != 0; q++)
                   2177:            if (*q == ':')
                   2178:              cnt++;
                   2179:          q = (char *) malloc (strlen (p) + 1);
                   2180:          strcpy (q, p);
                   2181:        }
                   2182:       l = (char **) malloc ((cnt + 3) * sizeof (char *));
                   2183:       pp = l;
                   2184:       if (ldr)
                   2185:        {
                   2186:          *pp++ = ldr;
                   2187:          for (; *ldr != 0; ldr++) 
                   2188:            if (*ldr == ':')
                   2189:              {
                   2190:                *ldr++ = 0;
                   2191:                *pp++ = ldr;
                   2192:              }
                   2193:        }
                   2194:       if (q)
                   2195:        {
                   2196:          *pp++ = q;
                   2197:          for (; *q != 0; q++) 
                   2198:            if (*q == ':')
                   2199:              {
                   2200:                *q++ = 0;
                   2201:                *pp++ = q;
                   2202:              }
                   2203:        }
                   2204:       /* built in directories are /lib, /usr/lib, and /usr/local/lib */
                   2205:       *pp++ = "/lib";
                   2206:       *pp++ = "/usr/lib";
                   2207:       *pp++ = "/usr/local/lib";
                   2208:       *pp = 0;
                   2209:     }
                   2210:   libname = name;
                   2211:   for (pp = l; *pp != 0 ; pp++)
                   2212:     {
                   2213:       struct direct **namelist;
                   2214:       int entries;
                   2215:       if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
                   2216:        {
                   2217:          sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
                   2218:          add_to_list (&libraries, buf);
                   2219:          if (debug)
                   2220:            fprintf (stderr, "%s\n", buf);
                   2221:          break;
                   2222:        }
                   2223:     }
                   2224:   if (*pp == 0)
                   2225:     {
                   2226:       if (debug)
                   2227:        fprintf (stderr, "not found\n");
                   2228:       else
                   2229:        fatal ("dynamic dependency %s not found", name);
                   2230:     }
                   2231: }
                   2232: 
                   2233: /* Scan the _DYNAMIC structure of the output file to find shared libraries
                   2234:    that it depends upon and any constructors or destructors they contain.  */
                   2235: 
                   2236: static void 
                   2237: scan_libraries (prog_name)
                   2238:      char *prog_name;
                   2239: {
                   2240:   struct exec *header;
                   2241:   char *base;
                   2242:   struct link_object *lo;
                   2243:   char buff[MAXPATHLEN];
                   2244:   struct id *list;
                   2245: 
                   2246:   mapfile (prog_name);
                   2247:   header = (struct exec *)object;
                   2248:   if (N_BADMAG (*header))
                   2249:     fatal ("bad magic number in file '%s'", prog_name);
                   2250:   if (header->a_dynamic == 0)
                   2251:     return;
                   2252: 
                   2253:   code = (char *) (N_TXTOFF (*header) + (long) header);
                   2254:   data = (char *) (N_DATOFF (*header) + (long) header);
                   2255:   symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
                   2256: 
                   2257:   if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
                   2258:     {
                   2259:       /* shared object */
                   2260:       ld = (struct link_dynamic *) (symtab->n_value + code);
                   2261:       base = code;
                   2262:     }
                   2263:   else
                   2264:     {
                   2265:       /* executable */
                   2266:       ld = (struct link_dynamic *) data;
                   2267:       base = code-PAGSIZ;
                   2268:     }
                   2269: 
                   2270:   if (debug)
                   2271:     fprintf (stderr, "dynamic dependencies.\n");
                   2272: 
                   2273:   ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
                   2274:   for (lo = (struct link_object *) ld_2->ld_need; lo;
                   2275:        lo = (struct link_object *) lo->lo_next)
                   2276:     {
                   2277:       char *name;
                   2278:       lo = (struct link_object *) ((long) lo + code);
                   2279:       name = (char *) (code + lo->lo_name);
                   2280:       if (lo->lo_library)
                   2281:        {
                   2282:          if (debug)
                   2283:            fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
                   2284:          sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
                   2285:          locatelib (buff);
                   2286:        }
                   2287:       else
                   2288:        {
                   2289:          if (debug)
                   2290:            fprintf (stderr, "\t%s\n", name);
                   2291:          add_to_list (&libraries, name);
                   2292:        }
                   2293:     }
                   2294: 
                   2295:   if (debug)
                   2296:     fprintf (stderr, "\n");
                   2297: 
                   2298:   /* now iterate through the library list adding their symbols to
                   2299:      the list.  */
                   2300:   for (list = libraries.first; list; list = list->next)
                   2301:     scan_prog_file (list->name, PASS_LIB);
                   2302: }
                   2303: 
                   2304: #else  /* SUNOS4_SHARED_LIBRARIES */
                   2305: #ifdef LDD_SUFFIX
                   2306: 
                   2307: /* Use the List Dynamic Dependencies program to find shared libraries that
                   2308:    the output file depends upon and their initialization/finalization
                   2309:    routines, if any.  */
                   2310: 
                   2311: static void 
                   2312: scan_libraries (prog_name)
                   2313:      char *prog_name;
                   2314: {
                   2315:   static struct head libraries;                /* list of shared libraries found */
                   2316:   struct id *list;
                   2317:   void (*int_handler) ();
                   2318:   void (*quit_handler) ();
                   2319:   char *ldd_argv[4];
                   2320:   int pid;
                   2321:   int argc = 0;
                   2322:   int pipe_fd[2];
                   2323:   char buf[1024];
                   2324:   FILE *inf;
                   2325: 
                   2326:   /* If we don't have an `ldd', complain.  */
                   2327:   if (ldd_file_name == 0)
                   2328:     {
                   2329:       error ("cannot find `ldd'");
                   2330:       return;
                   2331:     }
                   2332: 
                   2333:   ldd_argv[argc++] = ldd_file_name;
                   2334:   ldd_argv[argc++] = prog_name;
                   2335:   ldd_argv[argc++] = (char *) 0;
                   2336: 
                   2337:   if (pipe (pipe_fd) < 0)
                   2338:     fatal_perror ("pipe");
                   2339: 
                   2340:   inf = fdopen (pipe_fd[0], "r");
                   2341:   if (inf == (FILE *) 0)
                   2342:     fatal_perror ("fdopen");
                   2343: 
                   2344:   /* Trace if needed.  */
                   2345:   if (vflag)
                   2346:     {
                   2347:       char **p_argv;
                   2348:       char *str;
                   2349: 
                   2350:       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
                   2351:        fprintf (stderr, " %s", str);
                   2352: 
                   2353:       fprintf (stderr, "\n");
                   2354:     }
                   2355: 
                   2356:   fflush (stdout);
                   2357:   fflush (stderr);
                   2358: 
                   2359:   /* Spawn child ldd on pipe */
                   2360:   pid = vfork ();
                   2361:   if (pid == -1)
                   2362:     {
                   2363: #ifdef vfork
                   2364:       fatal_perror ("fork");
                   2365: #else
                   2366:       fatal_perror ("vfork");
                   2367: #endif
                   2368:     }
                   2369: 
                   2370:   if (pid == 0)                        /* child context */
                   2371:     {
                   2372:       /* setup stdout */
                   2373:       if (dup2 (pipe_fd[1], 1) < 0)
                   2374:        fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
                   2375: 
                   2376:       if (close (pipe_fd[0]) < 0)
                   2377:        fatal_perror ("close (%d)", pipe_fd[0]);
                   2378: 
                   2379:       if (close (pipe_fd[1]) < 0)
                   2380:        fatal_perror ("close (%d)", pipe_fd[1]);
                   2381: 
                   2382:       execv (ldd_file_name, ldd_argv);
                   2383:       fatal_perror ("executing %s", ldd_file_name);
                   2384:     }
                   2385: 
                   2386:   /* Parent context from here on.  */
                   2387:   int_handler  = (void (*) ()) signal (SIGINT,  SIG_IGN);
                   2388: #ifdef SIGQUIT
                   2389:   quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
                   2390: #endif
                   2391: 
                   2392:   if (close (pipe_fd[1]) < 0)
                   2393:     fatal_perror ("close (%d)", pipe_fd[1]);
                   2394: 
                   2395:   if (debug)
                   2396:     fprintf (stderr, "\nldd output with constructors/destructors.\n");
                   2397: 
                   2398:   /* Read each line of ldd output.  */
                   2399:   while (fgets (buf, sizeof buf, inf) != (char *) 0)
                   2400:     {
                   2401:       int ch, ch2;
                   2402:       char *name, *end, *p = buf;
                   2403: 
                   2404:       /* Extract names of libraries and add to list. */
                   2405:       PARSE_LDD_OUTPUT (p);
                   2406:       if (p == 0)
                   2407:        continue;
                   2408: 
                   2409:       name = p;
                   2410:       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
                   2411:        fatal ("dynamic dependency %s not found", buf);
                   2412: 
                   2413:       /* Find the end of the symbol name. */
                   2414:       for (end = p; 
                   2415:           (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|';
                   2416:           end++)
                   2417:        continue;
                   2418:       *end = '\0';
                   2419: 
                   2420:       if (access (name, R_OK) == 0)
                   2421:         add_to_list (&libraries, name);
                   2422:       else
                   2423:        fatal ("unable to open dynamic dependency '%s'", buf);
                   2424: 
                   2425:       if (debug)
                   2426:        fprintf (stderr, "\t%s\n", buf);
                   2427:     }
                   2428:   if (debug)
                   2429:     fprintf (stderr, "\n");
                   2430: 
                   2431:   if (fclose (inf) != 0)
                   2432:     fatal_perror ("fclose of pipe");
                   2433: 
                   2434:   do_wait (ldd_file_name);
                   2435: 
                   2436:   signal (SIGINT,  int_handler);
                   2437: #ifdef SIGQUIT
                   2438:   signal (SIGQUIT, quit_handler);
                   2439: #endif
                   2440: 
                   2441:   /* now iterate through the library list adding their symbols to
                   2442:      the list.  */
                   2443:   for (list = libraries.first; list; list = list->next)
                   2444:     scan_prog_file (list->name, PASS_LIB);
                   2445: }
                   2446: 
                   2447: #endif /* LDD_SUFFIX */
                   2448: #endif /* SUNOS4_SHARED_LIBRARIES */
                   2449: 
1.1.1.2   root     2450: #endif /* OBJECT_FORMAT_NONE */
                   2451: 
                   2452: 
                   2453: /*
                   2454:  * COFF specific stuff.
                   2455:  */
                   2456: 
                   2457: #ifdef OBJECT_FORMAT_COFF
                   2458: 
                   2459: #if defined(EXTENDED_COFF)
1.1.1.3   root     2460: #   define GCC_SYMBOLS(X)      (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
                   2461: #   define GCC_SYMENT          SYMR
                   2462: #   define GCC_OK_SYMBOL(X)    ((X).st == stProc && (X).sc == scText)
                   2463: #   define GCC_SYMINC(X)       (1)
                   2464: #   define GCC_SYMZERO(X)      (SYMHEADER(X).isymMax)
                   2465: #   define GCC_CHECK_HDR(X)    (PSYMTAB(X) != 0)
1.1.1.2   root     2466: #else
1.1.1.3   root     2467: #   define GCC_SYMBOLS(X)      (HEADER(ldptr).f_nsyms)
                   2468: #   define GCC_SYMENT          SYMENT
1.1.1.2   root     2469: #   define GCC_OK_SYMBOL(X) \
                   2470:      (((X).n_sclass == C_EXT) && \
                   2471:         (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
                   2472:          ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
1.1.1.3   root     2473: #   define GCC_SYMINC(X)       ((X).n_numaux+1)
                   2474: #   define GCC_SYMZERO(X)      0
                   2475: #   define GCC_CHECK_HDR(X)    (1)
1.1.1.2   root     2476: #endif
                   2477: 
                   2478: extern char *ldgetname ();
                   2479: 
                   2480: /* COFF version to scan the name list of the loaded program for
                   2481:    the symbols g++ uses for static constructors and destructors.
                   2482: 
                   2483:    The constructor table begins at __CTOR_LIST__ and contains a count
                   2484:    of the number of pointers (or -1 if the constructors are built in a
                   2485:    separate section by the linker), followed by the pointers to the
                   2486:    constructor functions, terminated with a null pointer.  The
                   2487:    destructor table has the same format, and begins at __DTOR_LIST__.  */
                   2488: 
                   2489: static void
                   2490: scan_prog_file (prog_name, which_pass)
                   2491:      char *prog_name;
                   2492:      enum pass which_pass;
                   2493: {
1.1.1.3   root     2494:   LDFILE *ldptr = NULL;
1.1.1.2   root     2495:   int sym_index, sym_count;
                   2496: 
1.1.1.8   root     2497:   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
1.1.1.2   root     2498:     return;
                   2499: 
                   2500:   if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
                   2501:     fatal ("%s: can't open as COFF file", prog_name);
                   2502:       
1.1.1.4   root     2503:   if (!MY_ISCOFF (HEADER (ldptr).f_magic))
1.1.1.2   root     2504:     fatal ("%s: not a COFF file", prog_name);
                   2505: 
1.1.1.3   root     2506:   if (GCC_CHECK_HDR (ldptr))
1.1.1.2   root     2507:     {
1.1.1.3   root     2508:       sym_count = GCC_SYMBOLS (ldptr);
                   2509:       sym_index = GCC_SYMZERO (ldptr);
                   2510:       while (sym_index < sym_count)
                   2511:        {
                   2512:          GCC_SYMENT symbol;
1.1.1.2   root     2513: 
1.1.1.3   root     2514:          if (ldtbread (ldptr, sym_index, &symbol) <= 0)
                   2515:            break;
                   2516:          sym_index += GCC_SYMINC (symbol);
1.1.1.2   root     2517: 
1.1.1.3   root     2518:          if (GCC_OK_SYMBOL (symbol))
                   2519:            {
                   2520:              char *name;
1.1.1.2   root     2521: 
1.1.1.3   root     2522:              if ((name = ldgetname (ldptr, &symbol)) == NULL)
                   2523:                continue;               /* should never happen */
1.1.1.2   root     2524: 
1.1.1.8   root     2525: #ifdef XCOFF_DEBUGGING_INFO
                   2526:              /* All AIX function names have a duplicate entry beginning
                   2527:                 with a dot. */
                   2528:              if (*name == '.')
                   2529:                ++name;
1.1.1.2   root     2530: #endif
                   2531: 
1.1.1.3   root     2532:              switch (is_ctor_dtor (name))
                   2533:                {
                   2534:                case 1:
                   2535:                  add_to_list (&constructors, name);
1.1.1.8   root     2536:                  if (which_pass == PASS_OBJ)
                   2537:                    add_to_list (&exports, name);
1.1.1.3   root     2538:                  break;
1.1.1.2   root     2539: 
1.1.1.3   root     2540:                case 2:
                   2541:                  add_to_list (&destructors, name);
1.1.1.8   root     2542:                  if (which_pass == PASS_OBJ)
                   2543:                    add_to_list (&exports, name);
1.1.1.3   root     2544:                  break;
1.1.1.2   root     2545: 
1.1.1.3   root     2546:                default:                /* not a constructor or destructor */
                   2547:                  continue;
                   2548:                }
1.1.1.2   root     2549: 
                   2550: #if !defined(EXTENDED_COFF)
1.1.1.3   root     2551:              if (debug)
                   2552:                fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
                   2553:                         symbol.n_scnum, symbol.n_sclass,
                   2554:                         (symbol.n_type ? "0" : ""), symbol.n_type,
                   2555:                         name);
1.1.1.2   root     2556: #else
1.1.1.3   root     2557:              if (debug)
                   2558:                fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
                   2559:                         symbol.iss, symbol.value, symbol.index, name);
1.1.1.2   root     2560: #endif
1.1.1.3   root     2561:            }
1.1.1.2   root     2562:        }
                   2563:     }
                   2564: 
                   2565:   (void) ldclose(ldptr);
                   2566: }
                   2567: 
1.1.1.8   root     2568: #ifdef XCOFF_SCAN_LIBS
                   2569: /* Scan imported AIX libraries for GCC static ctors and dtors.
                   2570:    FIXME: it is possible to link an executable without the actual import
                   2571:          library by using an "import file" - a text file listing symbols
                   2572:          exported by a library.  To support this, we would have to scan
                   2573:          import files as well as actual shared binaries to find GCC ctors.
                   2574:    TODO: use memory mapping instead of 'ld' routines, files are already
                   2575:         memory mapped, but we could eliminate the extra in-memory copies.
                   2576:         Is it worth the effort?  */
                   2577: 
                   2578: static void
                   2579: scan_libraries (prog_name)
                   2580:      char *prog_name;
                   2581: {
                   2582:   LDFILE *ldptr;
                   2583:   SCNHDR ldsh;
                   2584:   static struct path_prefix libpath; /* we should only do this once */
                   2585: 
                   2586:   if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
                   2587:     fatal ("%s: can't open as COFF file", prog_name);
                   2588:       
                   2589:   if (!MY_ISCOFF (HEADER (ldptr).f_magic))
                   2590:     fatal ("%s: not a COFF file", prog_name);
                   2591: 
                   2592:   /* find and read loader section */
                   2593:   if (ldnshread (ldptr, _LOADER, &ldsh))
                   2594:     {
                   2595:       LDHDR ldh;
                   2596:       char *impbuf;
1.1.1.9 ! root     2597:       int entry;
        !          2598: 
1.1.1.8   root     2599:       FSEEK (ldptr, ldsh.s_scnptr, BEGINNING);
1.1.1.9 ! root     2600:       FREAD (&ldh, sizeof (ldh), 1, ldptr);
1.1.1.8   root     2601:       /* read import library list */
                   2602:       impbuf = alloca (ldh.l_istlen);
                   2603:       FSEEK (ldptr, ldh.l_impoff + ldsh.s_scnptr, BEGINNING);
                   2604:       FREAD (impbuf, ldh.l_istlen, 1, ldptr);
1.1.1.9 ! root     2605: 
1.1.1.8   root     2606:       if (debug)
                   2607:        fprintf (stderr, "LIBPATH=%s\n", impbuf);
                   2608:       prefix_from_string (impbuf, &libpath);
1.1.1.9 ! root     2609: 
        !          2610:       /* skip LIBPATH and empty base and member fields */
        !          2611:       impbuf += strlen (impbuf) + 3;
        !          2612:       for (entry = 1; entry < ldh.l_nimpid; ++entry)
1.1.1.8   root     2613:        {
1.1.1.9 ! root     2614:          char *impath = impbuf;
        !          2615:          char *implib = impath + strlen (impath) + 1;
1.1.1.8   root     2616:          char *impmem = implib + strlen (implib) + 1;
1.1.1.9 ! root     2617:          char *soname = NULL;
        !          2618:          char *trial;
        !          2619:          int pathlen;
1.1.1.8   root     2620:          LDFILE *libptr = NULL;
                   2621:          struct prefix_list *pl;
                   2622:          ARCHDR ah;
1.1.1.9 ! root     2623: 
        !          2624:          impbuf = impmem + strlen (impmem) + 1;
        !          2625:          if (debug)
        !          2626:            fprintf (stderr, "PATH+BASE=%s%s\n", impath, implib);
        !          2627:          /* Skip AIX kernel exports */
        !          2628:          if (*impath == '/' && *(impath+1) == '\0'
        !          2629:              && strcmp (implib, "unix") == 0)
1.1.1.8   root     2630:            continue;
1.1.1.9 ! root     2631:          pathlen = strlen (impath);
        !          2632:           trial = alloca (MAX (pathlen + 1, libpath.max_len)
        !          2633:                          + strlen (implib) + 1);
        !          2634:          if (*impath)
1.1.1.8   root     2635:            {
1.1.1.9 ! root     2636:              strcpy (trial, impath);
        !          2637:              if (impath[pathlen - 1] != '/')
        !          2638:                trial[pathlen++] = '/';
        !          2639:              strcpy (trial + pathlen, implib);
        !          2640:              if (access (trial, R_OK) == 0)
        !          2641:                soname = trial;
1.1.1.8   root     2642:            }
                   2643:          else
1.1.1.9 ! root     2644:            for (pl = libpath.plist; pl; pl = pl->next)
        !          2645:              {
        !          2646:                strcpy (trial, pl->prefix);
        !          2647:                strcat (trial, implib);
        !          2648:                if (access (trial, R_OK) == 0)
        !          2649:                  {
        !          2650:                    soname = trial;
        !          2651:                    break;
        !          2652:                  }
        !          2653:              }
        !          2654: 
        !          2655:          if (! soname)
        !          2656:            fatal ("%s: library not found", implib);
1.1.1.8   root     2657:          if (debug)
1.1.1.9 ! root     2658:            if (*impmem)
        !          2659:              fprintf (stderr, "%s (%s)\n", soname, impmem);
        !          2660:            else
        !          2661:              fprintf (stderr, "%s\n", soname);
        !          2662: 
1.1.1.8   root     2663:          do
                   2664:            {
                   2665:              /* scan imported shared objects for GCC GLOBAL ctors */
                   2666:              short type;
                   2667:              if ((libptr = ldopen (soname, libptr)) == NULL)
                   2668:                fatal ("%s: can't open import library", soname);
                   2669:              if (TYPE (libptr) == ARTYPE)
                   2670:                {
                   2671:                  LDFILE *memptr;
1.1.1.9 ! root     2672:                  if (! *impmem)
1.1.1.8   root     2673:                    fatal ("%s: no archive member specified", soname);
                   2674:                  ldahread (libptr, &ah);
                   2675:                  if (strcmp (ah.ar_name, impmem))
                   2676:                    continue;
                   2677:                }
                   2678:              type = HEADER (libptr).f_magic;
                   2679:              if (HEADER (libptr).f_flags & F_SHROBJ)
                   2680:                {
                   2681:                  SCNHDR soldsh;
                   2682:                  LDHDR soldh;
                   2683:                  long symcnt, i;
                   2684:                  char *ldstrings;
                   2685:                  LDSYM *lsyms;
                   2686:                  if (!ldnshread (libptr, _LOADER, &soldsh))
                   2687:                    fatal ("%s: not an import library", soname);
                   2688:                  FSEEK (libptr, soldsh.s_scnptr, BEGINNING);
1.1.1.9 ! root     2689:                  if (FREAD (&soldh, sizeof (soldh), 1, libptr) != 1)
1.1.1.8   root     2690:                    fatal ("%s: can't read loader section", soname);
                   2691:                  /*fprintf (stderr, "\tscanning %s\n", soname);*/
                   2692:                  symcnt = soldh.l_nsyms;
1.1.1.9 ! root     2693:                  lsyms = (LDSYM*) alloca (symcnt * sizeof (*lsyms));
        !          2694:                  symcnt = FREAD (lsyms, sizeof (*lsyms), symcnt, libptr);
1.1.1.8   root     2695:                  ldstrings = alloca (soldh.l_stlen);
                   2696:                  FSEEK (libptr, soldsh.s_scnptr+soldh.l_stoff, BEGINNING);
                   2697:                  FREAD (ldstrings, soldh.l_stlen, 1, libptr);
                   2698:                  for (i = 0; i < symcnt; ++i)
                   2699:                    {
                   2700:                      LDSYM *l = lsyms + i;
                   2701:                      if (LDR_EXPORT (*l))
                   2702:                        {
                   2703:                          char *expname = 0;
                   2704:                          if (l->l_zeroes)
                   2705:                            expname = l->l_name;
                   2706:                          else if (l->l_offset < soldh.l_stlen)
                   2707:                            expname = ldstrings + l->l_offset;
                   2708:                          switch (is_ctor_dtor (expname))
                   2709:                            {
                   2710:                            case 3:
                   2711:                              if (debug)
                   2712:                                fprintf (stderr, "\t%s\n", expname);
                   2713:                              add_to_list (&constructors, expname);
                   2714:                              break;
                   2715: 
                   2716:                            case 4:
                   2717:                              add_to_list (&destructors, expname);
                   2718:                              break;
                   2719: 
                   2720:                            default: /* not a constructor or destructor */
                   2721:                              continue;
                   2722:                            }
                   2723:                        }
                   2724:                    }
                   2725:                }
                   2726:              else
                   2727:                fprintf (stderr, "%s: type = %04X flags = %04X\n", 
                   2728:                         ah.ar_name, type, HEADER (libptr).f_flags);
                   2729:            }
                   2730:          while (ldclose (libptr) == FAILURE);
                   2731:          /* printf (stderr, "closed %s\n", soname); */
                   2732:        }
                   2733:     }
                   2734: }
                   2735: #endif /* XCOFF_SCAN_LIBS */
                   2736: 
1.1.1.2   root     2737: #endif /* OBJECT_FORMAT_COFF */
1.1       root     2738: 
                   2739: 
                   2740: /*
                   2741:  * OSF/rose specific stuff.
                   2742:  */
                   2743: 
                   2744: #ifdef OBJECT_FORMAT_ROSE
                   2745: 
                   2746: /* Union of the various load commands */
                   2747: 
                   2748: typedef union load_union
                   2749: {
                   2750:   ldc_header_t                 hdr;    /* common header */
                   2751:   load_cmd_map_command_t       map;    /* map indexing other load cmds */
1.1.1.2   root     2752:   interpreter_command_t                iprtr;  /* interpreter pathname */
1.1       root     2753:   strings_command_t            str;    /* load commands strings section */
                   2754:   region_command_t             region; /* region load command */
                   2755:   reloc_command_t              reloc;  /* relocation section */
                   2756:   package_command_t            pkg;    /* package load command */
                   2757:   symbols_command_t            sym;    /* symbol sections */
                   2758:   entry_command_t              ent;    /* program start section */
                   2759:   gen_info_command_t           info;   /* object information */
                   2760:   func_table_command_t         func;   /* function constructors/destructors */
                   2761: } load_union_t;
                   2762: 
                   2763: /* Structure to point to load command and data section in memory.  */
                   2764: 
                   2765: typedef struct load_all
                   2766: {
                   2767:   load_union_t *load;                  /* load command */
                   2768:   char *section;                       /* pointer to section */
                   2769: } load_all_t;
                   2770: 
                   2771: /* Structure to contain information about a file mapped into memory.  */
                   2772: 
                   2773: struct file_info
                   2774: {
                   2775:   char *start;                         /* start of map */
                   2776:   char *name;                          /* filename */
                   2777:   long size;                           /* size of the file */
                   2778:   long  rounded_size;                  /* size rounded to page boundary */
                   2779:   int  fd;                             /* file descriptor */
                   2780:   int  rw;                             /* != 0 if opened read/write */
                   2781:   int  use_mmap;                       /* != 0 if mmap'ed */
                   2782: };
                   2783: 
                   2784: extern int decode_mach_o_hdr ();
                   2785: extern int encode_mach_o_hdr ();
                   2786: 
1.1.1.6   root     2787: static void add_func_table     PROTO((mo_header_t *, load_all_t *,
                   2788:                                       symbol_info_t *, int));
                   2789: static void print_header       PROTO((mo_header_t *));
                   2790: static void print_load_command PROTO((load_union_t*, size_t, int));
                   2791: static void bad_header         PROTO((int));
                   2792: static struct file_info        *read_file  PROTO((char *, int, int));
                   2793: static void end_file           PROTO((struct file_info *));
1.1       root     2794: 
                   2795: /* OSF/rose specific version to scan the name list of the loaded
                   2796:    program for the symbols g++ uses for static constructors and
                   2797:    destructors.
                   2798: 
                   2799:    The constructor table begins at __CTOR_LIST__ and contains a count
                   2800:    of the number of pointers (or -1 if the constructors are built in a
                   2801:    separate section by the linker), followed by the pointers to the
                   2802:    constructor functions, terminated with a null pointer.  The
                   2803:    destructor table has the same format, and begins at __DTOR_LIST__.  */
                   2804: 
                   2805: static void
                   2806: scan_prog_file (prog_name, which_pass)
                   2807:      char *prog_name;
                   2808:      enum pass which_pass;
                   2809: {
                   2810:   char *obj;
                   2811:   mo_header_t hdr;
                   2812:   load_all_t *load_array;
                   2813:   load_all_t *load_end;
                   2814:   load_all_t *load_cmd;
                   2815:   int symbol_load_cmds;
                   2816:   off_t offset;
                   2817:   int i;
                   2818:   int num_syms;
                   2819:   int status;
                   2820:   char *str_sect;
                   2821:   struct file_info *obj_file;
                   2822:   int prog_fd;
                   2823:   mo_lcid_t cmd_strings          = -1;
                   2824:   symbol_info_t *main_sym = 0;
                   2825:   int rw                 = (which_pass != PASS_FIRST);
                   2826: 
                   2827:   prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
                   2828:   if (prog_fd < 0)
1.1.1.3   root     2829:     fatal_perror ("can't read %s", prog_name);
1.1       root     2830: 
                   2831:   obj_file = read_file (prog_name, prog_fd, rw);
                   2832:   obj = obj_file->start;
                   2833: 
                   2834:   status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
                   2835:   if (status != MO_HDR_CONV_SUCCESS)
                   2836:     bad_header (status);
                   2837: 
                   2838: 
                   2839:   /* Do some basic sanity checks.  Note we explicitly use the big endian magic number,
                   2840:      since the hardware will automatically swap bytes for us on loading little endian
                   2841:      integers.  */
                   2842: 
                   2843: #ifndef CROSS_COMPILE
                   2844:   if (hdr.moh_magic != MOH_MAGIC_MSB
                   2845:       || hdr.moh_header_version != MOH_HEADER_VERSION
                   2846:       || hdr.moh_byte_order != OUR_BYTE_ORDER
                   2847:       || hdr.moh_data_rep_id != OUR_DATA_REP_ID
                   2848:       || hdr.moh_cpu_type != OUR_CPU_TYPE
                   2849:       || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
                   2850:       || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
                   2851:     {
1.1.1.3   root     2852:       fatal ("incompatibilities between object file & expected values");
1.1       root     2853:     }
                   2854: #endif
                   2855: 
                   2856:   if (debug)
                   2857:     print_header (&hdr);
                   2858: 
                   2859:   offset = hdr.moh_first_cmd_off;
                   2860:   load_end = load_array
                   2861:     = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
                   2862: 
                   2863:   /* Build array of load commands, calculating the offsets */
                   2864:   for (i = 0; i < hdr.moh_n_load_cmds; i++)
                   2865:     {
                   2866:       load_union_t *load_hdr;          /* load command header */
                   2867: 
                   2868:       load_cmd = load_end++;
                   2869:       load_hdr = (load_union_t *) (obj + offset);
                   2870: 
1.1.1.4   root     2871:       /* If modifying the program file, copy the header.  */
1.1       root     2872:       if (rw)
                   2873:        {
                   2874:          load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
1.1.1.7   root     2875:          bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
1.1       root     2876:          load_hdr = ptr;
                   2877: 
                   2878:          /* null out old command map, because we will rewrite at the end.  */
                   2879:          if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
                   2880:            {
                   2881:              cmd_strings = ptr->map.lcm_ld_cmd_strings;
                   2882:              ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
                   2883:            }
                   2884:        }
                   2885: 
                   2886:       load_cmd->load = load_hdr;
                   2887:       if (load_hdr->hdr.ldci_section_off > 0)
                   2888:        load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
                   2889: 
                   2890:       if (debug)
                   2891:        print_load_command (load_hdr, offset, i);
                   2892: 
                   2893:       offset += load_hdr->hdr.ldci_cmd_size;
                   2894:     }
                   2895: 
                   2896:   /* If the last command is the load command map and is not undefined,
                   2897:      decrement the count of load commands.  */
                   2898:   if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
                   2899:     {
                   2900:       load_end--;
                   2901:       hdr.moh_n_load_cmds--;
                   2902:     }
                   2903: 
                   2904:   /* Go through and process each symbol table section.  */
                   2905:   symbol_load_cmds = 0;
                   2906:   for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
                   2907:     {
                   2908:       load_union_t *load_hdr = load_cmd->load;
                   2909: 
                   2910:       if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
                   2911:        {
                   2912:          symbol_load_cmds++;
                   2913: 
                   2914:          if (debug)
                   2915:            {
1.1.1.2   root     2916:              char *kind = "unknown";
1.1       root     2917: 
                   2918:              switch (load_hdr->sym.symc_kind)
                   2919:                {
                   2920:                case SYMC_IMPORTS:         kind = "imports"; break;
                   2921:                case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
                   2922:                case SYMC_STABS:           kind = "stabs";   break;
                   2923:                }
                   2924: 
                   2925:              fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
                   2926:                       symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
                   2927:            }
                   2928: 
                   2929:          if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
                   2930:            continue;
                   2931: 
                   2932:          str_sect = load_array[load_hdr->sym.symc_strings_section].section;
                   2933:          if (str_sect == (char *)0)
                   2934:            fatal ("string section missing");
                   2935: 
                   2936:          if (load_cmd->section == (char *)0)
                   2937:            fatal ("section pointer missing");
                   2938: 
                   2939:          num_syms = load_hdr->sym.symc_nentries;
                   2940:          for (i = 0; i < num_syms; i++)
                   2941:            {
                   2942:              symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
                   2943:              char *name = sym->si_name.symbol_name + str_sect;
                   2944: 
                   2945:              if (name[0] != '_')
                   2946:                continue;
                   2947: 
                   2948:              if (rw)
                   2949:                {
1.1.1.6   root     2950:                  char *n = name + strlen (name) - strlen (NAME__MAIN);
                   2951: 
                   2952:                  if ((n - name) < 0 || strcmp (n, NAME__MAIN))
1.1       root     2953:                    continue;
1.1.1.6   root     2954:                  while (n != name)
                   2955:                    if (*--n != '_')
                   2956:                      continue;
1.1       root     2957: 
                   2958:                  main_sym = sym;
                   2959:                }
1.1.1.2   root     2960:              else
1.1       root     2961:                {
1.1.1.2   root     2962:                  switch (is_ctor_dtor (name))
                   2963:                    {
                   2964:                    case 1:
                   2965:                      add_to_list (&constructors, name);
                   2966:                      break;
                   2967: 
                   2968:                    case 2:
                   2969:                      add_to_list (&destructors, name);
                   2970:                      break;
                   2971: 
                   2972:                    default:    /* not a constructor or destructor */
                   2973:                      continue;
                   2974:                    }
1.1       root     2975:                }
                   2976: 
                   2977:              if (debug)
                   2978:                fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
                   2979:                         sym->si_type, sym->si_sc_type, sym->si_flags, name);
                   2980:            }
                   2981:        }
                   2982:     }
                   2983: 
                   2984:   if (symbol_load_cmds == 0)
1.1.1.3   root     2985:     fatal ("no symbol table found");
1.1       root     2986: 
                   2987:   /* Update the program file now, rewrite header and load commands.  At present,
                   2988:      we assume that there is enough space after the last load command to insert
                   2989:      one more.  Since the first section written out is page aligned, and the
                   2990:      number of load commands is small, this is ok for the present.  */
                   2991: 
                   2992:   if (rw)
                   2993:     {
                   2994:       load_union_t *load_map;
                   2995:       size_t size;
                   2996: 
                   2997:       if (cmd_strings == -1)
1.1.1.3   root     2998:        fatal ("no cmd_strings found");
                   2999: 
                   3000:       /* Add __main to initializer list.
                   3001:         If we are building a program instead of a shared library, don't
                   3002:         do anything, since in the current version, you cannot do mallocs
                   3003:         and such in the constructors.  */
1.1       root     3004: 
1.1.1.3   root     3005:       if (main_sym != (symbol_info_t *)0
                   3006:          && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
1.1       root     3007:        add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
                   3008: 
                   3009:       if (debug)
                   3010:        fprintf (stderr, "\nUpdating header and load commands.\n\n");
                   3011: 
                   3012:       hdr.moh_n_load_cmds++;
                   3013:       size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
                   3014: 
                   3015:       /* Create new load command map.  */
                   3016:       if (debug)
                   3017:        fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
                   3018:                 (int)hdr.moh_n_load_cmds, (long)size);
                   3019: 
                   3020:       load_map = (load_union_t *) xcalloc (1, size);
                   3021:       load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
                   3022:       load_map->map.ldc_header.ldci_cmd_size = size;
                   3023:       load_map->map.lcm_ld_cmd_strings = cmd_strings;
                   3024:       load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
                   3025:       load_array[hdr.moh_n_load_cmds-1].load = load_map;
                   3026: 
                   3027:       offset = hdr.moh_first_cmd_off;
                   3028:       for (i = 0; i < hdr.moh_n_load_cmds; i++)
                   3029:        {
                   3030:          load_map->map.lcm_map[i] = offset;
                   3031:          if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
                   3032:            hdr.moh_load_map_cmd_off = offset;
                   3033: 
                   3034:          offset += load_array[i].load->hdr.ldci_cmd_size;
                   3035:        }
                   3036: 
                   3037:       hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
                   3038: 
                   3039:       if (debug)
                   3040:        print_header (&hdr);
                   3041: 
                   3042:       /* Write header */
                   3043:       status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
                   3044:       if (status != MO_HDR_CONV_SUCCESS)
                   3045:        bad_header (status);
                   3046: 
                   3047:       if (debug)
                   3048:        fprintf (stderr, "writing load commands.\n\n");
                   3049: 
                   3050:       /* Write load commands */
                   3051:       offset = hdr.moh_first_cmd_off;
                   3052:       for (i = 0; i < hdr.moh_n_load_cmds; i++)
                   3053:        {
                   3054:          load_union_t *load_hdr = load_array[i].load;
                   3055:          size_t size = load_hdr->hdr.ldci_cmd_size;
                   3056: 
                   3057:          if (debug)
                   3058:            print_load_command (load_hdr, offset, i);
                   3059: 
1.1.1.7   root     3060:          bcopy ((char *)load_hdr, (char *)(obj + offset), size);
1.1       root     3061:          offset += size;
                   3062:        }
                   3063:     }
                   3064: 
                   3065:   end_file (obj_file);
                   3066: 
                   3067:   if (close (prog_fd))
1.1.1.3   root     3068:     fatal_perror ("closing %s", prog_name);
1.1       root     3069: 
                   3070:   if (debug)
                   3071:     fprintf (stderr, "\n");
                   3072: }
                   3073: 
                   3074: 
                   3075: /* Add a function table to the load commands to call a function
1.1.1.2   root     3076:    on initiation or termination of the process.  */
1.1       root     3077: 
                   3078: static void
                   3079: add_func_table (hdr_p, load_array, sym, type)
                   3080:      mo_header_t *hdr_p;               /* pointer to global header */
                   3081:      load_all_t *load_array;           /* array of ptrs to load cmds */
                   3082:      symbol_info_t *sym;               /* pointer to symbol entry */
                   3083:      int type;                         /* fntc_type value */
                   3084: {
                   3085:   /* Add a new load command.  */
                   3086:   int num_cmds = ++hdr_p->moh_n_load_cmds;
                   3087:   int load_index = num_cmds - 1;
                   3088:   size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
                   3089:   load_union_t *ptr = xcalloc (1, size);
                   3090:   load_all_t *load_cmd;
                   3091:   int i;
                   3092: 
                   3093:   /* Set the unresolved address bit in the header to force the loader to be
                   3094:      used, since kernel exec does not call the initialization functions.  */
                   3095:   hdr_p->moh_flags |= MOH_UNRESOLVED_F;
                   3096: 
                   3097:   load_cmd = &load_array[load_index];
                   3098:   load_cmd->load = ptr;
                   3099:   load_cmd->section = (char *)0;
                   3100: 
                   3101:   /* Fill in func table load command.  */
                   3102:   ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
                   3103:   ptr->func.ldc_header.ldci_cmd_size = size;
                   3104:   ptr->func.ldc_header.ldci_section_off = 0;
                   3105:   ptr->func.ldc_header.ldci_section_len = 0;
                   3106:   ptr->func.fntc_type = type;
                   3107:   ptr->func.fntc_nentries = 1;
                   3108: 
                   3109:   /* copy address, turn it from abs. address to (region,offset) if necessary.  */
                   3110:   /* Is the symbol already expressed as (region, offset)?  */
                   3111:   if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
                   3112:     {
                   3113:       ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
                   3114:       ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
                   3115:     }
                   3116: 
                   3117:   /* If not, figure out which region it's in.  */
                   3118:   else
                   3119:     {
                   3120:       mo_vm_addr_t addr = sym->si_value.abs_val;
                   3121:       int found = 0;
                   3122: 
                   3123:       for (i = 0; i < load_index; i++)
                   3124:        {
                   3125:          if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
                   3126:            {
                   3127:              region_command_t *region_ptr = &load_array[i].load->region;
                   3128: 
                   3129:              if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
                   3130:                  && addr >= region_ptr->regc_addr.vm_addr
                   3131:                  && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
                   3132:                {
                   3133:                  ptr->func.fntc_entry_loc[0].adr_lcid = i;
                   3134:                  ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
                   3135:                  found++;
                   3136:                  break;
                   3137:                }
                   3138:            }
                   3139:        }
                   3140: 
                   3141:       if (!found)
                   3142:        fatal ("could not convert 0x%l.8x into a region", addr);
                   3143:     }
                   3144: 
                   3145:   if (debug)
                   3146:     fprintf (stderr,
                   3147:             "%s function, region %d, offset = %ld (0x%.8lx)\n",
                   3148:             (type == FNTC_INITIALIZATION) ? "init" : "term",
                   3149:             (int)ptr->func.fntc_entry_loc[i].adr_lcid,
                   3150:             (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
                   3151:             (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
                   3152: 
                   3153: }
                   3154: 
                   3155: 
                   3156: /* Print the global header for an OSF/rose object.  */
                   3157: 
                   3158: static void
                   3159: print_header (hdr_ptr)
                   3160:      mo_header_t *hdr_ptr;
                   3161: {
                   3162:   fprintf (stderr, "\nglobal header:\n");
                   3163:   fprintf (stderr, "\tmoh_magic            = 0x%.8lx\n", hdr_ptr->moh_magic);
                   3164:   fprintf (stderr, "\tmoh_major_version    = %d\n", (int)hdr_ptr->moh_major_version);
                   3165:   fprintf (stderr, "\tmoh_minor_version    = %d\n", (int)hdr_ptr->moh_minor_version);
                   3166:   fprintf (stderr, "\tmoh_header_version   = %d\n", (int)hdr_ptr->moh_header_version);
                   3167:   fprintf (stderr, "\tmoh_max_page_size    = %d\n", (int)hdr_ptr->moh_max_page_size);
                   3168:   fprintf (stderr, "\tmoh_byte_order       = %d\n", (int)hdr_ptr->moh_byte_order);
                   3169:   fprintf (stderr, "\tmoh_data_rep_id      = %d\n", (int)hdr_ptr->moh_data_rep_id);
                   3170:   fprintf (stderr, "\tmoh_cpu_type         = %d\n", (int)hdr_ptr->moh_cpu_type);
                   3171:   fprintf (stderr, "\tmoh_cpu_subtype      = %d\n", (int)hdr_ptr->moh_cpu_subtype);
                   3172:   fprintf (stderr, "\tmoh_vendor_type      = %d\n", (int)hdr_ptr->moh_vendor_type);
                   3173:   fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
                   3174:   fprintf (stderr, "\tmoh_first_cmd_off    = %d\n", (int)hdr_ptr->moh_first_cmd_off);
                   3175:   fprintf (stderr, "\tmoh_sizeofcmds       = %d\n", (int)hdr_ptr->moh_sizeofcmds);
                   3176:   fprintf (stderr, "\tmon_n_load_cmds      = %d\n", (int)hdr_ptr->moh_n_load_cmds);
                   3177:   fprintf (stderr, "\tmoh_flags            = 0x%.8lx", (long)hdr_ptr->moh_flags);
                   3178: 
                   3179:   if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
                   3180:     fprintf (stderr, ", relocatable");
                   3181: 
                   3182:   if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
                   3183:     fprintf (stderr, ", linkable");
                   3184: 
                   3185:   if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
                   3186:     fprintf (stderr, ", execable");
                   3187: 
                   3188:   if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
                   3189:     fprintf (stderr, ", executable");
                   3190: 
                   3191:   if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
                   3192:     fprintf (stderr, ", unresolved");
                   3193: 
                   3194:   fprintf (stderr, "\n\n");
                   3195:   return;
                   3196: }
                   3197: 
                   3198: 
                   3199: /* Print a short summary of a load command.  */
                   3200: 
                   3201: static void
                   3202: print_load_command (load_hdr, offset, number)
                   3203:      load_union_t *load_hdr;
                   3204:      size_t offset;
                   3205:      int number;
                   3206: {
                   3207:   mo_long_t type = load_hdr->hdr.ldci_cmd_type;
                   3208:   char *type_str = (char *)0;
                   3209: 
                   3210:   switch (type)
                   3211:     {
                   3212:     case LDC_UNDEFINED:   type_str = "UNDEFINED";      break;
                   3213:     case LDC_CMD_MAP:    type_str = "CMD_MAP";         break;
                   3214:     case LDC_INTERPRETER: type_str = "INTERPRETER";    break;
                   3215:     case LDC_STRINGS:    type_str = "STRINGS";         break;
                   3216:     case LDC_REGION:     type_str = "REGION";          break;
                   3217:     case LDC_RELOC:      type_str = "RELOC";           break;
                   3218:     case LDC_PACKAGE:    type_str = "PACKAGE";         break;
                   3219:     case LDC_SYMBOLS:    type_str = "SYMBOLS";         break;
                   3220:     case LDC_ENTRY:      type_str = "ENTRY";           break;
                   3221:     case LDC_FUNC_TABLE:  type_str = "FUNC_TABLE";     break;
                   3222:     case LDC_GEN_INFO:   type_str = "GEN_INFO";        break;
                   3223:     }
                   3224: 
                   3225:   fprintf (stderr,
                   3226:           "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
                   3227:           number,
                   3228:           (long) load_hdr->hdr.ldci_cmd_size,
                   3229:           (long) offset,
                   3230:           (long) load_hdr->hdr.ldci_section_off,
                   3231:           (long) load_hdr->hdr.ldci_section_len);
                   3232: 
                   3233:   if (type_str == (char *)0)
                   3234:     fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
                   3235: 
                   3236:   else if (type != LDC_REGION)
                   3237:     fprintf (stderr, ", ty: %s\n", type_str);
                   3238: 
                   3239:   else
                   3240:     {
                   3241:       char *region = "";
                   3242:       switch (load_hdr->region.regc_usage_type)
                   3243:        {
                   3244:        case REG_TEXT_T:        region = ", .text";     break;
                   3245:        case REG_DATA_T:        region = ", .data";     break;
                   3246:        case REG_BSS_T:         region = ", .bss";      break;
                   3247:        case REG_GLUE_T:        region = ", .glue";     break;
                   3248: #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
                   3249:        case REG_RDATA_T:       region = ", .rdata";    break;
                   3250:        case REG_SDATA_T:       region = ", .sdata";    break;
                   3251:        case REG_SBSS_T:        region = ", .sbss";     break;
                   3252: #endif
                   3253:        }
                   3254: 
                   3255:       fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
                   3256:               type_str,
                   3257:               (long) load_hdr->region.regc_vm_addr,
                   3258:               (long) load_hdr->region.regc_vm_size,
                   3259:               region);
                   3260:     }
                   3261: 
                   3262:   return;
                   3263: }
                   3264: 
                   3265: 
                   3266: /* Fatal error when {en,de}code_mach_o_header fails.  */
                   3267: 
                   3268: static void
                   3269: bad_header (status)
                   3270:      int status;
                   3271: {
                   3272:   char *msg = (char *)0;
                   3273: 
                   3274:   switch (status)
                   3275:     {
                   3276:     case MO_ERROR_BAD_MAGIC:           msg = "bad magic number";               break;
                   3277:     case MO_ERROR_BAD_HDR_VERS:                msg = "bad header version";             break;
                   3278:     case MO_ERROR_BAD_RAW_HDR_VERS:    msg = "bad raw header version";         break;
                   3279:     case MO_ERROR_BUF2SML:             msg = "raw header buffer too small";    break;
                   3280:     case MO_ERROR_OLD_RAW_HDR_FILE:    msg = "old raw header file";            break;
                   3281:     case MO_ERROR_UNSUPPORTED_VERS:    msg = "unsupported version";            break;
                   3282:     }
                   3283: 
                   3284:   if (msg == (char *)0)
                   3285:     fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
                   3286:   else
                   3287:     fatal ("%s", msg);
                   3288: }
                   3289: 
                   3290: 
                   3291: /* Read a file into a memory buffer.  */
                   3292: 
                   3293: static struct file_info *
                   3294: read_file (name, fd, rw)
                   3295:      char *name;               /* filename */
                   3296:      int fd;                   /* file descriptor */
                   3297:      int rw;                   /* read/write */
                   3298: {
                   3299:   struct stat stat_pkt;
                   3300:   struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
                   3301: #ifdef USE_MMAP
                   3302:   static int page_size;
                   3303: #endif
                   3304: 
                   3305:   if (fstat (fd, &stat_pkt) < 0)
                   3306:     fatal_perror ("fstat %s", name);
                   3307: 
                   3308:   p->name        = name;
                   3309:   p->size        = stat_pkt.st_size;
                   3310:   p->rounded_size = stat_pkt.st_size;
                   3311:   p->fd                  = fd;
                   3312:   p->rw                  = rw;
                   3313: 
                   3314: #ifdef USE_MMAP
                   3315:   if (debug)
                   3316:     fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
                   3317: 
                   3318:   if (page_size == 0)
                   3319:     page_size = sysconf (_SC_PAGE_SIZE);
                   3320: 
                   3321:   p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
                   3322:   p->start = mmap ((caddr_t)0,
                   3323:                   (rw) ? p->rounded_size : p->size,
                   3324:                   (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
                   3325:                   MAP_FILE | MAP_VARIABLE | MAP_SHARED,
                   3326:                   fd,
                   3327:                   0L);
                   3328: 
                   3329:   if (p->start != (char *)0 && p->start != (char *)-1)
                   3330:     p->use_mmap = 1;
                   3331: 
                   3332:   else
                   3333: #endif /* USE_MMAP */
                   3334:     {
                   3335:       long len;
                   3336: 
                   3337:       if (debug)
                   3338:        fprintf (stderr, "read %s\n", name);
                   3339: 
                   3340:       p->use_mmap = 0;
                   3341:       p->start = xmalloc (p->size);
                   3342:       if (lseek (fd, 0L, SEEK_SET) < 0)
                   3343:        fatal_perror ("lseek to 0 on %s", name);
                   3344: 
                   3345:       len = read (fd, p->start, p->size);
                   3346:       if (len < 0)
                   3347:        fatal_perror ("read %s", name);
                   3348: 
                   3349:       if (len != p->size)
                   3350:        fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
                   3351:     }
                   3352: 
                   3353:   return p;
                   3354: }
                   3355: 
                   3356: /* Do anything necessary to write a file back from memory.  */
                   3357: 
                   3358: static void
                   3359: end_file (ptr)
                   3360:      struct file_info *ptr;    /* file information block */
                   3361: {
                   3362: #ifdef USE_MMAP
                   3363:   if (ptr->use_mmap)
                   3364:     {
                   3365:       if (ptr->rw)
                   3366:        {
                   3367:          if (debug)
                   3368:            fprintf (stderr, "msync %s\n", ptr->name);
                   3369: 
                   3370:          if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
                   3371:            fatal_perror ("msync %s", ptr->name);
                   3372:        }
                   3373: 
                   3374:       if (debug)
                   3375:        fprintf (stderr, "munmap %s\n", ptr->name);
                   3376: 
                   3377:       if (munmap (ptr->start, ptr->size))
                   3378:        fatal_perror ("munmap %s", ptr->name);
                   3379:     }
                   3380:   else
                   3381: #endif /* USE_MMAP */
                   3382:     {
                   3383:       if (ptr->rw)
                   3384:        {
                   3385:          long len;
                   3386: 
                   3387:          if (debug)
                   3388:            fprintf (stderr, "write %s\n", ptr->name);
                   3389: 
                   3390:          if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
                   3391:            fatal_perror ("lseek to 0 on %s", ptr->name);
                   3392: 
                   3393:          len = write (ptr->fd, ptr->start, ptr->size);
                   3394:          if (len < 0)
1.1.1.8   root     3395:            fatal_perror ("write %s", ptr->name);
1.1       root     3396: 
                   3397:          if (len != ptr->size)
                   3398:            fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
                   3399:        }
                   3400: 
1.1.1.8   root     3401:       free (ptr->start);
1.1       root     3402:     }
                   3403: 
1.1.1.8   root     3404:   free (ptr);
1.1       root     3405: }
                   3406: 
                   3407: #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.