Mercurial > hg > CbC > CbC_gcc
diff gcc/collect2.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/collect2.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/collect2.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,8 +1,6 @@ /* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1992-2017 Free Software Foundation, Inc. Contributed by Chris Smith (csmith@convex.com). Heavily modified by Michael Meissner (meissner@cygnus.com), Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). @@ -30,6 +28,8 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "filenames.h" +#include "file-find.h" /* TARGET_64BIT may be defined to use driver specific functionality. */ #undef TARGET_64BIT @@ -43,6 +43,8 @@ #include "collect2.h" #include "collect2-aix.h" +#include "collect-utils.h" +#include "diagnostic.h" #include "demangle.h" #include "obstack.h" #include "intl.h" @@ -174,14 +176,13 @@ int number; }; -bool vflag; /* true if -v or --version */ static int rflag; /* true if -r */ static int strip_flag; /* true if -s */ -static const char *demangle_flag; #ifdef COLLECT_EXPORT_LIST static int export_flag; /* true if -bE */ static int aix64_flag; /* true if -b64 */ static int aixrtl_flag; /* true if -brtl */ +static int aixlazy_flag; /* true if -blazy */ #endif enum lto_mode_d { @@ -191,9 +192,12 @@ }; /* Current LTO mode. */ +#ifdef ENABLE_LTO +static enum lto_mode_d lto_mode = LTO_MODE_WHOPR; +#else static enum lto_mode_d lto_mode = LTO_MODE_NONE; - -bool debug; /* true if -debug */ +#endif + bool helpflag; /* true if --help */ static int shared_obj; /* true if -shared */ @@ -215,6 +219,13 @@ const char *c_file_name; /* pathname of gcc */ static char *initname, *fininame; /* names of init and fini funcs */ + +#ifdef TARGET_AIX_VERSION +static char *aix_shared_initname; +static char *aix_shared_fininame; /* init/fini names as per the scheme + described in config/rs6000/aix.h */ +#endif + static struct head constructors; /* list of constructors found */ static struct head destructors; /* list of destructors found */ #ifdef COLLECT_EXPORT_LIST @@ -222,8 +233,7 @@ #endif static struct head frame_tables; /* list of frame unwind info tables */ -static bool at_file_supplied; /* Whether to use @file arguments */ -static char *response_file; /* Name of any current response file */ +bool at_file_supplied; /* Whether to use @file arguments */ struct obstack temporary_obstack; char * temporary_firstobj; @@ -236,21 +246,11 @@ static const char *target_system_root = ""; #endif -/* Structure to hold all the directories in which to search for files to - execute. */ - -struct prefix_list -{ - const char *prefix; /* String to prepend to the path. */ - struct prefix_list *next; /* Next in linked list. */ -}; - -struct path_prefix -{ - struct prefix_list *plist; /* List of prefixes to try */ - int max_len; /* Max length of a prefix in PLIST */ - const char *name; /* Name of this list (used in config stuff) */ -}; +/* Whether we may unlink the output file, which should be set as soon as we + know we have successfully produced it. This is typically useful to prevent + blindly attempting to unlink a read-only output that the target linker + would leave untouched. */ +bool may_unlink_output_file = false; #ifdef COLLECT_EXPORT_LIST /* Lists to keep libraries to be scanned for global constructors/destructors. */ @@ -282,26 +282,23 @@ /* Special kinds of symbols that a name may denote. */ -typedef enum { +enum symkind { SYM_REGULAR = 0, /* nothing special */ SYM_CTOR = 1, /* constructor */ SYM_DTOR = 2, /* destructor */ SYM_INIT = 3, /* shared object routine that calls all the ctors */ SYM_FINI = 4, /* shared object routine that calls all the dtors */ - SYM_DWEH = 5 /* DWARF exception handling table */ -} symkind; + SYM_DWEH = 5, /* DWARF exception handling table */ + SYM_AIXI = 6, + SYM_AIXD = 7 +}; + +const char tool_name[] = "collect2"; static symkind is_ctor_dtor (const char *); static void handler (int); -static char *find_a_file (struct path_prefix *, const char *); -static void add_prefix (struct path_prefix *, const char *); -static void prefix_from_env (const char *, struct path_prefix *); -static void prefix_from_string (const char *, struct path_prefix *); -static void do_wait (const char *, struct pex_obj *); -static void fork_execute (const char *, char **); -static void maybe_unlink (const char *); static void maybe_unlink_list (char **); static void add_to_list (struct head *, const char *); static int extract_init_priority (const char *); @@ -322,9 +319,6 @@ #ifdef SCAN_LIBRARIES static void scan_libraries (const char *); #endif -#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES -static int is_in_args (const char *, const char **, const char **); -#endif #ifdef COLLECT_EXPORT_LIST #if 0 static int is_in_list (const char *, struct id *); @@ -339,13 +333,13 @@ /* Enumerations describing which pass this is for scanning the program file ... */ -typedef enum { +enum scanpass { PASS_FIRST, /* without constructors */ PASS_OBJ, /* individual objects */ PASS_LIB, /* looking for shared libraries */ PASS_SECOND, /* with constructors linked in */ PASS_LTOINFO /* looking for objects with LTO info */ -} scanpass; +}; /* ... and which kinds of symbols are to be considered. */ @@ -357,6 +351,8 @@ SCAN_INIT = 1 << SYM_INIT, SCAN_FINI = 1 << SYM_FINI, SCAN_DWEH = 1 << SYM_DWEH, + SCAN_AIXI = 1 << SYM_AIXI, + SCAN_AIXD = 1 << SYM_AIXD, SCAN_ALL = ~0 }; @@ -384,7 +380,7 @@ /* Delete tempfiles and exit function. */ void -collect_exit (int status) +tool_cleanup (bool from_signal) { if (c_file != 0 && c_file[0]) maybe_unlink (c_file); @@ -402,37 +398,33 @@ if (ldout != 0 && ldout[0]) { - dump_file (ldout, stdout); + if (!from_signal) + dump_ld_file (ldout, stdout); maybe_unlink (ldout); } if (lderrout != 0 && lderrout[0]) { - dump_file (lderrout, stderr); + if (!from_signal) + dump_ld_file (lderrout, stderr); maybe_unlink (lderrout); } - - if (status != 0 && output_file != 0 && output_file[0]) - maybe_unlink (output_file); - - if (response_file) - maybe_unlink (response_file); - - exit (status); +} + +static void +collect_atexit (void) +{ + tool_cleanup (false); } - -/* Notify user of a non-error. */ -void -notice (const char *cmsgid, ...) +static void +handler (int signo) { - va_list ap; - - va_start (ap, cmsgid); - vfprintf (stderr, _(cmsgid), ap); - va_end (ap); + tool_cleanup (true); + + signal (signo, SIG_DFL); + raise (signo); } - /* Notify user of a non-error, without translating the format string. */ void notice_translated (const char *cmsgid, ...) @@ -443,93 +435,6 @@ vfprintf (stderr, cmsgid, ap); va_end (ap); } - -/* Die when sys call fails. */ - -void -fatal_perror (const char * cmsgid, ...) -{ - int e = errno; - va_list ap; - - va_start (ap, cmsgid); - fprintf (stderr, "collect2: "); - vfprintf (stderr, _(cmsgid), ap); - fprintf (stderr, ": %s\n", xstrerror (e)); - va_end (ap); - - collect_exit (FATAL_EXIT_CODE); -} - -/* Just die. */ - -void -fatal (const char * cmsgid, ...) -{ - va_list ap; - - va_start (ap, cmsgid); - fprintf (stderr, "collect2: "); - vfprintf (stderr, _(cmsgid), ap); - fprintf (stderr, "\n"); - va_end (ap); - - collect_exit (FATAL_EXIT_CODE); -} - -/* Write error message. */ - -void -error (const char * gmsgid, ...) -{ - va_list ap; - - va_start (ap, gmsgid); - fprintf (stderr, "collect2: "); - vfprintf (stderr, _(gmsgid), ap); - fprintf (stderr, "\n"); - va_end(ap); -} - -/* In case obstack is linked in, and abort is defined to fancy_abort, - provide a default entry. */ - -void -fancy_abort (const char *file, int line, const char *func) -{ - fatal ("internal gcc abort in %s, at %s:%d", func, file, line); -} - -static void -handler (int signo) -{ - if (c_file != 0 && c_file[0]) - maybe_unlink (c_file); - - if (o_file != 0 && o_file[0]) - maybe_unlink (o_file); - - if (ldout != 0 && ldout[0]) - maybe_unlink (ldout); - - if (lderrout != 0 && lderrout[0]) - maybe_unlink (lderrout); - -#ifdef COLLECT_EXPORT_LIST - if (export_file != 0 && export_file[0]) - maybe_unlink (export_file); -#endif - - if (lto_o_files) - maybe_unlink_list (lto_o_files); - - if (response_file) - maybe_unlink (response_file); - - signal (signo, SIG_DFL); - raise (signo); -} - int file_exists (const char *name) @@ -570,7 +475,7 @@ } void -dump_file (const char *name, FILE *to) +dump_ld_file (const char *name, FILE *to) { FILE *stream = fopen (name, "r"); @@ -667,6 +572,10 @@ { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 }, { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 }, { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 }, +#ifdef TARGET_AIX_VERSION + { "GLOBAL__AIXI_", sizeof ("GLOBAL__AIXI_")-1, SYM_AIXI, 0 }, + { "GLOBAL__AIXD_", sizeof ("GLOBAL__AIXD_")-1, SYM_AIXD, 0 }, +#endif { NULL, 0, SYM_REGULAR, 0 } }; @@ -680,7 +589,7 @@ { if (ch == p->name[0] && (!p->two_underscores || ((s - orig_s) >= 2)) - && strncmp(s, p->name, p->len) == 0) + && strncmp (s, p->name, p->len) == 0) { return p->ret; } @@ -705,168 +614,6 @@ Return 0 if not found, otherwise return its name, allocated with malloc. */ -static char * -find_a_file (struct path_prefix *pprefix, const char *name) -{ - char *temp; - struct prefix_list *pl; - int len = pprefix->max_len + strlen (name) + 1; - - if (debug) - fprintf (stderr, "Looking for '%s'\n", name); - -#ifdef HOST_EXECUTABLE_SUFFIX - len += strlen (HOST_EXECUTABLE_SUFFIX); -#endif - - temp = XNEWVEC (char, len); - - /* Determine the filename to execute (special case for absolute paths). */ - - if (IS_ABSOLUTE_PATH (name)) - { - if (access (name, X_OK) == 0) - { - strcpy (temp, name); - - if (debug) - fprintf (stderr, " - found: absolute path\n"); - - return temp; - } - -#ifdef HOST_EXECUTABLE_SUFFIX - /* Some systems have a suffix for executable files. - So try appending that. */ - strcpy (temp, name); - strcat (temp, HOST_EXECUTABLE_SUFFIX); - - if (access (temp, X_OK) == 0) - return temp; -#endif - - if (debug) - fprintf (stderr, " - failed to locate using absolute path\n"); - } - else - for (pl = pprefix->plist; pl; pl = pl->next) - { - struct stat st; - - strcpy (temp, pl->prefix); - strcat (temp, name); - - if (stat (temp, &st) >= 0 - && ! S_ISDIR (st.st_mode) - && access (temp, X_OK) == 0) - return temp; - -#ifdef HOST_EXECUTABLE_SUFFIX - /* Some systems have a suffix for executable files. - So try appending that. */ - strcat (temp, HOST_EXECUTABLE_SUFFIX); - - if (stat (temp, &st) >= 0 - && ! S_ISDIR (st.st_mode) - && access (temp, X_OK) == 0) - return temp; -#endif - } - - if (debug && pprefix->plist == NULL) - fprintf (stderr, " - failed: no entries in prefix list\n"); - - free (temp); - return 0; -} - -/* Add an entry for PREFIX to prefix list PPREFIX. */ - -static void -add_prefix (struct path_prefix *pprefix, const char *prefix) -{ - struct prefix_list *pl, **prev; - int len; - - if (pprefix->plist) - { - for (pl = pprefix->plist; pl->next; pl = pl->next) - ; - prev = &pl->next; - } - else - prev = &pprefix->plist; - - /* Keep track of the longest prefix. */ - - len = strlen (prefix); - if (len > pprefix->max_len) - pprefix->max_len = len; - - pl = XNEW (struct prefix_list); - pl->prefix = xstrdup (prefix); - - if (*prev) - pl->next = *prev; - else - pl->next = (struct prefix_list *) 0; - *prev = pl; -} - -/* Take the value of the environment variable ENV, break it into a path, and - add of the entries to PPREFIX. */ - -static void -prefix_from_env (const char *env, struct path_prefix *pprefix) -{ - const char *p; - p = getenv (env); - - if (p) - prefix_from_string (p, pprefix); -} - -static void -prefix_from_string (const char *p, struct path_prefix *pprefix) -{ - const char *startp, *endp; - char *nstore = XNEWVEC (char, strlen (p) + 3); - - if (debug) - fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); - - startp = endp = p; - while (1) - { - if (*endp == PATH_SEPARATOR || *endp == 0) - { - strncpy (nstore, startp, endp-startp); - if (endp == startp) - { - strcpy (nstore, "./"); - } - else if (! IS_DIR_SEPARATOR (endp[-1])) - { - nstore[endp-startp] = DIR_SEPARATOR; - nstore[endp-startp+1] = 0; - } - else - nstore[endp-startp] = 0; - - if (debug) - fprintf (stderr, " - add prefix: %s\n", nstore); - - add_prefix (pprefix, nstore); - if (*endp == 0) - break; - endp = startp = endp + 1; - } - else - endp++; - } - free (nstore); -} - #ifdef OBJECT_FORMAT_NONE /* Add an entry for the object file NAME to object file list LIST. @@ -894,7 +641,7 @@ files contain LTO info. The linker command line LTO_LD_ARGV represents the linker command that would produce a final executable without the use of LTO. OBJECT_LST is a vector of object file names - appearing in LTO_LD_ARGV that are to be considerd for link-time + appearing in LTO_LD_ARGV that are to be considered for link-time recompilation, where OBJECT is a pointer to the last valid element. (This awkward convention avoids an impedance mismatch with the usage of similarly-named variables in main().) The elements of @@ -952,7 +699,7 @@ size_t num_files; if (!lto_wrapper) - fatal ("COLLECT_LTO_WRAPPER must be set"); + fatal_error (input_location, "COLLECT_LTO_WRAPPER must be set"); num_lto_c_args++; @@ -975,7 +722,8 @@ *lto_c_ptr = NULL; /* Run the LTO back end. */ - pex = collect_execute (prog, lto_c_argv, NULL, NULL, PEX_SEARCH); + pex = collect_execute (prog, lto_c_argv, NULL, NULL, PEX_SEARCH, + at_file_supplied); { int c; FILE *stream; @@ -1013,11 +761,11 @@ do_wait (prog, pex); pex = NULL; - /* Compute memory needed for new LD arguments. At most number of original arguemtns + /* Compute memory needed for new LD arguments. At most number of original arguments plus number of partitions. */ for (lto_ld_argv_size = 0; lto_ld_argv[lto_ld_argv_size]; lto_ld_argv_size++) ; - out_lto_ld_argv = XCNEWVEC(char *, num_files + lto_ld_argv_size + 1); + out_lto_ld_argv = XCNEWVEC (char *, num_files + lto_ld_argv_size + 1); out_lto_ld_argv_size = 0; /* After running the LTO back end, we will relink, substituting @@ -1055,7 +803,7 @@ /* Run the linker again, this time replacing the object files optimized by the LTO with the temporary file generated by the LTO. */ - fork_execute ("ld", out_lto_ld_argv); + fork_execute ("ld", out_lto_ld_argv, HAVE_GNU_LD && at_file_supplied); post_ld_pass (true); free (lto_ld_argv); @@ -1065,9 +813,11 @@ { /* Our caller is relying on us to do the link even though there is no LTO back end work to be done. */ - fork_execute ("ld", lto_ld_argv); + fork_execute ("ld", lto_ld_argv, HAVE_GNU_LD && at_file_supplied); post_ld_pass (false); } + else + post_ld_pass (true); } /* Main program. */ @@ -1075,8 +825,21 @@ int main (int argc, char **argv) { - static const char *const ld_suffix = "ld"; - static const char *const plugin_ld_suffix = PLUGIN_LD; + enum linker_select + { + USE_DEFAULT_LD, + USE_PLUGIN_LD, + USE_GOLD_LD, + USE_BFD_LD, + USE_LD_MAX + } selected_linker = USE_DEFAULT_LD; + static const char *const ld_suffixes[USE_LD_MAX] = + { + "ld", + PLUGIN_LD_SUFFIX, + "ld.gold", + "ld.bfd" + }; static const char *const real_ld_suffix = "real-ld"; static const char *const collect_ld_suffix = "collect-ld"; static const char *const nm_suffix = "nm"; @@ -1087,16 +850,13 @@ static const char *const strip_suffix = "strip"; static const char *const gstrip_suffix = "gstrip"; + const char *full_ld_suffixes[USE_LD_MAX]; #ifdef CROSS_DIRECTORY_STRUCTURE /* If we look for a program in the compiler directories, we just use the short name, since these directories are already system-specific. But it we look for a program in the system directories, we need to qualify the program name with the target machine. */ - const char *const full_ld_suffix = - concat(target_machine, "-", ld_suffix, NULL); - const char *const full_plugin_ld_suffix = - concat(target_machine, "-", plugin_ld_suffix, NULL); const char *const full_nm_suffix = concat (target_machine, "-", nm_suffix, NULL); const char *const full_gnm_suffix = @@ -1110,13 +870,11 @@ const char *const full_gstrip_suffix = concat (target_machine, "-", gstrip_suffix, NULL); #else - const char *const full_ld_suffix = ld_suffix; - const char *const full_plugin_ld_suffix = plugin_ld_suffix; - const char *const full_nm_suffix = nm_suffix; - const char *const full_gnm_suffix = gnm_suffix; #ifdef LDD_SUFFIX const char *const full_ldd_suffix = ldd_suffix; #endif + const char *const full_nm_suffix = nm_suffix; + const char *const full_gnm_suffix = gnm_suffix; const char *const full_strip_suffix = strip_suffix; const char *const full_gstrip_suffix = gstrip_suffix; #endif /* CROSS_DIRECTORY_STRUCTURE */ @@ -1133,6 +891,7 @@ char **ld1_argv; const char **ld1; bool use_plugin = false; + bool use_collect_ld = false; /* The kinds of symbols we will have to consider when scanning the outcome of a first pass link. This is ALL to start with, then might @@ -1146,9 +905,28 @@ const char **ld2; char **object_lst; const char **object; +#ifdef TARGET_AIX_VERSION + int object_nbr = argc; +#endif int first_file; int num_c_args; char **old_argv; + int i; + + for (i = 0; i < USE_LD_MAX; i++) + full_ld_suffixes[i] +#ifdef CROSS_DIRECTORY_STRUCTURE + = concat (target_machine, "-", ld_suffixes[i], NULL); +#else + = ld_suffixes[i]; +#endif + + p = argv[0] + strlen (argv[0]); + while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) + --p; + progname = p; + + xmalloc_set_program_name (progname); old_argv = argv; expandargv (&argc, &argv); @@ -1159,10 +937,12 @@ num_c_args = argc + 9; +#ifndef HAVE_LD_DEMANGLE no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); /* Suppress demangling by the real linker, which may be broken. */ - putenv (xstrdup ("COLLECT_NO_DEMANGLE=")); + putenv (xstrdup ("COLLECT_NO_DEMANGLE=1")); +#endif #if defined (COLLECT2_HOST_INITIALIZATION) /* Perform system dependent initialization, if necessary. */ @@ -1180,6 +960,11 @@ gcc_init_libintl (); + diagnostic_initialize (global_dc, 0); + + if (atexit (collect_atexit) != 0) + fatal_error (input_location, "atexit failed"); + /* Do not invoke xcalloc before this point, since locale needs to be set first, in case a diagnostic is issued. */ @@ -1199,7 +984,6 @@ are called. We also look for the -flto or -flto-partition=none flag to know what LTO mode we are in. */ { - int i; bool no_partition = false; for (i = 1; argv[i] != NULL; i ++) @@ -1208,34 +992,42 @@ debug = true; else if (! strcmp (argv[i], "-flto-partition=none")) no_partition = true; - else if ((! strncmp (argv[i], "-flto=", 6) - || ! strcmp (argv[i], "-flto")) && ! use_plugin) - lto_mode = LTO_MODE_WHOPR; else if (!strncmp (argv[i], "-fno-lto", 8)) lto_mode = LTO_MODE_NONE; else if (! strcmp (argv[i], "-plugin")) { use_plugin = true; - lto_mode = LTO_MODE_NONE; + if (selected_linker == USE_DEFAULT_LD) + selected_linker = USE_PLUGIN_LD; } + else if (strcmp (argv[i], "-fuse-ld=bfd") == 0) + selected_linker = USE_BFD_LD; + else if (strcmp (argv[i], "-fuse-ld=gold") == 0) + selected_linker = USE_GOLD_LD; + #ifdef COLLECT_EXPORT_LIST - /* since -brtl, -bexport, -b64 are not position dependent - also check for them here */ - if ((argv[i][0] == '-') && (argv[i][1] == 'b')) - { - arg = argv[i]; - /* We want to disable automatic exports on AIX when user - explicitly puts an export list in command line */ - if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) - export_flag = 1; - else if (arg[2] == '6' && arg[3] == '4') - aix64_flag = 1; - else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l') - aixrtl_flag = 1; - } + /* These flags are position independent, although their order + is important - subsequent flags override earlier ones. */ + else if (strcmp (argv[i], "-b64") == 0) + aix64_flag = 1; + /* -bexport:filename always needs the :filename */ + else if (strncmp (argv[i], "-bE:", 4) == 0 + || strncmp (argv[i], "-bexport:", 9) == 0) + export_flag = 1; + else if (strcmp (argv[i], "-brtl") == 0 + || strcmp (argv[i], "-bsvr4") == 0 + || strcmp (argv[i], "-G") == 0) + aixrtl_flag = 1; + else if (strcmp (argv[i], "-bnortl") == 0) + aixrtl_flag = 0; + else if (strcmp (argv[i], "-blazy") == 0) + aixlazy_flag = 1; #endif } - vflag = debug; + verbose = debug; + find_file_set_debug (debug); + if (use_plugin) + lto_mode = LTO_MODE_NONE; if (no_partition && lto_mode == LTO_MODE_WHOPR) lto_mode = LTO_MODE_LTO; } @@ -1269,7 +1061,7 @@ c_ptr = CONST_CAST2 (const char **, char **, c_argv); if (argc < 2) - fatal ("no arguments"); + fatal_error (input_location, "no arguments"); #ifdef SIGQUIT if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) @@ -1301,63 +1093,88 @@ /* Maybe we know the right file to use (if not cross). */ ld_file_name = 0; #ifdef DEFAULT_LINKER - if (access (DEFAULT_LINKER, X_OK) == 0) + if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD) + { + char *linker_name; +# ifdef HOST_EXECUTABLE_SUFFIX + int len = (sizeof (DEFAULT_LINKER) + - sizeof (HOST_EXECUTABLE_SUFFIX)); + linker_name = NULL; + if (len > 0) + { + char *default_linker = xstrdup (DEFAULT_LINKER); + /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains + HOST_EXECUTABLE_SUFFIX. */ + if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX)) + { + default_linker[len] = '\0'; + linker_name = concat (default_linker, + &ld_suffixes[selected_linker][2], + HOST_EXECUTABLE_SUFFIX, NULL); + } + } + if (linker_name == NULL) +# endif + linker_name = concat (DEFAULT_LINKER, + &ld_suffixes[selected_linker][2], + NULL); + if (access (linker_name, X_OK) == 0) + ld_file_name = linker_name; + } + if (ld_file_name == 0 && access (DEFAULT_LINKER, X_OK) == 0) ld_file_name = DEFAULT_LINKER; if (ld_file_name == 0) #endif #ifdef REAL_LD_FILE_NAME - ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME); + ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME, X_OK); if (ld_file_name == 0) #endif /* Search the (target-specific) compiler dirs for ld'. */ - ld_file_name = find_a_file (&cpath, real_ld_suffix); + ld_file_name = find_a_file (&cpath, real_ld_suffix, X_OK); /* Likewise for `collect-ld'. */ if (ld_file_name == 0) - ld_file_name = find_a_file (&cpath, collect_ld_suffix); + { + ld_file_name = find_a_file (&cpath, collect_ld_suffix, X_OK); + use_collect_ld = ld_file_name != 0; + } /* Search the compiler directories for `ld'. We have protection against recursive calls in find_a_file. */ if (ld_file_name == 0) - ld_file_name = find_a_file (&cpath, - use_plugin - ? plugin_ld_suffix - : ld_suffix); + ld_file_name = find_a_file (&cpath, ld_suffixes[selected_linker], X_OK); /* Search the ordinary system bin directories for `ld' (if native linking) or `TARGET-ld' (if cross). */ if (ld_file_name == 0) - ld_file_name = find_a_file (&path, - use_plugin - ? full_plugin_ld_suffix - : full_ld_suffix); + ld_file_name = find_a_file (&path, full_ld_suffixes[selected_linker], X_OK); #ifdef REAL_NM_FILE_NAME - nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); + nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME, X_OK); if (nm_file_name == 0) #endif - nm_file_name = find_a_file (&cpath, gnm_suffix); + nm_file_name = find_a_file (&cpath, gnm_suffix, X_OK); if (nm_file_name == 0) - nm_file_name = find_a_file (&path, full_gnm_suffix); + nm_file_name = find_a_file (&path, full_gnm_suffix, X_OK); if (nm_file_name == 0) - nm_file_name = find_a_file (&cpath, nm_suffix); + nm_file_name = find_a_file (&cpath, nm_suffix, X_OK); if (nm_file_name == 0) - nm_file_name = find_a_file (&path, full_nm_suffix); + nm_file_name = find_a_file (&path, full_nm_suffix, X_OK); #ifdef LDD_SUFFIX - ldd_file_name = find_a_file (&cpath, ldd_suffix); + ldd_file_name = find_a_file (&cpath, ldd_suffix, X_OK); if (ldd_file_name == 0) - ldd_file_name = find_a_file (&path, full_ldd_suffix); + ldd_file_name = find_a_file (&path, full_ldd_suffix, X_OK); #endif #ifdef REAL_STRIP_FILE_NAME - strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME); + strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME, X_OK); if (strip_file_name == 0) #endif - strip_file_name = find_a_file (&cpath, gstrip_suffix); + strip_file_name = find_a_file (&cpath, gstrip_suffix, X_OK); if (strip_file_name == 0) - strip_file_name = find_a_file (&path, full_gstrip_suffix); + strip_file_name = find_a_file (&path, full_gstrip_suffix, X_OK); if (strip_file_name == 0) - strip_file_name = find_a_file (&cpath, strip_suffix); + strip_file_name = find_a_file (&cpath, strip_suffix, X_OK); if (strip_file_name == 0) - strip_file_name = find_a_file (&path, full_strip_suffix); + strip_file_name = find_a_file (&path, full_strip_suffix, X_OK); /* Determine the full path name of the C compiler to use. */ c_file_name = getenv ("COLLECT_GCC"); @@ -1370,12 +1187,12 @@ #endif } - p = find_a_file (&cpath, c_file_name); + p = find_a_file (&cpath, c_file_name, X_OK); /* Here it should be safe to use the system search path since we should have already qualified the name of the compiler when it is needed. */ if (p == 0) - p = find_a_file (&path, c_file_name); + p = find_a_file (&path, c_file_name, X_OK); if (p) c_file_name = p; @@ -1388,8 +1205,11 @@ #ifdef COLLECT_EXPORT_LIST export_file = make_temp_file (".x"); #endif - ldout = make_temp_file (".ld"); - lderrout = make_temp_file (".le"); + if (!debug) + { + ldout = make_temp_file (".ld"); + lderrout = make_temp_file (".le"); + } *c_ptr++ = c_file_name; *c_ptr++ = "-x"; *c_ptr++ = "c"; @@ -1450,12 +1270,6 @@ /* After the first file, put in the c++ rt0. */ first_file = 1; -#ifdef HAVE_LD_DEMANGLE - if (!demangle_flag && !no_demangle) - demangle_flag = "--demangle"; - if (demangle_flag) - *ld1++ = *ld2++ = demangle_flag; -#endif while ((arg = *++argv) != (char *) 0) { *ld1++ = *ld2++ = arg; @@ -1490,6 +1304,74 @@ "configuration"); #endif } + else if (!use_collect_ld + && strncmp (arg, "-fuse-ld=", 9) == 0) + { + /* Do not pass -fuse-ld={bfd|gold} to the linker. */ + ld1--; + ld2--; + } + else if (strncmp (arg, "-fno-lto", 8) == 0) + { + /* Do not pass -fno-lto to the linker. */ + ld1--; + ld2--; + } +#ifdef TARGET_AIX_VERSION + else + { + /* File containing a list of input files to process. */ + + FILE *stream; + char buf[MAXPATHLEN + 2]; + /* Number of additionnal object files. */ + int add_nbr = 0; + /* Maximum of additionnal object files before vector + expansion. */ + int add_max = 0; + const char *list_filename = arg + 2; + + /* Accept -fFILENAME and -f FILENAME. */ + if (*list_filename == '\0' && argv[1]) + { + ++argv; + list_filename = *argv; + *ld1++ = *ld2++ = *argv; + } + + stream = fopen (list_filename, "r"); + if (stream == NULL) + fatal_error (input_location, "can't open %s: %m", + list_filename); + + while (fgets (buf, sizeof buf, stream) != NULL) + { + /* Remove end of line. */ + int len = strlen (buf); + if (len >= 1 && buf[len - 1] =='\n') + buf[len - 1] = '\0'; + + /* Put on object vector. + Note: we only expanse vector here, so we must keep + extra space for remaining arguments. */ + if (add_nbr >= add_max) + { + int pos = + object - CONST_CAST2 (const char **, char **, + object_lst); + add_max = (add_max == 0) ? 16 : add_max * 2; + object_lst = XRESIZEVEC (char *, object_lst, + object_nbr + add_max); + object = CONST_CAST2 (const char **, char **, + object_lst) + pos; + object_nbr += add_max; + } + *object++ = xstrdup (buf); + add_nbr++; + } + fclose (stream); + } +#endif break; case 'l': @@ -1517,15 +1399,6 @@ case 'L': add_prefix (&cmdline_lib_dirs, arg+2); break; -#else -#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES - case 'L': - if (is_in_args (arg, - CONST_CAST2 (const char **, char **, ld1_argv), - ld1 - 1)) - --ld1; - break; -#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ #endif case 'o': @@ -1553,22 +1426,22 @@ case 'v': if (arg[2] == '\0') - vflag = true; + verbose = true; break; case '-': if (strcmp (arg, "--no-demangle") == 0) { - demangle_flag = arg; +#ifndef HAVE_LD_DEMANGLE no_demangle = 1; ld1--; ld2--; +#endif } else if (strncmp (arg, "--demangle", 10) == 0) { - demangle_flag = arg; +#ifndef HAVE_LD_DEMANGLE no_demangle = 0; -#ifndef HAVE_LD_DEMANGLE if (arg[10] == '=') { enum demangling_styles style @@ -1578,14 +1451,14 @@ else current_demangling_style = style; } -#endif ld1--; ld2--; +#endif } else if (strncmp (arg, "--sysroot=", 10) == 0) target_system_root = arg + 10; else if (strcmp (arg, "--version") == 0) - vflag = true; + verbose = true; else if (strcmp (arg, "--help") == 0) helpflag = true; break; @@ -1670,24 +1543,18 @@ exportf = fopen (export_file, "w"); if (exportf == (FILE *) 0) - fatal_perror ("fopen %s", export_file); + fatal_error (input_location, "fopen %s: %m", export_file); write_aix_file (exportf, exports.first); if (fclose (exportf)) - fatal_perror ("fclose %s", export_file); + fatal_error (input_location, "fclose %s: %m", export_file); } #endif *c_ptr++ = c_file; *c_ptr = *ld1 = *object = (char *) 0; - if (vflag) - { - notice ("collect2 version %s", version_string); -#ifdef TARGET_VERSION - TARGET_VERSION; -#endif - fprintf (stderr, "\n"); - } + if (verbose) + notice ("collect2 version %s\n", version_string); if (helpflag) { @@ -1802,9 +1669,9 @@ "%d destructors found\n", destructors.number), destructors.number); - notice_translated (ngettext("%d frame table found\n", - "%d frame tables found\n", - frame_tables.number), + notice_translated (ngettext ("%d frame table found\n", + "%d frame tables found\n", + frame_tables.number), frame_tables.number); } @@ -1839,7 +1706,7 @@ strip_argv[0] = strip_file_name; strip_argv[1] = output_file; strip_argv[2] = (char *) 0; - fork_execute ("strip", real_strip_argv); + fork_execute ("strip", real_strip_argv, false); } #ifdef COLLECT_EXPORT_LIST @@ -1856,15 +1723,15 @@ sort_ids (&constructors); sort_ids (&destructors); - maybe_unlink(output_file); + maybe_unlink (output_file); outf = fopen (c_file, "w"); if (outf == (FILE *) 0) - fatal_perror ("fopen %s", c_file); + fatal_error (input_location, "fopen %s: %m", c_file); write_c_file (outf, c_file); if (fclose (outf)) - fatal_perror ("fclose %s", c_file); + fatal_error (input_location, "fclose %s: %m", c_file); /* Tell the linker that we have initializer and finalizer functions. */ #ifdef LD_INIT_SWITCH @@ -1886,6 +1753,11 @@ if (! exports.first) *ld2++ = concat ("-bE:", export_file, NULL); +#ifdef TARGET_AIX_VERSION + add_to_list (&exports, aix_shared_initname); + add_to_list (&exports, aix_shared_fininame); +#endif + #ifndef LD_INIT_SWITCH add_to_list (&exports, initname); add_to_list (&exports, fininame); @@ -1894,10 +1766,10 @@ #endif exportf = fopen (export_file, "w"); if (exportf == (FILE *) 0) - fatal_perror ("fopen %s", export_file); + fatal_error (input_location, "fopen %s: %m", export_file); write_aix_file (exportf, exports.first); if (fclose (exportf)) - fatal_perror ("fclose %s", export_file); + fatal_error (input_location, "fclose %s: %m", export_file); } #endif @@ -1920,7 +1792,7 @@ /* Assemble the constructor and destructor tables. Link the tables in with the rest of the program. */ - fork_execute ("gcc", c_argv); + fork_execute ("gcc", c_argv, at_file_supplied); #ifdef COLLECT_EXPORT_LIST /* On AIX we must call tlink because of possible templates resolution. */ do_tlink (ld2_argv, object_lst); @@ -1933,7 +1805,7 @@ maybe_run_lto_and_relink (ld2_argv, object_lst, object, true); else { - fork_execute ("ld", ld2_argv); + fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied); post_ld_pass (false); } @@ -1953,169 +1825,22 @@ } -/* Wait for a process to finish, and exit if a nonzero status is found. */ - -int -collect_wait (const char *prog, struct pex_obj *pex) -{ - int status; - - if (!pex_get_status (pex, 1, &status)) - fatal_perror ("can't get program status"); - pex_free (pex); - - if (status) - { - if (WIFSIGNALED (status)) - { - int sig = WTERMSIG (status); - error ("%s terminated with signal %d [%s]%s", - prog, sig, strsignal(sig), - WCOREDUMP(status) ? ", core dumped" : ""); - collect_exit (FATAL_EXIT_CODE); - } - - if (WIFEXITED (status)) - return WEXITSTATUS (status); - } - return 0; -} - -static void -do_wait (const char *prog, struct pex_obj *pex) -{ - int ret = collect_wait (prog, pex); - if (ret != 0) - { - error ("%s returned %d exit status", prog, ret); - collect_exit (ret); - } - - if (response_file) - { - unlink (response_file); - response_file = NULL; - } -} - - -/* Execute a program, and wait for the reply. */ - -struct pex_obj * -collect_execute (const char *prog, char **argv, const char *outname, - const char *errname, int flags) -{ - struct pex_obj *pex; - const char *errmsg; - int err; - char *response_arg = NULL; - char *response_argv[3] ATTRIBUTE_UNUSED; - - if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL) - { - /* If using @file arguments, create a temporary file and put the - contents of argv into it. Then change argv to an array corresponding - to a single argument @FILE, where FILE is the temporary filename. */ - - char **current_argv = argv + 1; - char *argv0 = argv[0]; - int status; - FILE *f; - - /* Note: we assume argv contains at least one element; this is - checked above. */ - - response_file = make_temp_file (""); - - f = fopen (response_file, "w"); - - if (f == NULL) - fatal ("could not open response file %s", response_file); - - status = writeargv (current_argv, f); - - if (status) - fatal ("could not write to response file %s", response_file); - - status = fclose (f); - - if (EOF == status) - fatal ("could not close response file %s", response_file); - - response_arg = concat ("@", response_file, NULL); - response_argv[0] = argv0; - response_argv[1] = response_arg; - response_argv[2] = NULL; - - argv = response_argv; - } - - if (vflag || debug) - { - char **p_argv; - const char *str; - - if (argv[0]) - fprintf (stderr, "%s", argv[0]); - else - notice ("[cannot find %s]", prog); - - for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) - fprintf (stderr, " %s", str); - - fprintf (stderr, "\n"); - } - - fflush (stdout); - fflush (stderr); - - /* If we cannot find a program we need, complain error. Do this here - since we might not end up needing something that we could not find. */ - - if (argv[0] == 0) - fatal ("cannot find '%s'", prog); - - pex = pex_init (0, "collect2", NULL); - if (pex == NULL) - fatal_perror ("pex_init failed"); - - errmsg = pex_run (pex, flags, argv[0], argv, outname, - errname, &err); - if (errmsg != NULL) - { - if (err != 0) - { - errno = err; - fatal_perror (errmsg); - } - else - fatal (errmsg); - } - - if (response_arg) - free (response_arg); - - return pex; -} - -static void -fork_execute (const char *prog, char **argv) -{ - struct pex_obj *pex; - - pex = collect_execute (prog, argv, NULL, NULL, PEX_LAST | PEX_SEARCH); - do_wait (prog, pex); -} - -/* Unlink a file unless we are debugging. */ - -static void +/* Unlink FILE unless we are debugging or this is the output_file + and we may not unlink it. */ + +void maybe_unlink (const char *file) { - if (!debug) - unlink_if_ordinary (file); - else - notice ("[Leaving %s]\n", file); + if (debug) + { + notice ("[Leaving %s]\n", file); + return; + } + + if (file == output_file && !may_unlink_output_file) + return; + + unlink_if_ordinary (file); } /* Call maybe_unlink on the NULL-terminated list, FILE_LIST. */ @@ -2172,6 +1897,19 @@ { int pos = 0, pri; +#ifdef TARGET_AIX_VERSION + /* Run dependent module initializers before any constructors in this + module. */ + switch (is_ctor_dtor (name)) + { + case SYM_AIXI: + case SYM_AIXD: + return INT_MIN; + default: + break; + } +#endif + while (name[pos] == '_') ++pos; pos += 10; /* strlen ("GLOBAL__X_") */ @@ -2235,22 +1973,6 @@ } } -#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES -/* Given a STRING, return nonzero if it occurs in the list in range - [ARGS_BEGIN,ARGS_END). */ - -static int -is_in_args (const char *string, const char **args_begin, - const char **args_end) -{ - const char **args_pointer; - for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer) - if (strcmp (string, *args_pointer) == 0) - return 1; - return 0; -} -#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ - #ifdef COLLECT_EXPORT_LIST /* This function is really used only on AIX, but may be useful. */ #if 0 @@ -2314,12 +2036,8 @@ int frames = (frame_tables.number > 0); /* Figure out name of output_file, stripping off .so version. */ - p = strrchr (output_file, '/'); - if (p == 0) - p = output_file; - else - p++; - q = p; + q = p = lbasename (output_file); + while (q) { q = strchr (q,'.'); @@ -2330,7 +2048,7 @@ } else { - if (strncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0) + if (filename_ncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0) { q += strlen (SHLIB_SUFFIX); break; @@ -2352,11 +2070,22 @@ initname = concat ("_GLOBAL__FI_", prefix, NULL); fininame = concat ("_GLOBAL__FD_", prefix, NULL); +#ifdef TARGET_AIX_VERSION + aix_shared_initname = concat ("_GLOBAL__AIXI_", prefix, NULL); + aix_shared_fininame = concat ("_GLOBAL__AIXD_", prefix, NULL); +#endif free (prefix); /* Write the tables as C code. */ + /* This count variable is used to prevent multiple calls to the + constructors/destructors. + This guard against multiple calls is important on AIX as the initfini + functions are deliberately invoked multiple times as part of the + mechanisms GCC uses to order constructors across different dependent + shared libraries (see config/rs6000/aix.h). + */ fprintf (stream, "static int count;\n"); fprintf (stream, "typedef void entry_pt();\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); @@ -2379,12 +2108,23 @@ fprintf (stream, " struct object *next;\n"); fprintf (stream, "};\n"); + fprintf (stream, "extern void __register_frame_info_table_bases (void *, struct object *, void *tbase, void *dbase);\n"); fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); +#ifdef TARGET_AIX_VERSION + fprintf (stream, "extern void *__gcc_unwind_dbase;\n"); +#endif fprintf (stream, "static void reg_frame () {\n"); fprintf (stream, "\tstatic struct object ob;\n"); +#ifdef TARGET_AIX_VERSION + /* Use __gcc_unwind_dbase as the base address for data on AIX. + This might not be the start of the segment, signed offsets assumed. + */ + fprintf (stream, "\t__register_frame_info_table_bases (frame_table, &ob, (void *)0, &__gcc_unwind_dbase);\n"); +#else fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); +#endif fprintf (stream, "\t}\n"); fprintf (stream, "static void dereg_frame () {\n"); @@ -2427,8 +2167,8 @@ if (shared_obj) { - COLLECT_SHARED_INIT_FUNC(stream, initname); - COLLECT_SHARED_FINI_FUNC(stream, fininame); + COLLECT_SHARED_INIT_FUNC (stream, initname); + COLLECT_SHARED_FINI_FUNC (stream, fininame); } } @@ -2586,13 +2326,13 @@ /* LTO objects must be in a known format. This check prevents us from accepting an archive containing LTO objects, which - gcc cannnot currently handle. */ + gcc cannot currently handle. */ if (which_pass == PASS_LTOINFO && !maybe_lto_object_file (prog_name)) return; /* If we do not have an `nm', complain. */ if (nm_file_name == 0) - fatal ("cannot find 'nm'"); + fatal_error (input_location, "cannot find 'nm'"); nm_argv[argc++] = nm_file_name; if (NM_FLAGS[0] != '\0') @@ -2602,7 +2342,7 @@ nm_argv[argc++] = (char *) 0; /* Trace if needed. */ - if (vflag) + if (verbose) { const char **p_argv; const char *str; @@ -2618,7 +2358,7 @@ pex = pex_init (PEX_USE_PIPES, "collect2", NULL); if (pex == NULL) - fatal_perror ("pex_init failed"); + fatal_error (input_location, "pex_init failed: %m"); errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET, &err); @@ -2627,10 +2367,10 @@ if (err != 0) { errno = err; - fatal_perror (errmsg); + fatal_error (input_location, "%s: %m", _(errmsg)); } else - fatal (errmsg); + fatal_error (input_location, errmsg); } int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); @@ -2640,7 +2380,7 @@ inf = pex_read_output (pex, 0); if (inf == NULL) - fatal_perror ("can't open nm output"); + fatal_error (input_location, "can't open nm output: %m"); if (debug) { @@ -2703,6 +2443,7 @@ *end = '\0'; + switch (is_ctor_dtor (name)) { case SYM_CTOR: @@ -2723,7 +2464,8 @@ if (! (filter & SCAN_INIT)) break; if (which_pass != PASS_LIB) - fatal ("init function found in object %s", prog_name); + fatal_error (input_location, "init function found in object %s", + prog_name); #ifndef LD_INIT_SWITCH add_to_list (&constructors, name); #endif @@ -2733,7 +2475,8 @@ if (! (filter & SCAN_FINI)) break; if (which_pass != PASS_LIB) - fatal ("fini function found in object %s", prog_name); + fatal_error (input_location, "fini function found in object %s", + prog_name); #ifndef LD_FINI_SWITCH add_to_list (&destructors, name); #endif @@ -2798,7 +2541,7 @@ ldd_argv[argc++] = (char *) 0; /* Trace if needed. */ - if (vflag) + if (verbose) { const char **p_argv; const char *str; @@ -2814,7 +2557,7 @@ pex = pex_init (PEX_USE_PIPES, "collect2", NULL); if (pex == NULL) - fatal_perror ("pex_init failed"); + fatal_error (input_location, "pex_init failed: %m"); errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err); if (errmsg != NULL) @@ -2822,10 +2565,10 @@ if (err != 0) { errno = err; - fatal_perror (errmsg); + fatal_error (input_location, "%s: %m", _(errmsg)); } else - fatal (errmsg); + fatal_error (input_location, errmsg); } int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); @@ -2835,7 +2578,7 @@ inf = pex_read_output (pex, 0); if (inf == NULL) - fatal_perror ("can't open ldd output"); + fatal_error (input_location, "can't open ldd output: %m"); if (debug) notice ("\nldd output with constructors/destructors.\n"); @@ -2853,7 +2596,7 @@ name = p; if (strncmp (name, "not found", sizeof ("not found") - 1) == 0) - fatal ("dynamic dependency %s not found", buf); + fatal_error (input_location, "dynamic dependency %s not found", buf); /* Find the end of the symbol name. */ for (end = p; @@ -2865,7 +2608,8 @@ if (access (name, R_OK) == 0) add_to_list (&libraries, name); else - fatal ("unable to open dynamic dependency '%s'", buf); + fatal_error (input_location, "unable to open dynamic dependency '%s'", + buf); if (debug) fprintf (stderr, "\t%s\n", buf); @@ -2899,16 +2643,16 @@ #if defined (EXTENDED_COFF) -# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax) +# define GCC_SYMBOLS(X) (SYMHEADER (X).isymMax + SYMHEADER (X).iextMax) # define GCC_SYMENT SYMR # define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal) # define GCC_SYMINC(X) (1) -# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax) -# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0) +# define GCC_SYMZERO(X) (SYMHEADER (X).isymMax) +# define GCC_CHECK_HDR(X) (PSYMTAB (X) != 0) #else -# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms) +# define GCC_SYMBOLS(X) (HEADER (ldptr).f_nsyms) # define GCC_SYMENT SYMENT # if defined (C_WEAKEXT) # define GCC_OK_SYMBOL(X) \ @@ -2936,12 +2680,14 @@ /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */ #if TARGET_AIX_VERSION >= 51 # define GCC_CHECK_HDR(X) \ - ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ - || (HEADER (X).f_magic == 0767 && aix64_flag)) + (((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ + || (HEADER (X).f_magic == 0767 && aix64_flag)) \ + && !(HEADER (X).f_flags & F_LOADONLY)) #else # define GCC_CHECK_HDR(X) \ - ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ - || (HEADER (X).f_magic == 0757 && aix64_flag)) + (((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ + || (HEADER (X).f_magic == 0757 && aix64_flag)) \ + && !(HEADER (X).f_flags & F_LOADONLY)) #endif #endif @@ -3026,7 +2772,7 @@ if ((ldptr = ldopen (CONST_CAST (char *, prog_name), ldptr)) != NULL) { if (! MY_ISCOFF (HEADER (ldptr).f_magic)) - fatal ("%s: not a COFF file", prog_name); + fatal_error (input_location, "%s: not a COFF file", prog_name); if (GCC_CHECK_HDR (ldptr)) { @@ -3062,6 +2808,25 @@ switch (is_ctor_dtor (name)) { +#if TARGET_AIX_VERSION + /* Add AIX shared library initalisers/finalisers + to the constructors/destructors list of the + current module. */ + case SYM_AIXI: + if (! (filter & SCAN_CTOR)) + break; + if (is_shared && !aixlazy_flag) + add_to_list (&constructors, name); + break; + + case SYM_AIXD: + if (! (filter & SCAN_DTOR)) + break; + if (is_shared && !aixlazy_flag) + add_to_list (&destructors, name); + break; +#endif + case SYM_CTOR: if (! (filter & SCAN_CTOR)) break; @@ -3124,7 +2889,16 @@ provides an explicit export list. */ if (shared_obj && !is_shared && which_pass == PASS_OBJ && !export_flag) - add_to_list (&exports, name); + { + /* Do not auto-export __dso_handle or + __gcc_unwind_dbase. They are required + to be local to each module. */ + if (strcmp(name, "__dso_handle") != 0 + && strcmp(name, "__gcc_unwind_dbase") != 0) + { + add_to_list (&exports, name); + } + } #endif continue; } @@ -3156,7 +2930,8 @@ } else { - fatal ("%s: cannot open as COFF file", prog_name); + fatal_error (input_location, "%s: cannot open as COFF file", + prog_name); } #ifdef COLLECT_EXPORT_LIST /* On AIX loop continues while there are more members in archive. */ @@ -3164,7 +2939,7 @@ while (ldclose (ldptr) == FAILURE); #else /* Otherwise we simply close ldptr. */ - (void) ldclose(ldptr); + (void) ldclose (ldptr); #endif } #endif /* OBJECT_FORMAT_COFF */ @@ -3184,7 +2959,7 @@ if (libpaths[i]->max_len > l) l = libpaths[i]->max_len; - lib_buf = XNEWVEC (char, l + strlen(name) + 10); + lib_buf = XNEWVEC (char, l + strlen (name) + 10); for (i = 0; libpaths[i]; i++) { @@ -3192,10 +2967,10 @@ for (; list; list = list->next) { /* The following lines are needed because path_prefix list - may contain directories both with trailing '/' and + may contain directories both with trailing DIR_SEPARATOR and without it. */ const char *p = ""; - if (list->prefix[strlen(list->prefix)-1] != '/') + if (!IS_DIR_SEPARATOR (list->prefix[strlen (list->prefix)-1])) p = "/"; for (j = 0; j < 2; j++) { @@ -3214,7 +2989,7 @@ if (debug) fprintf (stderr, "not found\n"); else - fatal ("library lib%s not found", name); + fatal_error (input_location, "library lib%s not found", name); return (NULL); } #endif /* COLLECT_EXPORT_LIST */ @@ -3266,7 +3041,8 @@ argv[1] = output_file; argv[2] = (char *) 0; - pex = collect_execute (dsymutil, real_argv, NULL, NULL, PEX_LAST | PEX_SEARCH); + pex = collect_execute (dsymutil, real_argv, NULL, NULL, + PEX_LAST | PEX_SEARCH, false); do_wait (dsymutil, pex); }