From 4098a6d4368119ad098028bf0888e17a16b9f022 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sun, 23 Dec 2018 10:43:59 +0000 Subject: [PATCH] use simple-object instead of nm to determine if files contain LTO. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This replaces the use of nm to search for the LTO common symbol marker and uses simple object to see if there's a section starting with ".gnu.lto_." or ".gnu.offload_lto_" 2018-12-23 Iain Sandoe * collect2.c (maybe_run_lto_and_relink): Don’t say we have a temp file unless we actually did some LTO. (has_lto_section, is_lto_object_file): New. (maybe_lto_object_file): Remove. (scan_prog_file): Use is_lto_object_file() instead of scanning the output of nm. From-SVN: r267371 --- gcc/ChangeLog | 9 ++++ gcc/collect2.c | 120 +++++++++++++++++++++++-------------------------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bdc22b70efa..3691e65860e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-12-23 Iain Sandoe + + * collect2.c (maybe_run_lto_and_relink): Don’t say we have a temp file + unless we actually did some LTO. + (has_lto_section, is_lto_object_file): New. + (maybe_lto_object_file): Remove. + (scan_prog_file): Use is_lto_object_file() instead of scanning the + output of nm. + 2018-12-23 Iain Sandoe * collect2.c (main): Parse the output file early so we can make nicer diff --git a/gcc/collect2.c b/gcc/collect2.c index 60269682ecb..dcbd3e18a65 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see #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 @@ -804,7 +806,9 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, /* 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 +818,11 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, /* 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. */ } /* Main program. */ @@ -1710,7 +1715,7 @@ main (int argc, char **argv) if (lto_mode != LTO_MODE_NONE) maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); else - post_ld_pass (false); + post_ld_pass (/*temp_file*/false); return 0; } @@ -1780,7 +1785,7 @@ main (int argc, char **argv) #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); @@ -1874,7 +1879,7 @@ main (int argc, char **argv) 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 @@ -2332,38 +2337,52 @@ write_aix_file (FILE *stream, struct id *list) /* Check to make sure the file is an LTO object file. */ +static int +has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED, + off_t offset ATTRIBUTE_UNUSED, + off_t length ATTRIBUTE_UNUSED) +{ + 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 -maybe_lto_object_file (const char *prog_name) +is_lto_object_file (const char *prog_name) { - FILE *f; - unsigned char buf[4]; - int i; + const char *errmsg; + int err; + int found = 0; + off_t inoff = 0; + int infd = open (prog_name, O_RDONLY | O_BINARY); - 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 } - }; + if (infd == -1) + return false; - f = fopen (prog_name, "rb"); - if (f == NULL) + simple_object_read *inobj = simple_object_start_read (infd, inoff, + LTO_SEGMENT_NAME, + &errmsg, &err); + if (!inobj) 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) + 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\n", errmsg, xstrerror (err)); return false; } @@ -2386,7 +2405,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, int err; char *p, buf[1024]; FILE *inf; - int found_lto = 0; if (which_pass == PASS_SECOND) return; @@ -2394,8 +2412,13 @@ scan_prog_file (const char *prog_name, scanpass which_pass, /* 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) @@ -2450,12 +2473,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass, fatal_error (input_location, "can't 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) @@ -2466,30 +2484,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, 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. */ -- 2.30.2