mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
PR ld/17973 LTO file syms
LTO output objects have an STT_FILE symbol using the name of the file, a temporary file. This results in executables that can't be exactly reproduced, so the file name needs to be dropped. We don't want to lose all file symbols when linking a mix of lto and non-lto objects as a file symbol can be used to figure which source file generated a given local symbol. So lto output objects need to be marked. I chose to mark lto output objects with a new bfd flag. This flag is also used to fix a bug in the link-once handling; An object being loaded after "loading_lto_outputs" is set might be one extracted from an archive to satisfy new references from lto objects, not an lto object itself. The new flag is copied from archive to elements, and the same done for no_export. This fixes a bug in that --exclude-libs doesn't work with thin archives. I'm not completely happy with this part of the patch and may revist this to avoid the hack in _bfd_look_for_bfd_in_cache. PR ld/17973 include/ * bfdlink.h (struct bfd_link_info): Delete loading_lto_outputs. bfd/ * bfd.c (struct bfd): Add lto_output. * linker.c (_bfd_handle_already_linked): Explicitly test for objects added by the lto plugin. * opncls.c (_bfd_new_bfd_contained_in): Copy lto_output and no_export flags from archive. * archive.c (open_nested_file): New function, setting lto_output and no_export, extracted from.. (find_nested_archive): ..here. Flip params. Rename from _bfd_find_nested_archive. (_bfd_get_elt_at_filepos): Correct var typo. Use open_nested_file. (_bfd_look_for_bfd_in_cache): Copy no_export. * elflink.c (elf_link_add_object_symbols): Remove now unnecessary my_archive->no_export test. (elf_link_input_bfd): Drop existing lto_output STT_FILE syms. Don't use the file name when adding lto_output STT_FILE sym. * bfd-in2.h: Regenerate. ld/ * ldlang.h (struct lang_input_statement_flags): Add lto_output. * ldlang.c (lang_process): Don't set loading_lto_outputs. * ldfile.c (ldfile_try_open_bfd): Transfer entry flags.lto_output to bfd. * plugin.c (add_input_file, add_input_library): Set flags.lto_output.
This commit is contained in:
parent
0a60f874dc
commit
ce875075f9
@ -1,3 +1,23 @@
|
||||
2015-02-14 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/17973
|
||||
* bfd.c (struct bfd): Add lto_output.
|
||||
* linker.c (_bfd_handle_already_linked): Explicitly test for
|
||||
objects added by the lto plugin.
|
||||
* opncls.c (_bfd_new_bfd_contained_in): Copy lto_output and
|
||||
no_export flags from archive.
|
||||
* archive.c (open_nested_file): New function, setting lto_output
|
||||
and no_export, extracted from..
|
||||
(find_nested_archive): ..here. Flip params. Rename from
|
||||
_bfd_find_nested_archive.
|
||||
(_bfd_get_elt_at_filepos): Correct var typo. Use open_nested_file.
|
||||
(_bfd_look_for_bfd_in_cache): Copy no_export.
|
||||
* elflink.c (elf_link_add_object_symbols): Remove now unnecessary
|
||||
my_archive->no_export test.
|
||||
(elf_link_input_bfd): Drop existing lto_output STT_FILE syms.
|
||||
Don't use the file name when adding lto_output STT_FILE sym.
|
||||
* bfd-in2.h: Regenerate.
|
||||
|
||||
2015-02-13 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR binutils/17512
|
||||
|
@ -311,8 +311,12 @@ _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
|
||||
struct ar_cache *entry = (struct ar_cache *) htab_find (hash_table, &m);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
else
|
||||
return entry->arbfd;
|
||||
|
||||
/* Unfortunately this flag is set after checking that we have
|
||||
an archive, and checking for an archive means one element has
|
||||
sneaked into the cache. */
|
||||
entry->arbfd->no_export = arch_bfd->no_export;
|
||||
return entry->arbfd;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
@ -375,10 +379,27 @@ _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
|
||||
}
|
||||
|
||||
static bfd *
|
||||
_bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
|
||||
open_nested_file (const char *filename, bfd *archive)
|
||||
{
|
||||
const char *target;
|
||||
bfd *n_bfd;
|
||||
|
||||
target = NULL;
|
||||
if (!archive->target_defaulted)
|
||||
target = archive->xvec->name;
|
||||
n_bfd = bfd_openr (filename, target);
|
||||
if (n_bfd != NULL)
|
||||
{
|
||||
n_bfd->lto_output = archive->lto_output;
|
||||
n_bfd->no_export = archive->no_export;
|
||||
}
|
||||
return n_bfd;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
find_nested_archive (const char *filename, bfd *arch_bfd)
|
||||
{
|
||||
bfd *abfd;
|
||||
const char *target;
|
||||
|
||||
/* PR 15140: Don't allow a nested archive pointing to itself. */
|
||||
if (filename_cmp (filename, arch_bfd->filename) == 0)
|
||||
@ -394,10 +415,7 @@ _bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
|
||||
if (filename_cmp (filename, abfd->filename) == 0)
|
||||
return abfd;
|
||||
}
|
||||
target = NULL;
|
||||
if (!arch_bfd->target_defaulted)
|
||||
target = arch_bfd->xvec->name;
|
||||
abfd = bfd_openr (filename, target);
|
||||
abfd = open_nested_file (filename, arch_bfd);
|
||||
if (abfd)
|
||||
{
|
||||
abfd->archive_next = arch_bfd->nested_archives;
|
||||
@ -626,12 +644,12 @@ bfd *
|
||||
_bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
{
|
||||
struct areltdata *new_areldata;
|
||||
bfd *n_nfd;
|
||||
bfd *n_bfd;
|
||||
char *filename;
|
||||
|
||||
n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
|
||||
if (n_nfd)
|
||||
return n_nfd;
|
||||
n_bfd = _bfd_look_for_bfd_in_cache (archive, filepos);
|
||||
if (n_bfd)
|
||||
return n_bfd;
|
||||
|
||||
if (0 > bfd_seek (archive, filepos, SEEK_SET))
|
||||
return NULL;
|
||||
@ -643,8 +661,6 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
|
||||
if (bfd_is_thin_archive (archive))
|
||||
{
|
||||
const char *target;
|
||||
|
||||
/* This is a proxy entry for an external file. */
|
||||
if (! IS_ABSOLUTE_PATH (filename))
|
||||
{
|
||||
@ -660,7 +676,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
{
|
||||
/* This proxy entry refers to an element of a nested archive.
|
||||
Locate the member of that archive and return a bfd for it. */
|
||||
bfd *ext_arch = _bfd_find_nested_archive (archive, filename);
|
||||
bfd *ext_arch = find_nested_archive (filename, archive);
|
||||
|
||||
if (ext_arch == NULL
|
||||
|| ! bfd_check_format (ext_arch, bfd_archive))
|
||||
@ -668,57 +684,55 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
free (new_areldata);
|
||||
return NULL;
|
||||
}
|
||||
n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
|
||||
if (n_nfd == NULL)
|
||||
n_bfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
|
||||
if (n_bfd == NULL)
|
||||
{
|
||||
free (new_areldata);
|
||||
return NULL;
|
||||
}
|
||||
n_nfd->proxy_origin = bfd_tell (archive);
|
||||
return n_nfd;
|
||||
n_bfd->proxy_origin = bfd_tell (archive);
|
||||
return n_bfd;
|
||||
}
|
||||
|
||||
/* It's not an element of a nested archive;
|
||||
open the external file as a bfd. */
|
||||
target = NULL;
|
||||
if (!archive->target_defaulted)
|
||||
target = archive->xvec->name;
|
||||
n_nfd = bfd_openr (filename, target);
|
||||
if (n_nfd == NULL)
|
||||
n_bfd = open_nested_file (filename, archive);
|
||||
if (n_bfd == NULL)
|
||||
bfd_set_error (bfd_error_malformed_archive);
|
||||
}
|
||||
else
|
||||
{
|
||||
n_nfd = _bfd_create_empty_archive_element_shell (archive);
|
||||
n_bfd = _bfd_create_empty_archive_element_shell (archive);
|
||||
}
|
||||
|
||||
if (n_nfd == NULL)
|
||||
if (n_bfd == NULL)
|
||||
{
|
||||
free (new_areldata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n_nfd->proxy_origin = bfd_tell (archive);
|
||||
n_bfd->proxy_origin = bfd_tell (archive);
|
||||
|
||||
if (bfd_is_thin_archive (archive))
|
||||
{
|
||||
n_nfd->origin = 0;
|
||||
n_bfd->origin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_nfd->origin = n_nfd->proxy_origin;
|
||||
n_nfd->filename = xstrdup (filename);
|
||||
n_bfd->origin = n_bfd->proxy_origin;
|
||||
n_bfd->filename = xstrdup (filename);
|
||||
}
|
||||
|
||||
n_nfd->arelt_data = new_areldata;
|
||||
n_bfd->arelt_data = new_areldata;
|
||||
|
||||
/* Copy BFD_COMPRESS and BFD_DECOMPRESS flags. */
|
||||
n_nfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
|
||||
n_bfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
|
||||
|
||||
if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
|
||||
return n_nfd;
|
||||
if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_bfd))
|
||||
return n_bfd;
|
||||
|
||||
free (new_areldata);
|
||||
n_nfd->arelt_data = NULL;
|
||||
n_bfd->arelt_data = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -6438,6 +6438,9 @@ struct bfd
|
||||
/* If this is an input for a compiler plug-in library. */
|
||||
ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
|
||||
|
||||
/* Set if this is a plugin output file. */
|
||||
unsigned int lto_output : 1;
|
||||
|
||||
/* Set to dummy BFD created when claimed by a compiler plug-in
|
||||
library. */
|
||||
bfd *plugin_dummy_bfd;
|
||||
|
@ -210,6 +210,9 @@ CODE_FRAGMENT
|
||||
. {* If this is an input for a compiler plug-in library. *}
|
||||
. ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
|
||||
.
|
||||
. {* Set if this is a plugin output file. *}
|
||||
. unsigned int lto_output : 1;
|
||||
.
|
||||
. {* Set to dummy BFD created when claimed by a compiler plug-in
|
||||
. library. *}
|
||||
. bfd *plugin_dummy_bfd;
|
||||
|
@ -4085,8 +4085,7 @@ error_free_dyn:
|
||||
requested we not re-export it, then mark it as hidden. */
|
||||
if (definition
|
||||
&& !dynamic
|
||||
&& (abfd->no_export
|
||||
|| (abfd->my_archive && abfd->my_archive->no_export))
|
||||
&& abfd->no_export
|
||||
&& ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
|
||||
isym->st_other = (STV_HIDDEN
|
||||
| (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
|
||||
@ -9520,6 +9519,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|
||||
|
||||
if (ELF_ST_TYPE (isym->st_info) == STT_FILE)
|
||||
{
|
||||
if (input_bfd->lto_output)
|
||||
/* -flto puts a temp file name here. This means builds
|
||||
are not reproducible. Discard the symbol. */
|
||||
continue;
|
||||
have_file_sym = TRUE;
|
||||
flinfo->filesym_count += 1;
|
||||
}
|
||||
@ -9536,8 +9539,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|
||||
memset (&osym, 0, sizeof (osym));
|
||||
osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
|
||||
osym.st_shndx = SHN_ABS;
|
||||
if (!elf_link_output_sym (flinfo, input_bfd->filename, &osym,
|
||||
bfd_abs_section_ptr, NULL))
|
||||
if (!elf_link_output_sym (flinfo,
|
||||
(input_bfd->lto_output ? NULL
|
||||
: input_bfd->filename),
|
||||
&osym, bfd_abs_section_ptr, NULL))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -2896,7 +2896,7 @@ _bfd_handle_already_linked (asection *sec,
|
||||
files over IR because the first pass may contain a
|
||||
mix of LTO and normal objects and we must keep the
|
||||
first match, be it IR or real. */
|
||||
if (info->loading_lto_outputs
|
||||
if (sec->owner->lto_output
|
||||
&& (l->sec->owner->flags & BFD_PLUGIN) != 0)
|
||||
{
|
||||
l->sec = sec;
|
||||
|
@ -109,6 +109,8 @@ _bfd_new_bfd_contained_in (bfd *obfd)
|
||||
nbfd->my_archive = obfd;
|
||||
nbfd->direction = read_direction;
|
||||
nbfd->target_defaulted = obfd->target_defaulted;
|
||||
nbfd->lto_output = obfd->lto_output;
|
||||
nbfd->no_export = obfd->no_export;
|
||||
return nbfd;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2015-02-14 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/17973
|
||||
* bfdlink.h (struct bfd_link_info): Delete loading_lto_outputs.
|
||||
|
||||
2015-02-09 Mark Wielaard <mjw@redhat.com>
|
||||
|
||||
* dwarf2.h: Add DW_LANG_Fortran03 and DW_LANG_Fortran08.
|
||||
|
@ -301,9 +301,6 @@ struct bfd_link_info
|
||||
/* TRUE if the LTO plugin is active. */
|
||||
unsigned int lto_plugin_active: 1;
|
||||
|
||||
/* TRUE if we are loading LTO outputs. */
|
||||
unsigned int loading_lto_outputs: 1;
|
||||
|
||||
/* TRUE if global symbols in discarded sections should be stripped. */
|
||||
unsigned int strip_discarded: 1;
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2015-02-14 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/17973
|
||||
* ldlang.h (struct lang_input_statement_flags): Add lto_output.
|
||||
* ldlang.c (lang_process): Don't set loading_lto_outputs.
|
||||
* ldfile.c (ldfile_try_open_bfd): Transfer entry flags.lto_output
|
||||
to bfd.
|
||||
* plugin.c (add_input_file, add_input_library): Set flags.lto_output.
|
||||
|
||||
2015-02-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* NEWS: Mention support for LLVM plugin.
|
||||
|
@ -142,6 +142,11 @@ ldfile_try_open_bfd (const char *attempt,
|
||||
/* Linker needs to decompress sections. */
|
||||
entry->the_bfd->flags |= BFD_DECOMPRESS;
|
||||
|
||||
#ifdef ENABLE_PLUGINS
|
||||
if (entry->flags.lto_output)
|
||||
entry->the_bfd->lto_output = 1;
|
||||
#endif
|
||||
|
||||
/* If we are searching for this file, see if the architecture is
|
||||
compatible with the output file. If it isn't, keep searching.
|
||||
If we can't open the file as an object file, stop the search
|
||||
|
@ -6643,7 +6643,6 @@ lang_process (void)
|
||||
einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
|
||||
plugin_error_plugin ());
|
||||
/* Open any newly added files, updating the file chains. */
|
||||
link_info.loading_lto_outputs = TRUE;
|
||||
open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
|
||||
/* Restore the global list pointer now they have all been added. */
|
||||
lang_list_remove_tail (stat_ptr, &added);
|
||||
|
@ -283,6 +283,9 @@ struct lang_input_statement_flags
|
||||
|
||||
/* Set if the file was claimed from an archive. */
|
||||
unsigned int claim_archive : 1;
|
||||
|
||||
/* Set if added by the lto plugin add_input_file callback. */
|
||||
unsigned int lto_output : 1;
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
/* Head of list of pushed flags. */
|
||||
|
16
ld/plugin.c
16
ld/plugin.c
@ -772,10 +772,14 @@ get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
|
||||
static enum ld_plugin_status
|
||||
add_input_file (const char *pathname)
|
||||
{
|
||||
lang_input_statement_type *is;
|
||||
|
||||
ASSERT (called_plugin);
|
||||
if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
|
||||
NULL))
|
||||
is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
|
||||
NULL);
|
||||
if (!is)
|
||||
return LDPS_ERR;
|
||||
is->flags.lto_output = 1;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
@ -783,10 +787,14 @@ add_input_file (const char *pathname)
|
||||
static enum ld_plugin_status
|
||||
add_input_library (const char *pathname)
|
||||
{
|
||||
lang_input_statement_type *is;
|
||||
|
||||
ASSERT (called_plugin);
|
||||
if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
|
||||
NULL))
|
||||
is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
|
||||
NULL);
|
||||
if (!is)
|
||||
return LDPS_ERR;
|
||||
is->flags.lto_output = 1;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user