150397Sobrien/* Collect static initialization info into data structures that can be 250397Sobrien traversed by C++ initialization and finalization routines. 390075Sobrien Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 4169689Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 518334Speter Contributed by Chris Smith (csmith@convex.com). 618334Speter Heavily modified by Michael Meissner (meissner@cygnus.com), 718334Speter Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). 818334Speter 990075SobrienThis file is part of GCC. 1018334Speter 1190075SobrienGCC is free software; you can redistribute it and/or modify it under 1290075Sobrienthe terms of the GNU General Public License as published by the Free 1390075SobrienSoftware Foundation; either version 2, or (at your option) any later 1490075Sobrienversion. 1518334Speter 1690075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1790075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1890075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1990075Sobrienfor more details. 2018334Speter 2118334SpeterYou should have received a copy of the GNU General Public License 2290075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 23169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 24169689Skan02110-1301, USA. */ 2518334Speter 2618334Speter 2750397Sobrien/* Build tables of static constructors and destructors and run ld. */ 2818334Speter 2918334Speter#include "config.h" 3050397Sobrien#include "system.h" 31132718Skan#include "coretypes.h" 32132718Skan#include "tm.h" 3318334Speter#include <signal.h> 3490075Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD ) 3590075Sobrien# define SIGCHLD SIGCLD 3690075Sobrien#endif 3718334Speter 3890075Sobrien#ifndef LIBRARY_PATH_ENV 3990075Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH" 4090075Sobrien#endif 4190075Sobrien 4218334Speter#define COLLECT 4318334Speter 4452284Sobrien#include "collect2.h" 4518334Speter#include "demangle.h" 4618334Speter#include "obstack.h" 4752284Sobrien#include "intl.h" 4890075Sobrien#include "version.h" 4918334Speter 5018334Speter/* On certain systems, we have code that works by scanning the object file 5118334Speter directly. But this code uses system-specific header files and library 5218334Speter functions, so turn it off in a cross-compiler. Likewise, the names of 5350397Sobrien the utilities are not correct for a cross-compiler; we have to hope that 5418334Speter cross-versions are in the proper directories. */ 5518334Speter 56259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE 5718334Speter#undef OBJECT_FORMAT_COFF 5818334Speter#undef MD_EXEC_PREFIX 5918334Speter#undef REAL_LD_FILE_NAME 6018334Speter#undef REAL_NM_FILE_NAME 6118334Speter#undef REAL_STRIP_FILE_NAME 6218334Speter#endif 6318334Speter 6450397Sobrien/* If we cannot use a special method, use the ordinary one: 6518334Speter run nm to find what symbols are present. 6618334Speter In a cross-compiler, this means you need a cross nm, 6750397Sobrien but that is not quite as unpleasant as special headers. */ 6818334Speter 69132718Skan#if !defined (OBJECT_FORMAT_COFF) 7018334Speter#define OBJECT_FORMAT_NONE 7118334Speter#endif 7218334Speter 7318334Speter#ifdef OBJECT_FORMAT_COFF 7418334Speter 7518334Speter#include <a.out.h> 7618334Speter#include <ar.h> 7718334Speter 7818334Speter#ifdef UMAX 7918334Speter#include <sgs.h> 8018334Speter#endif 8118334Speter 8218334Speter/* Many versions of ldfcn.h define these. */ 8318334Speter#ifdef FREAD 8418334Speter#undef FREAD 8518334Speter#undef FWRITE 8618334Speter#endif 8718334Speter 8818334Speter#include <ldfcn.h> 8918334Speter 9018334Speter/* Some systems have an ISCOFF macro, but others do not. In some cases 9118334Speter the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines 92132718Skan that either do not have an ISCOFF macro in /usr/include or for those 9318334Speter where it is wrong. */ 9418334Speter 9518334Speter#ifndef MY_ISCOFF 9618334Speter#define MY_ISCOFF(X) ISCOFF (X) 9718334Speter#endif 9818334Speter 9918334Speter#endif /* OBJECT_FORMAT_COFF */ 10018334Speter 10118334Speter#ifdef OBJECT_FORMAT_NONE 10218334Speter 10318334Speter/* Default flags to pass to nm. */ 10418334Speter#ifndef NM_FLAGS 10552284Sobrien#define NM_FLAGS "-n" 10618334Speter#endif 10718334Speter 10818334Speter#endif /* OBJECT_FORMAT_NONE */ 10918334Speter 11018334Speter/* Some systems use __main in a way incompatible with its use in gcc, in these 11118334Speter cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to 112117395Skan give the same symbol without quotes for an alternative entry point. */ 11318334Speter#ifndef NAME__MAIN 11418334Speter#define NAME__MAIN "__main" 11518334Speter#endif 11618334Speter 11752284Sobrien/* This must match tree.h. */ 11852284Sobrien#define DEFAULT_INIT_PRIORITY 65535 11952284Sobrien 12090075Sobrien#ifndef COLLECT_SHARED_INIT_FUNC 12190075Sobrien#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \ 12290075Sobrien fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC)) 12390075Sobrien#endif 12490075Sobrien#ifndef COLLECT_SHARED_FINI_FUNC 12590075Sobrien#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \ 12690075Sobrien fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC)) 12790075Sobrien#endif 12890075Sobrien 129169689Skan#ifdef LDD_SUFFIX 13018334Speter#define SCAN_LIBRARIES 13118334Speter#endif 13218334Speter 13318334Speter#ifdef USE_COLLECT2 13418334Speterint do_collecting = 1; 13518334Speter#else 13618334Speterint do_collecting = 0; 13718334Speter#endif 13890075Sobrien 13990075Sobrien/* Nonzero if we should suppress the automatic demangling of identifiers 14090075Sobrien in linker error messages. Set from COLLECT_NO_DEMANGLE. */ 14190075Sobrienint no_demangle; 14218334Speter 14350397Sobrien/* Linked lists of constructor and destructor names. */ 14418334Speter 145132718Skanstruct id 14618334Speter{ 14718334Speter struct id *next; 14818334Speter int sequence; 14918334Speter char name[1]; 15018334Speter}; 15118334Speter 15218334Speterstruct head 15318334Speter{ 15418334Speter struct id *first; 15518334Speter struct id *last; 15618334Speter int number; 15718334Speter}; 15818334Speter 15918334Speter/* Enumeration giving which pass this is for scanning the program file. */ 16018334Speter 16118334Speterenum pass { 16218334Speter PASS_FIRST, /* without constructors */ 16318334Speter PASS_OBJ, /* individual objects */ 164169689Skan PASS_LIB, /* looking for shared libraries */ 16518334Speter PASS_SECOND /* with constructors linked in */ 16618334Speter}; 16718334Speter 16818334Speterint vflag; /* true if -v */ 16918334Speterstatic int rflag; /* true if -r */ 17018334Speterstatic int strip_flag; /* true if -s */ 171169689Skanstatic const char *demangle_flag; 17250397Sobrien#ifdef COLLECT_EXPORT_LIST 17350397Sobrienstatic int export_flag; /* true if -bE */ 17450397Sobrienstatic int aix64_flag; /* true if -b64 */ 175146895Skanstatic int aixrtl_flag; /* true if -brtl */ 17650397Sobrien#endif 17718334Speter 17818334Speterint debug; /* true if -debug */ 17918334Speter 180169689Skanstatic int shared_obj; /* true if -shared */ 18118334Speter 18290075Sobrienstatic const char *c_file; /* <xxx>.c for constructor/destructor list. */ 18390075Sobrienstatic const char *o_file; /* <xxx>.o for constructor/destructor list. */ 18450397Sobrien#ifdef COLLECT_EXPORT_LIST 185169689Skanstatic const char *export_file; /* <xxx>.x for AIX export list. */ 18650397Sobrien#endif 187169689Skanconst char *ldout; /* File for ld stdout. */ 188169689Skanconst char *lderrout; /* File for ld stderr. */ 18990075Sobrienstatic const char *output_file; /* Output file for ld. */ 19090075Sobrienstatic const char *nm_file_name; /* pathname of nm */ 19150397Sobrien#ifdef LDD_SUFFIX 19290075Sobrienstatic const char *ldd_file_name; /* pathname of ldd (or equivalent) */ 19350397Sobrien#endif 19490075Sobrienstatic const char *strip_file_name; /* pathname of strip */ 195169689Skanconst char *c_file_name; /* pathname of gcc */ 19618334Speterstatic char *initname, *fininame; /* names of init and fini funcs */ 19718334Speter 19818334Speterstatic struct head constructors; /* list of constructors found */ 19918334Speterstatic struct head destructors; /* list of destructors found */ 20050397Sobrien#ifdef COLLECT_EXPORT_LIST 20118334Speterstatic struct head exports; /* list of exported symbols */ 20250397Sobrien#endif 20350397Sobrienstatic struct head frame_tables; /* list of frame unwind info tables */ 20418334Speter 20518334Speterstruct obstack temporary_obstack; 20618334Speterchar * temporary_firstobj; 20718334Speter 20818334Speter/* Structure to hold all the directories in which to search for files to 20918334Speter execute. */ 21018334Speter 21118334Speterstruct prefix_list 21218334Speter{ 21390075Sobrien const char *prefix; /* String to prepend to the path. */ 21450397Sobrien struct prefix_list *next; /* Next in linked list. */ 21518334Speter}; 21618334Speter 21718334Speterstruct path_prefix 21818334Speter{ 21918334Speter struct prefix_list *plist; /* List of prefixes to try */ 22018334Speter int max_len; /* Max length of a prefix in PLIST */ 22190075Sobrien const char *name; /* Name of this list (used in config stuff) */ 22218334Speter}; 22318334Speter 22450397Sobrien#ifdef COLLECT_EXPORT_LIST 22590075Sobrien/* Lists to keep libraries to be scanned for global constructors/destructors. */ 22650397Sobrienstatic struct head libs; /* list of libraries */ 22750397Sobrienstatic struct path_prefix cmdline_lib_dirs; /* directories specified with -L */ 22850397Sobrienstatic struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */ 22950397Sobrienstatic struct path_prefix *libpaths[3] = {&cmdline_lib_dirs, 23050397Sobrien &libpath_lib_dirs, NULL}; 23150397Sobrien#endif 23250397Sobrien 233132718Skanstatic void handler (int); 234132718Skanstatic int is_ctor_dtor (const char *); 235132718Skanstatic char *find_a_file (struct path_prefix *, const char *); 236132718Skanstatic void add_prefix (struct path_prefix *, const char *); 237132718Skanstatic void prefix_from_env (const char *, struct path_prefix *); 238132718Skanstatic void prefix_from_string (const char *, struct path_prefix *); 239169689Skanstatic void do_wait (const char *, struct pex_obj *); 240132718Skanstatic void fork_execute (const char *, char **); 241132718Skanstatic void maybe_unlink (const char *); 242132718Skanstatic void add_to_list (struct head *, const char *); 243132718Skanstatic int extract_init_priority (const char *); 244132718Skanstatic void sort_ids (struct head *); 245132718Skanstatic void write_list (FILE *, const char *, struct id *); 24650397Sobrien#ifdef COLLECT_EXPORT_LIST 247132718Skanstatic void dump_list (FILE *, const char *, struct id *); 24850397Sobrien#endif 24950397Sobrien#if 0 250132718Skanstatic void dump_prefix_list (FILE *, const char *, struct prefix_list *); 25150397Sobrien#endif 252132718Skanstatic void write_list_with_asm (FILE *, const char *, struct id *); 253132718Skanstatic void write_c_file (FILE *, const char *); 254132718Skanstatic void write_c_file_stat (FILE *, const char *); 25590075Sobrien#ifndef LD_INIT_SWITCH 256132718Skanstatic void write_c_file_glob (FILE *, const char *); 25790075Sobrien#endif 258132718Skanstatic void scan_prog_file (const char *, enum pass); 25950397Sobrien#ifdef SCAN_LIBRARIES 260132718Skanstatic void scan_libraries (const char *); 26150397Sobrien#endif 26290075Sobrien#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES 263132718Skanstatic int is_in_args (const char *, const char **, const char **); 26490075Sobrien#endif 26550397Sobrien#ifdef COLLECT_EXPORT_LIST 26690075Sobrien#if 0 267132718Skanstatic int is_in_list (const char *, struct id *); 26850397Sobrien#endif 269132718Skanstatic void write_aix_file (FILE *, struct id *); 270132718Skanstatic char *resolve_lib_name (const char *); 27190075Sobrien#endif 272132718Skanstatic char *extract_string (const char **); 27318334Speter 27418334Speter/* Delete tempfiles and exit function. */ 27518334Speter 27618334Spetervoid 277132718Skancollect_exit (int status) 27818334Speter{ 27918334Speter if (c_file != 0 && c_file[0]) 28018334Speter maybe_unlink (c_file); 28118334Speter 28218334Speter if (o_file != 0 && o_file[0]) 28318334Speter maybe_unlink (o_file); 28418334Speter 28550397Sobrien#ifdef COLLECT_EXPORT_LIST 28618334Speter if (export_file != 0 && export_file[0]) 28718334Speter maybe_unlink (export_file); 28850397Sobrien#endif 28950397Sobrien 29018334Speter if (ldout != 0 && ldout[0]) 29118334Speter { 292169689Skan dump_file (ldout, stdout); 29318334Speter maybe_unlink (ldout); 29418334Speter } 29518334Speter 296169689Skan if (lderrout != 0 && lderrout[0]) 297169689Skan { 298169689Skan dump_file (lderrout, stderr); 299169689Skan maybe_unlink (lderrout); 300169689Skan } 301169689Skan 30218334Speter if (status != 0 && output_file != 0 && output_file[0]) 30318334Speter maybe_unlink (output_file); 30418334Speter 30518334Speter exit (status); 30618334Speter} 30718334Speter 30818334Speter 30952284Sobrien/* Notify user of a non-error. */ 31052284Sobrienvoid 311169689Skannotice (const char *cmsgid, ...) 31252284Sobrien{ 313132718Skan va_list ap; 31452284Sobrien 315169689Skan va_start (ap, cmsgid); 316169689Skan vfprintf (stderr, _(cmsgid), ap); 317132718Skan va_end (ap); 31852284Sobrien} 31952284Sobrien 32050397Sobrien/* Die when sys call fails. */ 32118334Speter 32218334Spetervoid 323169689Skanfatal_perror (const char * cmsgid, ...) 32418334Speter{ 32518334Speter int e = errno; 326132718Skan va_list ap; 32718334Speter 328169689Skan va_start (ap, cmsgid); 32918334Speter fprintf (stderr, "collect2: "); 330169689Skan vfprintf (stderr, _(cmsgid), ap); 33190075Sobrien fprintf (stderr, ": %s\n", xstrerror (e)); 332132718Skan va_end (ap); 33352284Sobrien 33450397Sobrien collect_exit (FATAL_EXIT_CODE); 33518334Speter} 33618334Speter 33750397Sobrien/* Just die. */ 33818334Speter 33918334Spetervoid 340169689Skanfatal (const char * cmsgid, ...) 34118334Speter{ 342132718Skan va_list ap; 343132718Skan 344169689Skan va_start (ap, cmsgid); 34518334Speter fprintf (stderr, "collect2: "); 346169689Skan vfprintf (stderr, _(cmsgid), ap); 34718334Speter fprintf (stderr, "\n"); 348132718Skan va_end (ap); 34952284Sobrien 35050397Sobrien collect_exit (FATAL_EXIT_CODE); 35118334Speter} 35218334Speter 35318334Speter/* Write error message. */ 35418334Speter 35518334Spetervoid 356169689Skanerror (const char * gmsgid, ...) 35718334Speter{ 358132718Skan va_list ap; 35952284Sobrien 360169689Skan va_start (ap, gmsgid); 36118334Speter fprintf (stderr, "collect2: "); 362169689Skan vfprintf (stderr, _(gmsgid), ap); 36318334Speter fprintf (stderr, "\n"); 364132718Skan va_end(ap); 36518334Speter} 36618334Speter 36718334Speter/* In case obstack is linked in, and abort is defined to fancy_abort, 36818334Speter provide a default entry. */ 36918334Speter 37018334Spetervoid 371169689Skanfancy_abort (const char *file, int line, const char *func) 37218334Speter{ 373169689Skan fatal ("internal gcc abort in %s, at %s:%d", func, file, line); 37418334Speter} 37518334Speter 37618334Speterstatic void 377132718Skanhandler (int signo) 37818334Speter{ 37918334Speter if (c_file != 0 && c_file[0]) 38018334Speter maybe_unlink (c_file); 38118334Speter 38218334Speter if (o_file != 0 && o_file[0]) 38318334Speter maybe_unlink (o_file); 38418334Speter 38518334Speter if (ldout != 0 && ldout[0]) 38618334Speter maybe_unlink (ldout); 38718334Speter 388169689Skan if (lderrout != 0 && lderrout[0]) 389169689Skan maybe_unlink (lderrout); 390169689Skan 39150397Sobrien#ifdef COLLECT_EXPORT_LIST 39250397Sobrien if (export_file != 0 && export_file[0]) 39350397Sobrien maybe_unlink (export_file); 39450397Sobrien#endif 39550397Sobrien 39618334Speter signal (signo, SIG_DFL); 397169689Skan raise (signo); 39818334Speter} 39918334Speter 40018334Speter 40118334Speterint 402132718Skanfile_exists (const char *name) 40318334Speter{ 40418334Speter return access (name, R_OK) == 0; 40518334Speter} 40618334Speter 40750397Sobrien/* Parse a reasonable subset of shell quoting syntax. */ 40850397Sobrien 40950397Sobrienstatic char * 410132718Skanextract_string (const char **pp) 41150397Sobrien{ 41290075Sobrien const char *p = *pp; 41350397Sobrien int backquote = 0; 41450397Sobrien int inside = 0; 41550397Sobrien 41650397Sobrien for (;;) 41750397Sobrien { 41850397Sobrien char c = *p; 41950397Sobrien if (c == '\0') 42050397Sobrien break; 42150397Sobrien ++p; 42250397Sobrien if (backquote) 42350397Sobrien obstack_1grow (&temporary_obstack, c); 42450397Sobrien else if (! inside && c == ' ') 42550397Sobrien break; 42650397Sobrien else if (! inside && c == '\\') 42750397Sobrien backquote = 1; 42850397Sobrien else if (c == '\'') 42950397Sobrien inside = !inside; 43050397Sobrien else 43150397Sobrien obstack_1grow (&temporary_obstack, c); 43250397Sobrien } 43350397Sobrien 43450397Sobrien obstack_1grow (&temporary_obstack, '\0'); 43550397Sobrien *pp = p; 436169689Skan return XOBFINISH (&temporary_obstack, char *); 43750397Sobrien} 43818334Speter 43918334Spetervoid 440169689Skandump_file (const char *name, FILE *to) 44118334Speter{ 44218334Speter FILE *stream = fopen (name, "r"); 44318334Speter 44418334Speter if (stream == 0) 44518334Speter return; 44618334Speter while (1) 44718334Speter { 44818334Speter int c; 44918334Speter while (c = getc (stream), 45090075Sobrien c != EOF && (ISIDNUM (c) || c == '$' || c == '.')) 45118334Speter obstack_1grow (&temporary_obstack, c); 45218334Speter if (obstack_object_size (&temporary_obstack) > 0) 45318334Speter { 45490075Sobrien const char *word, *p; 45590075Sobrien char *result; 45618334Speter obstack_1grow (&temporary_obstack, '\0'); 457169689Skan word = XOBFINISH (&temporary_obstack, const char *); 45818334Speter 45918334Speter if (*word == '.') 460169689Skan ++word, putc ('.', to); 46118334Speter p = word; 462117395Skan if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX))) 463117395Skan p += strlen (USER_LABEL_PREFIX); 46418334Speter 465169689Skan#ifdef HAVE_LD_DEMANGLE 466169689Skan result = 0; 467169689Skan#else 46818334Speter if (no_demangle) 46918334Speter result = 0; 47018334Speter else 47196263Sobrien result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); 472169689Skan#endif 47318334Speter 47418334Speter if (result) 47518334Speter { 47618334Speter int diff; 477169689Skan fputs (result, to); 47818334Speter 47918334Speter diff = strlen (word) - strlen (result); 48090075Sobrien while (diff > 0 && c == ' ') 481169689Skan --diff, putc (' ', to); 48218334Speter while (diff < 0 && c == ' ') 48318334Speter ++diff, c = getc (stream); 48418334Speter 48518334Speter free (result); 48618334Speter } 48718334Speter else 488169689Skan fputs (word, to); 48918334Speter 490169689Skan fflush (to); 49118334Speter obstack_free (&temporary_obstack, temporary_firstobj); 49218334Speter } 49318334Speter if (c == EOF) 49418334Speter break; 495169689Skan putc (c, to); 49618334Speter } 49750397Sobrien fclose (stream); 49818334Speter} 49918334Speter 50090075Sobrien/* Decide whether the given symbol is: a constructor (1), a destructor 50190075Sobrien (2), a routine in a shared object that calls all the constructors 50290075Sobrien (3) or destructors (4), a DWARF exception-handling table (5), or 50390075Sobrien nothing special (0). */ 50418334Speter 50518334Speterstatic int 506132718Skanis_ctor_dtor (const char *s) 50718334Speter{ 50890075Sobrien struct names { const char *const name; const int len; const int ret; 50990075Sobrien const int two_underscores; }; 51018334Speter 51190075Sobrien const struct names *p; 51290075Sobrien int ch; 51390075Sobrien const char *orig_s = s; 51418334Speter 51590075Sobrien static const struct names special[] = { 516102780Skan#ifndef NO_DOLLAR_IN_LABEL 517102780Skan { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 }, 518102780Skan { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 }, 519102780Skan#else 520102780Skan#ifndef NO_DOT_IN_LABEL 521102780Skan { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 }, 522102780Skan { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 }, 523102780Skan#endif /* NO_DOT_IN_LABEL */ 524102780Skan#endif /* NO_DOLLAR_IN_LABEL */ 52518334Speter { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 }, 52618334Speter { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 }, 52750397Sobrien { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 }, 52818334Speter { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 }, 52918334Speter { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 }, 53018334Speter { NULL, 0, 0, 0 } 53118334Speter }; 53218334Speter 53318334Speter while ((ch = *s) == '_') 53418334Speter ++s; 53518334Speter 53618334Speter if (s == orig_s) 53718334Speter return 0; 53818334Speter 53918334Speter for (p = &special[0]; p->len > 0; p++) 54018334Speter { 54118334Speter if (ch == p->name[0] 54218334Speter && (!p->two_underscores || ((s - orig_s) >= 2)) 54318334Speter && strncmp(s, p->name, p->len) == 0) 54418334Speter { 54518334Speter return p->ret; 54618334Speter } 54718334Speter } 54818334Speter return 0; 54918334Speter} 55018334Speter 55118334Speter/* We maintain two prefix lists: one from COMPILER_PATH environment variable 55218334Speter and one from the PATH variable. */ 55318334Speter 55418334Speterstatic struct path_prefix cpath, path; 55518334Speter 556259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE 55718334Speter/* This is the name of the target machine. We use it to form the name 55818334Speter of the files to execute. */ 55918334Speter 56090075Sobrienstatic const char *const target_machine = TARGET_MACHINE; 56118334Speter#endif 56218334Speter 56318334Speter/* Search for NAME using prefix list PPREFIX. We only look for executable 564132718Skan files. 56518334Speter 56650397Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 56718334Speter 56818334Speterstatic char * 569132718Skanfind_a_file (struct path_prefix *pprefix, const char *name) 57018334Speter{ 57118334Speter char *temp; 57218334Speter struct prefix_list *pl; 57318334Speter int len = pprefix->max_len + strlen (name) + 1; 57418334Speter 57550397Sobrien if (debug) 57650397Sobrien fprintf (stderr, "Looking for '%s'\n", name); 577132718Skan 57890075Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 57990075Sobrien len += strlen (HOST_EXECUTABLE_SUFFIX); 58018334Speter#endif 58118334Speter 582169689Skan temp = XNEWVEC (char, len); 58318334Speter 58418334Speter /* Determine the filename to execute (special case for absolute paths). */ 58518334Speter 58650397Sobrien if (*name == '/' 58752284Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 58852284Sobrien || (*name && name[1] == ':') 58950397Sobrien#endif 59050397Sobrien ) 59118334Speter { 59218334Speter if (access (name, X_OK) == 0) 59318334Speter { 59418334Speter strcpy (temp, name); 59550397Sobrien 59650397Sobrien if (debug) 59750397Sobrien fprintf (stderr, " - found: absolute path\n"); 598132718Skan 59918334Speter return temp; 60018334Speter } 60150397Sobrien 60290075Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 60352284Sobrien /* Some systems have a suffix for executable files. 60452284Sobrien So try appending that. */ 60552284Sobrien strcpy (temp, name); 60690075Sobrien strcat (temp, HOST_EXECUTABLE_SUFFIX); 607132718Skan 60852284Sobrien if (access (temp, X_OK) == 0) 60952284Sobrien return temp; 61052284Sobrien#endif 61152284Sobrien 61250397Sobrien if (debug) 61350397Sobrien fprintf (stderr, " - failed to locate using absolute path\n"); 61418334Speter } 61518334Speter else 61618334Speter for (pl = pprefix->plist; pl; pl = pl->next) 61718334Speter { 61890075Sobrien struct stat st; 61990075Sobrien 62018334Speter strcpy (temp, pl->prefix); 62118334Speter strcat (temp, name); 622132718Skan 62390075Sobrien if (stat (temp, &st) >= 0 62490075Sobrien && ! S_ISDIR (st.st_mode) 62590075Sobrien && access (temp, X_OK) == 0) 62618334Speter return temp; 62718334Speter 62890075Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 62918334Speter /* Some systems have a suffix for executable files. 63018334Speter So try appending that. */ 63190075Sobrien strcat (temp, HOST_EXECUTABLE_SUFFIX); 632132718Skan 63390075Sobrien if (stat (temp, &st) >= 0 63490075Sobrien && ! S_ISDIR (st.st_mode) 63590075Sobrien && access (temp, X_OK) == 0) 63618334Speter return temp; 63718334Speter#endif 63818334Speter } 63918334Speter 64050397Sobrien if (debug && pprefix->plist == NULL) 64150397Sobrien fprintf (stderr, " - failed: no entries in prefix list\n"); 64250397Sobrien 64318334Speter free (temp); 64418334Speter return 0; 64518334Speter} 64618334Speter 64718334Speter/* Add an entry for PREFIX to prefix list PPREFIX. */ 64818334Speter 64918334Speterstatic void 650132718Skanadd_prefix (struct path_prefix *pprefix, const char *prefix) 65118334Speter{ 65218334Speter struct prefix_list *pl, **prev; 65318334Speter int len; 65418334Speter 65518334Speter if (pprefix->plist) 65618334Speter { 65718334Speter for (pl = pprefix->plist; pl->next; pl = pl->next) 65818334Speter ; 65918334Speter prev = &pl->next; 66018334Speter } 66118334Speter else 66218334Speter prev = &pprefix->plist; 66318334Speter 664132718Skan /* Keep track of the longest prefix. */ 66518334Speter 66618334Speter len = strlen (prefix); 66718334Speter if (len > pprefix->max_len) 66818334Speter pprefix->max_len = len; 66918334Speter 670169689Skan pl = XNEW (struct prefix_list); 67152284Sobrien pl->prefix = xstrdup (prefix); 67218334Speter 67318334Speter if (*prev) 67418334Speter pl->next = *prev; 67518334Speter else 67618334Speter pl->next = (struct prefix_list *) 0; 67718334Speter *prev = pl; 67818334Speter} 67918334Speter 68018334Speter/* Take the value of the environment variable ENV, break it into a path, and 68118334Speter add of the entries to PPREFIX. */ 68218334Speter 68318334Speterstatic void 684132718Skanprefix_from_env (const char *env, struct path_prefix *pprefix) 68518334Speter{ 68690075Sobrien const char *p; 687117395Skan GET_ENVIRONMENT (p, env); 68818334Speter 68918334Speter if (p) 69018334Speter prefix_from_string (p, pprefix); 69118334Speter} 69218334Speter 69318334Speterstatic void 694132718Skanprefix_from_string (const char *p, struct path_prefix *pprefix) 69518334Speter{ 69690075Sobrien const char *startp, *endp; 697169689Skan char *nstore = XNEWVEC (char, strlen (p) + 3); 69818334Speter 69950397Sobrien if (debug) 70050397Sobrien fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); 701132718Skan 70218334Speter startp = endp = p; 70318334Speter while (1) 70418334Speter { 70518334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 70618334Speter { 70718334Speter strncpy (nstore, startp, endp-startp); 70818334Speter if (endp == startp) 70918334Speter { 71018334Speter strcpy (nstore, "./"); 71118334Speter } 71290075Sobrien else if (! IS_DIR_SEPARATOR (endp[-1])) 71318334Speter { 71490075Sobrien nstore[endp-startp] = DIR_SEPARATOR; 71518334Speter nstore[endp-startp+1] = 0; 71618334Speter } 71718334Speter else 71818334Speter nstore[endp-startp] = 0; 71918334Speter 72050397Sobrien if (debug) 72150397Sobrien fprintf (stderr, " - add prefix: %s\n", nstore); 722132718Skan 72318334Speter add_prefix (pprefix, nstore); 72418334Speter if (*endp == 0) 72518334Speter break; 72618334Speter endp = startp = endp + 1; 72718334Speter } 72818334Speter else 72918334Speter endp++; 73018334Speter } 73118334Speter} 73218334Speter 73350397Sobrien/* Main program. */ 73418334Speter 73518334Speterint 736132718Skanmain (int argc, char **argv) 73718334Speter{ 73890075Sobrien static const char *const ld_suffix = "ld"; 73990075Sobrien static const char *const real_ld_suffix = "real-ld"; 74090075Sobrien static const char *const collect_ld_suffix = "collect-ld"; 74190075Sobrien static const char *const nm_suffix = "nm"; 74290075Sobrien static const char *const gnm_suffix = "gnm"; 74318334Speter#ifdef LDD_SUFFIX 74490075Sobrien static const char *const ldd_suffix = LDD_SUFFIX; 74518334Speter#endif 74690075Sobrien static const char *const strip_suffix = "strip"; 74790075Sobrien static const char *const gstrip_suffix = "gstrip"; 74890075Sobrien 749259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE 75090075Sobrien /* If we look for a program in the compiler directories, we just use 75190075Sobrien the short name, since these directories are already system-specific. 75290075Sobrien But it we look for a program in the system directories, we need to 75390075Sobrien qualify the program name with the target machine. */ 75490075Sobrien 75590075Sobrien const char *const full_ld_suffix = 75690075Sobrien concat(target_machine, "-", ld_suffix, NULL); 75790075Sobrien const char *const full_nm_suffix = 75890075Sobrien concat (target_machine, "-", nm_suffix, NULL); 75990075Sobrien const char *const full_gnm_suffix = 76090075Sobrien concat (target_machine, "-", gnm_suffix, NULL); 76190075Sobrien#ifdef LDD_SUFFIX 76290075Sobrien const char *const full_ldd_suffix = 76390075Sobrien concat (target_machine, "-", ldd_suffix, NULL); 76490075Sobrien#endif 76590075Sobrien const char *const full_strip_suffix = 76690075Sobrien concat (target_machine, "-", strip_suffix, NULL); 76790075Sobrien const char *const full_gstrip_suffix = 76890075Sobrien concat (target_machine, "-", gstrip_suffix, NULL); 76990075Sobrien#else 77090075Sobrien const char *const full_ld_suffix = ld_suffix; 77190075Sobrien const char *const full_nm_suffix = nm_suffix; 77290075Sobrien const char *const full_gnm_suffix = gnm_suffix; 77390075Sobrien#ifdef LDD_SUFFIX 77490075Sobrien const char *const full_ldd_suffix = ldd_suffix; 77590075Sobrien#endif 77690075Sobrien const char *const full_strip_suffix = strip_suffix; 77790075Sobrien const char *const full_gstrip_suffix = gstrip_suffix; 778259563Spfg#endif /* CROSS_DIRECTORY_STRUCTURE */ 77990075Sobrien 78090075Sobrien const char *arg; 78150397Sobrien FILE *outf; 78250397Sobrien#ifdef COLLECT_EXPORT_LIST 78350397Sobrien FILE *exportf; 78450397Sobrien#endif 78590075Sobrien const char *ld_file_name; 78690075Sobrien const char *p; 78718334Speter char **c_argv; 78890075Sobrien const char **c_ptr; 78952284Sobrien char **ld1_argv; 79090075Sobrien const char **ld1; 79152284Sobrien char **ld2_argv; 79290075Sobrien const char **ld2; 79352284Sobrien char **object_lst; 79490075Sobrien const char **object; 79518334Speter int first_file; 79650397Sobrien int num_c_args = argc+9; 79718334Speter 79890075Sobrien no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); 79990075Sobrien 80090075Sobrien /* Suppress demangling by the real linker, which may be broken. */ 80190075Sobrien putenv (xstrdup ("COLLECT_NO_DEMANGLE=")); 80290075Sobrien 80352284Sobrien#if defined (COLLECT2_HOST_INITIALIZATION) 80490075Sobrien /* Perform system dependent initialization, if necessary. */ 80552284Sobrien COLLECT2_HOST_INITIALIZATION; 80652284Sobrien#endif 80752284Sobrien 80890075Sobrien#ifdef SIGCHLD 80990075Sobrien /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 81090075Sobrien receive the signal. A different setting is inheritable */ 81190075Sobrien signal (SIGCHLD, SIG_DFL); 81252284Sobrien#endif 81352284Sobrien 814169689Skan /* Unlock the stdio streams. */ 815169689Skan unlock_std_streams (); 816169689Skan 81790075Sobrien gcc_init_libintl (); 81890075Sobrien 81952284Sobrien /* Do not invoke xcalloc before this point, since locale needs to be 82052284Sobrien set first, in case a diagnostic is issued. */ 82152284Sobrien 822169689Skan ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+4)); 823169689Skan ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+11)); 824132718Skan object = (const char **)(object_lst = xcalloc(sizeof (char *), argc)); 82552284Sobrien 82618334Speter#ifdef DEBUG 82718334Speter debug = 1; 82818334Speter#endif 82918334Speter 83050397Sobrien /* Parse command line early for instances of -debug. This allows 83150397Sobrien the debug flag to be set before functions like find_a_file() 83250397Sobrien are called. */ 83350397Sobrien { 83450397Sobrien int i; 835132718Skan 83650397Sobrien for (i = 1; argv[i] != NULL; i ++) 837132718Skan { 838132718Skan if (! strcmp (argv[i], "-debug")) 839132718Skan debug = 1; 840132718Skan } 84150397Sobrien vflag = debug; 84250397Sobrien } 84350397Sobrien 84450397Sobrien#ifndef DEFAULT_A_OUT_NAME 84518334Speter output_file = "a.out"; 84650397Sobrien#else 84750397Sobrien output_file = DEFAULT_A_OUT_NAME; 84850397Sobrien#endif 84918334Speter 85018334Speter obstack_begin (&temporary_obstack, 0); 851132718Skan temporary_firstobj = obstack_alloc (&temporary_obstack, 0); 85250397Sobrien 853169689Skan#ifndef HAVE_LD_DEMANGLE 85490075Sobrien current_demangling_style = auto_demangling; 855169689Skan#endif 85650397Sobrien p = getenv ("COLLECT_GCC_OPTIONS"); 85750397Sobrien while (p && *p) 85850397Sobrien { 85990075Sobrien const char *q = extract_string (&p); 86050397Sobrien if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) 86150397Sobrien num_c_args++; 86250397Sobrien } 86350397Sobrien obstack_free (&temporary_obstack, temporary_firstobj); 86418334Speter 865132718Skan /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities 866132718Skan -fno-exceptions -w */ 867132718Skan num_c_args += 5; 86818334Speter 869132718Skan c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args)); 87090075Sobrien 87118334Speter if (argc < 2) 87218334Speter fatal ("no arguments"); 87318334Speter 87418334Speter#ifdef SIGQUIT 87518334Speter if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) 87618334Speter signal (SIGQUIT, handler); 87718334Speter#endif 87818334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 87918334Speter signal (SIGINT, handler); 88018334Speter#ifdef SIGALRM 88118334Speter if (signal (SIGALRM, SIG_IGN) != SIG_IGN) 88218334Speter signal (SIGALRM, handler); 88318334Speter#endif 88418334Speter#ifdef SIGHUP 88518334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 88618334Speter signal (SIGHUP, handler); 88718334Speter#endif 88818334Speter if (signal (SIGSEGV, SIG_IGN) != SIG_IGN) 88918334Speter signal (SIGSEGV, handler); 89018334Speter#ifdef SIGBUS 89118334Speter if (signal (SIGBUS, SIG_IGN) != SIG_IGN) 89218334Speter signal (SIGBUS, handler); 89318334Speter#endif 89418334Speter 89518334Speter /* Extract COMPILER_PATH and PATH into our prefix list. */ 89618334Speter prefix_from_env ("COMPILER_PATH", &cpath); 89718334Speter prefix_from_env ("PATH", &path); 89818334Speter 89918334Speter /* Try to discover a valid linker/nm/strip to use. */ 90018334Speter 90118334Speter /* Maybe we know the right file to use (if not cross). */ 90252284Sobrien ld_file_name = 0; 90352284Sobrien#ifdef DEFAULT_LINKER 90452284Sobrien if (access (DEFAULT_LINKER, X_OK) == 0) 90552284Sobrien ld_file_name = DEFAULT_LINKER; 90652284Sobrien if (ld_file_name == 0) 90752284Sobrien#endif 90818334Speter#ifdef REAL_LD_FILE_NAME 90918334Speter ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME); 91018334Speter if (ld_file_name == 0) 91118334Speter#endif 91218334Speter /* Search the (target-specific) compiler dirs for ld'. */ 91318334Speter ld_file_name = find_a_file (&cpath, real_ld_suffix); 91418334Speter /* Likewise for `collect-ld'. */ 91518334Speter if (ld_file_name == 0) 91618334Speter ld_file_name = find_a_file (&cpath, collect_ld_suffix); 91718334Speter /* Search the compiler directories for `ld'. We have protection against 91818334Speter recursive calls in find_a_file. */ 91918334Speter if (ld_file_name == 0) 92018334Speter ld_file_name = find_a_file (&cpath, ld_suffix); 92118334Speter /* Search the ordinary system bin directories 92218334Speter for `ld' (if native linking) or `TARGET-ld' (if cross). */ 92318334Speter if (ld_file_name == 0) 92418334Speter ld_file_name = find_a_file (&path, full_ld_suffix); 92518334Speter 92618334Speter#ifdef REAL_NM_FILE_NAME 92718334Speter nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); 92818334Speter if (nm_file_name == 0) 92918334Speter#endif 93018334Speter nm_file_name = find_a_file (&cpath, gnm_suffix); 93118334Speter if (nm_file_name == 0) 93218334Speter nm_file_name = find_a_file (&path, full_gnm_suffix); 93318334Speter if (nm_file_name == 0) 93418334Speter nm_file_name = find_a_file (&cpath, nm_suffix); 93518334Speter if (nm_file_name == 0) 93618334Speter nm_file_name = find_a_file (&path, full_nm_suffix); 93718334Speter 93818334Speter#ifdef LDD_SUFFIX 93918334Speter ldd_file_name = find_a_file (&cpath, ldd_suffix); 94018334Speter if (ldd_file_name == 0) 94118334Speter ldd_file_name = find_a_file (&path, full_ldd_suffix); 94218334Speter#endif 94318334Speter 94418334Speter#ifdef REAL_STRIP_FILE_NAME 94518334Speter strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME); 94618334Speter if (strip_file_name == 0) 94718334Speter#endif 94818334Speter strip_file_name = find_a_file (&cpath, gstrip_suffix); 94918334Speter if (strip_file_name == 0) 95018334Speter strip_file_name = find_a_file (&path, full_gstrip_suffix); 95118334Speter if (strip_file_name == 0) 95218334Speter strip_file_name = find_a_file (&cpath, strip_suffix); 95318334Speter if (strip_file_name == 0) 95418334Speter strip_file_name = find_a_file (&path, full_strip_suffix); 95518334Speter 95618334Speter /* Determine the full path name of the C compiler to use. */ 95718334Speter c_file_name = getenv ("COLLECT_GCC"); 95818334Speter if (c_file_name == 0) 95918334Speter { 960259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE 96190075Sobrien c_file_name = concat (target_machine, "-gcc", NULL); 96218334Speter#else 96318334Speter c_file_name = "gcc"; 96418334Speter#endif 96518334Speter } 96618334Speter 96718334Speter p = find_a_file (&cpath, c_file_name); 96818334Speter 96918334Speter /* Here it should be safe to use the system search path since we should have 97018334Speter already qualified the name of the compiler when it is needed. */ 97118334Speter if (p == 0) 97218334Speter p = find_a_file (&path, c_file_name); 97318334Speter 97418334Speter if (p) 97518334Speter c_file_name = p; 97618334Speter 97718334Speter *ld1++ = *ld2++ = ld_file_name; 97818334Speter 97950397Sobrien /* Make temp file names. */ 98050397Sobrien c_file = make_temp_file (".c"); 98150397Sobrien o_file = make_temp_file (".o"); 98250397Sobrien#ifdef COLLECT_EXPORT_LIST 98350397Sobrien export_file = make_temp_file (".x"); 98450397Sobrien#endif 98550397Sobrien ldout = make_temp_file (".ld"); 986169689Skan lderrout = make_temp_file (".le"); 98718334Speter *c_ptr++ = c_file_name; 98850397Sobrien *c_ptr++ = "-x"; 98950397Sobrien *c_ptr++ = "c"; 99018334Speter *c_ptr++ = "-c"; 99118334Speter *c_ptr++ = "-o"; 99218334Speter *c_ptr++ = o_file; 99318334Speter 99450397Sobrien#ifdef COLLECT_EXPORT_LIST 99550397Sobrien /* Generate a list of directories from LIBPATH. */ 99650397Sobrien prefix_from_env ("LIBPATH", &libpath_lib_dirs); 99750397Sobrien /* Add to this list also two standard directories where 99850397Sobrien AIX loader always searches for libraries. */ 99950397Sobrien add_prefix (&libpath_lib_dirs, "/lib"); 100050397Sobrien add_prefix (&libpath_lib_dirs, "/usr/lib"); 100150397Sobrien#endif 100250397Sobrien 1003132718Skan /* Get any options that the upper GCC wants to pass to the sub-GCC. 100450397Sobrien 100550397Sobrien AIX support needs to know if -shared has been specified before 100650397Sobrien parsing commandline arguments. */ 100750397Sobrien 100850397Sobrien p = getenv ("COLLECT_GCC_OPTIONS"); 100950397Sobrien while (p && *p) 101050397Sobrien { 101190075Sobrien const char *q = extract_string (&p); 101250397Sobrien if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) 1013117395Skan *c_ptr++ = xstrdup (q); 101452284Sobrien if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0) 1015117395Skan *c_ptr++ = xstrdup (q); 101690075Sobrien if (strcmp (q, "-shared") == 0) 101750397Sobrien shared_obj = 1; 101890075Sobrien if (*q == '-' && q[1] == 'B') 101990075Sobrien { 1020117395Skan *c_ptr++ = xstrdup (q); 102190075Sobrien if (q[2] == 0) 102290075Sobrien { 102390075Sobrien q = extract_string (&p); 1024117395Skan *c_ptr++ = xstrdup (q); 102590075Sobrien } 102690075Sobrien } 102750397Sobrien } 102850397Sobrien obstack_free (&temporary_obstack, temporary_firstobj); 1029132718Skan *c_ptr++ = "-fno-profile-arcs"; 1030132718Skan *c_ptr++ = "-fno-test-coverage"; 1031132718Skan *c_ptr++ = "-fno-branch-probabilities"; 103250397Sobrien *c_ptr++ = "-fno-exceptions"; 103390075Sobrien *c_ptr++ = "-w"; 103450397Sobrien 103518334Speter /* !!! When GCC calls collect2, 103618334Speter it does not know whether it is calling collect2 or ld. 103718334Speter So collect2 cannot meaningfully understand any options 103818334Speter except those ld understands. 103918334Speter If you propose to make GCC pass some other option, 104018334Speter just imagine what will happen if ld is really ld!!! */ 104118334Speter 104250397Sobrien /* Parse arguments. Remember output file spec, pass the rest to ld. */ 104318334Speter /* After the first file, put in the c++ rt0. */ 104418334Speter 104518334Speter first_file = 1; 1046169689Skan#ifdef HAVE_LD_DEMANGLE 1047169689Skan if (!demangle_flag && !no_demangle) 1048169689Skan demangle_flag = "--demangle"; 1049169689Skan if (demangle_flag) 1050169689Skan *ld1++ = *ld2++ = demangle_flag; 1051169689Skan#endif 105250397Sobrien while ((arg = *++argv) != (char *) 0) 105318334Speter { 105418334Speter *ld1++ = *ld2++ = arg; 105518334Speter 105618334Speter if (arg[0] == '-') 105718334Speter { 105818334Speter switch (arg[1]) 105918334Speter { 106050397Sobrien#ifdef COLLECT_EXPORT_LIST 106150397Sobrien /* We want to disable automatic exports on AIX when user 106250397Sobrien explicitly puts an export list in command line */ 106350397Sobrien case 'b': 106450397Sobrien if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) 1065169689Skan export_flag = 1; 106652284Sobrien else if (arg[2] == '6' && arg[3] == '4') 106750397Sobrien aix64_flag = 1; 1068146895Skan else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l') 1069146895Skan aixrtl_flag = 1; 107050397Sobrien break; 107150397Sobrien#endif 107250397Sobrien 107318334Speter case 'd': 107418334Speter if (!strcmp (arg, "-debug")) 107518334Speter { 107650397Sobrien /* Already parsed. */ 107718334Speter ld1--; 107818334Speter ld2--; 107918334Speter } 1080169689Skan if (!strcmp (arg, "-dynamic-linker") && argv[1]) 1081169689Skan { 1082169689Skan ++argv; 1083169689Skan *ld1++ = *ld2++ = *argv; 1084169689Skan } 108518334Speter break; 108618334Speter 108718334Speter case 'l': 108818334Speter if (first_file) 108918334Speter { 109018334Speter /* place o_file BEFORE this argument! */ 109118334Speter first_file = 0; 109218334Speter ld2--; 109318334Speter *ld2++ = o_file; 109418334Speter *ld2++ = arg; 109518334Speter } 109650397Sobrien#ifdef COLLECT_EXPORT_LIST 109750397Sobrien { 1098169689Skan /* Resolving full library name. */ 109990075Sobrien const char *s = resolve_lib_name (arg+2); 110050397Sobrien 110150397Sobrien /* Saving a full library name. */ 110250397Sobrien add_to_list (&libs, s); 110350397Sobrien } 110450397Sobrien#endif 110518334Speter break; 110618334Speter 110750397Sobrien#ifdef COLLECT_EXPORT_LIST 110850397Sobrien /* Saving directories where to search for libraries. */ 1109132718Skan case 'L': 111050397Sobrien add_prefix (&cmdline_lib_dirs, arg+2); 111150397Sobrien break; 1112132718Skan#else 111390075Sobrien#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES 111490075Sobrien case 'L': 111590075Sobrien if (is_in_args (arg, (const char **) ld1_argv, ld1-1)) 111690075Sobrien --ld1; 111790075Sobrien break; 111890075Sobrien#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ 111950397Sobrien#endif 112050397Sobrien 112118334Speter case 'o': 112218334Speter if (arg[2] == '\0') 112318334Speter output_file = *ld1++ = *ld2++ = *++argv; 112490075Sobrien else if (1 112590075Sobrien#ifdef SWITCHES_NEED_SPACES 112690075Sobrien && ! strchr (SWITCHES_NEED_SPACES, arg[1]) 112790075Sobrien#endif 112890075Sobrien ) 112990075Sobrien 113018334Speter output_file = &arg[2]; 113118334Speter break; 113218334Speter 113318334Speter case 'r': 113418334Speter if (arg[2] == '\0') 113518334Speter rflag = 1; 113618334Speter break; 113718334Speter 113818334Speter case 's': 113918334Speter if (arg[2] == '\0' && do_collecting) 114018334Speter { 114118334Speter /* We must strip after the nm run, otherwise C++ linking 114250397Sobrien will not work. Thus we strip in the second ld run, or 114318334Speter else with strip if there is no second ld run. */ 114418334Speter strip_flag = 1; 114518334Speter ld1--; 114618334Speter } 114718334Speter break; 114818334Speter 114918334Speter case 'v': 115018334Speter if (arg[2] == '\0') 115118334Speter vflag = 1; 115218334Speter break; 1153169689Skan 1154169689Skan case '-': 1155169689Skan if (strcmp (arg, "--no-demangle") == 0) 1156169689Skan { 1157169689Skan demangle_flag = arg; 1158169689Skan no_demangle = 1; 1159169689Skan ld1--; 1160169689Skan ld2--; 1161169689Skan } 1162169689Skan else if (strncmp (arg, "--demangle", 10) == 0) 1163169689Skan { 1164169689Skan demangle_flag = arg; 1165169689Skan no_demangle = 0; 1166169689Skan#ifndef HAVE_LD_DEMANGLE 1167169689Skan if (arg[10] == '=') 1168169689Skan { 1169169689Skan enum demangling_styles style 1170169689Skan = cplus_demangle_name_to_style (arg+11); 1171169689Skan if (style == unknown_demangling) 1172169689Skan error ("unknown demangling style '%s'", arg+11); 1173169689Skan else 1174169689Skan current_demangling_style = style; 1175169689Skan } 1176169689Skan#endif 1177169689Skan ld1--; 1178169689Skan ld2--; 1179169689Skan } 1180169689Skan break; 118118334Speter } 118218334Speter } 118390075Sobrien else if ((p = strrchr (arg, '.')) != (char *) 0 118450397Sobrien && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0 118590075Sobrien || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0 118690075Sobrien || strcmp (p, ".obj") == 0)) 118718334Speter { 118818334Speter if (first_file) 118918334Speter { 119018334Speter first_file = 0; 119118334Speter if (p[1] == 'o') 119218334Speter *ld2++ = o_file; 119318334Speter else 119418334Speter { 119518334Speter /* place o_file BEFORE this argument! */ 119618334Speter ld2--; 119718334Speter *ld2++ = o_file; 119818334Speter *ld2++ = arg; 119918334Speter } 120018334Speter } 120190075Sobrien if (p[1] == 'o' || p[1] == 'l') 120218334Speter *object++ = arg; 120350397Sobrien#ifdef COLLECT_EXPORT_LIST 120450397Sobrien /* libraries can be specified directly, i.e. without -l flag. */ 1205132718Skan else 1206132718Skan { 120750397Sobrien /* Saving a full library name. */ 1208169689Skan add_to_list (&libs, arg); 1209169689Skan } 121050397Sobrien#endif 121118334Speter } 121218334Speter } 121318334Speter 121450397Sobrien#ifdef COLLECT_EXPORT_LIST 121550397Sobrien /* This is added only for debugging purposes. */ 121650397Sobrien if (debug) 121750397Sobrien { 121850397Sobrien fprintf (stderr, "List of libraries:\n"); 121950397Sobrien dump_list (stderr, "\t", libs.first); 122050397Sobrien } 122118334Speter 122218334Speter /* The AIX linker will discard static constructors in object files if 122318334Speter nothing else in the file is referenced, so look at them first. */ 122418334Speter { 122590075Sobrien const char **export_object_lst = (const char **)object_lst; 122690075Sobrien 122750397Sobrien while (export_object_lst < object) 122850397Sobrien scan_prog_file (*export_object_lst++, PASS_OBJ); 122950397Sobrien } 123050397Sobrien { 123150397Sobrien struct id *list = libs.first; 123290075Sobrien 123350397Sobrien for (; list; list = list->next) 123450397Sobrien scan_prog_file (list->name, PASS_FIRST); 123550397Sobrien } 123690075Sobrien 123790075Sobrien if (exports.first) 123890075Sobrien { 123990075Sobrien char *buf = concat ("-bE:", export_file, NULL); 1240132718Skan 124190075Sobrien *ld1++ = buf; 124290075Sobrien *ld2++ = buf; 124390075Sobrien 124490075Sobrien exportf = fopen (export_file, "w"); 124590075Sobrien if (exportf == (FILE *) 0) 124690075Sobrien fatal_perror ("fopen %s", export_file); 124790075Sobrien write_aix_file (exportf, exports.first); 124890075Sobrien if (fclose (exportf)) 124990075Sobrien fatal_perror ("fclose %s", export_file); 125090075Sobrien } 125118334Speter#endif 125218334Speter 125318334Speter *c_ptr++ = c_file; 125490075Sobrien *c_ptr = *ld1 = *object = (char *) 0; 125518334Speter 125618334Speter if (vflag) 125718334Speter { 125852284Sobrien notice ("collect2 version %s", version_string); 125918334Speter#ifdef TARGET_VERSION 126018334Speter TARGET_VERSION; 126118334Speter#endif 126218334Speter fprintf (stderr, "\n"); 126318334Speter } 126418334Speter 126518334Speter if (debug) 126618334Speter { 126790075Sobrien const char *ptr; 126818334Speter fprintf (stderr, "ld_file_name = %s\n", 126918334Speter (ld_file_name ? ld_file_name : "not found")); 127018334Speter fprintf (stderr, "c_file_name = %s\n", 127118334Speter (c_file_name ? c_file_name : "not found")); 127218334Speter fprintf (stderr, "nm_file_name = %s\n", 127318334Speter (nm_file_name ? nm_file_name : "not found")); 127418334Speter#ifdef LDD_SUFFIX 127518334Speter fprintf (stderr, "ldd_file_name = %s\n", 127618334Speter (ldd_file_name ? ldd_file_name : "not found")); 127718334Speter#endif 127818334Speter fprintf (stderr, "strip_file_name = %s\n", 127918334Speter (strip_file_name ? strip_file_name : "not found")); 128018334Speter fprintf (stderr, "c_file = %s\n", 128118334Speter (c_file ? c_file : "not found")); 128218334Speter fprintf (stderr, "o_file = %s\n", 128318334Speter (o_file ? o_file : "not found")); 128418334Speter 128518334Speter ptr = getenv ("COLLECT_GCC_OPTIONS"); 128618334Speter if (ptr) 128718334Speter fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr); 128818334Speter 128918334Speter ptr = getenv ("COLLECT_GCC"); 129018334Speter if (ptr) 129118334Speter fprintf (stderr, "COLLECT_GCC = %s\n", ptr); 129218334Speter 129318334Speter ptr = getenv ("COMPILER_PATH"); 129418334Speter if (ptr) 129518334Speter fprintf (stderr, "COMPILER_PATH = %s\n", ptr); 129618334Speter 129790075Sobrien ptr = getenv (LIBRARY_PATH_ENV); 129818334Speter if (ptr) 129990075Sobrien fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr); 130018334Speter 130118334Speter fprintf (stderr, "\n"); 130218334Speter } 130318334Speter 130450397Sobrien /* Load the program, searching all libraries and attempting to provide 130550397Sobrien undefined symbols from repository information. */ 130618334Speter 130750397Sobrien /* On AIX we do this later. */ 130850397Sobrien#ifndef COLLECT_EXPORT_LIST 130952750Sobrien do_tlink (ld1_argv, object_lst); 131050397Sobrien#endif 131118334Speter 131250397Sobrien /* If -r or they will be run via some other method, do not build the 131350397Sobrien constructor or destructor list, just return now. */ 131450397Sobrien if (rflag 131550397Sobrien#ifndef COLLECT_EXPORT_LIST 131650397Sobrien || ! do_collecting 131750397Sobrien#endif 131850397Sobrien ) 131950397Sobrien { 132050397Sobrien#ifdef COLLECT_EXPORT_LIST 132152750Sobrien /* Do the link we avoided above if we are exiting. */ 132252750Sobrien do_tlink (ld1_argv, object_lst); 132352750Sobrien 132450397Sobrien /* But make sure we delete the export file we may have created. */ 132550397Sobrien if (export_file != 0 && export_file[0]) 132650397Sobrien maybe_unlink (export_file); 132750397Sobrien#endif 132850397Sobrien maybe_unlink (c_file); 132950397Sobrien maybe_unlink (o_file); 133050397Sobrien return 0; 133150397Sobrien } 133218334Speter 133318334Speter /* Examine the namelist with nm and search it for static constructors 133418334Speter and destructors to call. 133550397Sobrien Write the constructor and destructor tables to a .s file and reload. */ 133618334Speter 133790075Sobrien /* On AIX we already scanned for global constructors/destructors. */ 133850397Sobrien#ifndef COLLECT_EXPORT_LIST 133918334Speter scan_prog_file (output_file, PASS_FIRST); 134050397Sobrien#endif 134118334Speter 134218334Speter#ifdef SCAN_LIBRARIES 134318334Speter scan_libraries (output_file); 134418334Speter#endif 134518334Speter 134618334Speter if (debug) 134718334Speter { 134852284Sobrien notice ("%d constructor(s) found\n", constructors.number); 134952284Sobrien notice ("%d destructor(s) found\n", destructors.number); 135052284Sobrien notice ("%d frame table(s) found\n", frame_tables.number); 135118334Speter } 135218334Speter 135318334Speter if (constructors.number == 0 && destructors.number == 0 135450397Sobrien && frame_tables.number == 0 135550397Sobrien#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST) 135618334Speter /* If we will be running these functions ourselves, we want to emit 135750397Sobrien stubs into the shared library so that we do not have to relink 135818334Speter dependent programs when we add static objects. */ 135918334Speter && ! shared_obj 136018334Speter#endif 136118334Speter ) 136218334Speter { 136350397Sobrien#ifdef COLLECT_EXPORT_LIST 1364132718Skan /* Do tlink without additional code generation. */ 136550397Sobrien do_tlink (ld1_argv, object_lst); 136650397Sobrien#endif 136718334Speter /* Strip now if it was requested on the command line. */ 136818334Speter if (strip_flag) 136918334Speter { 1370169689Skan char **real_strip_argv = XCNEWVEC (char *, 3); 137190075Sobrien const char ** strip_argv = (const char **) real_strip_argv; 1372132718Skan 137318334Speter strip_argv[0] = strip_file_name; 137418334Speter strip_argv[1] = output_file; 137518334Speter strip_argv[2] = (char *) 0; 137690075Sobrien fork_execute ("strip", real_strip_argv); 137718334Speter } 137818334Speter 137918334Speter#ifdef COLLECT_EXPORT_LIST 138018334Speter maybe_unlink (export_file); 138118334Speter#endif 138250397Sobrien maybe_unlink (c_file); 138350397Sobrien maybe_unlink (o_file); 138418334Speter return 0; 138518334Speter } 138618334Speter 138790075Sobrien /* Sort ctor and dtor lists by priority. */ 138852284Sobrien sort_ids (&constructors); 138952284Sobrien sort_ids (&destructors); 139052284Sobrien 139118334Speter maybe_unlink(output_file); 139218334Speter outf = fopen (c_file, "w"); 139350397Sobrien if (outf == (FILE *) 0) 139452284Sobrien fatal_perror ("fopen %s", c_file); 139518334Speter 139618334Speter write_c_file (outf, c_file); 139718334Speter 139818334Speter if (fclose (outf)) 139952284Sobrien fatal_perror ("fclose %s", c_file); 140018334Speter 140118334Speter /* Tell the linker that we have initializer and finalizer functions. */ 140218334Speter#ifdef LD_INIT_SWITCH 140390075Sobrien#ifdef COLLECT_EXPORT_LIST 140490075Sobrien *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL); 140590075Sobrien#else 140618334Speter *ld2++ = LD_INIT_SWITCH; 140718334Speter *ld2++ = initname; 140818334Speter *ld2++ = LD_FINI_SWITCH; 140918334Speter *ld2++ = fininame; 141018334Speter#endif 141190075Sobrien#endif 141218334Speter 141318334Speter#ifdef COLLECT_EXPORT_LIST 141418334Speter if (shared_obj) 141518334Speter { 141690075Sobrien /* If we did not add export flag to link arguments before, add it to 141790075Sobrien second link phase now. No new exports should have been added. */ 141890075Sobrien if (! exports.first) 141990075Sobrien *ld2++ = concat ("-bE:", export_file, NULL); 142090075Sobrien 1421132718Skan#ifndef LD_INIT_SWITCH 142218334Speter add_to_list (&exports, initname); 142318334Speter add_to_list (&exports, fininame); 142418334Speter add_to_list (&exports, "_GLOBAL__DI"); 142518334Speter add_to_list (&exports, "_GLOBAL__DD"); 1426132718Skan#endif 142718334Speter exportf = fopen (export_file, "w"); 142850397Sobrien if (exportf == (FILE *) 0) 142952284Sobrien fatal_perror ("fopen %s", export_file); 143090075Sobrien write_aix_file (exportf, exports.first); 143118334Speter if (fclose (exportf)) 143252284Sobrien fatal_perror ("fclose %s", export_file); 143318334Speter } 143418334Speter#endif 143518334Speter 143690075Sobrien /* End of arguments to second link phase. */ 143790075Sobrien *ld2 = (char*) 0; 143890075Sobrien 143918334Speter if (debug) 144018334Speter { 144118334Speter fprintf (stderr, "\n========== output_file = %s, c_file = %s\n", 144218334Speter output_file, c_file); 144318334Speter write_c_file (stderr, "stderr"); 144418334Speter fprintf (stderr, "========== end of c_file\n\n"); 144518334Speter#ifdef COLLECT_EXPORT_LIST 144618334Speter fprintf (stderr, "\n========== export_file = %s\n", export_file); 144790075Sobrien write_aix_file (stderr, exports.first); 144818334Speter fprintf (stderr, "========== end of export_file\n\n"); 144918334Speter#endif 145018334Speter } 145118334Speter 145218334Speter /* Assemble the constructor and destructor tables. 145350397Sobrien Link the tables in with the rest of the program. */ 145418334Speter 145518334Speter fork_execute ("gcc", c_argv); 145650397Sobrien#ifdef COLLECT_EXPORT_LIST 1457132718Skan /* On AIX we must call tlink because of possible templates resolution. */ 145850397Sobrien do_tlink (ld2_argv, object_lst); 145950397Sobrien#else 1460132718Skan /* Otherwise, simply call ld because tlink is already done. */ 146118334Speter fork_execute ("ld", ld2_argv); 146218334Speter 146318334Speter /* Let scan_prog_file do any final mods (OSF/rose needs this for 146418334Speter constructors/destructors in shared libraries. */ 146518334Speter scan_prog_file (output_file, PASS_SECOND); 1466132718Skan#endif 146718334Speter 146818334Speter maybe_unlink (c_file); 146918334Speter maybe_unlink (o_file); 147050397Sobrien 147150397Sobrien#ifdef COLLECT_EXPORT_LIST 147218334Speter maybe_unlink (export_file); 147350397Sobrien#endif 147450397Sobrien 147518334Speter return 0; 147618334Speter} 147718334Speter 147818334Speter 1479117395Skan/* Wait for a process to finish, and exit if a nonzero status is found. */ 148018334Speter 148118334Speterint 1482169689Skancollect_wait (const char *prog, struct pex_obj *pex) 148318334Speter{ 148418334Speter int status; 148518334Speter 1486169689Skan if (!pex_get_status (pex, 1, &status)) 1487169689Skan fatal_perror ("can't get program status"); 1488169689Skan pex_free (pex); 1489169689Skan 149018334Speter if (status) 149118334Speter { 149218334Speter if (WIFSIGNALED (status)) 149318334Speter { 149418334Speter int sig = WTERMSIG (status); 149590075Sobrien error ("%s terminated with signal %d [%s]%s", 149690075Sobrien prog, sig, strsignal(sig), 1497117395Skan WCOREDUMP(status) ? ", core dumped" : ""); 149850397Sobrien collect_exit (FATAL_EXIT_CODE); 149918334Speter } 150018334Speter 150118334Speter if (WIFEXITED (status)) 150218334Speter return WEXITSTATUS (status); 150318334Speter } 150418334Speter return 0; 150518334Speter} 150618334Speter 150718334Speterstatic void 1508169689Skando_wait (const char *prog, struct pex_obj *pex) 150918334Speter{ 1510169689Skan int ret = collect_wait (prog, pex); 151118334Speter if (ret != 0) 151218334Speter { 151318334Speter error ("%s returned %d exit status", prog, ret); 151418334Speter collect_exit (ret); 151518334Speter } 151618334Speter} 151718334Speter 151818334Speter 151952284Sobrien/* Execute a program, and wait for the reply. */ 152018334Speter 1521169689Skanstruct pex_obj * 1522169689Skancollect_execute (const char *prog, char **argv, const char *outname, 1523169689Skan const char *errname) 152418334Speter{ 1525169689Skan struct pex_obj *pex; 1526169689Skan const char *errmsg; 1527169689Skan int err; 152818334Speter 152918334Speter if (vflag || debug) 153018334Speter { 153118334Speter char **p_argv; 153290075Sobrien const char *str; 153318334Speter 153418334Speter if (argv[0]) 153518334Speter fprintf (stderr, "%s", argv[0]); 153618334Speter else 153752284Sobrien notice ("[cannot find %s]", prog); 153818334Speter 153950397Sobrien for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) 154018334Speter fprintf (stderr, " %s", str); 154118334Speter 154218334Speter fprintf (stderr, "\n"); 154318334Speter } 154418334Speter 154518334Speter fflush (stdout); 154618334Speter fflush (stderr); 154718334Speter 154850397Sobrien /* If we cannot find a program we need, complain error. Do this here 154950397Sobrien since we might not end up needing something that we could not find. */ 155018334Speter 155118334Speter if (argv[0] == 0) 1552169689Skan fatal ("cannot find '%s'", prog); 155318334Speter 1554169689Skan pex = pex_init (0, "collect2", NULL); 1555169689Skan if (pex == NULL) 1556169689Skan fatal_perror ("pex_init failed"); 155752284Sobrien 1558169689Skan errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, outname, 1559169689Skan errname, &err); 1560169689Skan if (errmsg != NULL) 156118334Speter { 1562169689Skan if (err != 0) 1563169689Skan { 1564169689Skan errno = err; 1565260011Spfg fatal_perror ("%s", errmsg); 1566169689Skan } 1567169689Skan else 1568260011Spfg fatal ("%s", errmsg); 156918334Speter } 157052284Sobrien 1571169689Skan return pex; 157218334Speter} 157318334Speter 157418334Speterstatic void 1575132718Skanfork_execute (const char *prog, char **argv) 157618334Speter{ 1577169689Skan struct pex_obj *pex; 1578169689Skan 1579169689Skan pex = collect_execute (prog, argv, NULL, NULL); 1580169689Skan do_wait (prog, pex); 158118334Speter} 158218334Speter 158318334Speter/* Unlink a file unless we are debugging. */ 158418334Speter 158518334Speterstatic void 1586132718Skanmaybe_unlink (const char *file) 158718334Speter{ 158818334Speter if (!debug) 1589169689Skan unlink_if_ordinary (file); 159018334Speter else 159152284Sobrien notice ("[Leaving %s]\n", file); 159218334Speter} 159318334Speter 159418334Speter 159552284Sobrienstatic long sequence_number = 0; 159652284Sobrien 159718334Speter/* Add a name to a linked list. */ 159818334Speter 159918334Speterstatic void 1600132718Skanadd_to_list (struct head *head_ptr, const char *name) 160118334Speter{ 1602132718Skan struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1); 160318334Speter struct id *p; 160418334Speter strcpy (newid->name, name); 160518334Speter 160618334Speter if (head_ptr->first) 160718334Speter head_ptr->last->next = newid; 160818334Speter else 160918334Speter head_ptr->first = newid; 161018334Speter 161118334Speter /* Check for duplicate symbols. */ 161218334Speter for (p = head_ptr->first; 161318334Speter strcmp (name, p->name) != 0; 161418334Speter p = p->next) 161518334Speter ; 161618334Speter if (p != newid) 161718334Speter { 161818334Speter head_ptr->last->next = 0; 161918334Speter free (newid); 162018334Speter return; 162118334Speter } 162218334Speter 162318334Speter newid->sequence = ++sequence_number; 162418334Speter head_ptr->last = newid; 162518334Speter head_ptr->number++; 162618334Speter} 162718334Speter 162852284Sobrien/* Grab the init priority number from an init function name that 162952284Sobrien looks like "_GLOBAL_.I.12345.foo". */ 163052284Sobrien 163152284Sobrienstatic int 1632132718Skanextract_init_priority (const char *name) 163352284Sobrien{ 163452284Sobrien int pos = 0, pri; 163552284Sobrien 163652284Sobrien while (name[pos] == '_') 163752284Sobrien ++pos; 163852284Sobrien pos += 10; /* strlen ("GLOBAL__X_") */ 163952284Sobrien 164090075Sobrien /* Extract init_p number from ctor/dtor name. */ 164152284Sobrien pri = atoi (name + pos); 164252284Sobrien return pri ? pri : DEFAULT_INIT_PRIORITY; 164352284Sobrien} 164452284Sobrien 164552284Sobrien/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order. 164652284Sobrien ctors will be run from right to left, dtors from left to right. */ 164752284Sobrien 164852284Sobrienstatic void 1649132718Skansort_ids (struct head *head_ptr) 165052284Sobrien{ 165152284Sobrien /* id holds the current element to insert. id_next holds the next 165252284Sobrien element to insert. id_ptr iterates through the already sorted elements 165352284Sobrien looking for the place to insert id. */ 165452284Sobrien struct id *id, *id_next, **id_ptr; 165552284Sobrien 165652284Sobrien id = head_ptr->first; 165752284Sobrien 165852284Sobrien /* We don't have any sorted elements yet. */ 165952284Sobrien head_ptr->first = NULL; 166052284Sobrien 166152284Sobrien for (; id; id = id_next) 166252284Sobrien { 166352284Sobrien id_next = id->next; 166452284Sobrien id->sequence = extract_init_priority (id->name); 166552284Sobrien 166652284Sobrien for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next)) 166752284Sobrien if (*id_ptr == NULL 166852284Sobrien /* If the sequence numbers are the same, we put the id from the 166952284Sobrien file later on the command line later in the list. */ 167052284Sobrien || id->sequence > (*id_ptr)->sequence 167152284Sobrien /* Hack: do lexical compare, too. 167252284Sobrien || (id->sequence == (*id_ptr)->sequence 1673169689Skan && strcmp (id->name, (*id_ptr)->name) > 0) */ 167452284Sobrien ) 167552284Sobrien { 167652284Sobrien id->next = *id_ptr; 167752284Sobrien *id_ptr = id; 167852284Sobrien break; 167952284Sobrien } 168052284Sobrien } 168152284Sobrien 168252284Sobrien /* Now set the sequence numbers properly so write_c_file works. */ 168352284Sobrien for (id = head_ptr->first; id; id = id->next) 168452284Sobrien id->sequence = ++sequence_number; 168552284Sobrien} 168652284Sobrien 168718334Speter/* Write: `prefix', the names on list LIST, `suffix'. */ 168818334Speter 168918334Speterstatic void 1690132718Skanwrite_list (FILE *stream, const char *prefix, struct id *list) 169118334Speter{ 169218334Speter while (list) 169318334Speter { 169418334Speter fprintf (stream, "%sx%d,\n", prefix, list->sequence); 169518334Speter list = list->next; 169618334Speter } 169718334Speter} 169818334Speter 169990075Sobrien#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES 170090075Sobrien/* Given a STRING, return nonzero if it occurs in the list in range 170190075Sobrien [ARGS_BEGIN,ARGS_END). */ 170290075Sobrien 170390075Sobrienstatic int 1704132718Skanis_in_args (const char *string, const char **args_begin, 1705132718Skan const char **args_end) 170690075Sobrien{ 170790075Sobrien const char **args_pointer; 170890075Sobrien for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer) 170990075Sobrien if (strcmp (string, *args_pointer) == 0) 171090075Sobrien return 1; 171190075Sobrien return 0; 171290075Sobrien} 171390075Sobrien#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ 171490075Sobrien 171550397Sobrien#ifdef COLLECT_EXPORT_LIST 171650397Sobrien/* This function is really used only on AIX, but may be useful. */ 171790075Sobrien#if 0 171850397Sobrienstatic int 1719132718Skanis_in_list (const char *prefix, struct id *list) 172050397Sobrien{ 172150397Sobrien while (list) 172250397Sobrien { 172350397Sobrien if (!strcmp (prefix, list->name)) return 1; 172450397Sobrien list = list->next; 172550397Sobrien } 172650397Sobrien return 0; 172750397Sobrien} 172850397Sobrien#endif 172990075Sobrien#endif /* COLLECT_EXPORT_LIST */ 173050397Sobrien 173150397Sobrien/* Added for debugging purpose. */ 173250397Sobrien#ifdef COLLECT_EXPORT_LIST 173318334Speterstatic void 1734132718Skandump_list (FILE *stream, const char *prefix, struct id *list) 173550397Sobrien{ 173650397Sobrien while (list) 173750397Sobrien { 173850397Sobrien fprintf (stream, "%s%s,\n", prefix, list->name); 173950397Sobrien list = list->next; 174050397Sobrien } 174150397Sobrien} 174250397Sobrien#endif 174350397Sobrien 174450397Sobrien#if 0 174550397Sobrienstatic void 1746132718Skandump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list) 174750397Sobrien{ 174850397Sobrien while (list) 174950397Sobrien { 175050397Sobrien fprintf (stream, "%s%s,\n", prefix, list->prefix); 175150397Sobrien list = list->next; 175250397Sobrien } 175350397Sobrien} 175450397Sobrien#endif 175550397Sobrien 175650397Sobrienstatic void 1757132718Skanwrite_list_with_asm (FILE *stream, const char *prefix, struct id *list) 175818334Speter{ 175918334Speter while (list) 176018334Speter { 176118334Speter fprintf (stream, "%sx%d __asm__ (\"%s\");\n", 176218334Speter prefix, list->sequence, list->name); 176318334Speter list = list->next; 176418334Speter } 176518334Speter} 176618334Speter 176718334Speter/* Write out the constructor and destructor tables statically (for a shared 176818334Speter object), along with the functions to execute them. */ 176918334Speter 177018334Speterstatic void 1771132718Skanwrite_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED) 177218334Speter{ 177390075Sobrien const char *p, *q; 177490075Sobrien char *prefix, *r; 177550397Sobrien int frames = (frame_tables.number > 0); 177618334Speter 177718334Speter /* Figure out name of output_file, stripping off .so version. */ 177890075Sobrien p = strrchr (output_file, '/'); 177918334Speter if (p == 0) 178090075Sobrien p = output_file; 178118334Speter else 178218334Speter p++; 178318334Speter q = p; 178418334Speter while (q) 178518334Speter { 178690075Sobrien q = strchr (q,'.'); 178718334Speter if (q == 0) 178818334Speter { 178918334Speter q = p + strlen (p); 179018334Speter break; 179118334Speter } 179218334Speter else 179318334Speter { 179418334Speter if (strncmp (q, ".so", 3) == 0) 179518334Speter { 179618334Speter q += 3; 179718334Speter break; 179818334Speter } 179918334Speter else 180018334Speter q++; 180118334Speter } 180218334Speter } 180318334Speter /* q points to null at end of the string (or . of the .so version) */ 1804169689Skan prefix = XNEWVEC (char, q - p + 1); 180518334Speter strncpy (prefix, p, q - p); 180618334Speter prefix[q - p] = 0; 180790075Sobrien for (r = prefix; *r; r++) 180890075Sobrien if (!ISALNUM ((unsigned char)*r)) 180990075Sobrien *r = '_'; 181018334Speter if (debug) 181152284Sobrien notice ("\nwrite_c_file - output name is %s, prefix is %s\n", 181252284Sobrien output_file, prefix); 181318334Speter 181490075Sobrien initname = concat ("_GLOBAL__FI_", prefix, NULL); 181590075Sobrien fininame = concat ("_GLOBAL__FD_", prefix, NULL); 181618334Speter 181718334Speter free (prefix); 181818334Speter 1819132718Skan /* Write the tables as C code. */ 182018334Speter 182118334Speter fprintf (stream, "static int count;\n"); 182218334Speter fprintf (stream, "typedef void entry_pt();\n"); 182318334Speter write_list_with_asm (stream, "extern entry_pt ", constructors.first); 182450397Sobrien 182550397Sobrien if (frames) 182650397Sobrien { 182750397Sobrien write_list_with_asm (stream, "extern void *", frame_tables.first); 182850397Sobrien 182950397Sobrien fprintf (stream, "\tstatic void *frame_table[] = {\n"); 183050397Sobrien write_list (stream, "\t\t&", frame_tables.first); 183150397Sobrien fprintf (stream, "\t0\n};\n"); 183250397Sobrien 183350397Sobrien /* This must match what's in frame.h. */ 183450397Sobrien fprintf (stream, "struct object {\n"); 183550397Sobrien fprintf (stream, " void *pc_begin;\n"); 183650397Sobrien fprintf (stream, " void *pc_end;\n"); 183750397Sobrien fprintf (stream, " void *fde_begin;\n"); 183850397Sobrien fprintf (stream, " void *fde_array;\n"); 183950397Sobrien fprintf (stream, " __SIZE_TYPE__ count;\n"); 184050397Sobrien fprintf (stream, " struct object *next;\n"); 184150397Sobrien fprintf (stream, "};\n"); 184250397Sobrien 184350397Sobrien fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); 184450397Sobrien fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); 184550397Sobrien 184650397Sobrien fprintf (stream, "static void reg_frame () {\n"); 184750397Sobrien fprintf (stream, "\tstatic struct object ob;\n"); 184850397Sobrien fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); 184950397Sobrien fprintf (stream, "\t}\n"); 185050397Sobrien 185150397Sobrien fprintf (stream, "static void dereg_frame () {\n"); 185250397Sobrien fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); 185350397Sobrien fprintf (stream, "\t}\n"); 185450397Sobrien } 185550397Sobrien 185618334Speter fprintf (stream, "void %s() {\n", initname); 185750397Sobrien if (constructors.number > 0 || frames) 185818334Speter { 185918334Speter fprintf (stream, "\tstatic entry_pt *ctors[] = {\n"); 186018334Speter write_list (stream, "\t\t", constructors.first); 186150397Sobrien if (frames) 186250397Sobrien fprintf (stream, "\treg_frame,\n"); 186318334Speter fprintf (stream, "\t};\n"); 186418334Speter fprintf (stream, "\tentry_pt **p;\n"); 186518334Speter fprintf (stream, "\tif (count++ != 0) return;\n"); 186650397Sobrien fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames); 186718334Speter fprintf (stream, "\twhile (p > ctors) (*--p)();\n"); 186818334Speter } 186918334Speter else 187018334Speter fprintf (stream, "\t++count;\n"); 187118334Speter fprintf (stream, "}\n"); 187218334Speter write_list_with_asm (stream, "extern entry_pt ", destructors.first); 187318334Speter fprintf (stream, "void %s() {\n", fininame); 187450397Sobrien if (destructors.number > 0 || frames) 187518334Speter { 187618334Speter fprintf (stream, "\tstatic entry_pt *dtors[] = {\n"); 187718334Speter write_list (stream, "\t\t", destructors.first); 187850397Sobrien if (frames) 187950397Sobrien fprintf (stream, "\tdereg_frame,\n"); 188018334Speter fprintf (stream, "\t};\n"); 188118334Speter fprintf (stream, "\tentry_pt **p;\n"); 188218334Speter fprintf (stream, "\tif (--count != 0) return;\n"); 188318334Speter fprintf (stream, "\tp = dtors;\n"); 188418334Speter fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n", 188550397Sobrien destructors.number + frames); 188618334Speter } 188718334Speter fprintf (stream, "}\n"); 188818334Speter 188918334Speter if (shared_obj) 189018334Speter { 189190075Sobrien COLLECT_SHARED_INIT_FUNC(stream, initname); 189290075Sobrien COLLECT_SHARED_FINI_FUNC(stream, fininame); 189318334Speter } 189418334Speter} 189518334Speter 189650397Sobrien/* Write the constructor/destructor tables. */ 189718334Speter 189850397Sobrien#ifndef LD_INIT_SWITCH 189918334Speterstatic void 1900132718Skanwrite_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED) 190118334Speter{ 1902132718Skan /* Write the tables as C code. */ 190318334Speter 190450397Sobrien int frames = (frame_tables.number > 0); 190550397Sobrien 190618334Speter fprintf (stream, "typedef void entry_pt();\n\n"); 1907132718Skan 190818334Speter write_list_with_asm (stream, "extern entry_pt ", constructors.first); 190950397Sobrien 191050397Sobrien if (frames) 191150397Sobrien { 191250397Sobrien write_list_with_asm (stream, "extern void *", frame_tables.first); 191350397Sobrien 191450397Sobrien fprintf (stream, "\tstatic void *frame_table[] = {\n"); 191550397Sobrien write_list (stream, "\t\t&", frame_tables.first); 191650397Sobrien fprintf (stream, "\t0\n};\n"); 191750397Sobrien 191850397Sobrien /* This must match what's in frame.h. */ 191950397Sobrien fprintf (stream, "struct object {\n"); 192050397Sobrien fprintf (stream, " void *pc_begin;\n"); 192150397Sobrien fprintf (stream, " void *pc_end;\n"); 192250397Sobrien fprintf (stream, " void *fde_begin;\n"); 192350397Sobrien fprintf (stream, " void *fde_array;\n"); 192450397Sobrien fprintf (stream, " __SIZE_TYPE__ count;\n"); 192550397Sobrien fprintf (stream, " struct object *next;\n"); 192650397Sobrien fprintf (stream, "};\n"); 192750397Sobrien 192850397Sobrien fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); 192950397Sobrien fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); 193050397Sobrien 193150397Sobrien fprintf (stream, "static void reg_frame () {\n"); 193250397Sobrien fprintf (stream, "\tstatic struct object ob;\n"); 193350397Sobrien fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); 193450397Sobrien fprintf (stream, "\t}\n"); 193550397Sobrien 193650397Sobrien fprintf (stream, "static void dereg_frame () {\n"); 193750397Sobrien fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); 193850397Sobrien fprintf (stream, "\t}\n"); 193950397Sobrien } 194050397Sobrien 194118334Speter fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); 194250397Sobrien fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames); 194318334Speter write_list (stream, "\t", constructors.first); 194450397Sobrien if (frames) 194550397Sobrien fprintf (stream, "\treg_frame,\n"); 194618334Speter fprintf (stream, "\t0\n};\n\n"); 194718334Speter 194818334Speter write_list_with_asm (stream, "extern entry_pt ", destructors.first); 194918334Speter 195018334Speter fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n"); 195150397Sobrien fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames); 195218334Speter write_list (stream, "\t", destructors.first); 195350397Sobrien if (frames) 195450397Sobrien fprintf (stream, "\tdereg_frame,\n"); 195518334Speter fprintf (stream, "\t0\n};\n\n"); 195618334Speter 195718334Speter fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN); 195818334Speter fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN); 195918334Speter} 196050397Sobrien#endif /* ! LD_INIT_SWITCH */ 196118334Speter 196218334Speterstatic void 1963132718Skanwrite_c_file (FILE *stream, const char *name) 196418334Speter{ 196550397Sobrien fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); 196618334Speter#ifndef LD_INIT_SWITCH 196718334Speter if (! shared_obj) 196818334Speter write_c_file_glob (stream, name); 196918334Speter else 197018334Speter#endif 197118334Speter write_c_file_stat (stream, name); 197250397Sobrien fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n"); 197318334Speter} 197418334Speter 197550397Sobrien#ifdef COLLECT_EXPORT_LIST 197618334Speterstatic void 1977132718Skanwrite_aix_file (FILE *stream, struct id *list) 197818334Speter{ 197918334Speter for (; list; list = list->next) 198090075Sobrien { 198190075Sobrien fputs (list->name, stream); 198290075Sobrien putc ('\n', stream); 198390075Sobrien } 198418334Speter} 198550397Sobrien#endif 198618334Speter 198718334Speter#ifdef OBJECT_FORMAT_NONE 198818334Speter 198918334Speter/* Generic version to scan the name list of the loaded program for 199018334Speter the symbols g++ uses for static constructors and destructors. 199118334Speter 199218334Speter The constructor table begins at __CTOR_LIST__ and contains a count 199318334Speter of the number of pointers (or -1 if the constructors are built in a 199418334Speter separate section by the linker), followed by the pointers to the 199518334Speter constructor functions, terminated with a null pointer. The 199618334Speter destructor table has the same format, and begins at __DTOR_LIST__. */ 199718334Speter 199818334Speterstatic void 1999132718Skanscan_prog_file (const char *prog_name, enum pass which_pass) 200018334Speter{ 2001132718Skan void (*int_handler) (int); 2002169689Skan#ifdef SIGQUIT 2003132718Skan void (*quit_handler) (int); 2004169689Skan#endif 200590075Sobrien char *real_nm_argv[4]; 200690075Sobrien const char **nm_argv = (const char **) real_nm_argv; 200718334Speter int argc = 0; 2008169689Skan struct pex_obj *pex; 2009169689Skan const char *errmsg; 2010169689Skan int err; 201118334Speter char *p, buf[1024]; 201218334Speter FILE *inf; 201318334Speter 201418334Speter if (which_pass == PASS_SECOND) 201518334Speter return; 201618334Speter 201750397Sobrien /* If we do not have an `nm', complain. */ 201818334Speter if (nm_file_name == 0) 2019169689Skan fatal ("cannot find 'nm'"); 202018334Speter 202118334Speter nm_argv[argc++] = nm_file_name; 202218334Speter if (NM_FLAGS[0] != '\0') 202318334Speter nm_argv[argc++] = NM_FLAGS; 202418334Speter 202518334Speter nm_argv[argc++] = prog_name; 202650397Sobrien nm_argv[argc++] = (char *) 0; 202718334Speter 202818334Speter /* Trace if needed. */ 202918334Speter if (vflag) 203018334Speter { 203190075Sobrien const char **p_argv; 203290075Sobrien const char *str; 203318334Speter 203450397Sobrien for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) 203518334Speter fprintf (stderr, " %s", str); 203618334Speter 203718334Speter fprintf (stderr, "\n"); 203818334Speter } 203918334Speter 204018334Speter fflush (stdout); 204118334Speter fflush (stderr); 204218334Speter 2043169689Skan pex = pex_init (PEX_USE_PIPES, "collect2", NULL); 2044169689Skan if (pex == NULL) 2045169689Skan fatal_perror ("pex_init failed"); 204618334Speter 2047169689Skan errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, NULL, &err); 2048169689Skan if (errmsg != NULL) 204918334Speter { 2050169689Skan if (err != 0) 2051169689Skan { 2052169689Skan errno = err; 2053260011Spfg fatal_perror ("%s", errmsg); 2054169689Skan } 2055169689Skan else 2056260011Spfg fatal ("%s", errmsg); 205718334Speter } 205818334Speter 2059132718Skan int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); 206018334Speter#ifdef SIGQUIT 2061132718Skan quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); 206218334Speter#endif 206318334Speter 2064169689Skan inf = pex_read_output (pex, 0); 2065169689Skan if (inf == NULL) 2066169689Skan fatal_perror ("can't open nm output"); 206718334Speter 206818334Speter if (debug) 206918334Speter fprintf (stderr, "\nnm output with constructors/destructors.\n"); 207018334Speter 207118334Speter /* Read each line of nm output. */ 207250397Sobrien while (fgets (buf, sizeof buf, inf) != (char *) 0) 207318334Speter { 207418334Speter int ch, ch2; 207518334Speter char *name, *end; 207618334Speter 207718334Speter /* If it contains a constructor or destructor name, add the name 207850397Sobrien to the appropriate list. */ 207918334Speter 208018334Speter for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) 208118334Speter if (ch == ' ' && p[1] == 'U' && p[2] == ' ') 208218334Speter break; 208318334Speter 208418334Speter if (ch != '_') 208518334Speter continue; 2086132718Skan 208718334Speter name = p; 208818334Speter /* Find the end of the symbol name. 208950397Sobrien Do not include `|', because Encore nm can tack that on the end. */ 209050397Sobrien for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|'; 209118334Speter end++) 209218334Speter continue; 209318334Speter 209418334Speter 209518334Speter *end = '\0'; 209618334Speter switch (is_ctor_dtor (name)) 209718334Speter { 209818334Speter case 1: 209918334Speter if (which_pass != PASS_LIB) 210018334Speter add_to_list (&constructors, name); 210118334Speter break; 210218334Speter 210318334Speter case 2: 210418334Speter if (which_pass != PASS_LIB) 210518334Speter add_to_list (&destructors, name); 210618334Speter break; 210718334Speter 210818334Speter case 3: 210918334Speter if (which_pass != PASS_LIB) 211018334Speter fatal ("init function found in object %s", prog_name); 211118334Speter#ifndef LD_INIT_SWITCH 211218334Speter add_to_list (&constructors, name); 211318334Speter#endif 211418334Speter break; 211518334Speter 211618334Speter case 4: 211718334Speter if (which_pass != PASS_LIB) 211818334Speter fatal ("fini function found in object %s", prog_name); 211918334Speter#ifndef LD_FINI_SWITCH 212018334Speter add_to_list (&destructors, name); 212118334Speter#endif 212218334Speter break; 212318334Speter 212450397Sobrien case 5: 212550397Sobrien if (which_pass != PASS_LIB) 212650397Sobrien add_to_list (&frame_tables, name); 212752284Sobrien break; 212850397Sobrien 212918334Speter default: /* not a constructor or destructor */ 213018334Speter continue; 213118334Speter } 213218334Speter 213318334Speter if (debug) 213418334Speter fprintf (stderr, "\t%s\n", buf); 213518334Speter } 213618334Speter 213718334Speter if (debug) 213818334Speter fprintf (stderr, "\n"); 213918334Speter 2140169689Skan do_wait (nm_file_name, pex); 214118334Speter 214218334Speter signal (SIGINT, int_handler); 214318334Speter#ifdef SIGQUIT 214418334Speter signal (SIGQUIT, quit_handler); 214518334Speter#endif 214618334Speter} 214718334Speter 214818334Speter#ifdef LDD_SUFFIX 214918334Speter 215018334Speter/* Use the List Dynamic Dependencies program to find shared libraries that 215118334Speter the output file depends upon and their initialization/finalization 215218334Speter routines, if any. */ 215318334Speter 2154132718Skanstatic void 2155132718Skanscan_libraries (const char *prog_name) 215618334Speter{ 215718334Speter static struct head libraries; /* list of shared libraries found */ 215818334Speter struct id *list; 2159132718Skan void (*int_handler) (int); 2160169689Skan#ifdef SIGQUIT 2161132718Skan void (*quit_handler) (int); 2162169689Skan#endif 216390075Sobrien char *real_ldd_argv[4]; 216490075Sobrien const char **ldd_argv = (const char **) real_ldd_argv; 216518334Speter int argc = 0; 2166169689Skan struct pex_obj *pex; 2167169689Skan const char *errmsg; 2168169689Skan int err; 216918334Speter char buf[1024]; 217018334Speter FILE *inf; 217118334Speter 217250397Sobrien /* If we do not have an `ldd', complain. */ 217318334Speter if (ldd_file_name == 0) 217418334Speter { 2175169689Skan error ("cannot find 'ldd'"); 217618334Speter return; 217718334Speter } 217818334Speter 217918334Speter ldd_argv[argc++] = ldd_file_name; 218018334Speter ldd_argv[argc++] = prog_name; 218118334Speter ldd_argv[argc++] = (char *) 0; 218218334Speter 218318334Speter /* Trace if needed. */ 218418334Speter if (vflag) 218518334Speter { 218690075Sobrien const char **p_argv; 218790075Sobrien const char *str; 218818334Speter 218918334Speter for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) 219018334Speter fprintf (stderr, " %s", str); 219118334Speter 219218334Speter fprintf (stderr, "\n"); 219318334Speter } 219418334Speter 219518334Speter fflush (stdout); 219618334Speter fflush (stderr); 219718334Speter 2198169689Skan pex = pex_init (PEX_USE_PIPES, "collect2", NULL); 2199169689Skan if (pex == NULL) 2200169689Skan fatal_perror ("pex_init failed"); 220118334Speter 2202169689Skan errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err); 2203169689Skan if (errmsg != NULL) 220418334Speter { 2205169689Skan if (err != 0) 2206169689Skan { 2207169689Skan errno = err; 2208169689Skan fatal_perror (errmsg); 2209169689Skan } 2210169689Skan else 2211169689Skan fatal (errmsg); 221218334Speter } 221318334Speter 2214132718Skan int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); 221518334Speter#ifdef SIGQUIT 2216132718Skan quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); 221718334Speter#endif 221818334Speter 2219169689Skan inf = pex_read_output (pex, 0); 2220169689Skan if (inf == NULL) 2221169689Skan fatal_perror ("can't open ldd output"); 222218334Speter 222318334Speter if (debug) 222452284Sobrien notice ("\nldd output with constructors/destructors.\n"); 222518334Speter 222618334Speter /* Read each line of ldd output. */ 222718334Speter while (fgets (buf, sizeof buf, inf) != (char *) 0) 222818334Speter { 222990075Sobrien int ch2; 223018334Speter char *name, *end, *p = buf; 223118334Speter 223250397Sobrien /* Extract names of libraries and add to list. */ 223318334Speter PARSE_LDD_OUTPUT (p); 223418334Speter if (p == 0) 223518334Speter continue; 223618334Speter 223718334Speter name = p; 223818334Speter if (strncmp (name, "not found", sizeof ("not found") - 1) == 0) 223918334Speter fatal ("dynamic dependency %s not found", buf); 224018334Speter 224150397Sobrien /* Find the end of the symbol name. */ 2242132718Skan for (end = p; 224350397Sobrien (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|'; 224418334Speter end++) 224518334Speter continue; 224618334Speter *end = '\0'; 224718334Speter 224818334Speter if (access (name, R_OK) == 0) 2249169689Skan add_to_list (&libraries, name); 225018334Speter else 225118334Speter fatal ("unable to open dynamic dependency '%s'", buf); 225218334Speter 225318334Speter if (debug) 225418334Speter fprintf (stderr, "\t%s\n", buf); 225518334Speter } 225618334Speter if (debug) 225718334Speter fprintf (stderr, "\n"); 225818334Speter 2259169689Skan do_wait (ldd_file_name, pex); 226018334Speter 226118334Speter signal (SIGINT, int_handler); 226218334Speter#ifdef SIGQUIT 226318334Speter signal (SIGQUIT, quit_handler); 226418334Speter#endif 226518334Speter 2266132718Skan /* Now iterate through the library list adding their symbols to 226718334Speter the list. */ 226818334Speter for (list = libraries.first; list; list = list->next) 226918334Speter scan_prog_file (list->name, PASS_LIB); 227018334Speter} 227118334Speter 227218334Speter#endif /* LDD_SUFFIX */ 227318334Speter 227418334Speter#endif /* OBJECT_FORMAT_NONE */ 227518334Speter 227618334Speter 227718334Speter/* 227818334Speter * COFF specific stuff. 227918334Speter */ 228018334Speter 228118334Speter#ifdef OBJECT_FORMAT_COFF 228218334Speter 2283132718Skan#if defined (EXTENDED_COFF) 228490075Sobrien 228518334Speter# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax) 228618334Speter# define GCC_SYMENT SYMR 228752284Sobrien# define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal) 228818334Speter# define GCC_SYMINC(X) (1) 228918334Speter# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax) 229018334Speter# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0) 229190075Sobrien 229218334Speter#else 229390075Sobrien 229418334Speter# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms) 229518334Speter# define GCC_SYMENT SYMENT 2296132718Skan# if defined (C_WEAKEXT) 2297132718Skan# define GCC_OK_SYMBOL(X) \ 2298132718Skan (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \ 2299169689Skan ((X).n_scnum > N_UNDEF) && \ 2300169689Skan (aix64_flag \ 2301169689Skan || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ 2302169689Skan || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) 2303132718Skan# define GCC_UNDEF_SYMBOL(X) \ 2304132718Skan (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \ 2305169689Skan ((X).n_scnum == N_UNDEF)) 2306132718Skan# else 2307132718Skan# define GCC_OK_SYMBOL(X) \ 2308132718Skan (((X).n_sclass == C_EXT) && \ 2309169689Skan ((X).n_scnum > N_UNDEF) && \ 2310169689Skan (aix64_flag \ 2311169689Skan || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ 2312169689Skan || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) 2313132718Skan# define GCC_UNDEF_SYMBOL(X) \ 2314132718Skan (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF)) 2315132718Skan# endif 231618334Speter# define GCC_SYMINC(X) ((X).n_numaux+1) 231718334Speter# define GCC_SYMZERO(X) 0 231890075Sobrien 231990075Sobrien/* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */ 232090075Sobrien#ifdef _AIX51 232150397Sobrien# define GCC_CHECK_HDR(X) \ 232250397Sobrien ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ 232390075Sobrien || (HEADER (X).f_magic == 0767 && aix64_flag)) 232490075Sobrien#else 232590075Sobrien# define GCC_CHECK_HDR(X) \ 232690075Sobrien ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ 232750397Sobrien || (HEADER (X).f_magic == 0757 && aix64_flag)) 232818334Speter#endif 232918334Speter 233090075Sobrien#endif 233190075Sobrien 2332132718Skan#ifdef COLLECT_EXPORT_LIST 2333132718Skan/* Array of standard AIX libraries which should not 2334132718Skan be scanned for ctors/dtors. */ 2335132718Skanstatic const char *const aix_std_libs[] = { 2336132718Skan "/unix", 2337132718Skan "/lib/libc.a", 2338132718Skan "/lib/libm.a", 2339132718Skan "/lib/libc_r.a", 2340132718Skan "/lib/libm_r.a", 2341132718Skan "/usr/lib/libc.a", 2342132718Skan "/usr/lib/libm.a", 2343132718Skan "/usr/lib/libc_r.a", 2344132718Skan "/usr/lib/libm_r.a", 2345132718Skan "/usr/lib/threads/libc.a", 2346132718Skan "/usr/ccs/lib/libc.a", 2347132718Skan "/usr/ccs/lib/libm.a", 2348132718Skan "/usr/ccs/lib/libc_r.a", 2349132718Skan "/usr/ccs/lib/libm_r.a", 2350132718Skan NULL 2351132718Skan}; 235218334Speter 2353132718Skan/* This function checks the filename and returns 1 2354132718Skan if this name matches the location of a standard AIX library. */ 2355132718Skanstatic int ignore_library (const char *); 2356132718Skanstatic int 2357132718Skanignore_library (const char *name) 2358132718Skan{ 2359132718Skan const char *const *p = &aix_std_libs[0]; 2360132718Skan while (*p++ != NULL) 2361132718Skan if (! strcmp (name, *p)) return 1; 2362132718Skan return 0; 2363132718Skan} 2364132718Skan#endif /* COLLECT_EXPORT_LIST */ 2365132718Skan 2366132718Skan#if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME 2367132718Skanextern char *ldgetname (LDFILE *, GCC_SYMENT *); 2368132718Skan#endif 2369132718Skan 237018334Speter/* COFF version to scan the name list of the loaded program for 237118334Speter the symbols g++ uses for static constructors and destructors. 237218334Speter 237318334Speter The constructor table begins at __CTOR_LIST__ and contains a count 237418334Speter of the number of pointers (or -1 if the constructors are built in a 237518334Speter separate section by the linker), followed by the pointers to the 237618334Speter constructor functions, terminated with a null pointer. The 237718334Speter destructor table has the same format, and begins at __DTOR_LIST__. */ 237818334Speter 237918334Speterstatic void 2380132718Skanscan_prog_file (const char *prog_name, enum pass which_pass) 238118334Speter{ 238218334Speter LDFILE *ldptr = NULL; 238318334Speter int sym_index, sym_count; 238450397Sobrien int is_shared = 0; 238518334Speter 238618334Speter if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) 238718334Speter return; 238818334Speter 238950397Sobrien#ifdef COLLECT_EXPORT_LIST 239050397Sobrien /* We do not need scanning for some standard C libraries. */ 239150397Sobrien if (which_pass == PASS_FIRST && ignore_library (prog_name)) 239250397Sobrien return; 239318334Speter 239450397Sobrien /* On AIX we have a loop, because there is not much difference 239550397Sobrien between an object and an archive. This trick allows us to 239650397Sobrien eliminate scan_libraries() function. */ 239750397Sobrien do 239818334Speter { 239950397Sobrien#endif 240090075Sobrien /* Some platforms (e.g. OSF4) declare ldopen as taking a 2401169689Skan non-const char * filename parameter, even though it will not 2402169689Skan modify that string. So we must cast away const-ness here, 2403169689Skan which will cause -Wcast-qual to burp. */ 240490075Sobrien if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL) 240518334Speter { 240650397Sobrien if (! MY_ISCOFF (HEADER (ldptr).f_magic)) 240750397Sobrien fatal ("%s: not a COFF file", prog_name); 240818334Speter 240950397Sobrien if (GCC_CHECK_HDR (ldptr)) 241018334Speter { 241150397Sobrien sym_count = GCC_SYMBOLS (ldptr); 241250397Sobrien sym_index = GCC_SYMZERO (ldptr); 241318334Speter 241450397Sobrien#ifdef COLLECT_EXPORT_LIST 241550397Sobrien /* Is current archive member a shared object? */ 241650397Sobrien is_shared = HEADER (ldptr).f_flags & F_SHROBJ; 241750397Sobrien#endif 241818334Speter 241950397Sobrien while (sym_index < sym_count) 242050397Sobrien { 242150397Sobrien GCC_SYMENT symbol; 242250397Sobrien 242350397Sobrien if (ldtbread (ldptr, sym_index, &symbol) <= 0) 242450397Sobrien break; 242550397Sobrien sym_index += GCC_SYMINC (symbol); 242650397Sobrien 242750397Sobrien if (GCC_OK_SYMBOL (symbol)) 242850397Sobrien { 242950397Sobrien char *name; 243050397Sobrien 243150397Sobrien if ((name = ldgetname (ldptr, &symbol)) == NULL) 2432132718Skan continue; /* Should never happen. */ 243350397Sobrien 243418334Speter#ifdef XCOFF_DEBUGGING_INFO 243550397Sobrien /* All AIX function names have a duplicate entry 243650397Sobrien beginning with a dot. */ 243750397Sobrien if (*name == '.') 243850397Sobrien ++name; 243918334Speter#endif 244018334Speter 244150397Sobrien switch (is_ctor_dtor (name)) 244250397Sobrien { 244350397Sobrien case 1: 244490075Sobrien if (! is_shared) 244590075Sobrien add_to_list (&constructors, name); 2446132718Skan#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) 244750397Sobrien if (which_pass == PASS_OBJ) 244850397Sobrien add_to_list (&exports, name); 244950397Sobrien#endif 245050397Sobrien break; 245118334Speter 245250397Sobrien case 2: 245390075Sobrien if (! is_shared) 245490075Sobrien add_to_list (&destructors, name); 2455132718Skan#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) 245650397Sobrien if (which_pass == PASS_OBJ) 245750397Sobrien add_to_list (&exports, name); 245850397Sobrien#endif 245950397Sobrien break; 246018334Speter 246150397Sobrien#ifdef COLLECT_EXPORT_LIST 246250397Sobrien case 3: 246390075Sobrien#ifndef LD_INIT_SWITCH 246450397Sobrien if (is_shared) 246550397Sobrien add_to_list (&constructors, name); 246690075Sobrien#endif 246750397Sobrien break; 246818334Speter 246950397Sobrien case 4: 247090075Sobrien#ifndef LD_INIT_SWITCH 247150397Sobrien if (is_shared) 247250397Sobrien add_to_list (&destructors, name); 247390075Sobrien#endif 247450397Sobrien break; 247550397Sobrien#endif 247650397Sobrien 247752284Sobrien case 5: 247852284Sobrien if (! is_shared) 247952284Sobrien add_to_list (&frame_tables, name); 2480132718Skan#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) 248190075Sobrien if (which_pass == PASS_OBJ) 248290075Sobrien add_to_list (&exports, name); 248390075Sobrien#endif 248452284Sobrien break; 248552284Sobrien 248650397Sobrien default: /* not a constructor or destructor */ 248750397Sobrien#ifdef COLLECT_EXPORT_LIST 2488132718Skan /* Explicitly export all global symbols when 2489132718Skan building a shared object on AIX, but do not 2490132718Skan re-export symbols from another shared object 2491132718Skan and do not export symbols if the user 2492132718Skan provides an explicit export list. */ 2493132718Skan if (shared_obj && !is_shared 2494132718Skan && which_pass == PASS_OBJ && !export_flag) 2495132718Skan add_to_list (&exports, name); 249650397Sobrien#endif 249750397Sobrien continue; 249850397Sobrien } 249950397Sobrien 250090075Sobrien if (debug) 250118334Speter#if !defined(EXTENDED_COFF) 250250397Sobrien fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n", 250350397Sobrien symbol.n_scnum, symbol.n_sclass, 250450397Sobrien (symbol.n_type ? "0" : ""), symbol.n_type, 250550397Sobrien name); 250618334Speter#else 250750397Sobrien fprintf (stderr, 250850397Sobrien "\tiss = %5d, value = %5ld, index = %5d, name = %s\n", 250950397Sobrien symbol.iss, (long) symbol.value, symbol.index, name); 251050397Sobrien#endif 251150397Sobrien } 251250397Sobrien } 251350397Sobrien } 251450397Sobrien#ifdef COLLECT_EXPORT_LIST 251550397Sobrien else 251650397Sobrien { 251750397Sobrien /* If archive contains both 32-bit and 64-bit objects, 251850397Sobrien we want to skip objects in other mode so mismatch normal. */ 251918334Speter if (debug) 252050397Sobrien fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n", 252150397Sobrien prog_name, HEADER (ldptr).f_magic, aix64_flag); 252250397Sobrien } 252318334Speter#endif 252418334Speter } 252550397Sobrien else 252650397Sobrien { 252750397Sobrien fatal ("%s: cannot open as COFF file", prog_name); 252850397Sobrien } 252950397Sobrien#ifdef COLLECT_EXPORT_LIST 253050397Sobrien /* On AIX loop continues while there are more members in archive. */ 253118334Speter } 253250397Sobrien while (ldclose (ldptr) == FAILURE); 253350397Sobrien#else 253450397Sobrien /* Otherwise we simply close ldptr. */ 253518334Speter (void) ldclose(ldptr); 253650397Sobrien#endif 253718334Speter} 2538117395Skan#endif /* OBJECT_FORMAT_COFF */ 253918334Speter 254050397Sobrien#ifdef COLLECT_EXPORT_LIST 254150397Sobrien/* Given a library name without "lib" prefix, this function 254250397Sobrien returns a full library name including a path. */ 254350397Sobrienstatic char * 2544132718Skanresolve_lib_name (const char *name) 254550397Sobrien{ 254650397Sobrien char *lib_buf; 254750397Sobrien int i, j, l = 0; 2548146895Skan /* Library extensions for AIX dynamic linking. */ 2549146895Skan const char * const libexts[2] = {"a", "so"}; 255018336Speter 255150397Sobrien for (i = 0; libpaths[i]; i++) 255250397Sobrien if (libpaths[i]->max_len > l) 255350397Sobrien l = libpaths[i]->max_len; 255418336Speter 255550397Sobrien lib_buf = xmalloc (l + strlen(name) + 10); 255650397Sobrien 255750397Sobrien for (i = 0; libpaths[i]; i++) 255850397Sobrien { 255950397Sobrien struct prefix_list *list = libpaths[i]->plist; 256050397Sobrien for (; list; list = list->next) 256118334Speter { 256290075Sobrien /* The following lines are needed because path_prefix list 256390075Sobrien may contain directories both with trailing '/' and 256490075Sobrien without it. */ 256590075Sobrien const char *p = ""; 256690075Sobrien if (list->prefix[strlen(list->prefix)-1] != '/') 256790075Sobrien p = "/"; 2568146895Skan for (j = 0; j < 2; j++) 256918334Speter { 2570132718Skan sprintf (lib_buf, "%s%slib%s.%s", 2571146895Skan list->prefix, p, name, 2572146895Skan libexts[(j + aixrtl_flag) % 2]); 2573146895Skan if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); 257450397Sobrien if (file_exists (lib_buf)) 257518334Speter { 2576146895Skan if (debug) fprintf (stderr, "found: %s\n", lib_buf); 257750397Sobrien return (lib_buf); 257818334Speter } 257918334Speter } 258018334Speter } 258118334Speter } 258250397Sobrien if (debug) 258350397Sobrien fprintf (stderr, "not found\n"); 258450397Sobrien else 258590075Sobrien fatal ("library lib%s not found", name); 258650397Sobrien return (NULL); 258718334Speter} 2588117395Skan#endif /* COLLECT_EXPORT_LIST */ 2589