[v2,1/2] aarch64: Fix DT_RELR support with discarded sections

Message ID 164ea78d38dc1ee3fffe0380df23092fd3f8541d.1717522516.git.szabolcs.nagy@arm.com
State Superseded
Headers
Series aarch64: fix DT_RELR with discarded sections |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed

Commit Message

Szabolcs Nagy June 4, 2024, 5:41 p.m. UTC
  In case of discarded sections, via /DISCARD/ or .gnu.linkonce,
relr relocation accounting was wrong.  This broke building linux.

The issue was that the *_relocate_section logic was copied to
*_late_size_sections to record relative relocations that can
be packed, however *_relocate_section is not called on sections
that are discarded, while record_relr_non_got_relocs is called
for all input sections. The fix is to filter out the discarded
sections with the same logic that is used to count non-GOT
relocs for local symbols earlier.

GOT relocations are affected too if all sections are discarded
that reference the GOT entry of a particular symbol, however
this can cause unused GOT entries independently of DT_RELR, and
the only difference with DT_RELR is that a relative reloc may be
emitted instead of a R_AARCH64_NONE for the unused GOT entry
which is acceptable. A proper fix would require redoing the GOT
refcounting after we know the discarded sections.
---
v2:
- only commit msg update: i realized that the GOT case is not
  handled right when DT_RELR is disabled so there is no point
  trying to fix that here and unnecessary relative relocation
  in such corner-case is acceptable. i updated the test case
  patch to cover the GOT cases that currently work.
---
 bfd/elfnn-aarch64.c | 4 ++++
 1 file changed, 4 insertions(+)
  

Comments

Alan Modra June 6, 2024, 1:17 a.m. UTC | #1
On Tue, Jun 04, 2024 at 06:41:34PM +0100, Szabolcs Nagy wrote:
> --- a/bfd/elfnn-aarch64.c
> +++ b/bfd/elfnn-aarch64.c
> @@ -9327,6 +9327,10 @@ record_relr_non_got_relocs (bfd *input_bfd, struct bfd_link_info *info,
>      return true;
>    if (sec->alignment_power == 0)
>      return true;
> +  if (!bfd_is_abs_section (sec)
> +      && bfd_is_abs_section (sec->output_section))
> +    /* Input section has been discarded.  */
> +    return true;

I think you should be using discarded_section here and in
elfNN_aarch64_late_size_sections.

>    sreloc = elf_section_data (sec)->sreloc;
>    if (sreloc == NULL)
>      return true;
> -- 
> 2.25.1
  
Szabolcs Nagy June 6, 2024, 7:57 a.m. UTC | #2
The 06/06/2024 10:47, Alan Modra wrote:
> On Tue, Jun 04, 2024 at 06:41:34PM +0100, Szabolcs Nagy wrote:
> > --- a/bfd/elfnn-aarch64.c
> > +++ b/bfd/elfnn-aarch64.c
> > @@ -9327,6 +9327,10 @@ record_relr_non_got_relocs (bfd *input_bfd, struct bfd_link_info *info,
> >      return true;
> >    if (sec->alignment_power == 0)
> >      return true;
> > +  if (!bfd_is_abs_section (sec)
> > +      && bfd_is_abs_section (sec->output_section))
> > +    /* Input section has been discarded.  */
> > +    return true;
> 
> I think you should be using discarded_section here and in
> elfNN_aarch64_late_size_sections.

i was not sure why late_size_sections did it this way.

i will fix it.
  

Patch

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 81f1a646125..02873f2ceb2 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -9327,6 +9327,10 @@  record_relr_non_got_relocs (bfd *input_bfd, struct bfd_link_info *info,
     return true;
   if (sec->alignment_power == 0)
     return true;
+  if (!bfd_is_abs_section (sec)
+      && bfd_is_abs_section (sec->output_section))
+    /* Input section has been discarded.  */
+    return true;
   sreloc = elf_section_data (sec)->sreloc;
   if (sreloc == NULL)
     return true;