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>
* 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
temp names. Respond to “-save-temps” in the GCC OPTIONS.
(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
#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 (&lto_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 (&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
to the appropriate list unless this is a kind of symbol we're
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