LCOV - code coverage report
Current view: top level - gcc - collect2.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 52.7 % 799 421
Test Date: 2026-02-28 14:20:25 Functions: 52.0 % 25 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Collect static initialization info into data structures that can be
       2              :    traversed by C++ initialization and finalization routines.
       3              :    Copyright (C) 1992-2026 Free Software Foundation, Inc.
       4              :    Contributed by Chris Smith (csmith@convex.com).
       5              :    Heavily modified by Michael Meissner (meissner@cygnus.com),
       6              :    Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
       7              : 
       8              : This file is part of GCC.
       9              : 
      10              : GCC is free software; you can redistribute it and/or modify it under
      11              : the terms of the GNU General Public License as published by the Free
      12              : Software Foundation; either version 3, or (at your option) any later
      13              : version.
      14              : 
      15              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      16              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      18              : for more details.
      19              : 
      20              : You should have received a copy of the GNU General Public License
      21              : along with GCC; see the file COPYING3.  If not see
      22              : <http://www.gnu.org/licenses/>.  */
      23              : 
      24              : 
      25              : /* Build tables of static constructors and destructors and run ld.  */
      26              : 
      27              : #include "config.h"
      28              : #include "system.h"
      29              : #include "coretypes.h"
      30              : #include "tm.h"
      31              : #include "filenames.h"
      32              : #include "file-find.h"
      33              : #include "simple-object.h"
      34              : #include "lto-section-names.h"
      35              : 
      36              : /* TARGET_64BIT may be defined to use driver specific functionality. */
      37              : #undef TARGET_64BIT
      38              : #define TARGET_64BIT TARGET_64BIT_DEFAULT
      39              : 
      40              : #ifndef LIBRARY_PATH_ENV
      41              : #define LIBRARY_PATH_ENV "LIBRARY_PATH"
      42              : #endif
      43              : 
      44              : #define COLLECT
      45              : 
      46              : #include "collect2.h"
      47              : #include "collect2-aix.h"
      48              : #include "collect-utils.h"
      49              : #include "diagnostic.h"
      50              : #include "demangle.h"
      51              : #include "obstack.h"
      52              : #include "intl.h"
      53              : #include "version.h"
      54              : 
      55              : /* On certain systems, we have code that works by scanning the object file
      56              :    directly.  But this code uses system-specific header files and library
      57              :    functions, so turn it off in a cross-compiler.  Likewise, the names of
      58              :    the utilities are not correct for a cross-compiler; we have to hope that
      59              :    cross-versions are in the proper directories.  */
      60              : 
      61              : #ifdef CROSS_DIRECTORY_STRUCTURE
      62              : #ifndef CROSS_AIX_SUPPORT
      63              : #undef OBJECT_FORMAT_COFF
      64              : #endif
      65              : #undef MD_EXEC_PREFIX
      66              : #undef REAL_LD_FILE_NAME
      67              : #undef REAL_NM_FILE_NAME
      68              : #undef REAL_STRIP_FILE_NAME
      69              : #endif
      70              : 
      71              : /* If we cannot use a special method, use the ordinary one:
      72              :    run nm to find what symbols are present.
      73              :    In a cross-compiler, this means you need a cross nm,
      74              :    but that is not quite as unpleasant as special headers.  */
      75              : 
      76              : #if !defined (OBJECT_FORMAT_COFF)
      77              : #define OBJECT_FORMAT_NONE
      78              : #endif
      79              : 
      80              : #ifdef OBJECT_FORMAT_COFF
      81              : 
      82              : #ifndef CROSS_DIRECTORY_STRUCTURE
      83              : #include <a.out.h>
      84              : #include <ar.h>
      85              : 
      86              : #ifdef UMAX
      87              : #include <sgs.h>
      88              : #endif
      89              : 
      90              : /* Many versions of ldfcn.h define these.  */
      91              : #ifdef FREAD
      92              : #undef FREAD
      93              : #undef FWRITE
      94              : #endif
      95              : 
      96              : #include <ldfcn.h>
      97              : #endif
      98              : 
      99              : /* Some systems have an ISCOFF macro, but others do not.  In some cases
     100              :    the macro may be wrong.  MY_ISCOFF is defined in tm.h files for machines
     101              :    that either do not have an ISCOFF macro in /usr/include or for those
     102              :    where it is wrong.  */
     103              : 
     104              : #ifndef MY_ISCOFF
     105              : #define MY_ISCOFF(X) ISCOFF (X)
     106              : #endif
     107              : 
     108              : #endif /* OBJECT_FORMAT_COFF */
     109              : 
     110              : #ifdef OBJECT_FORMAT_NONE
     111              : 
     112              : /* Default flags to pass to nm.  */
     113              : #ifndef NM_FLAGS
     114              : #define NM_FLAGS "-n"
     115              : #endif
     116              : 
     117              : #endif /* OBJECT_FORMAT_NONE */
     118              : 
     119              : /* Some systems use __main in a way incompatible with its use in gcc, in these
     120              :    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
     121              :    give the same symbol without quotes for an alternative entry point.  */
     122              : #ifndef NAME__MAIN
     123              : #define NAME__MAIN "__main"
     124              : #endif
     125              : 
     126              : /* This must match tree.h.  */
     127              : #define DEFAULT_INIT_PRIORITY 65535
     128              : 
     129              : #ifndef COLLECT_SHARED_INIT_FUNC
     130              : #define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
     131              :   fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
     132              : #endif
     133              : #ifndef COLLECT_SHARED_FINI_FUNC
     134              : #define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
     135              :   fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
     136              : #endif
     137              : 
     138              : #ifdef LDD_SUFFIX
     139              : #define SCAN_LIBRARIES
     140              : #endif
     141              : 
     142              : #ifndef SHLIB_SUFFIX
     143              : #define SHLIB_SUFFIX ".so"
     144              : #endif
     145              : 
     146              : #ifdef USE_COLLECT2
     147              : int do_collecting = 1;
     148              : #else
     149              : int do_collecting = 0;
     150              : #endif
     151              : 
     152              : /* Cook up an always defined indication of whether we proceed the
     153              :    "EXPORT_LIST" way.  */
     154              : 
     155              : #ifdef COLLECT_EXPORT_LIST
     156              : #define DO_COLLECT_EXPORT_LIST 1
     157              : #else
     158              : #define DO_COLLECT_EXPORT_LIST 0
     159              : #endif
     160              : 
     161              : /* Nonzero if we should suppress the automatic demangling of identifiers
     162              :    in linker error messages.  Set from COLLECT_NO_DEMANGLE.  */
     163              : int no_demangle;
     164              : 
     165              : /* Linked lists of constructor and destructor names.  */
     166              : 
     167              : struct id
     168              : {
     169              :   struct id *next;
     170              :   int sequence;
     171              :   char name[1];
     172              : };
     173              : 
     174              : struct head
     175              : {
     176              :   struct id *first;
     177              :   struct id *last;
     178              :   int number;
     179              : };
     180              : 
     181              : static int rflag;                       /* true if -r */
     182              : static int strip_flag;                  /* true if -s */
     183              : #ifdef COLLECT_EXPORT_LIST
     184              : static int export_flag;                 /* true if -bE */
     185              : static int aix64_flag;                  /* true if -b64 */
     186              : static int aixrtl_flag;                 /* true if -brtl */
     187              : static int aixlazy_flag;                /* true if -blazy */
     188              : static int visibility_flag;             /* true if -fvisibility */
     189              : #endif
     190              : 
     191              : enum lto_mode_d {
     192              :   LTO_MODE_NONE,                        /* Not doing LTO.  */
     193              :   LTO_MODE_LTO,                         /* Normal LTO.  */
     194              :   LTO_MODE_WHOPR                        /* WHOPR.  */
     195              : };
     196              : 
     197              : /* Current LTO mode.  */
     198              : #ifdef ENABLE_LTO
     199              : static enum lto_mode_d lto_mode = LTO_MODE_WHOPR;
     200              : #else
     201              : static enum lto_mode_d lto_mode = LTO_MODE_NONE;
     202              : #endif
     203              : 
     204              : bool helpflag;                  /* true if --help */
     205              : 
     206              : static int shared_obj;                  /* true if -shared */
     207              : static int static_obj;                  /* true if -static */
     208              : 
     209              : static const char *c_file;              /* <xxx>.c for constructor/destructor list.  */
     210              : static const char *o_file;              /* <xxx>.o for constructor/destructor list.  */
     211              : #ifdef COLLECT_EXPORT_LIST
     212              : static const char *export_file;         /* <xxx>.x for AIX export list.  */
     213              : #endif
     214              : static char **lto_o_files;              /* Output files for LTO.  */
     215              : static const char *output_file;         /* Output file for ld.  */
     216              : static const char *nm_file_name;        /* pathname of nm */
     217              : #ifdef LDD_SUFFIX
     218              : static const char *ldd_file_name;       /* pathname of ldd (or equivalent) */
     219              : #endif
     220              : static const char *strip_file_name;             /* pathname of strip */
     221              : const char *c_file_name;                /* pathname of gcc */
     222              : static char *initname, *fininame;       /* names of init and fini funcs */
     223              : 
     224              : 
     225              : #ifdef TARGET_AIX_VERSION
     226              : static char *aix_shared_initname;
     227              : static char *aix_shared_fininame;       /* init/fini names as per the scheme
     228              :                                            described in config/rs6000/aix.h */
     229              : #endif
     230              : 
     231              : static struct head constructors;        /* list of constructors found */
     232              : static struct head destructors;         /* list of destructors found */
     233              : #ifdef COLLECT_EXPORT_LIST
     234              : static struct head exports;             /* list of exported symbols */
     235              : #endif
     236              : static struct head frame_tables;        /* list of frame unwind info tables */
     237              : 
     238              : bool at_file_supplied;          /* Whether to use @file arguments */
     239              : 
     240              : struct obstack temporary_obstack;
     241              : char * temporary_firstobj;
     242              : 
     243              : /* A string that must be prepended to a target OS path in order to find
     244              :    it on the host system.  */
     245              : #ifdef TARGET_SYSTEM_ROOT
     246              : static const char *target_system_root = TARGET_SYSTEM_ROOT;
     247              : #else
     248              : static const char *target_system_root = "";
     249              : #endif
     250              : 
     251              : /* Whether we may unlink the output file, which should be set as soon as we
     252              :    know we have successfully produced it.  This is typically useful to prevent
     253              :    blindly attempting to unlink a read-only output that the target linker
     254              :    would leave untouched.  */
     255              : bool may_unlink_output_file = false;
     256              : 
     257              : #ifdef COLLECT_EXPORT_LIST
     258              : /* Lists to keep libraries to be scanned for global constructors/destructors.  */
     259              : static struct head libs;                    /* list of libraries */
     260              : static struct head static_libs;             /* list of statically linked libraries */
     261              : static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
     262              : static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
     263              : static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
     264              :                                           &libpath_lib_dirs, NULL};
     265              : #endif
     266              : 
     267              : /* List of names of object files containing LTO information.
     268              :    These are a subset of the object file names appearing on the
     269              :    command line, and must be identical, in the sense of pointer
     270              :    equality, with the names passed to maybe_run_lto_and_relink().  */
     271              : 
     272              : struct lto_object
     273              : {
     274              :   const char *name;             /* Name of object file.  */
     275              :   struct lto_object *next;      /* Next in linked list.  */
     276              : };
     277              : 
     278              : struct lto_object_list
     279              : {
     280              :   struct lto_object *first;     /* First list element.  */
     281              :   struct lto_object *last;      /* Last list element.  */
     282              : };
     283              : 
     284              : static struct lto_object_list lto_objects;
     285              : 
     286              : /* Special kinds of symbols that a name may denote.  */
     287              : 
     288              : enum symkind {
     289              :   SYM_REGULAR = 0,  /* nothing special  */
     290              : 
     291              :   SYM_CTOR = 1,  /* constructor */
     292              :   SYM_DTOR = 2,  /* destructor  */
     293              :   SYM_INIT = 3,  /* shared object routine that calls all the ctors  */
     294              :   SYM_FINI = 4,  /* shared object routine that calls all the dtors  */
     295              :   SYM_DWEH = 5,  /* DWARF exception handling table  */
     296              :   SYM_AIXI = 6,
     297              :   SYM_AIXD = 7
     298              : };
     299              : 
     300              : const char tool_name[] = "collect2";
     301              : 
     302              : static symkind is_ctor_dtor (const char *);
     303              : 
     304              : static void maybe_unlink_list (char **);
     305              : static void add_to_list (struct head *, const char *);
     306              : static int extract_init_priority (const char *);
     307              : static void sort_ids (struct head *);
     308              : static void write_list (FILE *, const char *, struct id *);
     309              : #ifdef COLLECT_EXPORT_LIST
     310              : static void dump_list (FILE *, const char *, struct id *);
     311              : #endif
     312              : #if 0
     313              : static void dump_prefix_list (FILE *, const char *, struct prefix_list *);
     314              : #endif
     315              : static void write_list_with_asm (FILE *, const char *, struct id *);
     316              : static void write_c_file (FILE *, const char *);
     317              : static void write_c_file_stat (FILE *, const char *);
     318              : #ifndef LD_INIT_SWITCH
     319              : static void write_c_file_glob (FILE *, const char *);
     320              : #endif
     321              : #ifdef SCAN_LIBRARIES
     322              : static void scan_libraries (const char *);
     323              : #endif
     324              : #ifdef COLLECT_EXPORT_LIST
     325              : static int is_in_list (const char *, struct id *);
     326              : static void write_aix_file (FILE *, struct id *);
     327              : static char *resolve_lib_name (const char *);
     328              : #endif
     329              : static char *extract_string (const char **);
     330              : static void post_ld_pass (bool);
     331              : static void process_args (int *argcp, char **argv);
     332              : 
     333              : /* Enumerations describing which pass this is for scanning the
     334              :    program file ...  */
     335              : 
     336              : enum scanpass {
     337              :   PASS_FIRST,                           /* without constructors */
     338              :   PASS_OBJ,                             /* individual objects */
     339              :   PASS_LIB,                             /* looking for shared libraries */
     340              :   PASS_SECOND,                          /* with constructors linked in */
     341              :   PASS_LTOINFO                          /* looking for objects with LTO info */
     342              : };
     343              : 
     344              : /* ... and which kinds of symbols are to be considered.  */
     345              : 
     346              : enum scanfilter_masks {
     347              :   SCAN_NOTHING = 0,
     348              : 
     349              :   SCAN_CTOR = 1 << SYM_CTOR,
     350              :   SCAN_DTOR = 1 << SYM_DTOR,
     351              :   SCAN_INIT = 1 << SYM_INIT,
     352              :   SCAN_FINI = 1 << SYM_FINI,
     353              :   SCAN_DWEH = 1 << SYM_DWEH,
     354              :   SCAN_AIXI = 1 << SYM_AIXI,
     355              :   SCAN_AIXD = 1 << SYM_AIXD,
     356              :   SCAN_ALL  = ~0
     357              : };
     358              : 
     359              : /* This type is used for parameters and variables which hold
     360              :    combinations of the flags in enum scanfilter_masks.  */
     361              : typedef int scanfilter;
     362              : 
     363              : /* Scan the name list of the loaded program for the symbols g++ uses for
     364              :    static constructors and destructors.
     365              : 
     366              :    The SCANPASS argument tells which collect processing pass this is for and
     367              :    the SCANFILTER argument tells which kinds of symbols to consider in this
     368              :    pass.  Symbols of a special kind not in the filter mask are considered as
     369              :    regular ones.
     370              : 
     371              :    The constructor table begins at __CTOR_LIST__ and contains a count of the
     372              :    number of pointers (or -1 if the constructors are built in a separate
     373              :    section by the linker), followed by the pointers to the constructor
     374              :    functions, terminated with a null pointer.  The destructor table has the
     375              :    same format, and begins at __DTOR_LIST__.  */
     376              : 
     377              : static void scan_prog_file (const char *, scanpass, scanfilter);
     378              : 
     379              : 
     380              : /* Delete tempfiles and exit function.  */
     381              : 
     382              : void
     383        93805 : tool_cleanup (bool from_signal)
     384              : {
     385              :   /* maybe_unlink may call notice, which is not signal safe.  */
     386        93805 :   if (from_signal)
     387            0 :     verbose = false;
     388              : 
     389        93805 :   if (c_file != 0 && c_file[0])
     390        93805 :     maybe_unlink (c_file);
     391              : 
     392        93805 :   if (o_file != 0 && o_file[0])
     393        93805 :     maybe_unlink (o_file);
     394              : 
     395              : #ifdef COLLECT_EXPORT_LIST
     396              :   if (export_file != 0 && export_file[0])
     397              :     maybe_unlink (export_file);
     398              : #endif
     399              : 
     400        93805 :   if (lto_o_files)
     401         4356 :     maybe_unlink_list (lto_o_files);
     402        93805 : }
     403              : 
     404              : static void
     405        93805 : collect_atexit (void)
     406              : {
     407        93805 :   tool_cleanup (false);
     408        93805 : }
     409              : 
     410              : /* Notify user of a non-error, without translating the format string.  */
     411              : void
     412            0 : notice_translated (const char *cmsgid, ...)
     413              : {
     414            0 :   va_list ap;
     415              : 
     416            0 :   va_start (ap, cmsgid);
     417            0 :   vfprintf (stderr, cmsgid, ap);
     418            0 :   va_end (ap);
     419            0 : }
     420              : 
     421              : int
     422          508 : file_exists (const char *name)
     423              : {
     424          508 :   return access (name, R_OK) == 0;
     425              : }
     426              : 
     427              : /* Parse a reasonable subset of shell quoting syntax.  */
     428              : 
     429              : static char *
     430      5564908 : extract_string (const char **pp)
     431              : {
     432      5564908 :   const char *p = *pp;
     433      5564908 :   int backquote = 0;
     434      5564908 :   int inside = 0;
     435              : 
     436    170360604 :   for (;;)
     437              :     {
     438    170360604 :       char c = *p;
     439    170360604 :       if (c == '\0')
     440              :         break;
     441    170172994 :       ++p;
     442    170172994 :       if (backquote)
     443            0 :         obstack_1grow (&temporary_obstack, c);
     444    170172994 :       else if (! inside && c == ' ')
     445              :         break;
     446    164795696 :       else if (! inside && c == '\\')
     447              :         backquote = 1;
     448    164795696 :       else if (c == '\'')
     449     11122484 :         inside = !inside;
     450              :       else
     451    153673212 :         obstack_1grow (&temporary_obstack, c);
     452              :     }
     453              : 
     454      5564908 :   obstack_1grow (&temporary_obstack, '\0');
     455      5564908 :   *pp = p;
     456      5564908 :   return XOBFINISH (&temporary_obstack, char *);
     457              : }
     458              : 
     459              : /* Return the kind of symbol denoted by name S.  */
     460              : 
     461              : static symkind
     462            0 : is_ctor_dtor (const char *s)
     463              : {
     464            0 :   struct names { const char *const name; const int len; symkind ret;
     465              :     const int two_underscores; };
     466              : 
     467            0 :   const struct names *p;
     468            0 :   int ch;
     469            0 :   const char *orig_s = s;
     470              : 
     471            0 :   static const struct names special[] = {
     472              : #ifndef NO_DOLLAR_IN_LABEL
     473              :     { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, SYM_CTOR, 0 },
     474              :     { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, SYM_DTOR, 0 },
     475              : #else
     476              : #ifndef NO_DOT_IN_LABEL
     477              :     { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, SYM_CTOR, 0 },
     478              :     { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, SYM_DTOR, 0 },
     479              : #endif /* NO_DOT_IN_LABEL */
     480              : #endif /* NO_DOLLAR_IN_LABEL */
     481              :     { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, SYM_CTOR, 0 },
     482              :     { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, SYM_DTOR, 0 },
     483              :     { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 },
     484              :     { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 },
     485              :     { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 },
     486              : #ifdef TARGET_AIX_VERSION
     487              :     { "GLOBAL__AIXI_", sizeof ("GLOBAL__AIXI_")-1, SYM_AIXI, 0 },
     488              :     { "GLOBAL__AIXD_", sizeof ("GLOBAL__AIXD_")-1, SYM_AIXD, 0 },
     489              : #endif
     490              :     { NULL, 0, SYM_REGULAR, 0 }
     491              :   };
     492              : 
     493            0 :   while ((ch = *s) == '_')
     494            0 :     ++s;
     495              : 
     496            0 :   if (s == orig_s)
     497              :     return SYM_REGULAR;
     498              : 
     499            0 :   for (p = &special[0]; p->len > 0; p++)
     500              :     {
     501            0 :       if (ch == p->name[0]
     502            0 :           && (!p->two_underscores || ((s - orig_s) >= 2))
     503            0 :           && strncmp (s, p->name, p->len) == 0)
     504              :         {
     505            0 :           return p->ret;
     506              :         }
     507              :     }
     508              :   return SYM_REGULAR;
     509              : }
     510              : 
     511              : /* We maintain two prefix lists: one from COMPILER_PATH environment variable
     512              :    and one from the PATH variable.  */
     513              : 
     514              : static struct path_prefix cpath, path;
     515              : 
     516              : #ifdef CROSS_DIRECTORY_STRUCTURE
     517              : /* This is the name of the target machine.  We use it to form the name
     518              :    of the files to execute.  */
     519              : 
     520              : static const char *const target_machine = TARGET_MACHINE;
     521              : #endif
     522              : 
     523              : /* Search for NAME using prefix list PPREFIX.  We only look for executable
     524              :    files.
     525              : 
     526              :    Return 0 if not found, otherwise return its name, allocated with malloc.  */
     527              : 
     528              : #ifdef OBJECT_FORMAT_NONE
     529              : 
     530              : /* Add an entry for the object file NAME to object file list LIST.
     531              :    New entries are added at the end of the list. The original pointer
     532              :    value of NAME is preserved, i.e., no string copy is performed.  */
     533              : 
     534              : static void
     535         4673 : add_lto_object (struct lto_object_list *list, const char *name)
     536              : {
     537         4673 :   struct lto_object *n = XNEW (struct lto_object);
     538         4673 :   n->name = name;
     539         4673 :   n->next = NULL;
     540              : 
     541         4673 :   if (list->last)
     542          317 :     list->last->next = n;
     543              :   else
     544         4356 :     list->first = n;
     545              : 
     546         4673 :   list->last = n;
     547         4673 : }
     548              : #endif /* OBJECT_FORMAT_NONE */
     549              : 
     550              : 
     551              : /* Perform a link-time recompilation and relink if any of the object
     552              :    files contain LTO info.  The linker command line LTO_LD_ARGV
     553              :    represents the linker command that would produce a final executable
     554              :    without the use of LTO. OBJECT_LST is a vector of object file names
     555              :    appearing in LTO_LD_ARGV that are to be considered for link-time
     556              :    recompilation, where OBJECT is a pointer to the last valid element.
     557              :    (This awkward convention avoids an impedance mismatch with the
     558              :    usage of similarly-named variables in main().)  The elements of
     559              :    OBJECT_LST must be identical, i.e., pointer equal, to the
     560              :    corresponding arguments in LTO_LD_ARGV.
     561              : 
     562              :    Upon entry, at least one linker run has been performed without the
     563              :    use of any LTO info that might be present.  Any recompilations
     564              :    necessary for template instantiations have been performed, and
     565              :    initializer/finalizer tables have been created if needed and
     566              :    included in the linker command line LTO_LD_ARGV. If any of the
     567              :    object files contain LTO info, we run the LTO back end on all such
     568              :    files, and perform the final link with the LTO back end output
     569              :    substituted for the LTO-optimized files.  In some cases, a final
     570              :    link with all link-time generated code has already been performed,
     571              :    so there is no need to relink if no LTO info is found.  In other
     572              :    cases, our caller has not produced the final executable, and is
     573              :    relying on us to perform the required link whether LTO info is
     574              :    present or not.  In that case, the FORCE argument should be true.
     575              :    Note that the linker command line argument LTO_LD_ARGV passed into
     576              :    this function may be modified in place.  */
     577              : 
     578              : static void
     579         4356 : maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
     580              :                           const char **object, bool force)
     581              : {
     582         4356 :   const char **object_file = const_cast<const char **> (object_lst);
     583              : 
     584         4356 :   int num_lto_c_args = 1;    /* Allow space for the terminating NULL.  */
     585              : 
     586        30866 :   while (object_file < object)
     587              :   {
     588              :     /* If file contains LTO info, add it to the list of LTO objects.  */
     589        26510 :     scan_prog_file (*object_file++, PASS_LTOINFO, SCAN_ALL);
     590              : 
     591              :     /* Increment the argument count by the number of object file arguments
     592              :        we will add.  An upper bound suffices, so just count all of the
     593              :        object files regardless of whether they contain LTO info.  */
     594        26510 :     num_lto_c_args++;
     595              :   }
     596              : 
     597         4356 :   if (lto_objects.first)
     598              :     {
     599         4356 :       char **lto_c_argv;
     600         4356 :       const char **lto_c_ptr;
     601         4356 :       char **p;
     602         4356 :       char **lto_o_ptr;
     603         4356 :       struct lto_object *list;
     604         4356 :       char *lto_wrapper = getenv ("COLLECT_LTO_WRAPPER");
     605         4356 :       struct pex_obj *pex;
     606         4356 :       const char *prog = "lto-wrapper";
     607         4356 :       int lto_ld_argv_size = 0;
     608         4356 :       char **out_lto_ld_argv;
     609         4356 :       int out_lto_ld_argv_size;
     610         4356 :       size_t num_files;
     611              : 
     612         4356 :       if (!lto_wrapper)
     613            0 :         fatal_error (input_location, "environment variable "
     614              :                      "%<COLLECT_LTO_WRAPPER%> must be set");
     615              : 
     616         4356 :       num_lto_c_args++;
     617              : 
     618              :       /* There is at least one object file containing LTO info,
     619              :          so we need to run the LTO back end and relink.
     620              : 
     621              :          To do so we build updated ld arguments with first
     622              :          LTO object replaced by all partitions and other LTO
     623              :          objects removed.  */
     624              : 
     625         4356 :       lto_c_argv = (char **) xcalloc (num_lto_c_args, sizeof (char *));
     626         4356 :       lto_c_ptr = const_cast<const char **> (lto_c_argv);
     627              : 
     628         4356 :       *lto_c_ptr++ = lto_wrapper;
     629              : 
     630              :       /* Add LTO objects to the wrapper command line.  */
     631         9029 :       for (list = lto_objects.first; list; list = list->next)
     632         4673 :         *lto_c_ptr++ = list->name;
     633              : 
     634         4356 :       *lto_c_ptr = NULL;
     635              : 
     636              :       /* Run the LTO back end.  */
     637         4356 :       pex = collect_execute (prog, lto_c_argv, NULL, NULL, PEX_SEARCH,
     638              :                              at_file_supplied, "lto_args");
     639         4356 :       {
     640         4356 :         int c;
     641         4356 :         FILE *stream;
     642         4356 :         size_t i;
     643         4356 :         char *start, *end;
     644              : 
     645         4356 :         stream = pex_read_output (pex, 0);
     646         4356 :         gcc_assert (stream);
     647              : 
     648              :         num_files = 0;
     649       106350 :         while ((c = getc (stream)) != EOF)
     650              :           {
     651       101994 :             obstack_1grow (&temporary_obstack, c);
     652       101994 :             if (c == '\n')
     653         4778 :               ++num_files;
     654              :           }
     655              : 
     656              :         /* signal handler may access uninitialized memory
     657              :            and delete whatever it points to, if lto_o_files
     658              :            is not allocated with calloc.  */
     659         4356 :         lto_o_files = XCNEWVEC (char *, num_files + 1);
     660         4356 :         lto_o_files[num_files] = NULL;
     661         4356 :         start = XOBFINISH (&temporary_obstack, char *);
     662         9134 :         for (i = 0; i < num_files; ++i)
     663              :           {
     664              :             end = start;
     665       101994 :             while (*end != '\n')
     666        97216 :               ++end;
     667         4778 :             *end = '\0';
     668              : 
     669         4778 :             lto_o_files[i] = xstrdup (start);
     670              : 
     671         4778 :             start = end + 1;
     672              :           }
     673              : 
     674         4356 :         obstack_free (&temporary_obstack, temporary_firstobj);
     675              :       }
     676         4356 :       do_wait (prog, pex);
     677         4356 :       pex = NULL;
     678              : 
     679              :       /* Compute memory needed for new LD arguments.  At most number of original arguments
     680              :          plus number of partitions.  */
     681       137074 :       for (lto_ld_argv_size = 0; lto_ld_argv[lto_ld_argv_size]; lto_ld_argv_size++)
     682              :         ;
     683         4356 :       out_lto_ld_argv = XCNEWVEC (char *, num_files + lto_ld_argv_size + 1);
     684         4356 :       out_lto_ld_argv_size = 0;
     685              : 
     686              :       /* After running the LTO back end, we will relink, substituting
     687              :          the LTO output for the object files that we submitted to the
     688              :          LTO. Here, we modify the linker command line for the relink.  */
     689              : 
     690              :       /* Copy all arguments until we find first LTO file.  */
     691         4356 :       p = lto_ld_argv;
     692        92554 :       while (*p != NULL)
     693              :         {
     694       178190 :           for (list = lto_objects.first; list; list = list->next)
     695        94348 :             if (*p == list->name) /* Note test for pointer equality!  */
     696              :               break;
     697        83842 :           if (list)
     698              :             break;
     699        83842 :           out_lto_ld_argv[out_lto_ld_argv_size++] = *p++;
     700              :         }
     701              : 
     702              :       /* Now insert all LTO partitions.  */
     703         4356 :       lto_o_ptr = lto_o_files;
     704         9134 :       while (*lto_o_ptr)
     705         4778 :         out_lto_ld_argv[out_lto_ld_argv_size++] = *lto_o_ptr++;
     706              : 
     707              :       /* ... and copy the rest.  */
     708        48876 :       while (*p != NULL)
     709              :         {
     710        87571 :           for (list = lto_objects.first; list; list = list->next)
     711        47724 :             if (*p == list->name) /* Note test for pointer equality!  */
     712              :               break;
     713        44520 :           if (!list)
     714        39847 :             out_lto_ld_argv[out_lto_ld_argv_size++] = *p;
     715        44520 :           p++;
     716              :         }
     717         4356 :       out_lto_ld_argv[out_lto_ld_argv_size++] = 0;
     718              : 
     719              :       /* Run the linker again, this time replacing the object files
     720              :          optimized by the LTO with the temporary file generated by the LTO.  */
     721         4356 :       fork_execute ("ld", out_lto_ld_argv, HAVE_GNU_LD && at_file_supplied,
     722              :                     "ld_args");
     723              :       /* We assume that temp files were created, and therefore we need to take
     724              :          that into account (maybe run dsymutil).  */
     725         4356 :       post_ld_pass (/*temp_file*/true);
     726         4356 :       free (lto_ld_argv);
     727              : 
     728         4356 :       maybe_unlink_list (lto_o_files);
     729              :     }
     730            0 :   else if (force)
     731              :     {
     732              :       /* Our caller is relying on us to do the link
     733              :          even though there is no LTO back end work to be done.  */
     734            0 :       fork_execute ("ld", lto_ld_argv, HAVE_GNU_LD && at_file_supplied,
     735              :                     "ld_args");
     736              :       /* No LTO objects were found, so no new temp file.  */
     737            0 :       post_ld_pass (/*temp_file*/false);
     738              :     }
     739              :   else
     740              :     post_ld_pass (false); /* No LTO objects were found, no temp file.  */
     741         4356 : }
     742              : /* Entry point for linker invoation.  Called from main in collect2.cc.
     743              :    LD_ARGV is an array of arguments for the linker.  */
     744              : 
     745              : static void
     746        93805 : do_link (char **ld_argv, const char *atsuffix)
     747              : {
     748        93805 :   struct pex_obj *pex;
     749        93805 :   const char *prog = "ld";
     750        93805 :   pex = collect_execute (prog, ld_argv, NULL, NULL,
     751              :                          PEX_LAST | PEX_SEARCH,
     752              :                          HAVE_GNU_LD && at_file_supplied, atsuffix);
     753        93805 :   int ret = collect_wait (prog, pex);
     754        93805 :   if (ret)
     755              :     {
     756          131 :       error ("ld returned %d exit status", ret);
     757          131 :       exit (ret);
     758              :     }
     759              :   else
     760              :     {
     761              :       /* We have just successfully produced an output file, so assume that we
     762              :          may unlink it if need be for now on.  */
     763        93674 :       may_unlink_output_file = true;
     764              :     }
     765        93674 : }
     766              : 
     767              : /* Main program.  */
     768              : 
     769              : int
     770        93805 : main (int argc, char **argv)
     771              : {
     772        93805 :   enum linker_select
     773              :     {
     774              :       USE_DEFAULT_LD,
     775              :       USE_PLUGIN_LD,
     776              :       USE_GOLD_LD,
     777              :       USE_BFD_LD,
     778              :       USE_LLD_LD,
     779              :       USE_MOLD_LD,
     780              :       USE_WILD_LD,
     781              :       USE_LD_MAX
     782        93805 :     } selected_linker = USE_DEFAULT_LD;
     783        93805 :   static const char *const ld_suffixes[USE_LD_MAX] =
     784              :     {
     785              :       "ld",
     786              :       PLUGIN_LD_SUFFIX,
     787              :       "ld.gold",
     788              :       "ld.bfd",
     789              :       "ld.lld",
     790              :       "ld.mold",
     791              :       "wild"
     792              :     };
     793        93805 :   static const char *const real_ld_suffix = "real-ld";
     794        93805 :   static const char *const collect_ld_suffix = "collect-ld";
     795        93805 :   static const char *const nm_suffix    = "nm";
     796        93805 :   static const char *const gnm_suffix   = "gnm";
     797              : #ifdef LDD_SUFFIX
     798              :   static const char *const ldd_suffix   = LDD_SUFFIX;
     799              : #endif
     800        93805 :   static const char *const strip_suffix = "strip";
     801        93805 :   static const char *const gstrip_suffix = "gstrip";
     802              : 
     803        93805 :   const char *full_ld_suffixes[USE_LD_MAX];
     804              : #ifdef CROSS_DIRECTORY_STRUCTURE
     805              :   /* If we look for a program in the compiler directories, we just use
     806              :      the short name, since these directories are already system-specific.
     807              :      But it we look for a program in the system directories, we need to
     808              :      qualify the program name with the target machine.  */
     809              : 
     810              :   const char *const full_nm_suffix =
     811              :     concat (target_machine, "-", nm_suffix, NULL);
     812              :   const char *const full_gnm_suffix =
     813              :     concat (target_machine, "-", gnm_suffix, NULL);
     814              : #ifdef LDD_SUFFIX
     815              :   const char *const full_ldd_suffix =
     816              :     concat (target_machine, "-", ldd_suffix, NULL);
     817              : #endif
     818              :   const char *const full_strip_suffix =
     819              :     concat (target_machine, "-", strip_suffix, NULL);
     820              :   const char *const full_gstrip_suffix =
     821              :     concat (target_machine, "-", gstrip_suffix, NULL);
     822              : #else
     823              : #ifdef LDD_SUFFIX
     824              :   const char *const full_ldd_suffix     = ldd_suffix;
     825              : #endif
     826        93805 :   const char *const full_nm_suffix      = nm_suffix;
     827        93805 :   const char *const full_gnm_suffix     = gnm_suffix;
     828        93805 :   const char *const full_strip_suffix   = strip_suffix;
     829        93805 :   const char *const full_gstrip_suffix  = gstrip_suffix;
     830              : #endif /* CROSS_DIRECTORY_STRUCTURE */
     831              : 
     832        93805 :   const char *arg;
     833        93805 :   FILE *outf;
     834              : #ifdef COLLECT_EXPORT_LIST
     835              :   FILE *exportf;
     836              : #endif
     837        93805 :   const char *ld_file_name;
     838        93805 :   const char *p;
     839        93805 :   char **c_argv;
     840        93805 :   const char **c_ptr;
     841        93805 :   char **ld1_argv;
     842        93805 :   const char **ld1;
     843        93805 :   bool use_plugin = false;
     844        93805 :   bool use_collect_ld = false;
     845              : 
     846              :   /* The kinds of symbols we will have to consider when scanning the
     847              :      outcome of a first pass link.  This is ALL to start with, then might
     848              :      be adjusted before getting to the first pass link per se, typically on
     849              :      AIX where we perform an early scan of objects and libraries to fetch
     850              :      the list of global ctors/dtors and make sure they are not garbage
     851              :      collected.  */
     852        93805 :   scanfilter ld1_filter = SCAN_ALL;
     853              : 
     854        93805 :   char **ld2_argv;
     855        93805 :   const char **ld2;
     856        93805 :   char **object_lst;
     857        93805 :   const char **object;
     858              : #ifdef TARGET_AIX_VERSION
     859              :   int object_nbr = argc;
     860              : #endif
     861        93805 :   int first_file;
     862        93805 :   int num_c_args;
     863        93805 :   char **old_argv;
     864              : #ifdef COLLECT_EXPORT_LIST
     865              :   bool is_static = false;
     866              : #endif
     867        93805 :   int i;
     868              : 
     869       750440 :   for (i = 0; i < USE_LD_MAX; i++)
     870              : #ifdef CROSS_DIRECTORY_STRUCTURE
     871              :     /* lld and mold are platform-agnostic and not prefixed with target
     872              :        triple.  */
     873              :     if (!(i == USE_LLD_LD || i == USE_MOLD_LD || i == USE_WILD_LD))
     874              :       full_ld_suffixes[i] = concat (target_machine, "-", ld_suffixes[i],
     875              :                                     NULL);
     876              :     else
     877              : #endif
     878       656635 :       full_ld_suffixes[i] = ld_suffixes[i];
     879              : 
     880        93805 :   p = argv[0] + strlen (argv[0]);
     881       844245 :   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
     882       750440 :     --p;
     883        93805 :   progname = p;
     884              : 
     885        93805 :   xmalloc_set_program_name (progname);
     886              : 
     887        93805 :   old_argv = argv;
     888        93805 :   expandargv (&argc, &argv);
     889        93805 :   if (argv != old_argv)
     890            6 :     at_file_supplied = 1;
     891              : 
     892        93805 :   process_args (&argc, argv);
     893              : 
     894        93805 :   num_c_args = argc + 9;
     895              : 
     896              : #ifndef HAVE_LD_DEMANGLE
     897              :   no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
     898              : 
     899              :   /* Suppress demangling by the real linker, which may be broken.  */
     900              :   putenv (xstrdup ("COLLECT_NO_DEMANGLE=1"));
     901              : #endif
     902              : 
     903              : #if defined (COLLECT2_HOST_INITIALIZATION)
     904              :   /* Perform system dependent initialization, if necessary.  */
     905              :   COLLECT2_HOST_INITIALIZATION;
     906              : #endif
     907              : 
     908        93805 :   setup_signals ();
     909              : 
     910              :   /* Unlock the stdio streams.  */
     911        93805 :   unlock_std_streams ();
     912              : 
     913        93805 :   gcc_init_libintl ();
     914              : 
     915        93805 :   diagnostic_initialize (global_dc, 0);
     916              : 
     917        93805 :   if (atexit (collect_atexit) != 0)
     918            0 :     fatal_error (input_location, "atexit failed");
     919              : 
     920              :   /* Do not invoke xcalloc before this point, since locale needs to be
     921              :      set first, in case a diagnostic is issued.  */
     922              : 
     923        93805 :   ld1_argv = XCNEWVEC (char *, argc + 4);
     924        93805 :   ld1 = const_cast<const char **> (ld1_argv);
     925        93805 :   ld2_argv = XCNEWVEC (char *, argc + 11);
     926        93805 :   ld2 = const_cast<const char **> (ld2_argv);
     927        93805 :   object_lst = XCNEWVEC (char *, argc);
     928        93805 :   object = const_cast<const char **> (object_lst);
     929              : 
     930              : #ifdef DEBUG
     931              :   debug = true;
     932              : #endif
     933              : 
     934        93805 :   save_temps = false;
     935        93805 :   verbose = false;
     936              : 
     937              : #ifndef DEFAULT_A_OUT_NAME
     938        93805 :   output_file = "a.out";
     939              : #else
     940              :   output_file = DEFAULT_A_OUT_NAME;
     941              : #endif
     942              : 
     943              :   /* Parse command line / environment for flags we want early.
     944              :      This allows the debug flag to be set before functions like find_a_file()
     945              :      are called. */
     946        93805 :   {
     947        93805 :     bool no_partition = false;
     948              : 
     949      3979118 :     for (i = 1; argv[i] != NULL; i ++)
     950              :       {
     951      3885313 :         if (! strcmp (argv[i], "-debug"))
     952            0 :           debug = true;
     953      3885313 :         else if (startswith (argv[i], "-fno-lto"))
     954           35 :           lto_mode = LTO_MODE_NONE;
     955      3885278 :         else if (! strcmp (argv[i], "-plugin"))
     956              :           {
     957        89414 :             use_plugin = true;
     958        89414 :             if (selected_linker == USE_DEFAULT_LD)
     959              :               selected_linker = USE_PLUGIN_LD;
     960              :           }
     961      3795864 :         else if (strcmp (argv[i], "-fuse-ld=bfd") == 0)
     962              :           selected_linker = USE_BFD_LD;
     963      3795864 :         else if (strcmp (argv[i], "-fuse-ld=gold") == 0)
     964              :           selected_linker = USE_GOLD_LD;
     965      3795864 :         else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
     966              :           selected_linker = USE_LLD_LD;
     967      3795864 :         else if (strcmp (argv[i], "-fuse-ld=mold") == 0)
     968              :           selected_linker = USE_MOLD_LD;
     969      3795864 :         else if (strcmp (argv[i], "-fuse-ld=wild") == 0)
     970              :           selected_linker = USE_WILD_LD;
     971      3795864 :         else if (startswith (argv[i], "-o"))
     972              :           {
     973              :             /* Parse the output filename if it's given so that we can make
     974              :                meaningful temp filenames.  */
     975        93322 :             if (argv[i][2] != '\0')
     976            0 :               output_file = &argv[i][2];
     977        93322 :             else if (argv[i+1] != NULL)
     978        93322 :               output_file = argv[++i];
     979              :           }
     980              : 
     981              : #ifdef COLLECT_EXPORT_LIST
     982              :         /* These flags are position independent, although their order
     983              :            is important - subsequent flags override earlier ones. */
     984              :         else if (strcmp (argv[i], "-b64") == 0)
     985              :           aix64_flag = 1;
     986              :         /* -bexport:filename always needs the :filename */
     987              :         else if (startswith (argv[i], "-bE:")
     988              :                  || startswith (argv[i], "-bexport:"))
     989              :           export_flag = 1;
     990              :         else if (strcmp (argv[i], "-brtl") == 0
     991              :               || strcmp (argv[i], "-bsvr4") == 0
     992              :               || strcmp (argv[i], "-G") == 0)
     993              :           aixrtl_flag = 1;
     994              :         else if (strcmp (argv[i], "-bnortl") == 0)
     995              :           aixrtl_flag = 0;
     996              :         else if (strcmp (argv[i], "-blazy") == 0)
     997              :           aixlazy_flag = 1;
     998              : #endif
     999              :       }
    1000              : 
    1001        93805 :     obstack_begin (&temporary_obstack, 0);
    1002        93805 :     temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
    1003              : 
    1004              : #ifndef HAVE_LD_DEMANGLE
    1005              :   current_demangling_style = auto_demangling;
    1006              : #endif
    1007              : 
    1008              :     /* Now pick up any flags we want early from COLLECT_GCC_OPTIONS
    1009              :        The LTO options are passed here as are other options that might
    1010              :        be unsuitable for ld (e.g. -save-temps).  */
    1011        93805 :     p = getenv ("COLLECT_GCC_OPTIONS");
    1012      2469093 :     while (p && *p)
    1013              :       {
    1014      2375288 :         const char *q = extract_string (&p);
    1015      2375288 :         if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
    1016      1186993 :           num_c_args++;
    1017      2375288 :         if (startswith (q, "-flto-partition=none"))
    1018              :           no_partition = true;
    1019      2370926 :         else if (startswith (q, "-fno-lto"))
    1020           35 :           lto_mode = LTO_MODE_NONE;
    1021      2370891 :         else if (startswith (q, "-save-temps"))
    1022              :           /* FIXME: Honour =obj.  */
    1023          259 :           save_temps = true;
    1024      2370632 :         else if (strcmp (q, "-dumpdir") == 0)
    1025        93802 :           dumppfx = xstrdup (extract_string (&p));
    1026      2276830 :         else if (strcmp (q, "-o") == 0
    1027      2183508 :                  || strcmp (q, "-B") == 0
    1028      1981266 :                  || strcmp (q, "-isystem") == 0)
    1029       313364 :           (void) extract_string (&p);
    1030              :     }
    1031        93805 :     obstack_free (&temporary_obstack, temporary_firstobj);
    1032              : 
    1033        93805 :     verbose = verbose || debug;
    1034        93805 :     save_temps = save_temps || debug;
    1035        93805 :     find_file_set_debug (debug);
    1036        93805 :     if (use_plugin)
    1037        89414 :       lto_mode = LTO_MODE_NONE;
    1038        93805 :     if (no_partition && lto_mode == LTO_MODE_WHOPR)
    1039         4098 :       lto_mode = LTO_MODE_LTO;
    1040              :   }
    1041              : 
    1042              :   /* -fno-profile-arcs -fno-condition-coverage -fno-path-coverage
    1043              :      -fno-test-coverage
    1044              :      -fno-branch-probabilities -fno-exceptions -w -fno-whole-program */
    1045        93805 :   num_c_args += 8;
    1046              : 
    1047        93805 :   c_argv = XCNEWVEC (char *, num_c_args);
    1048        93805 :   c_ptr = const_cast<const char **> (c_argv);
    1049              : 
    1050        93805 :   if (argc < 2)
    1051            0 :     fatal_error (input_location, "no arguments");
    1052              : 
    1053              :   /* Extract COMPILER_PATH and PATH into our prefix list.  */
    1054        93805 :   prefix_from_env ("COMPILER_PATH", &cpath);
    1055        93805 :   prefix_from_env ("PATH", &path);
    1056              : 
    1057              :   /* Try to discover a valid linker/nm/strip to use.  */
    1058              : 
    1059              :   /* Maybe we know the right file to use (if not cross).  */
    1060        93805 :   ld_file_name = 0;
    1061              : #ifdef DEFAULT_LINKER
    1062              :   if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD ||
    1063              :       selected_linker == USE_LLD_LD || selected_linker == USE_MOLD_LD ||
    1064              :       selected_linker == USE_WILD_LD)
    1065              :     {
    1066              :       char *linker_name;
    1067              : # ifdef HOST_EXECUTABLE_SUFFIX
    1068              :       int len = (sizeof (DEFAULT_LINKER)
    1069              :                  - sizeof (HOST_EXECUTABLE_SUFFIX));
    1070              :       linker_name = NULL;
    1071              :       if (len > 0)
    1072              :         {
    1073              :           char *default_linker = xstrdup (DEFAULT_LINKER);
    1074              :           /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains
    1075              :              HOST_EXECUTABLE_SUFFIX.  */
    1076              :           if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX))
    1077              :             {
    1078              :               default_linker[len] = '\0';
    1079              :               linker_name = concat (default_linker,
    1080              :                                     &ld_suffixes[selected_linker][2],
    1081              :                                     HOST_EXECUTABLE_SUFFIX, NULL);
    1082              :             }
    1083              :         }
    1084              :       if (linker_name == NULL)
    1085              : # endif
    1086              :       linker_name = concat (DEFAULT_LINKER,
    1087              :                             &ld_suffixes[selected_linker][2],
    1088              :                             NULL);
    1089              :       if (access (linker_name, X_OK) == 0)
    1090              :         ld_file_name = linker_name;
    1091              :     }
    1092              :   if (ld_file_name == 0 && access (DEFAULT_LINKER, X_OK) == 0)
    1093              :     ld_file_name = DEFAULT_LINKER;
    1094              :   if (ld_file_name == 0)
    1095              : #endif
    1096              : #ifdef REAL_LD_FILE_NAME
    1097              :   ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME, X_OK);
    1098              :   if (ld_file_name == 0)
    1099              : #endif
    1100              :   /* Search the (target-specific) compiler dirs for ld'.  */
    1101        93805 :   ld_file_name = find_a_file (&cpath, real_ld_suffix, X_OK);
    1102              :   /* Likewise for `collect-ld'.  */
    1103        93805 :   if (ld_file_name == 0)
    1104              :     {
    1105        93805 :       ld_file_name = find_a_file (&cpath, collect_ld_suffix, X_OK);
    1106        93805 :       use_collect_ld = ld_file_name != 0;
    1107              :     }
    1108              :   /* Search the compiler directories for `ld'.  We have protection against
    1109              :      recursive calls in find_a_file.  */
    1110        93805 :   if (ld_file_name == 0)
    1111            0 :     ld_file_name = find_a_file (&cpath, ld_suffixes[selected_linker], X_OK);
    1112              :   /* Search the ordinary system bin directories
    1113              :      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
    1114            0 :   if (ld_file_name == 0)
    1115            0 :     ld_file_name = find_a_file (&path, full_ld_suffixes[selected_linker], X_OK);
    1116              : 
    1117              : #ifdef REAL_NM_FILE_NAME
    1118              :   nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME, X_OK);
    1119              :   if (nm_file_name == 0)
    1120              : #endif
    1121        93805 :   nm_file_name = find_a_file (&cpath, gnm_suffix, X_OK);
    1122        93805 :   if (nm_file_name == 0)
    1123        93805 :     nm_file_name = find_a_file (&path, full_gnm_suffix, X_OK);
    1124        93805 :   if (nm_file_name == 0)
    1125        93805 :     nm_file_name = find_a_file (&cpath, nm_suffix, X_OK);
    1126        93805 :   if (nm_file_name == 0)
    1127            0 :     nm_file_name = find_a_file (&path, full_nm_suffix, X_OK);
    1128              : 
    1129              : #ifdef LDD_SUFFIX
    1130              :   ldd_file_name = find_a_file (&cpath, ldd_suffix, X_OK);
    1131              :   if (ldd_file_name == 0)
    1132              :     ldd_file_name = find_a_file (&path, full_ldd_suffix, X_OK);
    1133              : #endif
    1134              : 
    1135              : #ifdef REAL_STRIP_FILE_NAME
    1136              :   strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME, X_OK);
    1137              :   if (strip_file_name == 0)
    1138              : #endif
    1139        93805 :   strip_file_name = find_a_file (&cpath, gstrip_suffix, X_OK);
    1140        93805 :   if (strip_file_name == 0)
    1141        93805 :     strip_file_name = find_a_file (&path, full_gstrip_suffix, X_OK);
    1142        93805 :   if (strip_file_name == 0)
    1143        93805 :     strip_file_name = find_a_file (&cpath, strip_suffix, X_OK);
    1144        93805 :   if (strip_file_name == 0)
    1145        93805 :     strip_file_name = find_a_file (&path, full_strip_suffix, X_OK);
    1146              : 
    1147              :   /* Determine the full path name of the C compiler to use.  */
    1148        93805 :   c_file_name = getenv ("COLLECT_GCC");
    1149        93805 :   if (c_file_name == 0)
    1150              :     {
    1151              : #ifdef CROSS_DIRECTORY_STRUCTURE
    1152              :       c_file_name = concat (target_machine, "-gcc", NULL);
    1153              : #else
    1154            0 :       c_file_name = "gcc";
    1155              : #endif
    1156              :     }
    1157              : 
    1158        93805 :   p = find_a_file (&cpath, c_file_name, X_OK);
    1159              : 
    1160              :   /* Here it should be safe to use the system search path since we should have
    1161              :      already qualified the name of the compiler when it is needed.  */
    1162        93805 :   if (p == 0)
    1163            0 :     p = find_a_file (&path, c_file_name, X_OK);
    1164              : 
    1165        93805 :   if (p)
    1166        93805 :     c_file_name = p;
    1167              : 
    1168        93805 :   *ld1++ = *ld2++ = ld_file_name;
    1169              : 
    1170              :   /* Make temp file names.  */
    1171        93805 :   if (save_temps)
    1172              :     {
    1173          253 :       c_file = concat (output_file, ".cdtor.c", NULL);
    1174          253 :       o_file = concat (output_file, ".cdtor.o", NULL);
    1175              : #ifdef COLLECT_EXPORT_LIST
    1176              :       export_file = concat (output_file, ".x", NULL);
    1177              : #endif
    1178              :     }
    1179              :   else
    1180              :     {
    1181        93552 :       c_file = make_temp_file (".cdtor.c");
    1182        93552 :       o_file = make_temp_file (".cdtor.o");
    1183              : #ifdef COLLECT_EXPORT_LIST
    1184              :       export_file = make_temp_file (".x");
    1185              : #endif
    1186              :     }
    1187              :   /* Build the command line to compile the ctor/dtor list.  */
    1188        93805 :   *c_ptr++ = c_file_name;
    1189        93805 :   *c_ptr++ = "-x";
    1190        93805 :   *c_ptr++ = "c";
    1191        93805 :   *c_ptr++ = "-c";
    1192        93805 :   *c_ptr++ = "-o";
    1193        93805 :   *c_ptr++ = o_file;
    1194              : 
    1195              : #ifdef COLLECT_EXPORT_LIST
    1196              :   /* Generate a list of directories from LIBPATH.  */
    1197              :   prefix_from_env ("LIBPATH", &libpath_lib_dirs);
    1198              :   /* Add to this list also two standard directories where
    1199              :      AIX loader always searches for libraries.  */
    1200              :   add_prefix (&libpath_lib_dirs, "/lib");
    1201              :   add_prefix (&libpath_lib_dirs, "/usr/lib");
    1202              : #endif
    1203              : 
    1204              :   /* Get any options that the upper GCC wants to pass to the sub-GCC.
    1205              : 
    1206              :      AIX support needs to know if -shared has been specified before
    1207              :      parsing commandline arguments.  */
    1208              : 
    1209        93805 :   p = getenv ("COLLECT_GCC_OPTIONS");
    1210      2469093 :   while (p && *p)
    1211              :     {
    1212      2375288 :       const char *q = extract_string (&p);
    1213      2375288 :       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
    1214      1186993 :         *c_ptr++ = xstrdup (q);
    1215      2375288 :       if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
    1216            0 :         *c_ptr++ = xstrdup (q);
    1217      2375288 :       if (strcmp (q, "-shared") == 0)
    1218          248 :         shared_obj = 1;
    1219      2375288 :       if (strcmp (q, "-static") == 0)
    1220           95 :         static_obj = 1;
    1221      2375288 :       if (*q == '-' && q[1] == 'B')
    1222              :         {
    1223       202242 :           *c_ptr++ = xstrdup (q);
    1224       202242 :           if (q[2] == 0)
    1225              :             {
    1226       202242 :               q = extract_string (&p);
    1227       202242 :               *c_ptr++ = xstrdup (q);
    1228              :             }
    1229              :         }
    1230      2173046 :       else if (strcmp (q, "-o") == 0
    1231      2079724 :                || strcmp (q, "-dumpdir") == 0
    1232      1985922 :                || strcmp (q, "-isystem") == 0)
    1233       204924 :         (void) extract_string (&p);
    1234              : #ifdef COLLECT_EXPORT_LIST
    1235              :       /* Detect any invocation with -fvisibility.  */
    1236              :       if (startswith (q, "-fvisibility"))
    1237              :         visibility_flag = 1;
    1238              : #endif
    1239              :     }
    1240        93805 :   obstack_free (&temporary_obstack, temporary_firstobj);
    1241        93805 :   *c_ptr++ = "-fno-profile-arcs";
    1242        93805 :   *c_ptr++ = "-fno-condition-coverage";
    1243        93805 :   *c_ptr++ = "-fno-path-coverage";
    1244        93805 :   *c_ptr++ = "-fno-test-coverage";
    1245        93805 :   *c_ptr++ = "-fno-branch-probabilities";
    1246        93805 :   *c_ptr++ = "-fno-exceptions";
    1247        93805 :   *c_ptr++ = "-w";
    1248        93805 :   *c_ptr++ = "-fno-whole-program";
    1249              : 
    1250              :   /* !!! When GCC calls collect2,
    1251              :      it does not know whether it is calling collect2 or ld.
    1252              :      So collect2 cannot meaningfully understand any options
    1253              :      except those ld understands.
    1254              :      If you propose to make GCC pass some other option,
    1255              :      just imagine what will happen if ld is really ld!!!  */
    1256              : 
    1257              :   /* Parse arguments.  Remember output file spec, pass the rest to ld.  */
    1258              :   /* After the first file, put in the c++ rt0.  */
    1259              : 
    1260              : #ifdef COLLECT_EXPORT_LIST
    1261              :   is_static = static_obj;
    1262              : #endif
    1263        93805 :   first_file = 1;
    1264      3885656 :   while ((arg = *++argv) != (char *) 0)
    1265              :     {
    1266      3791851 :       *ld1++ = *ld2++ = arg;
    1267              : 
    1268      3791851 :       if (arg[0] == '-')
    1269              :         {
    1270      3019396 :           switch (arg[1])
    1271              :             {
    1272        93462 :             case 'd':
    1273        93462 :               if (!strcmp (arg, "-debug"))
    1274              :                 {
    1275              :                   /* Already parsed.  */
    1276            0 :                   ld1--;
    1277            0 :                   ld2--;
    1278              :                 }
    1279        93462 :               if (!strcmp (arg, "-dynamic-linker") && argv[1])
    1280              :                 {
    1281        93462 :                   ++argv;
    1282        93462 :                   *ld1++ = *ld2++ = *argv;
    1283              :                 }
    1284              :               break;
    1285              : 
    1286        12230 :             case 'f':
    1287        12230 :               if (startswith (arg, "-flto"))
    1288              :                 {
    1289              : #ifdef ENABLE_LTO
    1290              :                   /* Do not pass LTO flag to the linker. */
    1291              :                   ld1--;
    1292              :                   ld2--;
    1293              : #else
    1294              :                   error ("LTO support has not been enabled in this "
    1295              :                          "configuration");
    1296              : #endif
    1297              :                 }
    1298           35 :               else if (!use_collect_ld
    1299           35 :                        && startswith (arg, "-fuse-ld="))
    1300              :                 {
    1301              :                   /* Do not pass -fuse-ld={bfd|gold|lld|mold|wild} to the linker. */
    1302              :                   ld1--;
    1303              :                   ld2--;
    1304              :                 }
    1305           35 :               else if (startswith (arg, "-fno-lto"))
    1306              :                 {
    1307              :                   /* Do not pass -fno-lto to the linker. */
    1308      3791851 :                   ld1--;
    1309      3791851 :                   ld2--;
    1310              :                 }
    1311              : #ifdef TARGET_AIX_VERSION
    1312              :               else
    1313              :                 {
    1314              :                   /* File containing a list of input files to process.  */
    1315              : 
    1316              :                   FILE *stream;
    1317              :                   char buf[MAXPATHLEN + 2];
    1318              :                   /* Number of additionnal object files.  */
    1319              :                   int add_nbr = 0;
    1320              :                   /* Maximum of additionnal object files before vector
    1321              :                      expansion.  */
    1322              :                   int add_max = 0;
    1323              :                   const char *list_filename = arg + 2;
    1324              : 
    1325              :                   /* Accept -fFILENAME and -f FILENAME.  */
    1326              :                   if (*list_filename == '\0' && argv[1])
    1327              :                     {
    1328              :                       ++argv;
    1329              :                       list_filename = *argv;
    1330              :                       *ld1++ = *ld2++ = *argv;
    1331              :                     }
    1332              : 
    1333              :                   stream = fopen (list_filename, "r");
    1334              :                   if (stream == NULL)
    1335              :                     fatal_error (input_location, "cannot open %s: %m",
    1336              :                                  list_filename);
    1337              : 
    1338              :                   while (fgets (buf, sizeof buf, stream) != NULL)
    1339              :                     {
    1340              :                       /* Remove end of line.  */
    1341              :                       int len = strlen (buf);
    1342              :                       if (len >= 1 && buf[len - 1] =='\n')
    1343              :                         buf[len - 1] = '\0';
    1344              : 
    1345              :                       /* Put on object vector.
    1346              :                          Note: we only expanse vector here, so we must keep
    1347              :                          extra space for remaining arguments.  */
    1348              :                       if (add_nbr >= add_max)
    1349              :                         {
    1350              :                           int pos =
    1351              :                             object - const_cast<const char **> (object_lst);
    1352              :                           add_max = (add_max == 0) ? 16 : add_max * 2;
    1353              :                           object_lst = XRESIZEVEC (char *, object_lst,
    1354              :                                                    object_nbr + add_max);
    1355              :                           object =
    1356              :                             const_cast<const char **> (object_lst) + pos;
    1357              :                           object_nbr += add_max;
    1358              :                         }
    1359              :                       *object++ = xstrdup (buf);
    1360              :                       add_nbr++;
    1361              :                     }
    1362              :                   fclose (stream);
    1363              :                 }
    1364              : #endif
    1365              :               break;
    1366              : 
    1367              : #ifdef COLLECT_EXPORT_LIST
    1368              :             case 'b':
    1369              :               if (!strcmp (arg, "-bstatic"))
    1370              :                 {
    1371              :                   is_static = true;
    1372              :                 }
    1373              :               else if (!strcmp (arg, "-bdynamic") || !strcmp (arg, "-bshared"))
    1374              :                 {
    1375              :                   is_static = false;
    1376              :                 }
    1377              :               break;
    1378              : #endif
    1379       819536 :             case 'l':
    1380       819536 :               if (first_file)
    1381              :                 {
    1382              :                   /* place o_file BEFORE this argument! */
    1383            0 :                   first_file = 0;
    1384            0 :                   ld2--;
    1385            0 :                   *ld2++ = o_file;
    1386            0 :                   *ld2++ = arg;
    1387              :                 }
    1388              : #ifdef COLLECT_EXPORT_LIST
    1389              :               {
    1390              :                 /* Resolving full library name.  */
    1391              :                 const char *s = resolve_lib_name (arg+2);
    1392              : 
    1393              :                 /* Saving a full library name.  */
    1394              :                 add_to_list (&libs, s);
    1395              :                 if (is_static)
    1396              :                     add_to_list (&static_libs, s);
    1397              :               }
    1398              : #endif
    1399              :               break;
    1400              : 
    1401              : #ifdef COLLECT_EXPORT_LIST
    1402              :             /* Saving directories where to search for libraries.  */
    1403              :             case 'L':
    1404              :               add_prefix (&cmdline_lib_dirs, arg+2);
    1405              :               break;
    1406              : #endif
    1407              : 
    1408        93322 :             case 'o':
    1409        93322 :               if (arg[2] != '\0')
    1410            0 :                 output_file = &arg[2];
    1411        93322 :               else if (argv[1])
    1412        93322 :                 output_file = *ld1++ = *ld2++ = *++argv;
    1413              :               break;
    1414              : 
    1415          232 :             case 'r':
    1416          232 :               if (arg[2] == '\0')
    1417          190 :                 rflag = 1;
    1418              :               break;
    1419              : 
    1420          402 :             case 's':
    1421          402 :               if (arg[2] == '\0' && do_collecting)
    1422              :                 {
    1423              :                   /* We must strip after the nm run, otherwise C++ linking
    1424              :                      will not work.  Thus we strip in the second ld run, or
    1425              :                      else with strip if there is no second ld run.  */
    1426            0 :                   strip_flag = 1;
    1427            0 :                   ld1--;
    1428              :                 }
    1429              :               break;
    1430              : 
    1431            0 :             case 'v':
    1432            0 :               if (arg[2] == '\0')
    1433            0 :                 verbose = true;
    1434              :               break;
    1435              : 
    1436       144920 :             case '-':
    1437       144920 :               if (strcmp (arg, "--no-demangle") == 0)
    1438              :                 {
    1439              : #ifndef HAVE_LD_DEMANGLE
    1440              :                   no_demangle = 1;
    1441              :                   ld1--;
    1442              :                   ld2--;
    1443              : #endif
    1444              :                 }
    1445       144920 :               else if (startswith (arg, "--demangle"))
    1446              :                 {
    1447              : #ifndef HAVE_LD_DEMANGLE
    1448              :                   no_demangle = 0;
    1449              :                   if (arg[10] == '=')
    1450              :                     {
    1451              :                       enum demangling_styles style
    1452              :                         = cplus_demangle_name_to_style (arg+11);
    1453              :                       if (style == unknown_demangling)
    1454              :                         error ("unknown demangling style %qs", arg+11);
    1455              :                       else
    1456              :                         current_demangling_style = style;
    1457              :                     }
    1458              :                   ld1--;
    1459              :                   ld2--;
    1460              : #endif
    1461              :                 }
    1462       144920 :               else if (startswith (arg, "--sysroot="))
    1463            0 :                 target_system_root = arg + 10;
    1464       144920 :               else if (strcmp (arg, "--version") == 0)
    1465            0 :                 verbose = true;
    1466       144920 :               else if (strcmp (arg, "--help") == 0)
    1467            5 :                 helpflag = true;
    1468              :               break;
    1469              :             }
    1470              :         }
    1471       772455 :       else if ((p = strrchr (arg, '.')) != (char *) 0
    1472       772455 :                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
    1473        89481 :                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
    1474           59 :                    || strcmp (p, ".obj") == 0))
    1475              :         {
    1476       678351 :           if (first_file)
    1477              :             {
    1478        93805 :               first_file = 0;
    1479        93805 :               if (p[1] == 'o')
    1480         4391 :                 *ld2++ = o_file;
    1481              :               else
    1482              :                 {
    1483              :                   /* place o_file BEFORE this argument! */
    1484        89414 :                   ld2--;
    1485        89414 :                   *ld2++ = o_file;
    1486        89414 :                   *ld2++ = arg;
    1487              :                 }
    1488              :             }
    1489       678351 :           if (p[1] == 'o' || p[1] == 'l')
    1490       575386 :             *object++ = arg;
    1491              : #ifdef COLLECT_EXPORT_LIST
    1492              :           /* libraries can be specified directly, i.e. without -l flag.  */
    1493              :           else
    1494              :             {
    1495              :               /* Saving a full library name.  */
    1496              :               add_to_list (&libs, arg);
    1497              :               if (is_static)
    1498              :                 add_to_list (&static_libs, arg);
    1499              :             }
    1500              : #endif
    1501              :         }
    1502              :     }
    1503              : 
    1504              : #ifdef COLLECT_EXPORT_LIST
    1505              :   /* This is added only for debugging purposes.  */
    1506              :   if (debug)
    1507              :     {
    1508              :       fprintf (stderr, "List of libraries:\n");
    1509              :       dump_list (stderr, "\t", libs.first);
    1510              :       fprintf (stderr, "List of statically linked libraries:\n");
    1511              :       dump_list (stderr, "\t", static_libs.first);
    1512              :     }
    1513              : 
    1514              :   /* The AIX linker will discard static constructors in object files if
    1515              :      nothing else in the file is referenced, so look at them first.  Unless
    1516              :      we are building a shared object, ignore the eh frame tables, as we
    1517              :      would otherwise reference them all, hence drag all the corresponding
    1518              :      objects even if nothing else is referenced.  */
    1519              :   {
    1520              :     const char **export_object_lst = const_cast<const char **> (object_lst);
    1521              : 
    1522              :     struct id *list = libs.first;
    1523              : 
    1524              :     /* Compute the filter to use from the current one, do scan, then adjust
    1525              :        the "current" filter to remove what we just included here.  This will
    1526              :        control whether we need a first pass link later on or not, and what
    1527              :        will remain to be scanned there.  */
    1528              : 
    1529              :     scanfilter this_filter = ld1_filter;
    1530              : #if HAVE_AS_REF
    1531              :     if (!shared_obj)
    1532              :       this_filter &= ~SCAN_DWEH;
    1533              : #endif
    1534              : 
    1535              :     /* Scan object files.  */
    1536              :     while (export_object_lst < object)
    1537              :       scan_prog_file (*export_object_lst++, PASS_OBJ, this_filter);
    1538              : 
    1539              :     /* Scan libraries.  */
    1540              :     for (; list; list = list->next)
    1541              :       scan_prog_file (list->name, PASS_FIRST, this_filter);
    1542              : 
    1543              :     ld1_filter = ld1_filter & ~this_filter;
    1544              :   }
    1545              : 
    1546              :   if (exports.first)
    1547              :     {
    1548              :       char *buf = concat ("-bE:", export_file, NULL);
    1549              : 
    1550              :       *ld1++ = buf;
    1551              :       *ld2++ = buf;
    1552              : 
    1553              :       exportf = fopen (export_file, "w");
    1554              :       if (exportf == (FILE *) 0)
    1555              :         fatal_error (input_location, "fopen %s: %m", export_file);
    1556              :       write_aix_file (exportf, exports.first);
    1557              :       if (fclose (exportf))
    1558              :         fatal_error (input_location, "fclose %s: %m", export_file);
    1559              :     }
    1560              : #endif
    1561              : 
    1562        93805 :   *c_ptr++ = c_file;
    1563        93805 :   *c_ptr = *ld1 = *object = (char *) 0;
    1564              : 
    1565        93805 :   if (verbose)
    1566            0 :     notice ("collect2 version %s\n", version_string);
    1567              : 
    1568        93805 :   if (helpflag)
    1569              :     {
    1570            5 :       printf ("Usage: collect2 [options]\n");
    1571            5 :       printf (" Wrap linker and generate constructor code if needed.\n");
    1572            5 :       printf (" Options:\n");
    1573            5 :       printf ("  -debug          Enable debug output\n");
    1574            5 :       printf ("  --help          Display this information\n");
    1575            5 :       printf ("  -v, --version   Display this program's version number\n");
    1576            5 :       printf ("\n");
    1577            5 :       printf ("Overview: https://gcc.gnu.org/onlinedocs/gccint/Collect2.html\n");
    1578            5 :       printf ("Report bugs: %s\n", bug_report_url);
    1579            5 :       printf ("\n");
    1580              :     }
    1581              : 
    1582        93805 :   if (debug)
    1583              :     {
    1584            0 :       const char *ptr;
    1585            0 :       fprintf (stderr, "ld_file_name        = %s\n",
    1586              :                (ld_file_name ? ld_file_name : "not found"));
    1587            0 :       fprintf (stderr, "c_file_name         = %s\n",
    1588            0 :                (c_file_name ? c_file_name : "not found"));
    1589            0 :       fprintf (stderr, "nm_file_name        = %s\n",
    1590            0 :                (nm_file_name ? nm_file_name : "not found"));
    1591              : #ifdef LDD_SUFFIX
    1592              :       fprintf (stderr, "ldd_file_name       = %s\n",
    1593              :                (ldd_file_name ? ldd_file_name : "not found"));
    1594              : #endif
    1595            0 :       fprintf (stderr, "strip_file_name     = %s\n",
    1596            0 :                (strip_file_name ? strip_file_name : "not found"));
    1597            0 :       fprintf (stderr, "c_file              = %s\n",
    1598            0 :                (c_file ? c_file : "not found"));
    1599            0 :       fprintf (stderr, "o_file              = %s\n",
    1600            0 :                (o_file ? o_file : "not found"));
    1601              : 
    1602            0 :       ptr = getenv ("COLLECT_GCC_OPTIONS");
    1603            0 :       if (ptr)
    1604            0 :         fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
    1605              : 
    1606            0 :       ptr = getenv ("COLLECT_GCC");
    1607            0 :       if (ptr)
    1608            0 :         fprintf (stderr, "COLLECT_GCC         = %s\n", ptr);
    1609              : 
    1610            0 :       ptr = getenv ("COMPILER_PATH");
    1611            0 :       if (ptr)
    1612            0 :         fprintf (stderr, "COMPILER_PATH       = %s\n", ptr);
    1613              : 
    1614            0 :       ptr = getenv (LIBRARY_PATH_ENV);
    1615            0 :       if (ptr)
    1616            0 :         fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
    1617              : 
    1618            0 :       fprintf (stderr, "\n");
    1619              :     }
    1620              : 
    1621              :   /* Load the program, searching all libraries and attempting to provide
    1622              :      undefined symbols from repository information.
    1623              : 
    1624              :      If -r or they will be run via some other method, do not build the
    1625              :      constructor or destructor list, just return now.  */
    1626        93805 :   {
    1627       187610 :     bool early_exit
    1628        93805 :       = rflag || (! DO_COLLECT_EXPORT_LIST && ! do_collecting);
    1629              : 
    1630              :     /* Perform the first pass link now, if we're about to exit or if we need
    1631              :        to scan for things we haven't collected yet before pursuing further.
    1632              : 
    1633              :        On AIX, the latter typically includes nothing for shared objects or
    1634              :        frame tables for an executable, out of what the required early scan on
    1635              :        objects and libraries has performed above.  In the !shared_obj case, we
    1636              :        expect the relevant tables to be dragged together with their associated
    1637              :        functions from precise cross reference insertions by the compiler.  */
    1638              : 
    1639        93805 :     if (early_exit || ld1_filter != SCAN_NOTHING)
    1640        93805 :       do_link (ld1_argv, "ld1_args");
    1641              : 
    1642        93674 :     if (early_exit)
    1643              :       {
    1644              : #ifdef COLLECT_EXPORT_LIST
    1645              :         /* Make sure we delete the export file we may have created.  */
    1646              :         if (export_file != 0 && export_file[0])
    1647              :           maybe_unlink (export_file);
    1648              : #endif
    1649        93674 :         if (lto_mode != LTO_MODE_NONE)
    1650         4356 :           maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
    1651              :         else
    1652              :           post_ld_pass (/*temp_file*/false);
    1653              : 
    1654        93674 :         return 0;
    1655              :       }
    1656              :   }
    1657              : 
    1658              :   /* Unless we have done it all already, examine the namelist and search for
    1659              :      static constructors and destructors to call.  Write the constructor and
    1660              :      destructor tables to a .s file and reload.  */
    1661              : 
    1662            0 :   if (ld1_filter != SCAN_NOTHING)
    1663            0 :     scan_prog_file (output_file, PASS_FIRST, ld1_filter);
    1664              : 
    1665              : #ifdef SCAN_LIBRARIES
    1666              :   scan_libraries (output_file);
    1667              : #endif
    1668              : 
    1669            0 :   if (debug)
    1670              :     {
    1671            0 :       notice_translated (ngettext ("%d constructor found\n",
    1672              :                                    "%d constructors found\n",
    1673              :                                    constructors.number),
    1674              :                          constructors.number);
    1675            0 :       notice_translated (ngettext ("%d destructor found\n",
    1676              :                                    "%d destructors found\n",
    1677              :                                    destructors.number),
    1678              :                          destructors.number);
    1679            0 :       notice_translated (ngettext ("%d frame table found\n",
    1680              :                                    "%d frame tables found\n",
    1681              :                                    frame_tables.number),
    1682              :                          frame_tables.number);
    1683              :     }
    1684              : 
    1685              :   /* If the scan exposed nothing of special interest, there's no need to
    1686              :      generate the glue code and relink so return now.  */
    1687              : 
    1688            0 :   if (constructors.number == 0 && destructors.number == 0
    1689            0 :       && frame_tables.number == 0
    1690              : #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
    1691              :       /* If we will be running these functions ourselves, we want to emit
    1692              :          stubs into the shared library so that we do not have to relink
    1693              :          dependent programs when we add static objects.  */
    1694              :       && ! shared_obj
    1695              : #endif
    1696              :       )
    1697              :     {
    1698              :       /* Do link without additional code generation now if we didn't
    1699              :          do it earlier for scanning purposes.  */
    1700            0 :       if (ld1_filter == SCAN_NOTHING)
    1701              :         do_link (ld1_argv, "ld1_args");
    1702              : 
    1703            0 :       if (lto_mode)
    1704            0 :         maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
    1705              : 
    1706              :       /* Strip now if it was requested on the command line.  */
    1707            0 :       if (strip_flag)
    1708              :         {
    1709            0 :           char **real_strip_argv = XCNEWVEC (char *, 3);
    1710            0 :           const char ** strip_argv =
    1711              :             const_cast<const char **> (real_strip_argv);
    1712              : 
    1713            0 :           strip_argv[0] = strip_file_name;
    1714            0 :           strip_argv[1] = output_file;
    1715            0 :           strip_argv[2] = (char *) 0;
    1716            0 :           fork_execute ("strip", real_strip_argv, false, NULL);
    1717              :         }
    1718              : 
    1719              : #ifdef COLLECT_EXPORT_LIST
    1720              :       maybe_unlink (export_file);
    1721              : #endif
    1722            0 :       post_ld_pass (/*temp_file*/false);
    1723            0 :       return 0;
    1724              :     }
    1725              : 
    1726              :   /* Sort ctor and dtor lists by priority.  */
    1727            0 :   sort_ids (&constructors);
    1728            0 :   sort_ids (&destructors);
    1729              : 
    1730            0 :   maybe_unlink (output_file);
    1731            0 :   outf = fopen (c_file, "w");
    1732            0 :   if (outf == (FILE *) 0)
    1733            0 :     fatal_error (input_location, "fopen %s: %m", c_file);
    1734              : 
    1735            0 :   write_c_file (outf, c_file);
    1736              : 
    1737            0 :   if (fclose (outf))
    1738            0 :     fatal_error (input_location, "fclose %s: %m", c_file);
    1739              : 
    1740              :   /* Tell the linker that we have initializer and finalizer functions.  */
    1741              : #ifdef LD_INIT_SWITCH
    1742              : #ifdef COLLECT_EXPORT_LIST
    1743              :   *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
    1744              : #else
    1745              :   *ld2++ = LD_INIT_SWITCH;
    1746              :   *ld2++ = initname;
    1747              :   *ld2++ = LD_FINI_SWITCH;
    1748              :   *ld2++ = fininame;
    1749              : #endif
    1750              : #endif
    1751              : 
    1752              : #ifdef COLLECT_EXPORT_LIST
    1753              :   if (shared_obj)
    1754              :     {
    1755              :       /* If we did not add export flag to link arguments before, add it to
    1756              :          second link phase now.  No new exports should have been added.  */
    1757              :       if (! exports.first)
    1758              :         *ld2++ = concat ("-bE:", export_file, NULL);
    1759              : 
    1760              : #ifdef TARGET_AIX_VERSION
    1761              :       add_to_list (&exports, aix_shared_initname);
    1762              :       add_to_list (&exports, aix_shared_fininame);
    1763              : #endif
    1764              : 
    1765              : #ifndef LD_INIT_SWITCH
    1766              :       add_to_list (&exports, initname);
    1767              :       add_to_list (&exports, fininame);
    1768              :       add_to_list (&exports, "_GLOBAL__DI");
    1769              :       add_to_list (&exports, "_GLOBAL__DD");
    1770              : #endif
    1771              :       exportf = fopen (export_file, "w");
    1772              :       if (exportf == (FILE *) 0)
    1773              :         fatal_error (input_location, "fopen %s: %m", export_file);
    1774              :       write_aix_file (exportf, exports.first);
    1775              :       if (fclose (exportf))
    1776              :         fatal_error (input_location, "fclose %s: %m", export_file);
    1777              :     }
    1778              : #endif
    1779              : 
    1780              :   /* End of arguments to second link phase.  */
    1781            0 :   *ld2 = (char*) 0;
    1782              : 
    1783            0 :   if (debug)
    1784              :     {
    1785            0 :       fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
    1786              :                output_file, c_file);
    1787            0 :       write_c_file (stderr, "stderr");
    1788            0 :       fprintf (stderr, "========== end of c_file\n\n");
    1789              : #ifdef COLLECT_EXPORT_LIST
    1790              :       fprintf (stderr, "\n========== export_file = %s\n", export_file);
    1791              :       write_aix_file (stderr, exports.first);
    1792              :       fprintf (stderr, "========== end of export_file\n\n");
    1793              : #endif
    1794              :     }
    1795              : 
    1796              :   /* Assemble the constructor and destructor tables.
    1797              :      Link the tables in with the rest of the program.  */
    1798              : 
    1799            0 :   fork_execute ("gcc",  c_argv, at_file_supplied, "gcc_args");
    1800              : #ifdef COLLECT_EXPORT_LIST
    1801              :   /* On AIX we must call link because of possible templates resolution.  */
    1802              :   do_link (ld2_argv, "ld2_args");
    1803              : 
    1804              :   if (lto_mode)
    1805              :     maybe_run_lto_and_relink (ld2_argv, object_lst, object, false);
    1806              : #else
    1807              :   /* Otherwise, simply call ld because link is already done.  */
    1808            0 :   if (lto_mode)
    1809            0 :     maybe_run_lto_and_relink (ld2_argv, object_lst, object, true);
    1810              :   else
    1811              :     {
    1812            0 :       fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied, "ld_args");
    1813            0 :       post_ld_pass (/*temp_file*/false);
    1814              :     }
    1815              : 
    1816              :   /* Let scan_prog_file do any final mods (OSF/rose needs this for
    1817              :      constructors/destructors in shared libraries.  */
    1818            0 :   scan_prog_file (output_file, PASS_SECOND, SCAN_ALL);
    1819              : #endif
    1820              : 
    1821            0 :   return 0;
    1822              : }
    1823              : 
    1824              : 
    1825              : /* Unlink FILE unless we are debugging or this is the output_file
    1826              :    and we may not unlink it.  */
    1827              : 
    1828              : void
    1829       197166 : maybe_unlink (const char *file)
    1830              : {
    1831       197166 :   if (save_temps && file_exists (file))
    1832              :     {
    1833            2 :       if (verbose)
    1834            0 :         notice ("[Leaving %s]\n", file);
    1835            2 :       return;
    1836              :     }
    1837              : 
    1838       197164 :   if (file == output_file && !may_unlink_output_file)
    1839              :     return;
    1840              : 
    1841       197164 :   unlink_if_ordinary (file);
    1842              : }
    1843              : 
    1844              : /* Call maybe_unlink on the NULL-terminated list, FILE_LIST.  */
    1845              : 
    1846              : static void
    1847         8712 : maybe_unlink_list (char **file_list)
    1848              : {
    1849         8712 :   char **tmp = file_list;
    1850              : 
    1851        18268 :   while (*tmp)
    1852         9556 :     maybe_unlink (*(tmp++));
    1853         8712 : }
    1854              : 
    1855              : 
    1856              : static long sequence_number = 0;
    1857              : 
    1858              : /* Add a name to a linked list.  */
    1859              : 
    1860              : static void
    1861            0 : add_to_list (struct head *head_ptr, const char *name)
    1862              : {
    1863            0 :   struct id *newid
    1864            0 :     = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
    1865            0 :   struct id *p;
    1866            0 :   strcpy (newid->name, name);
    1867              : 
    1868            0 :   if (head_ptr->first)
    1869            0 :     head_ptr->last->next = newid;
    1870              :   else
    1871            0 :     head_ptr->first = newid;
    1872              : 
    1873              :   /* Check for duplicate symbols.  */
    1874            0 :   for (p = head_ptr->first;
    1875            0 :        strcmp (name, p->name) != 0;
    1876            0 :        p = p->next)
    1877              :     ;
    1878            0 :   if (p != newid)
    1879              :     {
    1880            0 :       head_ptr->last->next = 0;
    1881            0 :       free (newid);
    1882            0 :       return;
    1883              :     }
    1884              : 
    1885            0 :   newid->sequence = ++sequence_number;
    1886            0 :   head_ptr->last = newid;
    1887            0 :   head_ptr->number++;
    1888              : }
    1889              : 
    1890              : /* Grab the init priority number from an init function name that
    1891              :    looks like "_GLOBAL_.I.12345.foo".  */
    1892              : 
    1893              : static int
    1894            0 : extract_init_priority (const char *name)
    1895              : {
    1896            0 :   int pos = 0, pri;
    1897              : 
    1898              : #ifdef TARGET_AIX_VERSION
    1899              :   /* Run dependent module initializers before any constructors in this
    1900              :      module.  */
    1901              :   switch (is_ctor_dtor (name))
    1902              :     {
    1903              :     case SYM_AIXI:
    1904              :     case SYM_AIXD:
    1905              :       return INT_MIN;
    1906              :     default:
    1907              :       break;
    1908              :     }
    1909              : #endif
    1910              : 
    1911            0 :   while (name[pos] == '_')
    1912            0 :     ++pos;
    1913            0 :   pos += 10; /* strlen ("GLOBAL__X_") */
    1914              : 
    1915              :   /* Extract init_p number from ctor/dtor name.  */
    1916            0 :   pri = atoi (name + pos);
    1917            0 :   return pri ? pri : DEFAULT_INIT_PRIORITY;
    1918              : }
    1919              : 
    1920              : /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
    1921              :    ctors will be run from right to left, dtors from left to right.  */
    1922              : 
    1923              : static void
    1924            0 : sort_ids (struct head *head_ptr)
    1925              : {
    1926              :   /* id holds the current element to insert.  id_next holds the next
    1927              :      element to insert.  id_ptr iterates through the already sorted elements
    1928              :      looking for the place to insert id.  */
    1929            0 :   struct id *id, *id_next, **id_ptr;
    1930              : 
    1931            0 :   id = head_ptr->first;
    1932              : 
    1933              :   /* We don't have any sorted elements yet.  */
    1934            0 :   head_ptr->first = NULL;
    1935              : 
    1936            0 :   for (; id; id = id_next)
    1937              :     {
    1938            0 :       id_next = id->next;
    1939            0 :       id->sequence = extract_init_priority (id->name);
    1940              : 
    1941            0 :       for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
    1942            0 :         if (*id_ptr == NULL
    1943              :             /* If the sequence numbers are the same, we put the id from the
    1944              :                file later on the command line later in the list.  */
    1945            0 :             || id->sequence > (*id_ptr)->sequence
    1946              :             /* Hack: do lexical compare, too.
    1947              :             || (id->sequence == (*id_ptr)->sequence
    1948              :                 && strcmp (id->name, (*id_ptr)->name) > 0) */
    1949              :             )
    1950              :           {
    1951            0 :             id->next = *id_ptr;
    1952            0 :             *id_ptr = id;
    1953            0 :             break;
    1954              :           }
    1955              :     }
    1956              : 
    1957              :   /* Now set the sequence numbers properly so write_c_file works.  */
    1958            0 :   for (id = head_ptr->first; id; id = id->next)
    1959            0 :     id->sequence = ++sequence_number;
    1960            0 : }
    1961              : 
    1962              : /* Write: `prefix', the names on list LIST, `suffix'.  */
    1963              : 
    1964              : static void
    1965            0 : write_list (FILE *stream, const char *prefix, struct id *list)
    1966              : {
    1967            0 :   while (list)
    1968              :     {
    1969            0 :       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
    1970            0 :       list = list->next;
    1971              :     }
    1972            0 : }
    1973              : 
    1974              : #ifdef COLLECT_EXPORT_LIST
    1975              : /* This function is really used only on AIX, but may be useful.  */
    1976              : static int
    1977              : is_in_list (const char *prefix, struct id *list)
    1978              : {
    1979              :   while (list)
    1980              :     {
    1981              :       if (!strcmp (prefix, list->name)) return 1;
    1982              :       list = list->next;
    1983              :     }
    1984              :     return 0;
    1985              : }
    1986              : #endif /* COLLECT_EXPORT_LIST */
    1987              : 
    1988              : /* Added for debugging purpose.  */
    1989              : #ifdef COLLECT_EXPORT_LIST
    1990              : static void
    1991              : dump_list (FILE *stream, const char *prefix, struct id *list)
    1992              : {
    1993              :   while (list)
    1994              :     {
    1995              :       fprintf (stream, "%s%s,\n", prefix, list->name);
    1996              :       list = list->next;
    1997              :     }
    1998              : }
    1999              : #endif
    2000              : 
    2001              : #if 0
    2002              : static void
    2003              : dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
    2004              : {
    2005              :   while (list)
    2006              :     {
    2007              :       fprintf (stream, "%s%s,\n", prefix, list->prefix);
    2008              :       list = list->next;
    2009              :     }
    2010              : }
    2011              : #endif
    2012              : 
    2013              : static void
    2014            0 : write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
    2015              : {
    2016            0 :   while (list)
    2017              :     {
    2018            0 :       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
    2019            0 :                prefix, list->sequence, list->name);
    2020            0 :       list = list->next;
    2021              :     }
    2022            0 : }
    2023              : 
    2024              : /* Write out the constructor and destructor tables statically (for a shared
    2025              :    object), along with the functions to execute them.  */
    2026              : 
    2027              : static void
    2028            0 : write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
    2029              : {
    2030            0 :   const char *p, *q;
    2031            0 :   char *prefix, *r;
    2032            0 :   int frames = (frame_tables.number > 0);
    2033              : 
    2034              :   /* Figure out name of output_file, stripping off .so version.  */
    2035            0 :   q = p = lbasename (output_file);
    2036              : 
    2037            0 :   while (q)
    2038              :     {
    2039            0 :       q = strchr (q,'.');
    2040            0 :       if (q == 0)
    2041              :         {
    2042            0 :           q = p + strlen (p);
    2043            0 :           break;
    2044              :         }
    2045              :       else
    2046              :         {
    2047            0 :           if (filename_ncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0)
    2048              :             {
    2049            0 :               q += strlen (SHLIB_SUFFIX);
    2050            0 :               break;
    2051              :             }
    2052              :           else
    2053            0 :             q++;
    2054              :         }
    2055              :     }
    2056              :   /* q points to null at end of the string (or . of the .so version) */
    2057            0 :   prefix = XNEWVEC (char, q - p + 1);
    2058            0 :   strncpy (prefix, p, q - p);
    2059            0 :   prefix[q - p] = 0;
    2060            0 :   for (r = prefix; *r; r++)
    2061            0 :     if (!ISALNUM ((unsigned char)*r))
    2062            0 :       *r = '_';
    2063            0 :   if (debug)
    2064            0 :     notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
    2065              :             output_file, prefix);
    2066              : 
    2067            0 :   initname = concat ("_GLOBAL__FI_", prefix, NULL);
    2068            0 :   fininame = concat ("_GLOBAL__FD_", prefix, NULL);
    2069              : #ifdef TARGET_AIX_VERSION
    2070              :   aix_shared_initname = concat ("_GLOBAL__AIXI_", prefix, NULL);
    2071              :   aix_shared_fininame = concat ("_GLOBAL__AIXD_", prefix, NULL);
    2072              : #endif
    2073              : 
    2074            0 :   free (prefix);
    2075              : 
    2076              :   /* Write the tables as C code.  */
    2077              : 
    2078              :   /* This count variable is used to prevent multiple calls to the
    2079              :      constructors/destructors.
    2080              :      This guard against multiple calls is important on AIX as the initfini
    2081              :      functions are deliberately invoked multiple times as part of the
    2082              :      mechanisms GCC uses to order constructors across different dependent
    2083              :      shared libraries (see config/rs6000/aix.h).
    2084              :    */
    2085            0 :   fprintf (stream, "static int count;\n");
    2086            0 :   fprintf (stream, "typedef void entry_pt();\n");
    2087            0 :   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
    2088              : 
    2089            0 :   if (frames)
    2090              :     {
    2091            0 :       write_list_with_asm (stream, "extern void *", frame_tables.first);
    2092              : 
    2093            0 :       fprintf (stream, "\tstatic void *frame_table[] = {\n");
    2094            0 :       write_list (stream, "\t\t&", frame_tables.first);
    2095            0 :       fprintf (stream, "\t0\n};\n");
    2096              : 
    2097              :       /* This must match what's in frame.h.  */
    2098            0 :       fprintf (stream, "struct object {\n");
    2099            0 :       fprintf (stream, "  void *pc_begin;\n");
    2100            0 :       fprintf (stream, "  void *pc_end;\n");
    2101            0 :       fprintf (stream, "  void *fde_begin;\n");
    2102            0 :       fprintf (stream, "  void *fde_array;\n");
    2103            0 :       fprintf (stream, "  __SIZE_TYPE__ count;\n");
    2104            0 :       fprintf (stream, "  struct object *next;\n");
    2105            0 :       fprintf (stream, "};\n");
    2106              : 
    2107            0 :       fprintf (stream, "extern void __register_frame_info_table_bases (void *, struct object *, void *tbase, void *dbase);\n");
    2108            0 :       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
    2109            0 :       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
    2110              : #ifdef TARGET_AIX_VERSION
    2111              :       fprintf (stream, "extern void *__gcc_unwind_dbase;\n");
    2112              : #endif
    2113              : 
    2114            0 :       fprintf (stream, "static void reg_frame () {\n");
    2115            0 :       fprintf (stream, "\tstatic struct object ob;\n");
    2116              : #ifdef TARGET_AIX_VERSION
    2117              :       /* Use __gcc_unwind_dbase as the base address for data on AIX.
    2118              :          This might not be the start of the segment, signed offsets assumed.
    2119              :        */
    2120              :       fprintf (stream, "\t__register_frame_info_table_bases (frame_table, &ob, (void *)0, &__gcc_unwind_dbase);\n");
    2121              : #else
    2122            0 :       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
    2123              : #endif
    2124            0 :       fprintf (stream, "\t}\n");
    2125              : 
    2126            0 :       fprintf (stream, "static void dereg_frame () {\n");
    2127            0 :       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
    2128            0 :       fprintf (stream, "\t}\n");
    2129              :     }
    2130              : 
    2131              : #ifdef COLLECT_EXPORT_LIST
    2132              :   /* Set visibility of initializers to default.  */
    2133              :   if (visibility_flag)
    2134              :     fprintf (stream, "#pragma GCC visibility push(default)\n");
    2135              : #endif
    2136            0 :   fprintf (stream, "void %s() {\n", initname);
    2137            0 :   if (constructors.number > 0 || frames)
    2138              :     {
    2139            0 :       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
    2140            0 :       write_list (stream, "\t\t", constructors.first);
    2141            0 :       if (frames)
    2142            0 :         fprintf (stream, "\treg_frame,\n");
    2143            0 :       fprintf (stream, "\t};\n");
    2144            0 :       fprintf (stream, "\tentry_pt **p;\n");
    2145            0 :       fprintf (stream, "\tif (count++ != 0) return;\n");
    2146            0 :       fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
    2147            0 :       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
    2148              :     }
    2149              :   else
    2150            0 :     fprintf (stream, "\t++count;\n");
    2151            0 :   fprintf (stream, "}\n");
    2152            0 :   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
    2153            0 :   fprintf (stream, "void %s() {\n", fininame);
    2154            0 :   if (destructors.number > 0 || frames)
    2155              :     {
    2156            0 :       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
    2157            0 :       write_list (stream, "\t\t", destructors.first);
    2158            0 :       if (frames)
    2159            0 :         fprintf (stream, "\tdereg_frame,\n");
    2160            0 :       fprintf (stream, "\t};\n");
    2161            0 :       fprintf (stream, "\tentry_pt **p;\n");
    2162            0 :       fprintf (stream, "\tif (--count != 0) return;\n");
    2163            0 :       fprintf (stream, "\tp = dtors;\n");
    2164            0 :       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
    2165            0 :                destructors.number + frames);
    2166              :     }
    2167            0 :   fprintf (stream, "}\n");
    2168              : #ifdef COLLECT_EXPORT_LIST
    2169              :   if (visibility_flag)
    2170              :     fprintf (stream, "#pragma GCC visibility pop\n");
    2171              : #endif
    2172              : 
    2173            0 :   if (shared_obj)
    2174              :     {
    2175              : #ifdef COLLECT_EXPORT_LIST
    2176              :       /* Set visibility of initializers to default.  */
    2177              :       if (visibility_flag)
    2178              :         fprintf (stream, "#pragma GCC visibility push(default)\n");
    2179              : #endif
    2180            0 :       COLLECT_SHARED_INIT_FUNC (stream, initname);
    2181            0 :       COLLECT_SHARED_FINI_FUNC (stream, fininame);
    2182              : #ifdef COLLECT_EXPORT_LIST
    2183              :       if (visibility_flag)
    2184              :         fprintf (stream, "#pragma GCC visibility pop\n");
    2185              : #endif
    2186              :     }
    2187            0 : }
    2188              : 
    2189              : /* Write the constructor/destructor tables.  */
    2190              : 
    2191              : #ifndef LD_INIT_SWITCH
    2192              : static void
    2193            0 : write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
    2194              : {
    2195              :   /* Write the tables as C code.  */
    2196              : 
    2197            0 :   int frames = (frame_tables.number > 0);
    2198              : 
    2199            0 :   fprintf (stream, "typedef void entry_pt();\n\n");
    2200              : 
    2201            0 :   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
    2202              : 
    2203            0 :   if (frames)
    2204              :     {
    2205            0 :       write_list_with_asm (stream, "extern void *", frame_tables.first);
    2206              : 
    2207            0 :       fprintf (stream, "\tstatic void *frame_table[] = {\n");
    2208            0 :       write_list (stream, "\t\t&", frame_tables.first);
    2209            0 :       fprintf (stream, "\t0\n};\n");
    2210              : 
    2211              :       /* This must match what's in frame.h.  */
    2212            0 :       fprintf (stream, "struct object {\n");
    2213            0 :       fprintf (stream, "  void *pc_begin;\n");
    2214            0 :       fprintf (stream, "  void *pc_end;\n");
    2215            0 :       fprintf (stream, "  void *fde_begin;\n");
    2216            0 :       fprintf (stream, "  void *fde_array;\n");
    2217            0 :       fprintf (stream, "  __SIZE_TYPE__ count;\n");
    2218            0 :       fprintf (stream, "  struct object *next;\n");
    2219            0 :       fprintf (stream, "};\n");
    2220              : 
    2221            0 :       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
    2222            0 :       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
    2223              : 
    2224            0 :       fprintf (stream, "static void reg_frame () {\n");
    2225            0 :       fprintf (stream, "\tstatic struct object ob;\n");
    2226            0 :       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
    2227            0 :       fprintf (stream, "\t}\n");
    2228              : 
    2229            0 :       fprintf (stream, "static void dereg_frame () {\n");
    2230            0 :       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
    2231            0 :       fprintf (stream, "\t}\n");
    2232              :     }
    2233              : 
    2234            0 :   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
    2235            0 :   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
    2236            0 :   write_list (stream, "\t", constructors.first);
    2237            0 :   if (frames)
    2238            0 :     fprintf (stream, "\treg_frame,\n");
    2239            0 :   fprintf (stream, "\t0\n};\n\n");
    2240              : 
    2241            0 :   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
    2242              : 
    2243            0 :   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
    2244            0 :   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
    2245            0 :   write_list (stream, "\t", destructors.first);
    2246            0 :   if (frames)
    2247            0 :     fprintf (stream, "\tdereg_frame,\n");
    2248            0 :   fprintf (stream, "\t0\n};\n\n");
    2249              : 
    2250            0 :   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
    2251            0 :   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
    2252            0 : }
    2253              : #endif /* ! LD_INIT_SWITCH */
    2254              : 
    2255              : static void
    2256            0 : write_c_file (FILE *stream, const char *name)
    2257              : {
    2258              : #ifndef LD_INIT_SWITCH
    2259            0 :   if (! shared_obj)
    2260            0 :     write_c_file_glob (stream, name);
    2261              :   else
    2262              : #endif
    2263            0 :     write_c_file_stat (stream, name);
    2264            0 : }
    2265              : 
    2266              : #ifdef COLLECT_EXPORT_LIST
    2267              : static void
    2268              : write_aix_file (FILE *stream, struct id *list)
    2269              : {
    2270              :   for (; list; list = list->next)
    2271              :     {
    2272              :       fputs (list->name, stream);
    2273              :       putc ('\n', stream);
    2274              :     }
    2275              : }
    2276              : #endif
    2277              : 
    2278              : #ifdef OBJECT_FORMAT_NONE
    2279              : 
    2280              : /* Check to make sure the file is an LTO object file.  */
    2281              : 
    2282              : static int
    2283       421800 : has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED,
    2284              :                  off_t offset ATTRIBUTE_UNUSED,
    2285              :                  off_t length ATTRIBUTE_UNUSED)
    2286              : {
    2287       421800 :   int *found = (int *) data;
    2288              : 
    2289       421800 :   if (!startswith (name, LTO_SECTION_NAME_PREFIX)
    2290       421800 :       && !startswith (name, OFFLOAD_SECTION_NAME_PREFIX))
    2291              :     return 1;
    2292              : 
    2293         4673 :   *found = 1;
    2294              : 
    2295              :   /* Stop iteration.  */
    2296         4673 :   return 0;
    2297              : }
    2298              : 
    2299              : static bool
    2300        26510 : is_lto_object_file (const char *prog_name)
    2301              : {
    2302        26510 :   const char *errmsg;
    2303        26510 :   int err;
    2304        26510 :   int found = 0;
    2305        26510 :   off_t inoff = 0;
    2306        26510 :   int infd = open (prog_name, O_RDONLY | O_BINARY);
    2307              : 
    2308        26510 :   if (infd == -1)
    2309              :     return false;
    2310              : 
    2311        26510 :   simple_object_read *inobj = simple_object_start_read (infd, inoff,
    2312              :                                                         LTO_SEGMENT_NAME,
    2313              :                                                         &errmsg, &err);
    2314        26510 :   if (!inobj)
    2315              :     {
    2316            0 :       close (infd);
    2317            0 :       return false;
    2318              :     }
    2319              : 
    2320        26510 :   errmsg = simple_object_find_sections (inobj, has_lto_section,
    2321              :                                         (void *) &found, &err);
    2322        26510 :   simple_object_release_read (inobj);
    2323        26510 :   close (infd);
    2324        26510 :   if (! errmsg && found)
    2325              :     return true;
    2326              : 
    2327        21837 :   if (errmsg)
    2328            0 :     fatal_error (0, "%s: %s", errmsg, xstrerror (err));
    2329              :   return false;
    2330              : }
    2331              : 
    2332              : /* Generic version to scan the name list of the loaded program for
    2333              :    the symbols g++ uses for static constructors and destructors.  */
    2334              : 
    2335              : static void
    2336        26510 : scan_prog_file (const char *prog_name, scanpass which_pass,
    2337              :                 scanfilter filter)
    2338              : {
    2339        26510 :   void (*int_handler) (int);
    2340              : #ifdef SIGQUIT
    2341        26510 :   void (*quit_handler) (int);
    2342              : #endif
    2343        26510 :   char *real_nm_argv[4];
    2344        26510 :   const char **nm_argv = const_cast<const char **> (real_nm_argv);
    2345        26510 :   int argc = 0;
    2346        26510 :   struct pex_obj *pex;
    2347        26510 :   const char *errmsg;
    2348        26510 :   int err;
    2349        26510 :   char *p, buf[1024];
    2350        26510 :   FILE *inf;
    2351              : 
    2352        26510 :   if (which_pass == PASS_SECOND)
    2353        26510 :     return;
    2354              : 
    2355              :   /* LTO objects must be in a known format.  This check prevents
    2356              :      us from accepting an archive containing LTO objects, which
    2357              :      gcc cannot currently handle.  */
    2358        26510 :   if (which_pass == PASS_LTOINFO)
    2359              :     {
    2360        26510 :       if(is_lto_object_file (prog_name)) {
    2361         4673 :         add_lto_object (&lto_objects, prog_name);
    2362              :       }
    2363        26510 :       return;
    2364              :     }
    2365              : 
    2366              :   /* If we do not have an `nm', complain.  */
    2367            0 :   if (nm_file_name == 0)
    2368            0 :     fatal_error (input_location, "cannot find %<nm%>");
    2369              : 
    2370            0 :   nm_argv[argc++] = nm_file_name;
    2371            0 :   if (NM_FLAGS[0] != '\0')
    2372            0 :     nm_argv[argc++] = NM_FLAGS;
    2373              : 
    2374            0 :   nm_argv[argc++] = prog_name;
    2375            0 :   nm_argv[argc++] = (char *) 0;
    2376              : 
    2377              :   /* Trace if needed.  */
    2378            0 :   if (verbose)
    2379              :     {
    2380              :       const char **p_argv;
    2381              :       const char *str;
    2382              : 
    2383            0 :       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
    2384            0 :         fprintf (stderr, " %s", str);
    2385              : 
    2386            0 :       fprintf (stderr, "\n");
    2387              :     }
    2388              : 
    2389            0 :   fflush (stdout);
    2390            0 :   fflush (stderr);
    2391              : 
    2392            0 :   pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
    2393            0 :   if (pex == NULL)
    2394              :     fatal_error (input_location, "%<pex_init%> failed: %m");
    2395              : 
    2396            0 :   errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET,
    2397              :                     &err);
    2398            0 :   if (errmsg != NULL)
    2399              :     {
    2400            0 :       if (err != 0)
    2401              :         {
    2402            0 :           errno = err;
    2403            0 :           fatal_error (input_location, "%s: %m", _(errmsg));
    2404              :         }
    2405              :       else
    2406            0 :         fatal_error (input_location, errmsg);
    2407              :     }
    2408              : 
    2409            0 :   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
    2410              : #ifdef SIGQUIT
    2411            0 :   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
    2412              : #endif
    2413              : 
    2414            0 :   inf = pex_read_output (pex, 0);
    2415            0 :   if (inf == NULL)
    2416            0 :     fatal_error (input_location, "cannot open nm output: %m");
    2417              : 
    2418            0 :   if (debug)
    2419            0 :     fprintf (stderr, "\nnm output with constructors/destructors.\n");
    2420              : 
    2421              :   /* Read each line of nm output.  */
    2422            0 :   while (fgets (buf, sizeof buf, inf) != (char *) 0)
    2423              :     {
    2424            0 :       int ch, ch2;
    2425            0 :       char *name, *end;
    2426              : 
    2427            0 :       if (debug)
    2428            0 :         fprintf (stderr, "\t%s\n", buf);
    2429              : 
    2430              :       /* If it contains a constructor or destructor name, add the name
    2431              :          to the appropriate list unless this is a kind of symbol we're
    2432              :          not supposed to even consider.  */
    2433              : 
    2434            0 :       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
    2435            0 :         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
    2436              :           break;
    2437              : 
    2438            0 :       if (ch != '_')
    2439            0 :         continue;
    2440              : 
    2441              :       name = p;
    2442              :       /* Find the end of the symbol name.
    2443              :          Do not include `|', because Encore nm can tack that on the end.  */
    2444            0 :       for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
    2445              :            end++)
    2446            0 :         continue;
    2447              : 
    2448              : 
    2449            0 :       *end = '\0';
    2450              : 
    2451            0 :       switch (is_ctor_dtor (name))
    2452              :         {
    2453            0 :         case SYM_CTOR:
    2454            0 :           if (! (filter & SCAN_CTOR))
    2455              :             break;
    2456            0 :           if (which_pass != PASS_LIB)
    2457            0 :             add_to_list (&constructors, name);
    2458              :           break;
    2459              : 
    2460            0 :         case SYM_DTOR:
    2461            0 :           if (! (filter & SCAN_DTOR))
    2462              :             break;
    2463            0 :           if (which_pass != PASS_LIB)
    2464            0 :             add_to_list (&destructors, name);
    2465              :           break;
    2466              : 
    2467            0 :         case SYM_INIT:
    2468            0 :           if (! (filter & SCAN_INIT))
    2469              :             break;
    2470            0 :           if (which_pass != PASS_LIB)
    2471            0 :             fatal_error (input_location, "init function found in object %s",
    2472              :                          prog_name);
    2473              : #ifndef LD_INIT_SWITCH
    2474            0 :           add_to_list (&constructors, name);
    2475              : #endif
    2476            0 :           break;
    2477              : 
    2478            0 :         case SYM_FINI:
    2479            0 :           if (! (filter & SCAN_FINI))
    2480              :             break;
    2481            0 :           if (which_pass != PASS_LIB)
    2482            0 :             fatal_error (input_location, "fini function found in object %s",
    2483              :                          prog_name);
    2484              : #ifndef LD_FINI_SWITCH
    2485            0 :           add_to_list (&destructors, name);
    2486              : #endif
    2487            0 :           break;
    2488              : 
    2489            0 :         case SYM_DWEH:
    2490            0 :           if (! (filter & SCAN_DWEH))
    2491              :             break;
    2492            0 :           if (which_pass != PASS_LIB)
    2493            0 :             add_to_list (&frame_tables, name);
    2494              :           break;
    2495              : 
    2496            0 :         default:                /* not a constructor or destructor */
    2497            0 :           continue;
    2498              :         }
    2499            0 :     }
    2500              : 
    2501            0 :   if (debug)
    2502            0 :     fprintf (stderr, "\n");
    2503              : 
    2504            0 :   do_wait (nm_file_name, pex);
    2505              : 
    2506            0 :   signal (SIGINT,  int_handler);
    2507              : #ifdef SIGQUIT
    2508            0 :   signal (SIGQUIT, quit_handler);
    2509              : #endif
    2510              : }
    2511              : 
    2512              : #ifdef LDD_SUFFIX
    2513              : 
    2514              : /* Use the List Dynamic Dependencies program to find shared libraries that
    2515              :    the output file depends upon and their initialization/finalization
    2516              :    routines, if any.  */
    2517              : 
    2518              : static void
    2519              : scan_libraries (const char *prog_name)
    2520              : {
    2521              :   static struct head libraries;         /* list of shared libraries found */
    2522              :   struct id *list;
    2523              :   void (*int_handler) (int);
    2524              : #ifdef SIGQUIT
    2525              :   void (*quit_handler) (int);
    2526              : #endif
    2527              :   char *real_ldd_argv[4];
    2528              :   const char **ldd_argv = const_cast<const char **> (real_ldd_argv);
    2529              :   int argc = 0;
    2530              :   struct pex_obj *pex;
    2531              :   const char *errmsg;
    2532              :   int err;
    2533              :   char buf[1024];
    2534              :   FILE *inf;
    2535              : 
    2536              :   /* If we do not have an `ldd', complain.  */
    2537              :   if (ldd_file_name == 0)
    2538              :     {
    2539              :       error ("cannot find %<ldd%>");
    2540              :       return;
    2541              :     }
    2542              : 
    2543              :   ldd_argv[argc++] = ldd_file_name;
    2544              :   ldd_argv[argc++] = prog_name;
    2545              :   ldd_argv[argc++] = (char *) 0;
    2546              : 
    2547              :   /* Trace if needed.  */
    2548              :   if (verbose)
    2549              :     {
    2550              :       const char **p_argv;
    2551              :       const char *str;
    2552              : 
    2553              :       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
    2554              :         fprintf (stderr, " %s", str);
    2555              : 
    2556              :       fprintf (stderr, "\n");
    2557              :     }
    2558              : 
    2559              :   fflush (stdout);
    2560              :   fflush (stderr);
    2561              : 
    2562              :   pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
    2563              :   if (pex == NULL)
    2564              :     fatal_error (input_location, "%<pex_init%> failed: %m");
    2565              : 
    2566              :   errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
    2567              :   if (errmsg != NULL)
    2568              :     {
    2569              :       if (err != 0)
    2570              :         {
    2571              :           errno = err;
    2572              :           fatal_error (input_location, "%s: %m", _(errmsg));
    2573              :         }
    2574              :       else
    2575              :         fatal_error (input_location, errmsg);
    2576              :     }
    2577              : 
    2578              :   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
    2579              : #ifdef SIGQUIT
    2580              :   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
    2581              : #endif
    2582              : 
    2583              :   inf = pex_read_output (pex, 0);
    2584              :   if (inf == NULL)
    2585              :     fatal_error (input_location, "cannot open ldd output: %m");
    2586              : 
    2587              :   if (debug)
    2588              :     notice ("\nldd output with constructors/destructors.\n");
    2589              : 
    2590              :   /* Read each line of ldd output.  */
    2591              :   while (fgets (buf, sizeof buf, inf) != (char *) 0)
    2592              :     {
    2593              :       int ch2;
    2594              :       char *name, *end, *p = buf;
    2595              : 
    2596              :       /* Extract names of libraries and add to list.  */
    2597              :       PARSE_LDD_OUTPUT (p);
    2598              :       if (p == 0)
    2599              :         continue;
    2600              : 
    2601              :       name = p;
    2602              :       if (startswith (name, "not found"))
    2603              :         fatal_error (input_location, "dynamic dependency %s not found", buf);
    2604              : 
    2605              :       /* Find the end of the symbol name.  */
    2606              :       for (end = p;
    2607              :            (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
    2608              :            end++)
    2609              :         continue;
    2610              :       *end = '\0';
    2611              : 
    2612              :       if (access (name, R_OK) == 0)
    2613              :         add_to_list (&libraries, name);
    2614              :       else
    2615              :         fatal_error (input_location, "unable to open dynamic dependency "
    2616              :                      "%qs", buf);
    2617              : 
    2618              :       if (debug)
    2619              :         fprintf (stderr, "\t%s\n", buf);
    2620              :     }
    2621              :   if (debug)
    2622              :     fprintf (stderr, "\n");
    2623              : 
    2624              :   do_wait (ldd_file_name, pex);
    2625              : 
    2626              :   signal (SIGINT,  int_handler);
    2627              : #ifdef SIGQUIT
    2628              :   signal (SIGQUIT, quit_handler);
    2629              : #endif
    2630              : 
    2631              :   /* Now iterate through the library list adding their symbols to
    2632              :      the list.  */
    2633              :   for (list = libraries.first; list; list = list->next)
    2634              :     scan_prog_file (list->name, PASS_LIB, SCAN_ALL);
    2635              : }
    2636              : 
    2637              : #endif /* LDD_SUFFIX */
    2638              : 
    2639              : #endif /* OBJECT_FORMAT_NONE */
    2640              : 
    2641              : 
    2642              : /*
    2643              :  * COFF specific stuff.
    2644              :  */
    2645              : 
    2646              : #ifdef OBJECT_FORMAT_COFF
    2647              : 
    2648              : #   define GCC_SYMBOLS(X)       (HEADER (ldptr).f_nsyms)
    2649              : #   define GCC_SYMENT           SYMENT
    2650              : #   if defined (C_WEAKEXT)
    2651              : #     define GCC_OK_SYMBOL(X) \
    2652              :        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
    2653              :         ((X).n_scnum > N_UNDEF) && \
    2654              :         (aix64_flag \
    2655              :          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
    2656              :              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
    2657              : #     define GCC_UNDEF_SYMBOL(X) \
    2658              :        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
    2659              :         ((X).n_scnum == N_UNDEF))
    2660              : #   else
    2661              : #     define GCC_OK_SYMBOL(X) \
    2662              :        (((X).n_sclass == C_EXT) && \
    2663              :         ((X).n_scnum > N_UNDEF) && \
    2664              :         (aix64_flag \
    2665              :          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
    2666              :              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
    2667              : #     define GCC_UNDEF_SYMBOL(X) \
    2668              :        (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
    2669              : #   endif
    2670              : #   define GCC_SYMINC(X)        ((X).n_numaux+1)
    2671              : #   define GCC_SYMZERO(X)       0
    2672              : 
    2673              : /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
    2674              : #if TARGET_AIX_VERSION >= 51
    2675              : #   define GCC_CHECK_HDR(X) \
    2676              :      (((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
    2677              :        || (HEADER (X).f_magic == 0767 && aix64_flag)) \
    2678              :       && !(HEADER (X).f_flags & F_LOADONLY))
    2679              : #else
    2680              : #   define GCC_CHECK_HDR(X) \
    2681              :      (((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
    2682              :        || (HEADER (X).f_magic == 0757 && aix64_flag)) \
    2683              :       && !(HEADER (X).f_flags & F_LOADONLY))
    2684              : #endif
    2685              : 
    2686              : #ifdef COLLECT_EXPORT_LIST
    2687              : /* Array of standard AIX libraries which should not
    2688              :    be scanned for ctors/dtors.  */
    2689              : static const char *const aix_std_libs[] = {
    2690              :   "/unix",
    2691              :   "/lib/libc.a",
    2692              :   "/lib/libm.a",
    2693              :   "/lib/libc_r.a",
    2694              :   "/lib/libm_r.a",
    2695              :   "/usr/lib/libc.a",
    2696              :   "/usr/lib/libm.a",
    2697              :   "/usr/lib/libc_r.a",
    2698              :   "/usr/lib/libm_r.a",
    2699              :   "/usr/lib/threads/libc.a",
    2700              :   "/usr/ccs/lib/libc.a",
    2701              :   "/usr/ccs/lib/libm.a",
    2702              :   "/usr/ccs/lib/libc_r.a",
    2703              :   "/usr/ccs/lib/libm_r.a",
    2704              :   NULL
    2705              : };
    2706              : 
    2707              : /* This function checks the filename and returns 1
    2708              :    if this name matches the location of a standard AIX library.  */
    2709              : static int ignore_library (const char *);
    2710              : static int
    2711              : ignore_library (const char *name)
    2712              : {
    2713              :   const char *const *p;
    2714              :   size_t length;
    2715              : 
    2716              :   if (target_system_root[0] != '\0')
    2717              :     {
    2718              :       length = strlen (target_system_root);
    2719              :       if (strncmp (name, target_system_root, length) != 0)
    2720              :         return 0;
    2721              :       name += length;
    2722              :     }
    2723              :   for (p = &aix_std_libs[0]; *p != NULL; ++p)
    2724              :     if (strcmp (name, *p) == 0)
    2725              :       return 1;
    2726              :   return 0;
    2727              : }
    2728              : #endif /* COLLECT_EXPORT_LIST */
    2729              : 
    2730              : #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
    2731              : extern char *ldgetname (LDFILE *, GCC_SYMENT *);
    2732              : #endif
    2733              : 
    2734              : /* COFF version to scan the name list of the loaded program for
    2735              :    the symbols g++ uses for static constructors and destructors.  */
    2736              : 
    2737              : static void
    2738              : scan_prog_file (const char *prog_name, scanpass which_pass,
    2739              :                 scanfilter filter)
    2740              : {
    2741              :   LDFILE *ldptr = NULL;
    2742              :   int sym_index, sym_count;
    2743              :   int is_shared = 0;
    2744              : 
    2745              :   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
    2746              :     return;
    2747              : 
    2748              : #ifdef COLLECT_EXPORT_LIST
    2749              :   /* We do not need scanning for some standard C libraries.  */
    2750              :   if (which_pass == PASS_FIRST && ignore_library (prog_name))
    2751              :     return;
    2752              : 
    2753              :   /* On AIX we have a loop, because there is not much difference
    2754              :      between an object and an archive. This trick allows us to
    2755              :      eliminate scan_libraries() function.  */
    2756              :   do
    2757              :     {
    2758              : #endif
    2759              :       /* Some platforms (e.g. OSF4) declare ldopen as taking a
    2760              :          non-const char * filename parameter, even though it will not
    2761              :          modify that string.  So we must cast away const-ness here,
    2762              :          using CONST_CAST to prevent complaints from -Wcast-qual.  */
    2763              :       if ((ldptr = ldopen (const_cast<char *> (prog_name), ldptr)) != NULL)
    2764              :         {
    2765              :           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
    2766              :             {
    2767              :               warning (0, "%s: not a COFF file", prog_name);
    2768              :               continue;
    2769              :             }
    2770              : 
    2771              :           if (GCC_CHECK_HDR (ldptr))
    2772              :             {
    2773              :               sym_count = GCC_SYMBOLS (ldptr);
    2774              :               sym_index = GCC_SYMZERO (ldptr);
    2775              : 
    2776              : #ifdef COLLECT_EXPORT_LIST
    2777              :               /* Is current archive member a shared object?  */
    2778              :               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
    2779              : #endif
    2780              : 
    2781              :               while (sym_index < sym_count)
    2782              :                 {
    2783              :                   GCC_SYMENT symbol;
    2784              : 
    2785              :                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
    2786              :                     break;
    2787              :                   sym_index += GCC_SYMINC (symbol);
    2788              : 
    2789              :                   if (GCC_OK_SYMBOL (symbol))
    2790              :                     {
    2791              :                       char *name;
    2792              : 
    2793              :                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
    2794              :                         continue;               /* Should never happen.  */
    2795              : 
    2796              : #ifdef XCOFF_DEBUGGING_INFO
    2797              :                       /* All AIX function names have a duplicate entry
    2798              :                          beginning with a dot.  */
    2799              :                       if (*name == '.')
    2800              :                         ++name;
    2801              : #endif
    2802              : 
    2803              :                       switch (is_ctor_dtor (name))
    2804              :                         {
    2805              : #if TARGET_AIX_VERSION
    2806              :                       /* Add AIX shared library initalisers/finalisers
    2807              :                          to the constructors/destructors list of the
    2808              :                          current module.  */
    2809              :                         case SYM_AIXI:
    2810              :                           if (! (filter & SCAN_CTOR))
    2811              :                             break;
    2812              :                           if (is_shared && !aixlazy_flag
    2813              : #ifdef COLLECT_EXPORT_LIST
    2814              :                               && ! static_obj
    2815              :                               && ! is_in_list (prog_name, static_libs.first)
    2816              : #endif
    2817              :                               )
    2818              :                             add_to_list (&constructors, name);
    2819              :                           break;
    2820              : 
    2821              :                         case SYM_AIXD:
    2822              :                           if (! (filter & SCAN_DTOR))
    2823              :                             break;
    2824              :                           if (is_shared && !aixlazy_flag)
    2825              :                             add_to_list (&destructors, name);
    2826              :                           break;
    2827              : #endif
    2828              : 
    2829              :                         case SYM_CTOR:
    2830              :                           if (! (filter & SCAN_CTOR))
    2831              :                             break;
    2832              :                           if (! is_shared)
    2833              :                             add_to_list (&constructors, name);
    2834              : #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
    2835              :                           if (which_pass == PASS_OBJ)
    2836              :                             add_to_list (&exports, name);
    2837              : #endif
    2838              :                           break;
    2839              : 
    2840              :                         case SYM_DTOR:
    2841              :                           if (! (filter & SCAN_DTOR))
    2842              :                             break;
    2843              :                           if (! is_shared)
    2844              :                             add_to_list (&destructors, name);
    2845              : #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
    2846              :                           if (which_pass == PASS_OBJ)
    2847              :                             add_to_list (&exports, name);
    2848              : #endif
    2849              :                           break;
    2850              : 
    2851              : #ifdef COLLECT_EXPORT_LIST
    2852              :                         case SYM_INIT:
    2853              :                           if (! (filter & SCAN_INIT))
    2854              :                             break;
    2855              : #ifndef LD_INIT_SWITCH
    2856              :                           if (is_shared)
    2857              :                             add_to_list (&constructors, name);
    2858              : #endif
    2859              :                           break;
    2860              : 
    2861              :                         case SYM_FINI:
    2862              :                           if (! (filter & SCAN_FINI))
    2863              :                             break;
    2864              : #ifndef LD_INIT_SWITCH
    2865              :                           if (is_shared)
    2866              :                             add_to_list (&destructors, name);
    2867              : #endif
    2868              :                           break;
    2869              : #endif
    2870              : 
    2871              :                         case SYM_DWEH:
    2872              :                           if (! (filter & SCAN_DWEH))
    2873              :                             break;
    2874              :                           if (! is_shared)
    2875              :                             add_to_list (&frame_tables, name);
    2876              : #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
    2877              :                           if (which_pass == PASS_OBJ)
    2878              :                             add_to_list (&exports, name);
    2879              : #endif
    2880              :                           break;
    2881              : 
    2882              :                         default:        /* not a constructor or destructor */
    2883              : #ifdef COLLECT_EXPORT_LIST
    2884              :                           /* Explicitly export all global symbols when
    2885              :                              building a shared object on AIX, but do not
    2886              :                              re-export symbols from another shared object
    2887              :                              and do not export symbols if the user
    2888              :                              provides an explicit export list.  */
    2889              :                           if (shared_obj && !is_shared
    2890              :                               && which_pass == PASS_OBJ && !export_flag)
    2891              :                             {
    2892              :                               /* Do not auto-export __dso_handle or
    2893              :                                  __gcc_unwind_dbase.  They are required
    2894              :                                  to be local to each module.  */
    2895              :                               if (strcmp(name, "__dso_handle") != 0
    2896              :                                   && strcmp(name, "__gcc_unwind_dbase") != 0)
    2897              :                                 {
    2898              :                                   add_to_list (&exports, name);
    2899              :                                 }
    2900              :                             }
    2901              : #endif
    2902              :                           continue;
    2903              :                         }
    2904              : 
    2905              :                       if (debug)
    2906              :                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
    2907              :                                  symbol.n_scnum, symbol.n_sclass,
    2908              :                                  (symbol.n_type ? "0" : ""), symbol.n_type,
    2909              :                                  name);
    2910              :                     }
    2911              :                 }
    2912              :             }
    2913              : #ifdef COLLECT_EXPORT_LIST
    2914              :           else
    2915              :             {
    2916              :               /* If archive contains both 32-bit and 64-bit objects,
    2917              :                  we want to skip objects in other mode so mismatch normal.  */
    2918              :               if (debug)
    2919              :                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
    2920              :                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
    2921              :             }
    2922              : #endif
    2923              :         }
    2924              :       else
    2925              :         {
    2926              :           fatal_error (input_location, "%s: cannot open as COFF file",
    2927              :                        prog_name);
    2928              :         }
    2929              : #ifdef COLLECT_EXPORT_LIST
    2930              :       /* On AIX loop continues while there are more members in archive.  */
    2931              :     }
    2932              :   while (ldclose (ldptr) == FAILURE);
    2933              : #else
    2934              :   /* Otherwise we simply close ldptr.  */
    2935              :   (void) ldclose (ldptr);
    2936              : #endif
    2937              : }
    2938              : #endif /* OBJECT_FORMAT_COFF */
    2939              : 
    2940              : #ifdef COLLECT_EXPORT_LIST
    2941              : /* Given a library name without "lib" prefix, this function
    2942              :    returns a full library name including a path.  */
    2943              : static char *
    2944              : resolve_lib_name (const char *name)
    2945              : {
    2946              :   char *lib_buf;
    2947              :   int i, j, l = 0;
    2948              :   /* Library extensions for AIX dynamic linking.  */
    2949              :   const char * const libexts[2] = {"a", "so"};
    2950              : 
    2951              :   for (i = 0; libpaths[i]; i++)
    2952              :     if (libpaths[i]->max_len > l)
    2953              :       l = libpaths[i]->max_len;
    2954              : 
    2955              :   lib_buf = XNEWVEC (char, l + strlen (name) + 10);
    2956              : 
    2957              :   for (i = 0; libpaths[i]; i++)
    2958              :     {
    2959              :       struct prefix_list *list = libpaths[i]->plist;
    2960              :       for (; list; list = list->next)
    2961              :         {
    2962              :           /* The following lines are needed because path_prefix list
    2963              :              may contain directories both with trailing DIR_SEPARATOR and
    2964              :              without it.  */
    2965              :           const char *p = "";
    2966              :           if (!IS_DIR_SEPARATOR (list->prefix[strlen (list->prefix)-1]))
    2967              :             p = "/";
    2968              :           for (j = 0; j < 2; j++)
    2969              :             {
    2970              :               sprintf (lib_buf, "%s%slib%s.%s",
    2971              :                        list->prefix, p, name,
    2972              :                        libexts[(j + aixrtl_flag) % 2]);
    2973              :               if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
    2974              :               if (file_exists (lib_buf))
    2975              :                 {
    2976              :                   if (debug) fprintf (stderr, "found: %s\n", lib_buf);
    2977              :                   return (lib_buf);
    2978              :                 }
    2979              :             }
    2980              :         }
    2981              :     }
    2982              :   if (debug)
    2983              :     fprintf (stderr, "not found\n");
    2984              :   else
    2985              :     fatal_error (input_location, "library lib%s not found", name);
    2986              :   return (NULL);
    2987              : }
    2988              : #endif /* COLLECT_EXPORT_LIST */
    2989              : 
    2990              : #ifdef COLLECT_RUN_DSYMUTIL
    2991              : static int flag_dsym = false;
    2992              : static int flag_idsym = false;
    2993              : 
    2994              : static void
    2995              : process_args (int *argcp, char **argv) {
    2996              :   int i, j;
    2997              :   int argc = *argcp;
    2998              :   for (i=0; i<argc; ++i)
    2999              :     {
    3000              :       if (strcmp (argv[i], "-dsym") == 0)
    3001              :         {
    3002              :           flag_dsym = true;
    3003              :           /* Remove the flag, as we handle all processing for it.  */
    3004              :           j = i;
    3005              :           do
    3006              :             argv[j] = argv[j+1];
    3007              :           while (++j < argc);
    3008              :           --i;
    3009              :           argc = --(*argcp);
    3010              :         }
    3011              :       else if (strcmp (argv[i], "-idsym") == 0)
    3012              :         {
    3013              :           flag_idsym = true;
    3014              :           /* Remove the flag, as we handle all processing for it.  */
    3015              :           j = i;
    3016              :           do
    3017              :             argv[j] = argv[j+1];
    3018              :           while (++j < argc);
    3019              :           --i;
    3020              :           argc = --(*argcp);
    3021              :         }
    3022              :     }
    3023              : }
    3024              : 
    3025              : static void
    3026              : do_dsymutil (const char *output_file) {
    3027              :   const char *dsymutil = 0;
    3028              :   struct pex_obj *pex;
    3029              :   char **real_argv = XCNEWVEC (char *, verbose ? 4 : 3);
    3030              :   const char ** argv = const_cast<const char **> (real_argv);
    3031              : /* For cross-builds search the PATH using target-qualified name if we
    3032              :    have not already found a suitable dsymutil.  In practice, all modern
    3033              :    versions of dsymutil handle all supported archs, however the approach
    3034              :    here is consistent with the way other installations work (and one can
    3035              :    always symlink a multitarget dsymutil with a target-specific name).  */
    3036              :   const char *dsname = "dsymutil";
    3037              : #ifdef CROSS_DIRECTORY_STRUCTURE
    3038              :   const char *qname = concat (target_machine, "-", dsname, NULL);
    3039              : #else
    3040              :   const char *qname = dsname;
    3041              : #endif
    3042              : #ifdef DEFAULT_DSYMUTIL
    3043              :   /* Configured default takes priority.  */
    3044              :   if (dsymutil == 0 && access (DEFAULT_DSYMUTIL, X_OK) == 0)
    3045              :     dsymutil = DEFAULT_DSYMUTIL;
    3046              :   if (dsymutil == 0)
    3047              : #endif
    3048              : #ifdef DSYMUTIL
    3049              :   /* Followed by one supplied in the target header, somewhat like the
    3050              :      REAL_XX_NAME used elsewhere.  */
    3051              :     dsymutil = find_a_file (&cpath, DSYMUTIL, X_OK);
    3052              :   if (dsymutil == 0)
    3053              :     dsymutil = find_a_file (&path, DSYMUTIL, X_OK);
    3054              :   if (dsymutil == 0)
    3055              : #endif
    3056              :     dsymutil = find_a_file (&cpath, dsname, X_OK);
    3057              :   if (dsymutil == 0)
    3058              :     dsymutil = find_a_file (&path, qname, X_OK);
    3059              : 
    3060              :   argv[0] = dsymutil;
    3061              :   argv[1] = output_file;
    3062              :   if (verbose)
    3063              :     {
    3064              :       argv[2] = "-v";
    3065              :       argv[3] = (char *) 0;
    3066              :     }
    3067              :   else
    3068              :     argv[2] = (char *) 0;
    3069              : 
    3070              :   pex = collect_execute (dsymutil, real_argv, NULL, NULL,
    3071              :                          PEX_LAST | PEX_SEARCH, false, NULL);
    3072              :   do_wait (dsymutil, pex);
    3073              : }
    3074              : 
    3075              : static void
    3076              : post_ld_pass (bool temp_file) {
    3077              :   if (!(temp_file && flag_idsym) && !flag_dsym)
    3078              :     return;
    3079              : 
    3080              :   do_dsymutil (output_file);
    3081              : }
    3082              : #else
    3083              : static void
    3084            0 : process_args (int *argcp ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { }
    3085            0 : static void post_ld_pass (bool temp_file ATTRIBUTE_UNUSED) { }
    3086              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.