Commit 4098a6d4 by Iain Sandoe Committed by Iain Sandoe

use simple-object instead of nm to determine if files contain LTO.

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  <iain@sandoe.co.uk>

	* 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
parent 513825f0
2018-12-23 Iain Sandoe <iain@sandoe.co.uk> 2018-12-23 Iain Sandoe <iain@sandoe.co.uk>
* 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 <iain@sandoe.co.uk>
* collect2.c (main): Parse the output file early so we can make nicer * collect2.c (main): Parse the output file early so we can make nicer
temp names. Respond to “-save-temps” in the GCC OPTIONS. temp names. Respond to “-save-temps” in the GCC OPTIONS.
(maybe_unlink): Don’t print “[Leaving…”] for files we never created (maybe_unlink): Don’t print “[Leaving…”] for files we never created
...@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h" #include "tm.h"
#include "filenames.h" #include "filenames.h"
#include "file-find.h" #include "file-find.h"
#include "simple-object.h"
#include "lto-section-names.h"
/* TARGET_64BIT may be defined to use driver specific functionality. */ /* TARGET_64BIT may be defined to use driver specific functionality. */
#undef TARGET_64BIT #undef TARGET_64BIT
...@@ -804,7 +806,9 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, ...@@ -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 /* Run the linker again, this time replacing the object files
optimized by the LTO with the temporary file generated by the LTO. */ 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); 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); free (lto_ld_argv);
maybe_unlink_list (lto_o_files); maybe_unlink_list (lto_o_files);
...@@ -814,10 +818,11 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, ...@@ -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 /* Our caller is relying on us to do the link
even though there is no LTO back end work to be done. */ even though there is no LTO back end work to be done. */
fork_execute ("ld", lto_ld_argv, HAVE_GNU_LD && at_file_supplied); 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 else
post_ld_pass (true); post_ld_pass (false); /* No LTO objects were found, no temp file. */
} }
/* Main program. */ /* Main program. */
...@@ -1710,7 +1715,7 @@ main (int argc, char **argv) ...@@ -1710,7 +1715,7 @@ main (int argc, char **argv)
if (lto_mode != LTO_MODE_NONE) if (lto_mode != LTO_MODE_NONE)
maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
else else
post_ld_pass (false); post_ld_pass (/*temp_file*/false);
return 0; return 0;
} }
...@@ -1780,7 +1785,7 @@ main (int argc, char **argv) ...@@ -1780,7 +1785,7 @@ main (int argc, char **argv)
#ifdef COLLECT_EXPORT_LIST #ifdef COLLECT_EXPORT_LIST
maybe_unlink (export_file); maybe_unlink (export_file);
#endif #endif
post_ld_pass (false); post_ld_pass (/*temp_file*/false);
maybe_unlink (c_file); maybe_unlink (c_file);
maybe_unlink (o_file); maybe_unlink (o_file);
...@@ -1874,7 +1879,7 @@ main (int argc, char **argv) ...@@ -1874,7 +1879,7 @@ main (int argc, char **argv)
else else
{ {
fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied); 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 /* 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) ...@@ -2332,38 +2337,52 @@ write_aix_file (FILE *stream, struct id *list)
/* Check to make sure the file is an LTO object file. */ /* 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 static bool
maybe_lto_object_file (const char *prog_name) is_lto_object_file (const char *prog_name)
{ {
FILE *f; const char *errmsg;
unsigned char buf[4]; int err;
int i; 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' }; if (infd == -1)
static unsigned char coffmagic[2] = { 0x4c, 0x01 }; return false;
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"); simple_object_read *inobj = simple_object_start_read (infd, inoff,
if (f == NULL) LTO_SEGMENT_NAME,
&errmsg, &err);
if (!inobj)
return false; return false;
if (fread (buf, sizeof (buf), 1, f) != 1)
buf[0] = 0;
fclose (f);
if (memcmp (buf, elfmagic, sizeof (elfmagic)) == 0 errmsg = simple_object_find_sections (inobj, has_lto_section,
|| memcmp (buf, coffmagic, sizeof (coffmagic)) == 0 (void *) &found, &err);
|| memcmp (buf, coffmagic_x64, sizeof (coffmagic_x64)) == 0) if (! errmsg && found)
return true; 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; return false;
} }
...@@ -2386,7 +2405,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, ...@@ -2386,7 +2405,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
int err; int err;
char *p, buf[1024]; char *p, buf[1024];
FILE *inf; FILE *inf;
int found_lto = 0;
if (which_pass == PASS_SECOND) if (which_pass == PASS_SECOND)
return; return;
...@@ -2394,8 +2412,13 @@ scan_prog_file (const char *prog_name, scanpass which_pass, ...@@ -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 /* LTO objects must be in a known format. This check prevents
us from accepting an archive containing LTO objects, which us from accepting an archive containing LTO objects, which
gcc cannot currently handle. */ gcc cannot currently handle. */
if (which_pass == PASS_LTOINFO && !maybe_lto_object_file (prog_name)) if (which_pass == PASS_LTOINFO)
return; {
if(is_lto_object_file (prog_name)) {
add_lto_object (&lto_objects, prog_name);
}
return;
}
/* If we do not have an `nm', complain. */ /* If we do not have an `nm', complain. */
if (nm_file_name == 0) if (nm_file_name == 0)
...@@ -2450,12 +2473,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass, ...@@ -2450,12 +2473,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
fatal_error (input_location, "can't open nm output: %m"); fatal_error (input_location, "can't open nm output: %m");
if (debug) if (debug)
{ fprintf (stderr, "\nnm output with constructors/destructors.\n");
if (which_pass == PASS_LTOINFO)
fprintf (stderr, "\nnm output with LTO info marker symbol.\n");
else
fprintf (stderr, "\nnm output with constructors/destructors.\n");
}
/* Read each line of nm output. */ /* Read each line of nm output. */
while (fgets (buf, sizeof buf, inf) != (char *) 0) while (fgets (buf, sizeof buf, inf) != (char *) 0)
...@@ -2466,30 +2484,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, ...@@ -2466,30 +2484,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
if (debug) if (debug)
fprintf (stderr, "\t%s\n", buf); 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 (&lto_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 /* If it contains a constructor or destructor name, add the name
to the appropriate list unless this is a kind of symbol we're to the appropriate list unless this is a kind of symbol we're
not supposed to even consider. */ not supposed to even consider. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment