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-07-11 15:47:05 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        95136 : tool_cleanup (bool from_signal)
     384              : {
     385              :   /* maybe_unlink may call notice, which is not signal safe.  */
     386        95136 :   if (from_signal)
     387            0 :     verbose = false;
     388              : 
     389        95136 :   if (c_file != 0 && c_file[0])
     390        95136 :     maybe_unlink (c_file);
     391              : 
     392        95136 :   if (o_file != 0 && o_file[0])
     393        95136 :     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        95136 :   if (lto_o_files)
     401         4412 :     maybe_unlink_list (lto_o_files);
     402        95136 : }
     403              : 
     404              : static void
     405        95136 : collect_atexit (void)
     406              : {
     407        95136 :   tool_cleanup (false);
     408        95136 : }
     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          526 : file_exists (const char *name)
     423              : {
     424          526 :   return access (name, R_OK) == 0;
     425              : }
     426              : 
     427              : /* Parse a reasonable subset of shell quoting syntax.  */
     428              : 
     429              : static char *
     430      5661418 : extract_string (const char **pp)
     431              : {
     432      5661418 :   const char *p = *pp;
     433      5661418 :   int backquote = 0;
     434      5661418 :   int inside = 0;
     435              : 
     436    173228604 :   for (;;)
     437              :     {
     438    173228604 :       char c = *p;
     439    173228604 :       if (c == '\0')
     440              :         break;
     441    173038332 :       ++p;
     442    173038332 :       if (backquote)
     443            0 :         obstack_1grow (&temporary_obstack, c);
     444    173038332 :       else if (! inside && c == ' ')
     445              :         break;
     446    167567186 :       else if (! inside && c == '\\')
     447              :         backquote = 1;
     448    167567186 :       else if (c == '\'')
     449     11317020 :         inside = !inside;
     450              :       else
     451    156250166 :         obstack_1grow (&temporary_obstack, c);
     452              :     }
     453              : 
     454      5661418 :   obstack_1grow (&temporary_obstack, '\0');
     455      5661418 :   *pp = p;
     456      5661418 :   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         4731 : add_lto_object (struct lto_object_list *list, const char *name)
     536              : {
     537         4731 :   struct lto_object *n = XNEW (struct lto_object);
     538         4731 :   n->name = name;
     539         4731 :   n->next = NULL;
     540              : 
     541         4731 :   if (list->last)
     542          319 :     list->last->next = n;
     543              :   else
     544         4412 :     list->first = n;
     545              : 
     546         4731 :   list->last = n;
     547         4731 : }
     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         4412 : maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
     580              :                           const char **object, bool force)
     581              : {
     582         4412 :   const char **object_file = const_cast<const char **> (object_lst);
     583              : 
     584         4412 :   int num_lto_c_args = 1;    /* Allow space for the terminating NULL.  */
     585              : 
     586        31261 :   while (object_file < object)
     587              :   {
     588              :     /* If file contains LTO info, add it to the list of LTO objects.  */
     589        26849 :     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        26849 :     num_lto_c_args++;
     595              :   }
     596              : 
     597         4412 :   if (lto_objects.first)
     598              :     {
     599         4412 :       char **lto_c_argv;
     600         4412 :       const char **lto_c_ptr;
     601         4412 :       char **p;
     602         4412 :       char **lto_o_ptr;
     603         4412 :       struct lto_object *list;
     604         4412 :       char *lto_wrapper = getenv ("COLLECT_LTO_WRAPPER");
     605         4412 :       struct pex_obj *pex;
     606         4412 :       const char *prog = "lto-wrapper";
     607         4412 :       int lto_ld_argv_size = 0;
     608         4412 :       char **out_lto_ld_argv;
     609         4412 :       int out_lto_ld_argv_size;
     610         4412 :       size_t num_files;
     611              : 
     612         4412 :       if (!lto_wrapper)
     613            0 :         fatal_error (input_location, "environment variable "
     614              :                      "%<COLLECT_LTO_WRAPPER%> must be set");
     615              : 
     616         4412 :       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         4412 :       lto_c_argv = (char **) xcalloc (num_lto_c_args, sizeof (char *));
     626         4412 :       lto_c_ptr = const_cast<const char **> (lto_c_argv);
     627              : 
     628         4412 :       *lto_c_ptr++ = lto_wrapper;
     629              : 
     630              :       /* Add LTO objects to the wrapper command line.  */
     631         9143 :       for (list = lto_objects.first; list; list = list->next)
     632         4731 :         *lto_c_ptr++ = list->name;
     633              : 
     634         4412 :       *lto_c_ptr = NULL;
     635              : 
     636              :       /* Run the LTO back end.  */
     637         4412 :       pex = collect_execute (prog, lto_c_argv, NULL, NULL, PEX_SEARCH,
     638              :                              at_file_supplied, "lto_args");
     639         4412 :       {
     640         4412 :         int c;
     641         4412 :         FILE *stream;
     642         4412 :         size_t i;
     643         4412 :         char *start, *end;
     644              : 
     645         4412 :         stream = pex_read_output (pex, 0);
     646         4412 :         gcc_assert (stream);
     647              : 
     648              :         num_files = 0;
     649       107637 :         while ((c = getc (stream)) != EOF)
     650              :           {
     651       103225 :             obstack_1grow (&temporary_obstack, c);
     652       103225 :             if (c == '\n')
     653         4837 :               ++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         4412 :         lto_o_files = XCNEWVEC (char *, num_files + 1);
     660         4412 :         lto_o_files[num_files] = NULL;
     661         4412 :         start = XOBFINISH (&temporary_obstack, char *);
     662         9249 :         for (i = 0; i < num_files; ++i)
     663              :           {
     664              :             end = start;
     665       103225 :             while (*end != '\n')
     666        98388 :               ++end;
     667         4837 :             *end = '\0';
     668              : 
     669         4837 :             lto_o_files[i] = xstrdup (start);
     670              : 
     671         4837 :             start = end + 1;
     672              :           }
     673              : 
     674         4412 :         obstack_free (&temporary_obstack, temporary_firstobj);
     675              :       }
     676         4412 :       do_wait (prog, pex);
     677         4412 :       pex = NULL;
     678              : 
     679              :       /* Compute memory needed for new LD arguments.  At most number of original arguments
     680              :          plus number of partitions.  */
     681       138846 :       for (lto_ld_argv_size = 0; lto_ld_argv[lto_ld_argv_size]; lto_ld_argv_size++)
     682              :         ;
     683         4412 :       out_lto_ld_argv = XCNEWVEC (char *, num_files + lto_ld_argv_size + 1);
     684         4412 :       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         4412 :       p = lto_ld_argv;
     692        93743 :       while (*p != NULL)
     693              :         {
     694       180444 :           for (list = lto_objects.first; list; list = list->next)
     695        95525 :             if (*p == list->name) /* Note test for pointer equality!  */
     696              :               break;
     697        84919 :           if (list)
     698              :             break;
     699        84919 :           out_lto_ld_argv[out_lto_ld_argv_size++] = *p++;
     700              :         }
     701              : 
     702              :       /* Now insert all LTO partitions.  */
     703         4412 :       lto_o_ptr = lto_o_files;
     704         9249 :       while (*lto_o_ptr)
     705         4837 :         out_lto_ld_argv[out_lto_ld_argv_size++] = *lto_o_ptr++;
     706              : 
     707              :       /* ... and copy the rest.  */
     708        49515 :       while (*p != NULL)
     709              :         {
     710        88709 :           for (list = lto_objects.first; list; list = list->next)
     711        48337 :             if (*p == list->name) /* Note test for pointer equality!  */
     712              :               break;
     713        45103 :           if (!list)
     714        40372 :             out_lto_ld_argv[out_lto_ld_argv_size++] = *p;
     715        45103 :           p++;
     716              :         }
     717         4412 :       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         4412 :       fork_execute ("ld", out_lto_ld_argv, HAVE_LD_AT_FILE && 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         4412 :       post_ld_pass (/*temp_file*/true);
     726         4412 :       free (lto_ld_argv);
     727              : 
     728         4412 :       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_LD_AT_FILE && 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         4412 : }
     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        95136 : do_link (char **ld_argv, const char *atsuffix)
     747              : {
     748        95136 :   struct pex_obj *pex;
     749        95136 :   const char *prog = "ld";
     750        95136 :   pex = collect_execute (prog, ld_argv, NULL, NULL,
     751              :                          PEX_LAST | PEX_SEARCH,
     752              :                          HAVE_LD_AT_FILE && at_file_supplied, atsuffix);
     753        95136 :   int ret = collect_wait (prog, pex);
     754        95136 :   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        95005 :       may_unlink_output_file = true;
     764              :     }
     765        95005 : }
     766              : 
     767              : /* Main program.  */
     768              : 
     769              : int
     770        95136 : main (int argc, char **argv)
     771              : {
     772        95136 :   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        95136 :     } selected_linker = USE_DEFAULT_LD;
     783        95136 :   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        95136 :   static const char *const real_ld_suffix = "real-ld";
     794        95136 :   static const char *const collect_ld_suffix = "collect-ld";
     795        95136 :   static const char *const nm_suffix    = "nm";
     796        95136 :   static const char *const gnm_suffix   = "gnm";
     797              : #ifdef LDD_SUFFIX
     798              :   static const char *const ldd_suffix   = LDD_SUFFIX;
     799              : #endif
     800        95136 :   static const char *const strip_suffix = "strip";
     801        95136 :   static const char *const gstrip_suffix = "gstrip";
     802              : 
     803        95136 :   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        95136 :   const char *const full_nm_suffix      = nm_suffix;
     827        95136 :   const char *const full_gnm_suffix     = gnm_suffix;
     828        95136 :   const char *const full_strip_suffix   = strip_suffix;
     829        95136 :   const char *const full_gstrip_suffix  = gstrip_suffix;
     830              : #endif /* CROSS_DIRECTORY_STRUCTURE */
     831              : 
     832        95136 :   const char *arg;
     833        95136 :   FILE *outf;
     834              : #ifdef COLLECT_EXPORT_LIST
     835              :   FILE *exportf;
     836              : #endif
     837        95136 :   const char *ld_file_name;
     838        95136 :   const char *p;
     839        95136 :   char **c_argv;
     840        95136 :   const char **c_ptr;
     841        95136 :   char **ld1_argv;
     842        95136 :   const char **ld1;
     843        95136 :   bool use_plugin = false;
     844        95136 :   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        95136 :   scanfilter ld1_filter = SCAN_ALL;
     853              : 
     854        95136 :   char **ld2_argv;
     855        95136 :   const char **ld2;
     856        95136 :   char **object_lst;
     857        95136 :   const char **object;
     858              : #ifdef TARGET_AIX_VERSION
     859              :   int object_nbr = argc;
     860              : #endif
     861        95136 :   int first_file;
     862        95136 :   int num_c_args;
     863        95136 :   char **old_argv;
     864              : #ifdef COLLECT_EXPORT_LIST
     865              :   bool is_static = false;
     866              : #endif
     867        95136 :   int i;
     868              : 
     869       761088 :   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       665952 :       full_ld_suffixes[i] = ld_suffixes[i];
     879              : 
     880        95136 :   p = argv[0] + strlen (argv[0]);
     881       856224 :   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
     882       761088 :     --p;
     883        95136 :   progname = p;
     884              : 
     885        95136 :   xmalloc_set_program_name (progname);
     886              : 
     887        95136 :   old_argv = argv;
     888        95136 :   expandargv (&argc, &argv);
     889        95136 :   if (argv != old_argv)
     890            6 :     at_file_supplied = 1;
     891              : 
     892        95136 :   process_args (&argc, argv);
     893              : 
     894        95136 :   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        95136 :   setup_signals ();
     909              : 
     910              :   /* Unlock the stdio streams.  */
     911        95136 :   unlock_std_streams ();
     912              : 
     913        95136 :   gcc_init_libintl ();
     914              : 
     915        95136 :   diagnostic_initialize (global_dc, 0);
     916              : 
     917        95136 :   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        95136 :   ld1_argv = XCNEWVEC (char *, argc + 4);
     924        95136 :   ld1 = const_cast<const char **> (ld1_argv);
     925        95136 :   ld2_argv = XCNEWVEC (char *, argc + 11);
     926        95136 :   ld2 = const_cast<const char **> (ld2_argv);
     927        95136 :   object_lst = XCNEWVEC (char *, argc);
     928        95136 :   object = const_cast<const char **> (object_lst);
     929              : 
     930              : #ifdef DEBUG
     931              :   debug = true;
     932              : #endif
     933              : 
     934        95136 :   save_temps = false;
     935        95136 :   verbose = false;
     936              : 
     937              : #ifndef DEFAULT_A_OUT_NAME
     938        95136 :   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        95136 :   {
     947        95136 :     bool no_partition = false;
     948              : 
     949      4036206 :     for (i = 1; argv[i] != NULL; i ++)
     950              :       {
     951      3941070 :         if (! strcmp (argv[i], "-debug"))
     952            0 :           debug = true;
     953      3941070 :         else if (startswith (argv[i], "-fno-lto"))
     954           35 :           lto_mode = LTO_MODE_NONE;
     955      3941035 :         else if (! strcmp (argv[i], "-plugin"))
     956              :           {
     957        90689 :             use_plugin = true;
     958        90689 :             if (selected_linker == USE_DEFAULT_LD)
     959              :               selected_linker = USE_PLUGIN_LD;
     960              :           }
     961      3850346 :         else if (strcmp (argv[i], "-fuse-ld=bfd") == 0)
     962              :           selected_linker = USE_BFD_LD;
     963      3850346 :         else if (strcmp (argv[i], "-fuse-ld=gold") == 0)
     964              :           selected_linker = USE_GOLD_LD;
     965      3850346 :         else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
     966              :           selected_linker = USE_LLD_LD;
     967      3850346 :         else if (strcmp (argv[i], "-fuse-ld=mold") == 0)
     968              :           selected_linker = USE_MOLD_LD;
     969      3850346 :         else if (strcmp (argv[i], "-fuse-ld=wild") == 0)
     970              :           selected_linker = USE_WILD_LD;
     971      3850346 :         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        94653 :             if (argv[i][2] != '\0')
     976            0 :               output_file = &argv[i][2];
     977        94653 :             else if (argv[i+1] != NULL)
     978        94653 :               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        95136 :     obstack_begin (&temporary_obstack, 0);
    1002        95136 :     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        95136 :     p = read_collect_gcc_options ();
    1012      2512135 :     while (p && *p)
    1013              :       {
    1014      2416999 :         const char *q = extract_string (&p);
    1015      2416999 :         if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
    1016      1205856 :           num_c_args++;
    1017      2416999 :         if (startswith (q, "-flto-partition=none"))
    1018              :           no_partition = true;
    1019      2412581 :         else if (startswith (q, "-fno-lto"))
    1020           35 :           lto_mode = LTO_MODE_NONE;
    1021      2412546 :         else if (startswith (q, "-save-temps"))
    1022              :           /* FIXME: Honour =obj.  */
    1023          268 :           save_temps = true;
    1024      2412278 :         else if (strcmp (q, "-dumpdir") == 0)
    1025        95133 :           dumppfx = xstrdup (extract_string (&p));
    1026      2317145 :         else if (strcmp (q, "-o") == 0
    1027      2222492 :                  || strcmp (q, "-B") == 0
    1028      2016940 :                  || strcmp (q, "-isystem") == 0)
    1029       318577 :           (void) extract_string (&p);
    1030              :     }
    1031        95136 :     obstack_free (&temporary_obstack, temporary_firstobj);
    1032              : 
    1033        95136 :     verbose = verbose || debug;
    1034        95136 :     save_temps = save_temps || debug;
    1035        95136 :     find_file_set_debug (debug);
    1036        95136 :     if (use_plugin)
    1037        90689 :       lto_mode = LTO_MODE_NONE;
    1038        95136 :     if (no_partition && lto_mode == LTO_MODE_WHOPR)
    1039         4152 :       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        95136 :   num_c_args += 8;
    1046              : 
    1047        95136 :   c_argv = XCNEWVEC (char *, num_c_args);
    1048        95136 :   c_ptr = const_cast<const char **> (c_argv);
    1049              : 
    1050        95136 :   if (argc < 2)
    1051            0 :     fatal_error (input_location, "no arguments");
    1052              : 
    1053              :   /* Extract COMPILER_PATH and PATH into our prefix list.  */
    1054        95136 :   prefix_from_env ("COMPILER_PATH", &cpath);
    1055        95136 :   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        95136 :   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        95136 :   ld_file_name = find_a_file (&cpath, real_ld_suffix, X_OK);
    1102              :   /* Likewise for `collect-ld'.  */
    1103        95136 :   if (ld_file_name == 0)
    1104              :     {
    1105        95136 :       ld_file_name = find_a_file (&cpath, collect_ld_suffix, X_OK);
    1106        95136 :       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        95136 :   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        95136 :   nm_file_name = find_a_file (&cpath, gnm_suffix, X_OK);
    1122        95136 :   if (nm_file_name == 0)
    1123        95136 :     nm_file_name = find_a_file (&path, full_gnm_suffix, X_OK);
    1124        95136 :   if (nm_file_name == 0)
    1125        95136 :     nm_file_name = find_a_file (&cpath, nm_suffix, X_OK);
    1126        95136 :   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        95136 :   strip_file_name = find_a_file (&cpath, gstrip_suffix, X_OK);
    1140        95136 :   if (strip_file_name == 0)
    1141        95136 :     strip_file_name = find_a_file (&path, full_gstrip_suffix, X_OK);
    1142        95136 :   if (strip_file_name == 0)
    1143        95136 :     strip_file_name = find_a_file (&cpath, strip_suffix, X_OK);
    1144        95136 :   if (strip_file_name == 0)
    1145        95136 :     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        95136 :   c_file_name = getenv ("COLLECT_GCC");
    1149        95136 :   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        95136 :   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        95136 :   if (p == 0)
    1163            0 :     p = find_a_file (&path, c_file_name, X_OK);
    1164              : 
    1165        95136 :   if (p)
    1166        95136 :     c_file_name = p;
    1167              : 
    1168        95136 :   *ld1++ = *ld2++ = ld_file_name;
    1169              : 
    1170              :   /* Make temp file names.  */
    1171        95136 :   if (save_temps)
    1172              :     {
    1173          262 :       c_file = concat (output_file, ".cdtor.c", NULL);
    1174          262 :       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        94874 :       c_file = make_temp_file (".cdtor.c");
    1182        94874 :       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        95136 :   *c_ptr++ = c_file_name;
    1189        95136 :   *c_ptr++ = "-x";
    1190        95136 :   *c_ptr++ = "c";
    1191        95136 :   *c_ptr++ = "-c";
    1192        95136 :   *c_ptr++ = "-o";
    1193        95136 :   *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        95136 :   p = read_collect_gcc_options ();
    1210      2512135 :   while (p && *p)
    1211              :     {
    1212      2416999 :       const char *q = extract_string (&p);
    1213      2416999 :       if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
    1214      1205856 :         *c_ptr++ = xstrdup (q);
    1215      2416999 :       if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
    1216            0 :         *c_ptr++ = xstrdup (q);
    1217      2416999 :       if (strcmp (q, "-shared") == 0)
    1218          266 :         shared_obj = 1;
    1219      2416999 :       if (strcmp (q, "-static") == 0)
    1220           97 :         static_obj = 1;
    1221      2416999 :       if (*q == '-' && q[1] == 'B')
    1222              :         {
    1223       205552 :           *c_ptr++ = xstrdup (q);
    1224       205552 :           if (q[2] == 0)
    1225              :             {
    1226       205552 :               q = extract_string (&p);
    1227       205552 :               *c_ptr++ = xstrdup (q);
    1228              :             }
    1229              :         }
    1230      2211447 :       else if (strcmp (q, "-o") == 0
    1231      2116794 :                || strcmp (q, "-dumpdir") == 0
    1232      2021661 :                || strcmp (q, "-isystem") == 0)
    1233       208158 :         (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        95136 :   obstack_free (&temporary_obstack, temporary_firstobj);
    1241        95136 :   *c_ptr++ = "-fno-profile-arcs";
    1242        95136 :   *c_ptr++ = "-fno-condition-coverage";
    1243        95136 :   *c_ptr++ = "-fno-path-coverage";
    1244        95136 :   *c_ptr++ = "-fno-test-coverage";
    1245        95136 :   *c_ptr++ = "-fno-branch-probabilities";
    1246        95136 :   *c_ptr++ = "-fno-exceptions";
    1247        95136 :   *c_ptr++ = "-w";
    1248        95136 :   *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        95136 :   first_file = 1;
    1264      3941433 :   while ((arg = *++argv) != (char *) 0)
    1265              :     {
    1266      3846297 :       *ld1++ = *ld2++ = arg;
    1267              : 
    1268      3846297 :       if (arg[0] == '-')
    1269              :         {
    1270      3062680 :           switch (arg[1])
    1271              :             {
    1272        94773 :             case 'd':
    1273        94773 :               if (!strcmp (arg, "-debug"))
    1274              :                 {
    1275              :                   /* Already parsed.  */
    1276            0 :                   ld1--;
    1277            0 :                   ld2--;
    1278              :                 }
    1279        94773 :               if (!strcmp (arg, "-dynamic-linker") && argv[1])
    1280              :                 {
    1281        94773 :                   ++argv;
    1282        94773 :                   *ld1++ = *ld2++ = *argv;
    1283              :                 }
    1284              :               break;
    1285              : 
    1286        12237 :             case 'f':
    1287        12237 :               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      3846297 :                   ld1--;
    1309      3846297 :                   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 additional object files.  */
    1319              :                   int add_nbr = 0;
    1320              :                   /* Maximum of additional 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       831108 :             case 'l':
    1380       831108 :               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        94653 :             case 'o':
    1409        94653 :               if (arg[2] != '\0')
    1410            0 :                 output_file = &arg[2];
    1411        94653 :               else if (argv[1])
    1412        94653 :                 output_file = *ld1++ = *ld2++ = *++argv;
    1413              :               break;
    1414              : 
    1415          230 :             case 'r':
    1416          230 :               if (arg[2] == '\0')
    1417          188 :                 rflag = 1;
    1418              :               break;
    1419              : 
    1420          422 :             case 's':
    1421          422 :               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       146879 :             case '-':
    1437       146879 :               if (strcmp (arg, "--no-demangle") == 0)
    1438              :                 {
    1439              : #ifndef HAVE_LD_DEMANGLE
    1440              :                   no_demangle = 1;
    1441              :                   ld1--;
    1442              :                   ld2--;
    1443              : #endif
    1444              :                 }
    1445       146879 :               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       146879 :               else if (startswith (arg, "--sysroot="))
    1463            0 :                 target_system_root = arg + 10;
    1464       146879 :               else if (strcmp (arg, "--version") == 0)
    1465            0 :                 verbose = true;
    1466       146879 :               else if (strcmp (arg, "--help") == 0)
    1467            5 :                 helpflag = true;
    1468              :               break;
    1469              :             }
    1470              :         }
    1471       783617 :       else if ((p = strrchr (arg, '.')) != (char *) 0
    1472       783617 :                && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
    1473        90756 :                    || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
    1474           59 :                    || strcmp (p, ".obj") == 0))
    1475              :         {
    1476       688180 :           if (first_file)
    1477              :             {
    1478        95136 :               first_file = 0;
    1479        95136 :               if (p[1] == 'o')
    1480         4447 :                 *ld2++ = o_file;
    1481              :               else
    1482              :                 {
    1483              :                   /* place o_file BEFORE this argument! */
    1484        90689 :                   ld2--;
    1485        90689 :                   *ld2++ = o_file;
    1486        90689 :                   *ld2++ = arg;
    1487              :                 }
    1488              :             }
    1489       688180 :           if (p[1] == 'o' || p[1] == 'l')
    1490       583482 :             *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        95136 :   *c_ptr++ = c_file;
    1563        95136 :   *c_ptr = *ld1 = *object = (char *) 0;
    1564              : 
    1565        95136 :   if (verbose)
    1566            0 :     notice ("collect2 version %s\n", version_string);
    1567              : 
    1568        95136 :   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        95136 :   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 = read_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        95136 :   {
    1627       190272 :     bool early_exit
    1628        95136 :       = 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        95136 :     if (early_exit || ld1_filter != SCAN_NOTHING)
    1640        95136 :       do_link (ld1_argv, "ld1_args");
    1641              : 
    1642        95005 :     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        95005 :         if (lto_mode != LTO_MODE_NONE)
    1650         4412 :           maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
    1651              :         else
    1652              :           post_ld_pass (/*temp_file*/false);
    1653              : 
    1654        95005 :         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_LD_AT_FILE && at_file_supplied,
    1813              :                     "ld_args");
    1814            0 :       post_ld_pass (/*temp_file*/false);
    1815              :     }
    1816              : 
    1817              :   /* Let scan_prog_file do any final mods (OSF/rose needs this for
    1818              :      constructors/destructors in shared libraries.  */
    1819            0 :   scan_prog_file (output_file, PASS_SECOND, SCAN_ALL);
    1820              : #endif
    1821              : 
    1822            0 :   return 0;
    1823              : }
    1824              : 
    1825              : 
    1826              : /* Unlink FILE unless we are debugging or this is the output_file
    1827              :    and we may not unlink it.  */
    1828              : 
    1829              : void
    1830       199946 : maybe_unlink (const char *file)
    1831              : {
    1832       199946 :   if (save_temps && file_exists (file))
    1833              :     {
    1834            2 :       if (verbose)
    1835            0 :         notice ("[Leaving %s]\n", file);
    1836            2 :       return;
    1837              :     }
    1838              : 
    1839       199944 :   if (file == output_file && !may_unlink_output_file)
    1840              :     return;
    1841              : 
    1842       199944 :   unlink_if_ordinary (file);
    1843              : }
    1844              : 
    1845              : /* Call maybe_unlink on the NULL-terminated list, FILE_LIST.  */
    1846              : 
    1847              : static void
    1848         8824 : maybe_unlink_list (char **file_list)
    1849              : {
    1850         8824 :   char **tmp = file_list;
    1851              : 
    1852        18498 :   while (*tmp)
    1853         9674 :     maybe_unlink (*(tmp++));
    1854         8824 : }
    1855              : 
    1856              : 
    1857              : static long sequence_number = 0;
    1858              : 
    1859              : /* Add a name to a linked list.  */
    1860              : 
    1861              : static void
    1862            0 : add_to_list (struct head *head_ptr, const char *name)
    1863              : {
    1864            0 :   struct id *newid
    1865            0 :     = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
    1866            0 :   struct id *p;
    1867            0 :   strcpy (newid->name, name);
    1868              : 
    1869            0 :   if (head_ptr->first)
    1870            0 :     head_ptr->last->next = newid;
    1871              :   else
    1872            0 :     head_ptr->first = newid;
    1873              : 
    1874              :   /* Check for duplicate symbols.  */
    1875            0 :   for (p = head_ptr->first;
    1876            0 :        strcmp (name, p->name) != 0;
    1877            0 :        p = p->next)
    1878              :     ;
    1879            0 :   if (p != newid)
    1880              :     {
    1881            0 :       head_ptr->last->next = 0;
    1882            0 :       free (newid);
    1883            0 :       return;
    1884              :     }
    1885              : 
    1886            0 :   newid->sequence = ++sequence_number;
    1887            0 :   head_ptr->last = newid;
    1888            0 :   head_ptr->number++;
    1889              : }
    1890              : 
    1891              : /* Grab the init priority number from an init function name that
    1892              :    looks like "_GLOBAL_.I.12345.foo".  */
    1893              : 
    1894              : static int
    1895            0 : extract_init_priority (const char *name)
    1896              : {
    1897            0 :   int pos = 0, pri;
    1898              : 
    1899              : #ifdef TARGET_AIX_VERSION
    1900              :   /* Run dependent module initializers before any constructors in this
    1901              :      module.  */
    1902              :   switch (is_ctor_dtor (name))
    1903              :     {
    1904              :     case SYM_AIXI:
    1905              :     case SYM_AIXD:
    1906              :       return INT_MIN;
    1907              :     default:
    1908              :       break;
    1909              :     }
    1910              : #endif
    1911              : 
    1912            0 :   while (name[pos] == '_')
    1913            0 :     ++pos;
    1914            0 :   pos += 10; /* strlen ("GLOBAL__X_") */
    1915              : 
    1916              :   /* Extract init_p number from ctor/dtor name.  */
    1917            0 :   pri = atoi (name + pos);
    1918            0 :   return pri ? pri : DEFAULT_INIT_PRIORITY;
    1919              : }
    1920              : 
    1921              : /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
    1922              :    ctors will be run from right to left, dtors from left to right.  */
    1923              : 
    1924              : static void
    1925            0 : sort_ids (struct head *head_ptr)
    1926              : {
    1927              :   /* id holds the current element to insert.  id_next holds the next
    1928              :      element to insert.  id_ptr iterates through the already sorted elements
    1929              :      looking for the place to insert id.  */
    1930            0 :   struct id *id, *id_next, **id_ptr;
    1931              : 
    1932            0 :   id = head_ptr->first;
    1933              : 
    1934              :   /* We don't have any sorted elements yet.  */
    1935            0 :   head_ptr->first = NULL;
    1936              : 
    1937            0 :   for (; id; id = id_next)
    1938              :     {
    1939            0 :       id_next = id->next;
    1940            0 :       id->sequence = extract_init_priority (id->name);
    1941              : 
    1942            0 :       for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
    1943            0 :         if (*id_ptr == NULL
    1944              :             /* If the sequence numbers are the same, we put the id from the
    1945              :                file later on the command line later in the list.  */
    1946            0 :             || id->sequence > (*id_ptr)->sequence
    1947              :             /* Hack: do lexical compare, too.
    1948              :             || (id->sequence == (*id_ptr)->sequence
    1949              :                 && strcmp (id->name, (*id_ptr)->name) > 0) */
    1950              :             )
    1951              :           {
    1952            0 :             id->next = *id_ptr;
    1953            0 :             *id_ptr = id;
    1954            0 :             break;
    1955              :           }
    1956              :     }
    1957              : 
    1958              :   /* Now set the sequence numbers properly so write_c_file works.  */
    1959            0 :   for (id = head_ptr->first; id; id = id->next)
    1960            0 :     id->sequence = ++sequence_number;
    1961            0 : }
    1962              : 
    1963              : /* Write: `prefix', the names on list LIST, `suffix'.  */
    1964              : 
    1965              : static void
    1966            0 : write_list (FILE *stream, const char *prefix, struct id *list)
    1967              : {
    1968            0 :   while (list)
    1969              :     {
    1970            0 :       fprintf (stream, "%sx%d,\n", prefix, list->sequence);
    1971            0 :       list = list->next;
    1972              :     }
    1973            0 : }
    1974              : 
    1975              : #ifdef COLLECT_EXPORT_LIST
    1976              : /* This function is really used only on AIX, but may be useful.  */
    1977              : static int
    1978              : is_in_list (const char *prefix, struct id *list)
    1979              : {
    1980              :   while (list)
    1981              :     {
    1982              :       if (!strcmp (prefix, list->name)) return 1;
    1983              :       list = list->next;
    1984              :     }
    1985              :     return 0;
    1986              : }
    1987              : #endif /* COLLECT_EXPORT_LIST */
    1988              : 
    1989              : /* Added for debugging purpose.  */
    1990              : #ifdef COLLECT_EXPORT_LIST
    1991              : static void
    1992              : dump_list (FILE *stream, const char *prefix, struct id *list)
    1993              : {
    1994              :   while (list)
    1995              :     {
    1996              :       fprintf (stream, "%s%s,\n", prefix, list->name);
    1997              :       list = list->next;
    1998              :     }
    1999              : }
    2000              : #endif
    2001              : 
    2002              : #if 0
    2003              : static void
    2004              : dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
    2005              : {
    2006              :   while (list)
    2007              :     {
    2008              :       fprintf (stream, "%s%s,\n", prefix, list->prefix);
    2009              :       list = list->next;
    2010              :     }
    2011              : }
    2012              : #endif
    2013              : 
    2014              : static void
    2015            0 : write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
    2016              : {
    2017            0 :   while (list)
    2018              :     {
    2019            0 :       fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
    2020            0 :                prefix, list->sequence, list->name);
    2021            0 :       list = list->next;
    2022              :     }
    2023            0 : }
    2024              : 
    2025              : /* Write out the constructor and destructor tables statically (for a shared
    2026              :    object), along with the functions to execute them.  */
    2027              : 
    2028              : static void
    2029            0 : write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
    2030              : {
    2031            0 :   const char *p, *q;
    2032            0 :   char *prefix, *r;
    2033            0 :   int frames = (frame_tables.number > 0);
    2034              : 
    2035              :   /* Figure out name of output_file, stripping off .so version.  */
    2036            0 :   q = p = lbasename (output_file);
    2037              : 
    2038            0 :   while (q)
    2039              :     {
    2040            0 :       q = strchr (q,'.');
    2041            0 :       if (q == 0)
    2042              :         {
    2043            0 :           q = p + strlen (p);
    2044            0 :           break;
    2045              :         }
    2046              :       else
    2047              :         {
    2048            0 :           if (filename_ncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0)
    2049              :             {
    2050            0 :               q += strlen (SHLIB_SUFFIX);
    2051            0 :               break;
    2052              :             }
    2053              :           else
    2054            0 :             q++;
    2055              :         }
    2056              :     }
    2057              :   /* q points to null at end of the string (or . of the .so version) */
    2058            0 :   prefix = XNEWVEC (char, q - p + 1);
    2059            0 :   strncpy (prefix, p, q - p);
    2060            0 :   prefix[q - p] = 0;
    2061            0 :   for (r = prefix; *r; r++)
    2062            0 :     if (!ISALNUM ((unsigned char)*r))
    2063            0 :       *r = '_';
    2064            0 :   if (debug)
    2065            0 :     notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
    2066              :             output_file, prefix);
    2067              : 
    2068            0 :   initname = concat ("_GLOBAL__FI_", prefix, NULL);
    2069            0 :   fininame = concat ("_GLOBAL__FD_", prefix, NULL);
    2070              : #ifdef TARGET_AIX_VERSION
    2071              :   aix_shared_initname = concat ("_GLOBAL__AIXI_", prefix, NULL);
    2072              :   aix_shared_fininame = concat ("_GLOBAL__AIXD_", prefix, NULL);
    2073              : #endif
    2074              : 
    2075            0 :   free (prefix);
    2076              : 
    2077              :   /* Write the tables as C code.  */
    2078              : 
    2079              :   /* This count variable is used to prevent multiple calls to the
    2080              :      constructors/destructors.
    2081              :      This guard against multiple calls is important on AIX as the initfini
    2082              :      functions are deliberately invoked multiple times as part of the
    2083              :      mechanisms GCC uses to order constructors across different dependent
    2084              :      shared libraries (see config/rs6000/aix.h).
    2085              :    */
    2086            0 :   fprintf (stream, "static int count;\n");
    2087            0 :   fprintf (stream, "typedef void entry_pt();\n");
    2088            0 :   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
    2089              : 
    2090            0 :   if (frames)
    2091              :     {
    2092            0 :       write_list_with_asm (stream, "extern void *", frame_tables.first);
    2093              : 
    2094            0 :       fprintf (stream, "\tstatic void *frame_table[] = {\n");
    2095            0 :       write_list (stream, "\t\t&", frame_tables.first);
    2096            0 :       fprintf (stream, "\t0\n};\n");
    2097              : 
    2098              :       /* This must match what's in frame.h.  */
    2099            0 :       fprintf (stream, "struct object {\n");
    2100            0 :       fprintf (stream, "  void *pc_begin;\n");
    2101            0 :       fprintf (stream, "  void *pc_end;\n");
    2102            0 :       fprintf (stream, "  void *fde_begin;\n");
    2103            0 :       fprintf (stream, "  void *fde_array;\n");
    2104            0 :       fprintf (stream, "  __SIZE_TYPE__ count;\n");
    2105            0 :       fprintf (stream, "  struct object *next;\n");
    2106            0 :       fprintf (stream, "};\n");
    2107              : 
    2108            0 :       fprintf (stream, "extern void __register_frame_info_table_bases (void *, struct object *, void *tbase, void *dbase);\n");
    2109            0 :       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
    2110            0 :       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
    2111              : #ifdef TARGET_AIX_VERSION
    2112              :       fprintf (stream, "extern void *__gcc_unwind_dbase;\n");
    2113              : #endif
    2114              : 
    2115            0 :       fprintf (stream, "static void reg_frame () {\n");
    2116            0 :       fprintf (stream, "\tstatic struct object ob;\n");
    2117              : #ifdef TARGET_AIX_VERSION
    2118              :       /* Use __gcc_unwind_dbase as the base address for data on AIX.
    2119              :          This might not be the start of the segment, signed offsets assumed.
    2120              :        */
    2121              :       fprintf (stream, "\t__register_frame_info_table_bases (frame_table, &ob, (void *)0, &__gcc_unwind_dbase);\n");
    2122              : #else
    2123            0 :       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
    2124              : #endif
    2125            0 :       fprintf (stream, "\t}\n");
    2126              : 
    2127            0 :       fprintf (stream, "static void dereg_frame () {\n");
    2128            0 :       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
    2129            0 :       fprintf (stream, "\t}\n");
    2130              :     }
    2131              : 
    2132              : #ifdef COLLECT_EXPORT_LIST
    2133              :   /* Set visibility of initializers to default.  */
    2134              :   if (visibility_flag)
    2135              :     fprintf (stream, "#pragma GCC visibility push(default)\n");
    2136              : #endif
    2137            0 :   fprintf (stream, "void %s() {\n", initname);
    2138            0 :   if (constructors.number > 0 || frames)
    2139              :     {
    2140            0 :       fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
    2141            0 :       write_list (stream, "\t\t", constructors.first);
    2142            0 :       if (frames)
    2143            0 :         fprintf (stream, "\treg_frame,\n");
    2144            0 :       fprintf (stream, "\t};\n");
    2145            0 :       fprintf (stream, "\tentry_pt **p;\n");
    2146            0 :       fprintf (stream, "\tif (count++ != 0) return;\n");
    2147            0 :       fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
    2148            0 :       fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
    2149              :     }
    2150              :   else
    2151            0 :     fprintf (stream, "\t++count;\n");
    2152            0 :   fprintf (stream, "}\n");
    2153            0 :   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
    2154            0 :   fprintf (stream, "void %s() {\n", fininame);
    2155            0 :   if (destructors.number > 0 || frames)
    2156              :     {
    2157            0 :       fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
    2158            0 :       write_list (stream, "\t\t", destructors.first);
    2159            0 :       if (frames)
    2160            0 :         fprintf (stream, "\tdereg_frame,\n");
    2161            0 :       fprintf (stream, "\t};\n");
    2162            0 :       fprintf (stream, "\tentry_pt **p;\n");
    2163            0 :       fprintf (stream, "\tif (--count != 0) return;\n");
    2164            0 :       fprintf (stream, "\tp = dtors;\n");
    2165            0 :       fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
    2166            0 :                destructors.number + frames);
    2167              :     }
    2168            0 :   fprintf (stream, "}\n");
    2169              : #ifdef COLLECT_EXPORT_LIST
    2170              :   if (visibility_flag)
    2171              :     fprintf (stream, "#pragma GCC visibility pop\n");
    2172              : #endif
    2173              : 
    2174            0 :   if (shared_obj)
    2175              :     {
    2176              : #ifdef COLLECT_EXPORT_LIST
    2177              :       /* Set visibility of initializers to default.  */
    2178              :       if (visibility_flag)
    2179              :         fprintf (stream, "#pragma GCC visibility push(default)\n");
    2180              : #endif
    2181            0 :       COLLECT_SHARED_INIT_FUNC (stream, initname);
    2182            0 :       COLLECT_SHARED_FINI_FUNC (stream, fininame);
    2183              : #ifdef COLLECT_EXPORT_LIST
    2184              :       if (visibility_flag)
    2185              :         fprintf (stream, "#pragma GCC visibility pop\n");
    2186              : #endif
    2187              :     }
    2188            0 : }
    2189              : 
    2190              : /* Write the constructor/destructor tables.  */
    2191              : 
    2192              : #ifndef LD_INIT_SWITCH
    2193              : static void
    2194            0 : write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
    2195              : {
    2196              :   /* Write the tables as C code.  */
    2197              : 
    2198            0 :   int frames = (frame_tables.number > 0);
    2199              : 
    2200            0 :   fprintf (stream, "typedef void entry_pt();\n\n");
    2201              : 
    2202            0 :   write_list_with_asm (stream, "extern entry_pt ", constructors.first);
    2203              : 
    2204            0 :   if (frames)
    2205              :     {
    2206            0 :       write_list_with_asm (stream, "extern void *", frame_tables.first);
    2207              : 
    2208            0 :       fprintf (stream, "\tstatic void *frame_table[] = {\n");
    2209            0 :       write_list (stream, "\t\t&", frame_tables.first);
    2210            0 :       fprintf (stream, "\t0\n};\n");
    2211              : 
    2212              :       /* This must match what's in frame.h.  */
    2213            0 :       fprintf (stream, "struct object {\n");
    2214            0 :       fprintf (stream, "  void *pc_begin;\n");
    2215            0 :       fprintf (stream, "  void *pc_end;\n");
    2216            0 :       fprintf (stream, "  void *fde_begin;\n");
    2217            0 :       fprintf (stream, "  void *fde_array;\n");
    2218            0 :       fprintf (stream, "  __SIZE_TYPE__ count;\n");
    2219            0 :       fprintf (stream, "  struct object *next;\n");
    2220            0 :       fprintf (stream, "};\n");
    2221              : 
    2222            0 :       fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
    2223            0 :       fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
    2224              : 
    2225            0 :       fprintf (stream, "static void reg_frame () {\n");
    2226            0 :       fprintf (stream, "\tstatic struct object ob;\n");
    2227            0 :       fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
    2228            0 :       fprintf (stream, "\t}\n");
    2229              : 
    2230            0 :       fprintf (stream, "static void dereg_frame () {\n");
    2231            0 :       fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
    2232            0 :       fprintf (stream, "\t}\n");
    2233              :     }
    2234              : 
    2235            0 :   fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
    2236            0 :   fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
    2237            0 :   write_list (stream, "\t", constructors.first);
    2238            0 :   if (frames)
    2239            0 :     fprintf (stream, "\treg_frame,\n");
    2240            0 :   fprintf (stream, "\t0\n};\n\n");
    2241              : 
    2242            0 :   write_list_with_asm (stream, "extern entry_pt ", destructors.first);
    2243              : 
    2244            0 :   fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
    2245            0 :   fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
    2246            0 :   write_list (stream, "\t", destructors.first);
    2247            0 :   if (frames)
    2248            0 :     fprintf (stream, "\tdereg_frame,\n");
    2249            0 :   fprintf (stream, "\t0\n};\n\n");
    2250              : 
    2251            0 :   fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
    2252            0 :   fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
    2253            0 : }
    2254              : #endif /* ! LD_INIT_SWITCH */
    2255              : 
    2256              : static void
    2257            0 : write_c_file (FILE *stream, const char *name)
    2258              : {
    2259              : #ifndef LD_INIT_SWITCH
    2260            0 :   if (! shared_obj)
    2261            0 :     write_c_file_glob (stream, name);
    2262              :   else
    2263              : #endif
    2264            0 :     write_c_file_stat (stream, name);
    2265            0 : }
    2266              : 
    2267              : #ifdef COLLECT_EXPORT_LIST
    2268              : static void
    2269              : write_aix_file (FILE *stream, struct id *list)
    2270              : {
    2271              :   for (; list; list = list->next)
    2272              :     {
    2273              :       fputs (list->name, stream);
    2274              :       putc ('\n', stream);
    2275              :     }
    2276              : }
    2277              : #endif
    2278              : 
    2279              : #ifdef OBJECT_FORMAT_NONE
    2280              : 
    2281              : /* Check to make sure the file is an LTO object file.  */
    2282              : 
    2283              : static int
    2284       427214 : has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED,
    2285              :                  off_t offset ATTRIBUTE_UNUSED,
    2286              :                  off_t length ATTRIBUTE_UNUSED)
    2287              : {
    2288       427214 :   int *found = (int *) data;
    2289              : 
    2290       427214 :   if (!startswith (name, LTO_SECTION_NAME_PREFIX)
    2291       427214 :       && !startswith (name, OFFLOAD_SECTION_NAME_PREFIX))
    2292              :     return 1;
    2293              : 
    2294         4731 :   *found = 1;
    2295              : 
    2296              :   /* Stop iteration.  */
    2297         4731 :   return 0;
    2298              : }
    2299              : 
    2300              : static bool
    2301        26849 : is_lto_object_file (const char *prog_name)
    2302              : {
    2303        26849 :   const char *errmsg;
    2304        26849 :   int err;
    2305        26849 :   int found = 0;
    2306        26849 :   off_t inoff = 0;
    2307        26849 :   int infd = open (prog_name, O_RDONLY | O_BINARY);
    2308              : 
    2309        26849 :   if (infd == -1)
    2310              :     return false;
    2311              : 
    2312        26849 :   simple_object_read *inobj = simple_object_start_read (infd, inoff,
    2313              :                                                         LTO_SEGMENT_NAME,
    2314              :                                                         &errmsg, &err);
    2315        26849 :   if (!inobj)
    2316              :     {
    2317            0 :       close (infd);
    2318            0 :       return false;
    2319              :     }
    2320              : 
    2321        26849 :   errmsg = simple_object_find_sections (inobj, has_lto_section,
    2322              :                                         (void *) &found, &err);
    2323        26849 :   simple_object_release_read (inobj);
    2324        26849 :   close (infd);
    2325        26849 :   if (! errmsg && found)
    2326              :     return true;
    2327              : 
    2328        22118 :   if (errmsg)
    2329            0 :     fatal_error (0, "%s: %s", errmsg, xstrerror (err));
    2330              :   return false;
    2331              : }
    2332              : 
    2333              : /* Generic version to scan the name list of the loaded program for
    2334              :    the symbols g++ uses for static constructors and destructors.  */
    2335              : 
    2336              : static void
    2337        26849 : scan_prog_file (const char *prog_name, scanpass which_pass,
    2338              :                 scanfilter filter)
    2339              : {
    2340        26849 :   void (*int_handler) (int);
    2341              : #ifdef SIGQUIT
    2342        26849 :   void (*quit_handler) (int);
    2343              : #endif
    2344        26849 :   char *real_nm_argv[4];
    2345        26849 :   const char **nm_argv = const_cast<const char **> (real_nm_argv);
    2346        26849 :   int argc = 0;
    2347        26849 :   struct pex_obj *pex;
    2348        26849 :   const char *errmsg;
    2349        26849 :   int err;
    2350        26849 :   char *p, buf[1024];
    2351        26849 :   FILE *inf;
    2352              : 
    2353        26849 :   if (which_pass == PASS_SECOND)
    2354        26849 :     return;
    2355              : 
    2356              :   /* LTO objects must be in a known format.  This check prevents
    2357              :      us from accepting an archive containing LTO objects, which
    2358              :      gcc cannot currently handle.  */
    2359        26849 :   if (which_pass == PASS_LTOINFO)
    2360              :     {
    2361        26849 :       if(is_lto_object_file (prog_name)) {
    2362         4731 :         add_lto_object (&lto_objects, prog_name);
    2363              :       }
    2364        26849 :       return;
    2365              :     }
    2366              : 
    2367              :   /* If we do not have an `nm', complain.  */
    2368            0 :   if (nm_file_name == 0)
    2369            0 :     fatal_error (input_location, "cannot find %<nm%>");
    2370              : 
    2371            0 :   nm_argv[argc++] = nm_file_name;
    2372            0 :   if (NM_FLAGS[0] != '\0')
    2373            0 :     nm_argv[argc++] = NM_FLAGS;
    2374              : 
    2375            0 :   nm_argv[argc++] = prog_name;
    2376            0 :   nm_argv[argc++] = (char *) 0;
    2377              : 
    2378              :   /* Trace if needed.  */
    2379            0 :   if (verbose)
    2380              :     {
    2381              :       const char **p_argv;
    2382              :       const char *str;
    2383              : 
    2384            0 :       for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
    2385            0 :         fprintf (stderr, " %s", str);
    2386              : 
    2387            0 :       fprintf (stderr, "\n");
    2388              :     }
    2389              : 
    2390            0 :   fflush (stdout);
    2391            0 :   fflush (stderr);
    2392              : 
    2393            0 :   pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
    2394            0 :   if (pex == NULL)
    2395              :     fatal_error (input_location, "%<pex_init%> failed: %m");
    2396              : 
    2397            0 :   errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET,
    2398              :                     &err);
    2399            0 :   if (errmsg != NULL)
    2400              :     {
    2401            0 :       if (err != 0)
    2402              :         {
    2403            0 :           errno = err;
    2404            0 :           fatal_error (input_location, "%s: %m", _(errmsg));
    2405              :         }
    2406              :       else
    2407            0 :         fatal_error (input_location, errmsg);
    2408              :     }
    2409              : 
    2410            0 :   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
    2411              : #ifdef SIGQUIT
    2412            0 :   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
    2413              : #endif
    2414              : 
    2415            0 :   inf = pex_read_output (pex, 0);
    2416            0 :   if (inf == NULL)
    2417            0 :     fatal_error (input_location, "cannot open nm output: %m");
    2418              : 
    2419            0 :   if (debug)
    2420            0 :     fprintf (stderr, "\nnm output with constructors/destructors.\n");
    2421              : 
    2422              :   /* Read each line of nm output.  */
    2423            0 :   while (fgets (buf, sizeof buf, inf) != (char *) 0)
    2424              :     {
    2425            0 :       int ch, ch2;
    2426            0 :       char *name, *end;
    2427              : 
    2428            0 :       if (debug)
    2429            0 :         fprintf (stderr, "\t%s\n", buf);
    2430              : 
    2431              :       /* If it contains a constructor or destructor name, add the name
    2432              :          to the appropriate list unless this is a kind of symbol we're
    2433              :          not supposed to even consider.  */
    2434              : 
    2435            0 :       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
    2436            0 :         if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
    2437              :           break;
    2438              : 
    2439            0 :       if (ch != '_')
    2440            0 :         continue;
    2441              : 
    2442              :       name = p;
    2443              :       /* Find the end of the symbol name.
    2444              :          Do not include `|', because Encore nm can tack that on the end.  */
    2445            0 :       for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
    2446              :            end++)
    2447            0 :         continue;
    2448              : 
    2449              : 
    2450            0 :       *end = '\0';
    2451              : 
    2452            0 :       switch (is_ctor_dtor (name))
    2453              :         {
    2454            0 :         case SYM_CTOR:
    2455            0 :           if (! (filter & SCAN_CTOR))
    2456              :             break;
    2457            0 :           if (which_pass != PASS_LIB)
    2458            0 :             add_to_list (&constructors, name);
    2459              :           break;
    2460              : 
    2461            0 :         case SYM_DTOR:
    2462            0 :           if (! (filter & SCAN_DTOR))
    2463              :             break;
    2464            0 :           if (which_pass != PASS_LIB)
    2465            0 :             add_to_list (&destructors, name);
    2466              :           break;
    2467              : 
    2468            0 :         case SYM_INIT:
    2469            0 :           if (! (filter & SCAN_INIT))
    2470              :             break;
    2471            0 :           if (which_pass != PASS_LIB)
    2472            0 :             fatal_error (input_location, "init function found in object %s",
    2473              :                          prog_name);
    2474              : #ifndef LD_INIT_SWITCH
    2475            0 :           add_to_list (&constructors, name);
    2476              : #endif
    2477            0 :           break;
    2478              : 
    2479            0 :         case SYM_FINI:
    2480            0 :           if (! (filter & SCAN_FINI))
    2481              :             break;
    2482            0 :           if (which_pass != PASS_LIB)
    2483            0 :             fatal_error (input_location, "fini function found in object %s",
    2484              :                          prog_name);
    2485              : #ifndef LD_FINI_SWITCH
    2486            0 :           add_to_list (&destructors, name);
    2487              : #endif
    2488            0 :           break;
    2489              : 
    2490            0 :         case SYM_DWEH:
    2491            0 :           if (! (filter & SCAN_DWEH))
    2492              :             break;
    2493            0 :           if (which_pass != PASS_LIB)
    2494            0 :             add_to_list (&frame_tables, name);
    2495              :           break;
    2496              : 
    2497            0 :         default:                /* not a constructor or destructor */
    2498            0 :           continue;
    2499              :         }
    2500            0 :     }
    2501              : 
    2502            0 :   if (debug)
    2503            0 :     fprintf (stderr, "\n");
    2504              : 
    2505            0 :   do_wait (nm_file_name, pex);
    2506              : 
    2507            0 :   signal (SIGINT,  int_handler);
    2508              : #ifdef SIGQUIT
    2509            0 :   signal (SIGQUIT, quit_handler);
    2510              : #endif
    2511              : }
    2512              : 
    2513              : #ifdef LDD_SUFFIX
    2514              : 
    2515              : /* Use the List Dynamic Dependencies program to find shared libraries that
    2516              :    the output file depends upon and their initialization/finalization
    2517              :    routines, if any.  */
    2518              : 
    2519              : static void
    2520              : scan_libraries (const char *prog_name)
    2521              : {
    2522              :   static struct head libraries;         /* list of shared libraries found */
    2523              :   struct id *list;
    2524              :   void (*int_handler) (int);
    2525              : #ifdef SIGQUIT
    2526              :   void (*quit_handler) (int);
    2527              : #endif
    2528              :   char *real_ldd_argv[4];
    2529              :   const char **ldd_argv = const_cast<const char **> (real_ldd_argv);
    2530              :   int argc = 0;
    2531              :   struct pex_obj *pex;
    2532              :   const char *errmsg;
    2533              :   int err;
    2534              :   char buf[1024];
    2535              :   FILE *inf;
    2536              : 
    2537              :   /* If we do not have an `ldd', complain.  */
    2538              :   if (ldd_file_name == 0)
    2539              :     {
    2540              :       error ("cannot find %<ldd%>");
    2541              :       return;
    2542              :     }
    2543              : 
    2544              :   ldd_argv[argc++] = ldd_file_name;
    2545              :   ldd_argv[argc++] = prog_name;
    2546              :   ldd_argv[argc++] = (char *) 0;
    2547              : 
    2548              :   /* Trace if needed.  */
    2549              :   if (verbose)
    2550              :     {
    2551              :       const char **p_argv;
    2552              :       const char *str;
    2553              : 
    2554              :       for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
    2555              :         fprintf (stderr, " %s", str);
    2556              : 
    2557              :       fprintf (stderr, "\n");
    2558              :     }
    2559              : 
    2560              :   fflush (stdout);
    2561              :   fflush (stderr);
    2562              : 
    2563              :   pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
    2564              :   if (pex == NULL)
    2565              :     fatal_error (input_location, "%<pex_init%> failed: %m");
    2566              : 
    2567              :   errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
    2568              :   if (errmsg != NULL)
    2569              :     {
    2570              :       if (err != 0)
    2571              :         {
    2572              :           errno = err;
    2573              :           fatal_error (input_location, "%s: %m", _(errmsg));
    2574              :         }
    2575              :       else
    2576              :         fatal_error (input_location, errmsg);
    2577              :     }
    2578              : 
    2579              :   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
    2580              : #ifdef SIGQUIT
    2581              :   quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
    2582              : #endif
    2583              : 
    2584              :   inf = pex_read_output (pex, 0);
    2585              :   if (inf == NULL)
    2586              :     fatal_error (input_location, "cannot open ldd output: %m");
    2587              : 
    2588              :   if (debug)
    2589              :     notice ("\nldd output with constructors/destructors.\n");
    2590              : 
    2591              :   /* Read each line of ldd output.  */
    2592              :   while (fgets (buf, sizeof buf, inf) != (char *) 0)
    2593              :     {
    2594              :       int ch2;
    2595              :       char *name, *end, *p = buf;
    2596              : 
    2597              :       /* Extract names of libraries and add to list.  */
    2598              :       PARSE_LDD_OUTPUT (p);
    2599              :       if (p == 0)
    2600              :         continue;
    2601              : 
    2602              :       name = p;
    2603              :       if (startswith (name, "not found"))
    2604              :         fatal_error (input_location, "dynamic dependency %s not found", buf);
    2605              : 
    2606              :       /* Find the end of the symbol name.  */
    2607              :       for (end = p;
    2608              :            (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
    2609              :            end++)
    2610              :         continue;
    2611              :       *end = '\0';
    2612              : 
    2613              :       if (access (name, R_OK) == 0)
    2614              :         add_to_list (&libraries, name);
    2615              :       else
    2616              :         fatal_error (input_location, "unable to open dynamic dependency "
    2617              :                      "%qs", buf);
    2618              : 
    2619              :       if (debug)
    2620              :         fprintf (stderr, "\t%s\n", buf);
    2621              :     }
    2622              :   if (debug)
    2623              :     fprintf (stderr, "\n");
    2624              : 
    2625              :   do_wait (ldd_file_name, pex);
    2626              : 
    2627              :   signal (SIGINT,  int_handler);
    2628              : #ifdef SIGQUIT
    2629              :   signal (SIGQUIT, quit_handler);
    2630              : #endif
    2631              : 
    2632              :   /* Now iterate through the library list adding their symbols to
    2633              :      the list.  */
    2634              :   for (list = libraries.first; list; list = list->next)
    2635              :     scan_prog_file (list->name, PASS_LIB, SCAN_ALL);
    2636              : }
    2637              : 
    2638              : #endif /* LDD_SUFFIX */
    2639              : 
    2640              : #endif /* OBJECT_FORMAT_NONE */
    2641              : 
    2642              : 
    2643              : /*
    2644              :  * COFF specific stuff.
    2645              :  */
    2646              : 
    2647              : #ifdef OBJECT_FORMAT_COFF
    2648              : 
    2649              : #   define GCC_SYMBOLS(X)       (HEADER (ldptr).f_nsyms)
    2650              : #   define GCC_SYMENT           SYMENT
    2651              : #   if defined (C_WEAKEXT)
    2652              : #     define GCC_OK_SYMBOL(X) \
    2653              :        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
    2654              :         ((X).n_scnum > N_UNDEF) && \
    2655              :         (aix64_flag \
    2656              :          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
    2657              :              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
    2658              : #     define GCC_UNDEF_SYMBOL(X) \
    2659              :        (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
    2660              :         ((X).n_scnum == N_UNDEF))
    2661              : #   else
    2662              : #     define GCC_OK_SYMBOL(X) \
    2663              :        (((X).n_sclass == C_EXT) && \
    2664              :         ((X).n_scnum > N_UNDEF) && \
    2665              :         (aix64_flag \
    2666              :          || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
    2667              :              || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
    2668              : #     define GCC_UNDEF_SYMBOL(X) \
    2669              :        (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
    2670              : #   endif
    2671              : #   define GCC_SYMINC(X)        ((X).n_numaux+1)
    2672              : #   define GCC_SYMZERO(X)       0
    2673              : 
    2674              : /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
    2675              : #if TARGET_AIX_VERSION >= 51
    2676              : #   define GCC_CHECK_HDR(X) \
    2677              :      (((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
    2678              :        || (HEADER (X).f_magic == 0767 && aix64_flag)) \
    2679              :       && !(HEADER (X).f_flags & F_LOADONLY))
    2680              : #else
    2681              : #   define GCC_CHECK_HDR(X) \
    2682              :      (((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
    2683              :        || (HEADER (X).f_magic == 0757 && aix64_flag)) \
    2684              :       && !(HEADER (X).f_flags & F_LOADONLY))
    2685              : #endif
    2686              : 
    2687              : #ifdef COLLECT_EXPORT_LIST
    2688              : /* Array of standard AIX libraries which should not
    2689              :    be scanned for ctors/dtors.  */
    2690              : static const char *const aix_std_libs[] = {
    2691              :   "/unix",
    2692              :   "/lib/libc.a",
    2693              :   "/lib/libm.a",
    2694              :   "/lib/libc_r.a",
    2695              :   "/lib/libm_r.a",
    2696              :   "/usr/lib/libc.a",
    2697              :   "/usr/lib/libm.a",
    2698              :   "/usr/lib/libc_r.a",
    2699              :   "/usr/lib/libm_r.a",
    2700              :   "/usr/lib/threads/libc.a",
    2701              :   "/usr/ccs/lib/libc.a",
    2702              :   "/usr/ccs/lib/libm.a",
    2703              :   "/usr/ccs/lib/libc_r.a",
    2704              :   "/usr/ccs/lib/libm_r.a",
    2705              :   NULL
    2706              : };
    2707              : 
    2708              : /* This function checks the filename and returns 1
    2709              :    if this name matches the location of a standard AIX library.  */
    2710              : static int ignore_library (const char *);
    2711              : static int
    2712              : ignore_library (const char *name)
    2713              : {
    2714              :   const char *const *p;
    2715              :   size_t length;
    2716              : 
    2717              :   if (target_system_root[0] != '\0')
    2718              :     {
    2719              :       length = strlen (target_system_root);
    2720              :       if (strncmp (name, target_system_root, length) != 0)
    2721              :         return 0;
    2722              :       name += length;
    2723              :     }
    2724              :   for (p = &aix_std_libs[0]; *p != NULL; ++p)
    2725              :     if (strcmp (name, *p) == 0)
    2726              :       return 1;
    2727              :   return 0;
    2728              : }
    2729              : #endif /* COLLECT_EXPORT_LIST */
    2730              : 
    2731              : #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
    2732              : extern char *ldgetname (LDFILE *, GCC_SYMENT *);
    2733              : #endif
    2734              : 
    2735              : /* COFF version to scan the name list of the loaded program for
    2736              :    the symbols g++ uses for static constructors and destructors.  */
    2737              : 
    2738              : static void
    2739              : scan_prog_file (const char *prog_name, scanpass which_pass,
    2740              :                 scanfilter filter)
    2741              : {
    2742              :   LDFILE *ldptr = NULL;
    2743              :   int sym_index, sym_count;
    2744              :   int is_shared = 0;
    2745              : 
    2746              :   if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
    2747              :     return;
    2748              : 
    2749              : #ifdef COLLECT_EXPORT_LIST
    2750              :   /* We do not need scanning for some standard C libraries.  */
    2751              :   if (which_pass == PASS_FIRST && ignore_library (prog_name))
    2752              :     return;
    2753              : 
    2754              :   /* On AIX we have a loop, because there is not much difference
    2755              :      between an object and an archive. This trick allows us to
    2756              :      eliminate scan_libraries() function.  */
    2757              :   do
    2758              :     {
    2759              : #endif
    2760              :       /* Some platforms (e.g. OSF4) declare ldopen as taking a
    2761              :          non-const char * filename parameter, even though it will not
    2762              :          modify that string.  So we must cast away const-ness here,
    2763              :          using CONST_CAST to prevent complaints from -Wcast-qual.  */
    2764              :       if ((ldptr = ldopen (const_cast<char *> (prog_name), ldptr)) != NULL)
    2765              :         {
    2766              :           if (! MY_ISCOFF (HEADER (ldptr).f_magic))
    2767              :             {
    2768              :               warning (0, "%s: not a COFF file", prog_name);
    2769              :               continue;
    2770              :             }
    2771              : 
    2772              :           if (GCC_CHECK_HDR (ldptr))
    2773              :             {
    2774              :               sym_count = GCC_SYMBOLS (ldptr);
    2775              :               sym_index = GCC_SYMZERO (ldptr);
    2776              : 
    2777              : #ifdef COLLECT_EXPORT_LIST
    2778              :               /* Is current archive member a shared object?  */
    2779              :               is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
    2780              : #endif
    2781              : 
    2782              :               while (sym_index < sym_count)
    2783              :                 {
    2784              :                   GCC_SYMENT symbol;
    2785              : 
    2786              :                   if (ldtbread (ldptr, sym_index, &symbol) <= 0)
    2787              :                     break;
    2788              :                   sym_index += GCC_SYMINC (symbol);
    2789              : 
    2790              :                   if (GCC_OK_SYMBOL (symbol))
    2791              :                     {
    2792              :                       char *name;
    2793              : 
    2794              :                       if ((name = ldgetname (ldptr, &symbol)) == NULL)
    2795              :                         continue;               /* Should never happen.  */
    2796              : 
    2797              : #ifdef XCOFF_DEBUGGING_INFO
    2798              :                       /* All AIX function names have a duplicate entry
    2799              :                          beginning with a dot.  */
    2800              :                       if (*name == '.')
    2801              :                         ++name;
    2802              : #endif
    2803              : 
    2804              :                       switch (is_ctor_dtor (name))
    2805              :                         {
    2806              : #if TARGET_AIX_VERSION
    2807              :                       /* Add AIX shared library initialisers/finalisers
    2808              :                          to the constructors/destructors list of the
    2809              :                          current module.  */
    2810              :                         case SYM_AIXI:
    2811              :                           if (! (filter & SCAN_CTOR))
    2812              :                             break;
    2813              :                           if (is_shared && !aixlazy_flag
    2814              : #ifdef COLLECT_EXPORT_LIST
    2815              :                               && ! static_obj
    2816              :                               && ! is_in_list (prog_name, static_libs.first)
    2817              : #endif
    2818              :                               )
    2819              :                             add_to_list (&constructors, name);
    2820              :                           break;
    2821              : 
    2822              :                         case SYM_AIXD:
    2823              :                           if (! (filter & SCAN_DTOR))
    2824              :                             break;
    2825              :                           if (is_shared && !aixlazy_flag)
    2826              :                             add_to_list (&destructors, name);
    2827              :                           break;
    2828              : #endif
    2829              : 
    2830              :                         case SYM_CTOR:
    2831              :                           if (! (filter & SCAN_CTOR))
    2832              :                             break;
    2833              :                           if (! is_shared)
    2834              :                             add_to_list (&constructors, name);
    2835              : #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
    2836              :                           if (which_pass == PASS_OBJ)
    2837              :                             add_to_list (&exports, name);
    2838              : #endif
    2839              :                           break;
    2840              : 
    2841              :                         case SYM_DTOR:
    2842              :                           if (! (filter & SCAN_DTOR))
    2843              :                             break;
    2844              :                           if (! is_shared)
    2845              :                             add_to_list (&destructors, name);
    2846              : #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
    2847              :                           if (which_pass == PASS_OBJ)
    2848              :                             add_to_list (&exports, name);
    2849              : #endif
    2850              :                           break;
    2851              : 
    2852              : #ifdef COLLECT_EXPORT_LIST
    2853              :                         case SYM_INIT:
    2854              :                           if (! (filter & SCAN_INIT))
    2855              :                             break;
    2856              : #ifndef LD_INIT_SWITCH
    2857              :                           if (is_shared)
    2858              :                             add_to_list (&constructors, name);
    2859              : #endif
    2860              :                           break;
    2861              : 
    2862              :                         case SYM_FINI:
    2863              :                           if (! (filter & SCAN_FINI))
    2864              :                             break;
    2865              : #ifndef LD_INIT_SWITCH
    2866              :                           if (is_shared)
    2867              :                             add_to_list (&destructors, name);
    2868              : #endif
    2869              :                           break;
    2870              : #endif
    2871              : 
    2872              :                         case SYM_DWEH:
    2873              :                           if (! (filter & SCAN_DWEH))
    2874              :                             break;
    2875              :                           if (! is_shared)
    2876              :                             add_to_list (&frame_tables, name);
    2877              : #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
    2878              :                           if (which_pass == PASS_OBJ)
    2879              :                             add_to_list (&exports, name);
    2880              : #endif
    2881              :                           break;
    2882              : 
    2883              :                         default:        /* not a constructor or destructor */
    2884              : #ifdef COLLECT_EXPORT_LIST
    2885              :                           /* Explicitly export all global symbols when
    2886              :                              building a shared object on AIX, but do not
    2887              :                              re-export symbols from another shared object
    2888              :                              and do not export symbols if the user
    2889              :                              provides an explicit export list.  */
    2890              :                           if (shared_obj && !is_shared
    2891              :                               && which_pass == PASS_OBJ && !export_flag)
    2892              :                             {
    2893              :                               /* Do not auto-export __dso_handle or
    2894              :                                  __gcc_unwind_dbase.  They are required
    2895              :                                  to be local to each module.  */
    2896              :                               if (strcmp(name, "__dso_handle") != 0
    2897              :                                   && strcmp(name, "__gcc_unwind_dbase") != 0)
    2898              :                                 {
    2899              :                                   add_to_list (&exports, name);
    2900              :                                 }
    2901              :                             }
    2902              : #endif
    2903              :                           continue;
    2904              :                         }
    2905              : 
    2906              :                       if (debug)
    2907              :                         fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
    2908              :                                  symbol.n_scnum, symbol.n_sclass,
    2909              :                                  (symbol.n_type ? "0" : ""), symbol.n_type,
    2910              :                                  name);
    2911              :                     }
    2912              :                 }
    2913              :             }
    2914              : #ifdef COLLECT_EXPORT_LIST
    2915              :           else
    2916              :             {
    2917              :               /* If archive contains both 32-bit and 64-bit objects,
    2918              :                  we want to skip objects in other mode so mismatch normal.  */
    2919              :               if (debug)
    2920              :                 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
    2921              :                          prog_name, HEADER (ldptr).f_magic, aix64_flag);
    2922              :             }
    2923              : #endif
    2924              :         }
    2925              :       else
    2926              :         {
    2927              :           fatal_error (input_location, "%s: cannot open as COFF file",
    2928              :                        prog_name);
    2929              :         }
    2930              : #ifdef COLLECT_EXPORT_LIST
    2931              :       /* On AIX loop continues while there are more members in archive.  */
    2932              :     }
    2933              :   while (ldclose (ldptr) == FAILURE);
    2934              : #else
    2935              :   /* Otherwise we simply close ldptr.  */
    2936              :   (void) ldclose (ldptr);
    2937              : #endif
    2938              : }
    2939              : #endif /* OBJECT_FORMAT_COFF */
    2940              : 
    2941              : #ifdef COLLECT_EXPORT_LIST
    2942              : /* Given a library name without "lib" prefix, this function
    2943              :    returns a full library name including a path.  */
    2944              : static char *
    2945              : resolve_lib_name (const char *name)
    2946              : {
    2947              :   char *lib_buf;
    2948              :   int i, j, l = 0;
    2949              :   /* Library extensions for AIX dynamic linking.  */
    2950              :   const char * const libexts[2] = {"a", "so"};
    2951              : 
    2952              :   for (i = 0; libpaths[i]; i++)
    2953              :     if (libpaths[i]->max_len > l)
    2954              :       l = libpaths[i]->max_len;
    2955              : 
    2956              :   lib_buf = XNEWVEC (char, l + strlen (name) + 10);
    2957              : 
    2958              :   for (i = 0; libpaths[i]; i++)
    2959              :     {
    2960              :       struct prefix_list *list = libpaths[i]->plist;
    2961              :       for (; list; list = list->next)
    2962              :         {
    2963              :           /* The following lines are needed because path_prefix list
    2964              :              may contain directories both with trailing DIR_SEPARATOR and
    2965              :              without it.  */
    2966              :           const char *p = "";
    2967              :           if (!IS_DIR_SEPARATOR (list->prefix[strlen (list->prefix)-1]))
    2968              :             p = "/";
    2969              :           for (j = 0; j < 2; j++)
    2970              :             {
    2971              :               sprintf (lib_buf, "%s%slib%s.%s",
    2972              :                        list->prefix, p, name,
    2973              :                        libexts[(j + aixrtl_flag) % 2]);
    2974              :               if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
    2975              :               if (file_exists (lib_buf))
    2976              :                 {
    2977              :                   if (debug) fprintf (stderr, "found: %s\n", lib_buf);
    2978              :                   return (lib_buf);
    2979              :                 }
    2980              :             }
    2981              :         }
    2982              :     }
    2983              :   if (debug)
    2984              :     fprintf (stderr, "not found\n");
    2985              :   else
    2986              :     fatal_error (input_location, "library lib%s not found", name);
    2987              :   return (NULL);
    2988              : }
    2989              : #endif /* COLLECT_EXPORT_LIST */
    2990              : 
    2991              : #ifdef COLLECT_RUN_DSYMUTIL
    2992              : static int flag_dsym = false;
    2993              : static int flag_idsym = false;
    2994              : 
    2995              : static void
    2996              : process_args (int *argcp, char **argv) {
    2997              :   int i, j;
    2998              :   int argc = *argcp;
    2999              :   for (i=0; i<argc; ++i)
    3000              :     {
    3001              :       if (strcmp (argv[i], "-dsym") == 0)
    3002              :         {
    3003              :           flag_dsym = true;
    3004              :           /* Remove the flag, as we handle all processing for it.  */
    3005              :           j = i;
    3006              :           do
    3007              :             argv[j] = argv[j+1];
    3008              :           while (++j < argc);
    3009              :           --i;
    3010              :           argc = --(*argcp);
    3011              :         }
    3012              :       else if (strcmp (argv[i], "-idsym") == 0)
    3013              :         {
    3014              :           flag_idsym = true;
    3015              :           /* Remove the flag, as we handle all processing for it.  */
    3016              :           j = i;
    3017              :           do
    3018              :             argv[j] = argv[j+1];
    3019              :           while (++j < argc);
    3020              :           --i;
    3021              :           argc = --(*argcp);
    3022              :         }
    3023              :     }
    3024              : }
    3025              : 
    3026              : static void
    3027              : do_dsymutil (const char *output_file) {
    3028              :   const char *dsymutil = 0;
    3029              :   struct pex_obj *pex;
    3030              :   char **real_argv = XCNEWVEC (char *, verbose ? 4 : 3);
    3031              :   const char ** argv = const_cast<const char **> (real_argv);
    3032              : /* For cross-builds search the PATH using target-qualified name if we
    3033              :    have not already found a suitable dsymutil.  In practice, all modern
    3034              :    versions of dsymutil handle all supported archs, however the approach
    3035              :    here is consistent with the way other installations work (and one can
    3036              :    always symlink a multitarget dsymutil with a target-specific name).  */
    3037              :   const char *dsname = "dsymutil";
    3038              : #ifdef CROSS_DIRECTORY_STRUCTURE
    3039              :   const char *qname = concat (target_machine, "-", dsname, NULL);
    3040              : #else
    3041              :   const char *qname = dsname;
    3042              : #endif
    3043              : #ifdef DEFAULT_DSYMUTIL
    3044              :   /* Configured default takes priority.  */
    3045              :   if (dsymutil == 0 && access (DEFAULT_DSYMUTIL, X_OK) == 0)
    3046              :     dsymutil = DEFAULT_DSYMUTIL;
    3047              :   if (dsymutil == 0)
    3048              : #endif
    3049              : #ifdef DSYMUTIL
    3050              :   /* Followed by one supplied in the target header, somewhat like the
    3051              :      REAL_XX_NAME used elsewhere.  */
    3052              :     dsymutil = find_a_file (&cpath, DSYMUTIL, X_OK);
    3053              :   if (dsymutil == 0)
    3054              :     dsymutil = find_a_file (&path, DSYMUTIL, X_OK);
    3055              :   if (dsymutil == 0)
    3056              : #endif
    3057              :     dsymutil = find_a_file (&cpath, dsname, X_OK);
    3058              :   if (dsymutil == 0)
    3059              :     dsymutil = find_a_file (&path, qname, X_OK);
    3060              : 
    3061              :   argv[0] = dsymutil;
    3062              :   argv[1] = output_file;
    3063              :   if (verbose)
    3064              :     {
    3065              :       argv[2] = "-v";
    3066              :       argv[3] = (char *) 0;
    3067              :     }
    3068              :   else
    3069              :     argv[2] = (char *) 0;
    3070              : 
    3071              :   pex = collect_execute (dsymutil, real_argv, NULL, NULL,
    3072              :                          PEX_LAST | PEX_SEARCH, false, NULL);
    3073              :   do_wait (dsymutil, pex);
    3074              : }
    3075              : 
    3076              : static void
    3077              : post_ld_pass (bool temp_file) {
    3078              :   if (!(temp_file && flag_idsym) && !flag_dsym)
    3079              :     return;
    3080              : 
    3081              :   do_dsymutil (output_file);
    3082              : }
    3083              : #else
    3084              : static void
    3085            0 : process_args (int *argcp ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { }
    3086            0 : static void post_ld_pass (bool temp_file ATTRIBUTE_UNUSED) { }
    3087              : #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.