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