Mercurial > hg > CbC > CbC_gcc
diff gcc/collect2.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/collect2.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/collect2.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,6 +1,6 @@ /* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. - Copyright (C) 1992-2018 Free Software Foundation, Inc. + Copyright (C) 1992-2020 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 +30,8 @@ #include "tm.h" #include "filenames.h" #include "file-find.h" +#include "simple-object.h" +#include "lto-section-names.h" /* TARGET_64BIT may be defined to use driver specific functionality. */ #undef TARGET_64BIT @@ -203,8 +205,8 @@ static int shared_obj; /* true if -shared */ static int static_obj; /* true if -static */ -static const char *c_file; /* <xxx>.c for constructor/destructor list. */ -static const char *o_file; /* <xxx>.o for constructor/destructor list. */ +static char *c_file; /* <xxx>.c for constructor/destructor list. */ +static char *o_file; /* <xxx>.o for constructor/destructor list. */ #ifdef COLLECT_EXPORT_LIST static const char *export_file; /* <xxx>.x for AIX export list. */ #endif @@ -614,7 +616,7 @@ Return 0 if not found, otherwise return its name, allocated with malloc. */ -#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_COFF) +#ifdef OBJECT_FORMAT_NONE /* Add an entry for the object file NAME to object file list LIST. New entries are added at the end of the list. The original pointer @@ -634,7 +636,7 @@ list->last = n; } -#endif +#endif /* OBJECT_FORMAT_NONE */ /* Perform a link-time recompilation and relink if any of the object @@ -699,7 +701,8 @@ size_t num_files; if (!lto_wrapper) - fatal_error (input_location, "COLLECT_LTO_WRAPPER must be set"); + fatal_error (input_location, "environment variable " + "%<COLLECT_LTO_WRAPPER%> must be set"); num_lto_c_args++; @@ -804,7 +807,9 @@ /* 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, HAVE_GNU_LD && at_file_supplied); - post_ld_pass (true); + /* We assume that temp files were created, and therefore we need to take + that into account (maybe run dsymutil). */ + post_ld_pass (/*temp_file*/true); free (lto_ld_argv); maybe_unlink_list (lto_o_files); @@ -814,10 +819,35 @@ /* 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, HAVE_GNU_LD && at_file_supplied); - post_ld_pass (false); + /* No LTO objects were found, so no new temp file. */ + post_ld_pass (/*temp_file*/false); } else - post_ld_pass (true); + post_ld_pass (false); /* No LTO objects were found, no temp file. */ +} +/* Entry point for linker invoation. Called from main in collect2.c. + LD_ARGV is an array of arguments for the linker. */ + +static void +do_link (char **ld_argv) +{ + struct pex_obj *pex; + const char *prog = "ld"; + pex = collect_execute (prog, ld_argv, NULL, NULL, + PEX_LAST | PEX_SEARCH, + HAVE_GNU_LD && at_file_supplied); + int ret = collect_wait (prog, pex); + if (ret) + { + error ("ld returned %d exit status", ret); + exit (ret); + } + else + { + /* We have just successfully produced an output file, so assume that we + may unlink it if need be for now on. */ + may_unlink_output_file = true; + } } /* Main program. */ @@ -831,6 +861,7 @@ USE_PLUGIN_LD, USE_GOLD_LD, USE_BFD_LD, + USE_LLD_LD, USE_LD_MAX } selected_linker = USE_DEFAULT_LD; static const char *const ld_suffixes[USE_LD_MAX] = @@ -838,7 +869,8 @@ "ld", PLUGIN_LD_SUFFIX, "ld.gold", - "ld.bfd" + "ld.bfd", + "ld.lld" }; static const char *const real_ld_suffix = "real-ld"; static const char *const collect_ld_suffix = "collect-ld"; @@ -979,13 +1011,21 @@ object = CONST_CAST2 (const char **, char **, object_lst); #ifdef DEBUG - debug = 1; + debug = true; #endif - /* Parse command line early for instances of -debug. This allows - the debug flag to be set before functions like find_a_file() - are called. We also look for the -flto or -flto-partition=none flag to know - what LTO mode we are in. */ + save_temps = false; + verbose = false; + +#ifndef DEFAULT_A_OUT_NAME + output_file = "a.out"; +#else + output_file = DEFAULT_A_OUT_NAME; +#endif + + /* Parse command line / environment for flags we want early. + This allows the debug flag to be set before functions like find_a_file() + are called. */ { bool no_partition = false; @@ -993,8 +1033,6 @@ { if (! strcmp (argv[i], "-debug")) debug = true; - else if (! strcmp (argv[i], "-flto-partition=none")) - no_partition = true; else if (!strncmp (argv[i], "-fno-lto", 8)) lto_mode = LTO_MODE_NONE; else if (! strcmp (argv[i], "-plugin")) @@ -1007,6 +1045,17 @@ selected_linker = USE_BFD_LD; else if (strcmp (argv[i], "-fuse-ld=gold") == 0) selected_linker = USE_GOLD_LD; + else if (strcmp (argv[i], "-fuse-ld=lld") == 0) + selected_linker = USE_LLD_LD; + else if (strncmp (argv[i], "-o", 2) == 0) + { + /* Parse the output filename if it's given so that we can make + meaningful temp filenames. */ + if (argv[i][2] == '\0') + output_file = argv[i+1]; + else + output_file = &argv[i][2]; + } #ifdef COLLECT_EXPORT_LIST /* These flags are position independent, although their order @@ -1027,7 +1076,35 @@ aixlazy_flag = 1; #endif } - verbose = debug; + + obstack_begin (&temporary_obstack, 0); + temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); + +#ifndef HAVE_LD_DEMANGLE + current_demangling_style = auto_demangling; +#endif + + /* Now pick up any flags we want early from COLLECT_GCC_OPTIONS + The LTO options are passed here as are other options that might + be unsuitable for ld (e.g. -save-temps). */ + p = getenv ("COLLECT_GCC_OPTIONS"); + while (p && *p) + { + const char *q = extract_string (&p); + if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) + num_c_args++; + if (strncmp (q, "-flto-partition=none", 20) == 0) + no_partition = true; + else if (strncmp (q, "-fno-lto", 8) == 0) + lto_mode = LTO_MODE_NONE; + else if (strncmp (q, "-save-temps", 11) == 0) + /* FIXME: Honour =obj. */ + save_temps = true; + } + obstack_free (&temporary_obstack, temporary_firstobj); + + verbose = verbose || debug; + save_temps = save_temps || debug; find_file_set_debug (debug); if (use_plugin) lto_mode = LTO_MODE_NONE; @@ -1035,27 +1112,6 @@ lto_mode = LTO_MODE_LTO; } -#ifndef DEFAULT_A_OUT_NAME - output_file = "a.out"; -#else - output_file = DEFAULT_A_OUT_NAME; -#endif - - obstack_begin (&temporary_obstack, 0); - temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); - -#ifndef HAVE_LD_DEMANGLE - current_demangling_style = auto_demangling; -#endif - p = getenv ("COLLECT_GCC_OPTIONS"); - while (p && *p) - { - const char *q = extract_string (&p); - if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) - num_c_args++; - } - obstack_free (&temporary_obstack, temporary_firstobj); - /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities -fno-exceptions -w -fno-whole-program */ num_c_args += 6; @@ -1096,7 +1152,8 @@ /* Maybe we know the right file to use (if not cross). */ ld_file_name = 0; #ifdef DEFAULT_LINKER - if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD) + if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD || + selected_linker == USE_LLD_LD) { char *linker_name; # ifdef HOST_EXECUTABLE_SUFFIX @@ -1203,8 +1260,22 @@ *ld1++ = *ld2++ = ld_file_name; /* Make temp file names. */ - c_file = make_temp_file (".c"); - o_file = make_temp_file (".o"); + if (save_temps) + { + c_file = (char *) xmalloc (strlen (output_file) + + sizeof (".cdtor.c") + 1); + strcpy (c_file, output_file); + strcat (c_file, ".cdtor.c"); + o_file = (char *) xmalloc (strlen (output_file) + + sizeof (".cdtor.o") + 1); + strcpy (o_file, output_file); + strcat (o_file, ".cdtor.o"); + } + else + { + c_file = make_temp_file (".cdtor.c"); + o_file = make_temp_file (".cdtor.o"); + } #ifdef COLLECT_EXPORT_LIST export_file = make_temp_file (".x"); #endif @@ -1213,6 +1284,7 @@ ldout = make_temp_file (".ld"); lderrout = make_temp_file (".le"); } + /* Build the command line to compile the ctor/dtor list. */ *c_ptr++ = c_file_name; *c_ptr++ = "-x"; *c_ptr++ = "c"; @@ -1315,7 +1387,7 @@ else if (!use_collect_ld && strncmp (arg, "-fuse-ld=", 9) == 0) { - /* Do not pass -fuse-ld={bfd|gold} to the linker. */ + /* Do not pass -fuse-ld={bfd|gold|lld} to the linker. */ ld1--; ld2--; } @@ -1349,7 +1421,7 @@ stream = fopen (list_filename, "r"); if (stream == NULL) - fatal_error (input_location, "can't open %s: %m", + fatal_error (input_location, "cannot open %s: %m", list_filename); while (fgets (buf, sizeof buf, stream) != NULL) @@ -1469,7 +1541,7 @@ enum demangling_styles style = cplus_demangle_name_to_style (arg+11); if (style == unknown_demangling) - error ("unknown demangling style '%s'", arg+11); + error ("unknown demangling style %qs", arg+11); else current_demangling_style = style; } @@ -1593,7 +1665,7 @@ printf (" --help Display this information\n"); printf (" -v, --version Display this program's version number\n"); printf ("\n"); - printf ("Overview: http://gcc.gnu.org/onlinedocs/gccint/Collect2.html\n"); + printf ("Overview: https://gcc.gnu.org/onlinedocs/gccint/Collect2.html\n"); printf ("Report bugs: %s\n", bug_report_url); printf ("\n"); } @@ -1656,7 +1728,7 @@ functions from precise cross reference insertions by the compiler. */ if (early_exit || ld1_filter != SCAN_NOTHING) - do_tlink (ld1_argv, object_lst); + do_link (ld1_argv); if (early_exit) { @@ -1668,10 +1740,8 @@ if (lto_mode != LTO_MODE_NONE) maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); else - post_ld_pass (false); - - maybe_unlink (c_file); - maybe_unlink (o_file); + post_ld_pass (/*temp_file*/false); + return 0; } } @@ -1716,10 +1786,10 @@ #endif ) { - /* Do tlink without additional code generation now if we didn't + /* Do link without additional code generation now if we didn't do it earlier for scanning purposes. */ if (ld1_filter == SCAN_NOTHING) - do_tlink (ld1_argv, object_lst); + do_link (ld1_argv); if (lto_mode) maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); @@ -1740,7 +1810,7 @@ #ifdef COLLECT_EXPORT_LIST maybe_unlink (export_file); #endif - post_ld_pass (false); + post_ld_pass (/*temp_file*/false); maybe_unlink (c_file); maybe_unlink (o_file); @@ -1822,19 +1892,19 @@ 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); + /* On AIX we must call link because of possible templates resolution. */ + do_link (ld2_argv); if (lto_mode) maybe_run_lto_and_relink (ld2_argv, object_lst, object, false); #else - /* Otherwise, simply call ld because tlink is already done. */ + /* Otherwise, simply call ld because link is already done. */ if (lto_mode) maybe_run_lto_and_relink (ld2_argv, object_lst, object, true); else { fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied); - post_ld_pass (false); + post_ld_pass (/*temp_file*/false); } /* Let scan_prog_file do any final mods (OSF/rose needs this for @@ -1859,9 +1929,10 @@ void maybe_unlink (const char *file) { - if (debug) + if (save_temps && file_exists (file)) { - notice ("[Leaving %s]\n", file); + if (verbose) + notice ("[Leaving %s]\n", file); return; } @@ -2291,38 +2362,52 @@ /* Check to make sure the file is an LTO object file. */ -static bool -maybe_lto_object_file (const char *prog_name) +static int +has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED, + off_t offset ATTRIBUTE_UNUSED, + off_t length ATTRIBUTE_UNUSED) { - FILE *f; - unsigned char buf[4]; - int i; - - static unsigned char elfmagic[4] = { 0x7f, 'E', 'L', 'F' }; - static unsigned char coffmagic[2] = { 0x4c, 0x01 }; - static unsigned char coffmagic_x64[2] = { 0x64, 0x86 }; - static unsigned char machomagic[4][4] = { - { 0xcf, 0xfa, 0xed, 0xfe }, - { 0xce, 0xfa, 0xed, 0xfe }, - { 0xfe, 0xed, 0xfa, 0xcf }, - { 0xfe, 0xed, 0xfa, 0xce } - }; - - f = fopen (prog_name, "rb"); - if (f == NULL) + int *found = (int *) data; + + if (strncmp (name, LTO_SECTION_NAME_PREFIX, + sizeof (LTO_SECTION_NAME_PREFIX) - 1) != 0) + { + if (strncmp (name, OFFLOAD_SECTION_NAME_PREFIX, + sizeof (OFFLOAD_SECTION_NAME_PREFIX) - 1) != 0) + return 1; + } + + *found = 1; + + /* Stop iteration. */ + return 0; +} + +static bool +is_lto_object_file (const char *prog_name) +{ + const char *errmsg; + int err; + int found = 0; + off_t inoff = 0; + int infd = open (prog_name, O_RDONLY | O_BINARY); + + if (infd == -1) return false; - if (fread (buf, sizeof (buf), 1, f) != 1) - buf[0] = 0; - fclose (f); - - if (memcmp (buf, elfmagic, sizeof (elfmagic)) == 0 - || memcmp (buf, coffmagic, sizeof (coffmagic)) == 0 - || memcmp (buf, coffmagic_x64, sizeof (coffmagic_x64)) == 0) + + simple_object_read *inobj = simple_object_start_read (infd, inoff, + LTO_SEGMENT_NAME, + &errmsg, &err); + if (!inobj) + return false; + + errmsg = simple_object_find_sections (inobj, has_lto_section, + (void *) &found, &err); + if (! errmsg && found) return true; - for (i = 0; i < 4; i++) - if (memcmp (buf, machomagic[i], sizeof (machomagic[i])) == 0) - return true; - + + if (errmsg) + fatal_error (0, "%s: %s", errmsg, xstrerror (err)); return false; } @@ -2345,7 +2430,6 @@ int err; char *p, buf[1024]; FILE *inf; - int found_lto = 0; if (which_pass == PASS_SECOND) return; @@ -2353,12 +2437,17 @@ /* LTO objects must be in a known format. This check prevents us from accepting an archive containing LTO objects, which gcc cannot currently handle. */ - if (which_pass == PASS_LTOINFO && !maybe_lto_object_file (prog_name)) - return; + if (which_pass == PASS_LTOINFO) + { + if(is_lto_object_file (prog_name)) { + add_lto_object (<o_objects, prog_name); + } + return; + } /* If we do not have an `nm', complain. */ if (nm_file_name == 0) - fatal_error (input_location, "cannot find 'nm'"); + fatal_error (input_location, "cannot find %<nm%>"); nm_argv[argc++] = nm_file_name; if (NM_FLAGS[0] != '\0') @@ -2384,7 +2473,7 @@ pex = pex_init (PEX_USE_PIPES, "collect2", NULL); if (pex == NULL) - fatal_error (input_location, "pex_init failed: %m"); + fatal_error (input_location, "%<pex_init%> failed: %m"); errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET, &err); @@ -2406,15 +2495,10 @@ inf = pex_read_output (pex, 0); if (inf == NULL) - fatal_error (input_location, "can't open nm output: %m"); + fatal_error (input_location, "cannot open nm output: %m"); if (debug) - { - if (which_pass == PASS_LTOINFO) - fprintf (stderr, "\nnm output with LTO info marker symbol.\n"); - else - fprintf (stderr, "\nnm output with constructors/destructors.\n"); - } + fprintf (stderr, "\nnm output with constructors/destructors.\n"); /* Read each line of nm output. */ while (fgets (buf, sizeof buf, inf) != (char *) 0) @@ -2425,30 +2509,6 @@ if (debug) fprintf (stderr, "\t%s\n", buf); - if (which_pass == PASS_LTOINFO) - { - if (found_lto) - continue; - - /* Look for the LTO info marker symbol, and add filename to - the LTO objects list if found. */ - for (p = buf; (ch = *p) != '\0' && ch != '\n'; p++) - if (ch == ' ' && p[1] == '_' && p[2] == '_' - && (strncmp (p + (p[3] == '_' ? 2 : 1), "__gnu_lto_v1", 12) == 0) - && ISSPACE (p[p[3] == '_' ? 14 : 13])) - { - add_lto_object (<o_objects, prog_name); - - /* We need to read all the input, so we can't just - return here. But we can avoid useless work. */ - found_lto = 1; - - break; - } - - continue; - } - /* If it contains a constructor or destructor name, add the name to the appropriate list unless this is a kind of symbol we're not supposed to even consider. */ @@ -2558,7 +2618,7 @@ /* If we do not have an `ldd', complain. */ if (ldd_file_name == 0) { - error ("cannot find 'ldd'"); + error ("cannot find %<ldd%>"); return; } @@ -2604,7 +2664,7 @@ inf = pex_read_output (pex, 0); if (inf == NULL) - fatal_error (input_location, "can't open ldd output: %m"); + fatal_error (input_location, "cannot open ldd output: %m"); if (debug) notice ("\nldd output with constructors/destructors.\n"); @@ -2634,8 +2694,8 @@ if (access (name, R_OK) == 0) add_to_list (&libraries, name); else - fatal_error (input_location, "unable to open dynamic dependency '%s'", - buf); + fatal_error (input_location, "unable to open dynamic dependency " + "%qs", buf); if (debug) fprintf (stderr, "\t%s\n", buf); @@ -2763,10 +2823,8 @@ LDFILE *ldptr = NULL; int sym_index, sym_count; int is_shared = 0; - int found_lto = 0; - - if (which_pass != PASS_FIRST && which_pass != PASS_OBJ - && which_pass != PASS_LTOINFO) + + if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) return; #ifdef COLLECT_EXPORT_LIST @@ -2779,7 +2837,6 @@ eliminate scan_libraries() function. */ do { - found_lto = 0; #endif /* Some platforms (e.g. OSF4) declare ldopen as taking a non-const char * filename parameter, even though it will not @@ -2822,19 +2879,6 @@ ++name; #endif - if (which_pass == PASS_LTOINFO) - { - if (found_lto) - continue; - if (strncmp (name, "__gnu_lto_v1", 12) == 0) - { - add_lto_object (<o_objects, prog_name); - found_lto = 1; - break; - } - continue; - } - switch (is_ctor_dtor (name)) { #if TARGET_AIX_VERSION