This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ELF/BFD: Hold the number of internal static relocs in `->reloc_count'
- From: "Maciej W. Rozycki" <macro at imgtec dot com>
- To: Alan Modra <amodra at gmail dot com>, "Joseph S. Myers" <joseph at codesourcery dot com>, "Jose E. Marchesi" <jose dot marchesi at oracle dot com>
- Cc: <binutils at sourceware dot org>
- Date: Thu, 1 Jun 2017 23:09:26 +0100
- Subject: [PATCH] ELF/BFD: Hold the number of internal static relocs in `->reloc_count'
- Authentication-results: sourceware.org; auth=none
Correct a commit e5713223cbc1 ("MIPS/BFD: For n64 hold the number of
internal relocs in `->reloc_count'") regression and change internal
relocation handling in the generic ELF BFD linker code such that, except
in the presence of R_SPARC_OLO10 relocations, a section's `reloc_count'
holds the number of internal rather than external relocations, making
the handling more consistent between GAS, which sets `->reloc_count'
with a call to `bfd_set_reloc', and LD, which sets `->reloc_count' as it
reads input sections.
The handling of dynamic relocations remains unchanged and they continue
holding the number of external relocations in `->reloc_count'; they are
also not converted to the internal form except in `elf_link_sort_relocs'
(which does not handle the general, i.e. non-n64-MIPS case of composed
relocations correctly as per the ELF gABI, though it does not seem to
matter for the targets we currently support).
The n64 MIPS backend is the only one with `int_rels_per_ext_rel' set to
non-one, and consequently the change is trivial for all the remaining
backends and targets.
bfd/
* elf-bfd.h (RELOC_AGAINST_DISCARDED_SECTION): Subtract `count'
from `reloc_count' rather than decrementing it.
* elf.c (bfd_section_from_shdr): Multiply the adjustment to
`reloc_count' by `int_rels_per_ext_rel'.
* elf32-score.c (score_elf_final_link_relocate): Do not multiply
`reloc_count' by `int_rels_per_ext_rel' for last relocation
entry determination.
(s3_bfd_score_elf_check_relocs): Likewise.
* elf32-score7.c (score_elf_final_link_relocate): Likewise.
(s7_bfd_score_elf_relocate_section): Likewise.
(s7_bfd_score_elf_check_relocs): Likewise.
* elf64-mips.c (mips_elf64_get_reloc_upper_bound): Remove
prototype and function.
(mips_elf64_slurp_one_reloc_table): Do not update `reloc_count'.
(mips_elf64_slurp_reloc_table): Assert that `reloc_count' is
triple rather than once the sum of REL and RELA relocation entry
counts.
(bfd_elf64_get_reloc_upper_bound): Remove macro.
* elflink.c (_bfd_elf_link_read_relocs): Do not multiply
`reloc_count' by `int_rels_per_ext_rel' for internal relocation
storage allocation size determination.
(elf_link_input_bfd): Multiply `.ctors' and `.dtors' section's
size by `int_rels_per_ext_rel'. Do not multiply `reloc_count'
by `int_rels_per_ext_rel' for last relocation entry
determination.
(bfd_elf_final_link): Do not multiply `reloc_count' by
`int_rels_per_ext_rel' for internal relocation storage
allocation size determination.
(init_reloc_cookie_rels): Do not multiply `reloc_count' by
`int_rels_per_ext_rel' for last relocation entry determination.
(elf_gc_smash_unused_vtentry_relocs): Likewise.
* elfxx-mips.c (_bfd_mips_elf_check_relocs): Likewise.
(_bfd_mips_elf_relocate_section): Likewise.
---
NB the `bfd_get_dynamic_reloc_upper_bound' backend method is only used by
ELF/x86 backends, but I have left the n64 MIPS handler in place to keep
the internal API complete just in case.
I think it would be good to convert all the remaining places and use the
actual count of internal relocations across the ELF BFD linker, including
the SPARC backend in particular. That would let code discard placeholder
R_MIPS_NONE relocations currently retained by the n64 MIPS backend, except
for `mips_elf64_slurp_one_reloc_table', used by the `-r' and `-R' options
to `objdump', where we want to retain them for presentation purposes.
This would let us remove the special arrangements made for n64 MIPS with
RELOC_AGAINST_DISCARDED_SECTION and commit 545fd46b6bb2 ("MIPS/BFD: Handle
linker garbage collection with n64 relocs"),
<https://sourceware.org/ml/binutils/2012-04/msg00455.html>. I think I
know how to resolve the issue with the general case of composed dynamic
relocations and `elf_link_sort_relocs' too.
We're nearing the end of the 2.29 development cycle though and I'd feel
more comfortable if such changes were made further away from an upcoming
release, so as a code clean-up rather than an actual issue fix I'm going
to defer any further work in this area for the time being; I have some
outstanding MIPS changes I'd prefer to get into 2.29 too, so I'd rather
focus on them instead now.
I have run this change through regression testing across my usual targets
with no problems observed. I have also run n64 MIPS glibc testing and
this change removes the `stdlib/test-canon2' failure as well as any other
regressions from commit e5713223cbc1, bringing results back to the state
as immediately before it.
The lack of any regressions in the LD test suite from commit e5713223cbc1
has also been concerning me, so I plan to make an n64 MIPS test case that
will reproduce the conditions that triggered with `stdlib/test-canon2' and
include it with or after this change, to cover the handling of n64 MIPS
relocation triplets; this will also undoubtedly help with any further work
in this area.
Any questions or comments? Otherwise, OK to apply?
Maciej
binutils-elf-bfd-int-rels-per-ext-rel.diff
Index: binutils/bfd/elf-bfd.h
===================================================================
--- binutils.orig/bfd/elf-bfd.h 2017-06-01 21:40:51.000000000 +0100
+++ binutils/bfd/elf-bfd.h 2017-06-01 21:44:09.393225649 +0100
@@ -2767,7 +2767,7 @@ extern asection _bfd_elf_large_com_secti
memmove (rel, rel + count, \
(relend - rel - count) * sizeof (*rel)); \
\
- input_section->reloc_count--; \
+ input_section->reloc_count -= count; \
relend -= count; \
rel--; \
continue; \
Index: binutils/bfd/elf.c
===================================================================
--- binutils.orig/bfd/elf.c 2017-06-01 21:40:51.000000000 +0100
+++ binutils/bfd/elf.c 2017-06-01 21:44:09.409459027 +0100
@@ -2374,7 +2374,8 @@ bfd_section_from_shdr (bfd *abfd, unsign
*hdr2 = *hdr;
*p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
- target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
+ target_sect->reloc_count += (NUM_SHDR_ENTRIES (hdr)
+ * bed->s->int_rels_per_ext_rel);
target_sect->flags |= SEC_RELOC;
target_sect->relocation = NULL;
target_sect->rel_filepos = hdr->sh_offset;
Index: binutils/bfd/elf32-score.c
===================================================================
--- binutils.orig/bfd/elf32-score.c 2017-06-01 21:40:51.000000000 +0100
+++ binutils/bfd/elf32-score.c 2017-06-01 21:44:09.421611050 +0100
@@ -2038,7 +2038,7 @@ score_elf_final_link_relocate (reloc_how
bfd_vma lo_value = 0;
bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relocs + input_section->reloc_count;
lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
if ((local_p) && (lo16_rel != NULL))
{
@@ -2808,7 +2808,7 @@ s3_bfd_score_elf_check_relocs (bfd *abfd
sreloc = NULL;
bed = get_elf_backend_data (abfd);
- rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+ rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; ++rel)
{
unsigned long r_symndx;
Index: binutils/bfd/elf32-score7.c
===================================================================
--- binutils.orig/bfd/elf32-score7.c 2017-06-01 21:40:51.000000000 +0100
+++ binutils/bfd/elf32-score7.c 2017-06-01 21:44:09.429674607 +0100
@@ -1906,7 +1906,7 @@ score_elf_final_link_relocate (reloc_how
bfd_vma lo_value = 0;
bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relocs + input_section->reloc_count;
lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
if ((local_p) && (lo16_rel != NULL))
{
@@ -1944,7 +1944,7 @@ score_elf_final_link_relocate (reloc_how
addend |= 0xffffc000;
bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relocs + input_section->reloc_count;
lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
if ((local_p) && (lo16_rel != NULL))
{
@@ -2481,7 +2481,7 @@ s7_bfd_score_elf_relocate_section (bfd *
addend |= 0xffffc000;
bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relocs + input_section->reloc_count;
lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
if (lo16_rel != NULL)
{
@@ -2617,7 +2617,7 @@ s7_bfd_score_elf_check_relocs (bfd *abfd
sreloc = NULL;
bed = get_elf_backend_data (abfd);
- rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+ rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; ++rel)
{
unsigned long r_symndx;
Index: binutils/bfd/elf64-mips.c
===================================================================
--- binutils.orig/bfd/elf64-mips.c 2017-06-01 21:40:51.665831938 +0100
+++ binutils/bfd/elf64-mips.c 2017-06-01 21:44:09.440778599 +0100
@@ -86,8 +86,6 @@ static void mips_elf64_info_to_howto_rel
(bfd *, arelent *, Elf_Internal_Rela *);
static void mips_elf64_info_to_howto_rela
(bfd *, arelent *, Elf_Internal_Rela *);
-static long mips_elf64_get_reloc_upper_bound
- (bfd *, asection *);
static long mips_elf64_get_dynamic_reloc_upper_bound
(bfd *);
static bfd_boolean mips_elf64_slurp_one_reloc_table
@@ -3648,12 +3646,6 @@ mips_elf64_info_to_howto_rela (bfd *abfd
to three relocs, we must tell the user to allocate more space. */
static long
-mips_elf64_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
-{
- return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
-}
-
-static long
mips_elf64_get_dynamic_reloc_upper_bound (bfd *abfd)
{
return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
@@ -3819,8 +3811,6 @@ mips_elf64_slurp_one_reloc_table (bfd *a
}
}
- asect->reloc_count += relent - relents;
-
if (allocated != NULL)
free (allocated);
@@ -3835,8 +3825,7 @@ mips_elf64_slurp_one_reloc_table (bfd *a
/* Read the relocations. On Irix 6, there can be two reloc sections
associated with a single data section. This is copied from
elfcode.h as well, with changes as small as accounting for 3
- internal relocs per external reloc and resetting reloc_count to
- zero before processing the relocs of a section. */
+ internal relocs per external reloc. */
static bfd_boolean
mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect,
@@ -3864,7 +3853,7 @@ mips_elf64_slurp_reloc_table (bfd *abfd,
rel_hdr2 = d->rela.hdr;
reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
- BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+ BFD_ASSERT (asect->reloc_count == 3 * (reloc_count + reloc_count2));
BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
|| (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
@@ -3890,9 +3879,6 @@ mips_elf64_slurp_reloc_table (bfd *abfd,
if (relents == NULL)
return FALSE;
- /* The slurp_one_reloc_table routine increments reloc_count. */
- asect->reloc_count = 0;
-
if (rel_hdr != NULL
&& ! mips_elf64_slurp_one_reloc_table (abfd, asect,
rel_hdr, reloc_count,
@@ -4437,7 +4423,6 @@ const struct elf_size_info mips_elf64_si
#define bfd_elf64_bfd_print_private_bfd_data \
_bfd_mips_elf_print_private_bfd_data
-#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
#define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
#define bfd_elf64_mkobject _bfd_mips_elf_mkobject
Index: binutils/bfd/elflink.c
===================================================================
--- binutils.orig/bfd/elflink.c 2017-06-01 21:40:51.679023736 +0100
+++ binutils/bfd/elflink.c 2017-06-01 21:44:09.454957776 +0100
@@ -2450,8 +2450,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
{
bfd_size_type size;
- size = o->reloc_count;
- size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
+ size = o->reloc_count * sizeof (Elf_Internal_Rela);
if (keep_memory)
internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
else
@@ -10402,7 +10401,8 @@ elf_link_input_bfd (struct elf_final_lin
".fini_array") == 0))
&& (o->name[6] == 0 || o->name[6] == '.'))
{
- if (o->size != o->reloc_count * address_size)
+ if (o->size * bed->s->int_rels_per_ext_rel
+ != o->reloc_count * address_size)
{
_bfd_error_handler
/* xgettext:c-format */
@@ -10426,7 +10426,7 @@ elf_link_input_bfd (struct elf_final_lin
relocs against removed link-once sections. */
rel = internal_relocs;
- relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = rel + o->reloc_count;
for ( ; rel < relend; rel++)
{
unsigned long r_symndx = rel->r_info >> r_sym_shift;
@@ -10614,7 +10614,7 @@ elf_link_input_bfd (struct elf_final_lin
/* Adjust the reloc addresses and symbol indices. */
irela = internal_relocs;
- irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ irelaend = irela + o->reloc_count;
rel_hash = esdo->rel.hashes + esdo->rel.count;
/* We start processing the REL relocs, if any. When we reach
IRELAMID in the loop, we switch to the RELA relocs. */
@@ -11788,8 +11788,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
if (max_internal_reloc_count != 0)
{
- amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
- amt *= sizeof (Elf_Internal_Rela);
+ amt = max_internal_reloc_count * sizeof (Elf_Internal_Rela);
flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
if (flinfo.internal_relocs == NULL)
goto error_return;
@@ -12588,8 +12587,7 @@ init_reloc_cookie_rels (struct elf_reloc
if (cookie->rels == NULL)
return FALSE;
cookie->rel = cookie->rels;
- cookie->relend = (cookie->rels
- + sec->reloc_count * bed->s->int_rels_per_ext_rel);
+ cookie->relend = cookie->rels + sec->reloc_count;
}
cookie->rel = cookie->rels;
return TRUE;
@@ -13174,7 +13172,7 @@ elf_gc_smash_unused_vtentry_relocs (stru
bed = get_elf_backend_data (sec->owner);
log_file_align = bed->s->log_file_align;
- relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relstart + sec->reloc_count;
for (rel = relstart; rel < relend; ++rel)
if (rel->r_offset >= hstart && rel->r_offset < hend)
Index: binutils/bfd/elfxx-mips.c
===================================================================
--- binutils.orig/bfd/elfxx-mips.c 2017-06-01 21:40:51.720671819 +0100
+++ binutils/bfd/elfxx-mips.c 2017-06-01 21:44:09.481494798 +0100
@@ -8102,7 +8102,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
bed = get_elf_backend_data (abfd);
- rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+ rel_end = relocs + sec->reloc_count;
/* Check for the mips16 stub sections. */
@@ -10034,7 +10034,7 @@ _bfd_mips_elf_relocate_section (bfd *out
const struct elf_backend_data *bed;
bed = get_elf_backend_data (output_bfd);
- relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relocs + input_section->reloc_count;
for (rel = relocs; rel < relend; ++rel)
{
const char *name;