Annotation of gcc/collect2.c, revision 1.1.1.8

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