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 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 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 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 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 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 (<o_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 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 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 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 * 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 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 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 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 3278e4b17023SJohn Marino process_args (int *argcp ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { } 3279e4b17023SJohn Marino static void post_ld_pass (bool temp_file ATTRIBUTE_UNUSED) { } 3280e4b17023SJohn Marino #endif 3281