Bug 23560 - ld generates bad aarch64 veneers/long branch stubs
Summary: ld generates bad aarch64 veneers/long branch stubs
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.31
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-08-21 21:33 UTC by Rafael Auler
Modified: 2020-01-13 12:16 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rafael Auler 2018-08-21 21:33:47 UTC
Hi,

I noticed ld is failing to generate long branch stubs for aarch64 under certain conditions. After debugging the issue to try to understand what was happening, I observed that the function elfNN_aarch64_size_stubs() has a loop to compute the veneers, cache them into a special hash table and then redo layout (calling the layout_sections_again callback), doing this until no new stubs are needed. It then writes the stubs later by traversing the stub hash table with aarch64_build_one_stub() calls in elfNN_aarch64_build_stubs().

The problem is that layout_sections_again may change a symbol value (by changing its containing section's output_offset) but will not update the hash entry containing the stub destination, which was pre-computed with a now outdated value, thus generating a veneer with a bad target.

I could reproduce this on ld 2.31, but I wrote the patch for ld 2.36.

diff --git a/binutils-2.26.1/bfd/elfnn-aarch64.c b/binutils-2.26.1/bfd/elfnn-aarch64.c
--- a/binutils-2.26.1/bfd/elfnn-aarch64.c
+++ b/binutils-2.26.1/bfd/elfnn-aarch64.c
@@ -4163,6 +4163,9 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 		    {
 		      /* The proper stub has already been created.  */
 		      free (stub_name);
+		      /* Always update this stub target since it may have
+			 changed after layout */
+		      stub_entry->target_value = sym_value + irela->r_addend;
 		      continue;
 		    }
Comment 1 Sourceware Commits 2018-08-22 09:05:37 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3da64fe404031c093e8b59565d935fed214e28c1

commit 3da64fe404031c093e8b59565d935fed214e28c1
Author: Rafeal Auler <rafaelauler@gmail.com>
Date:   Wed Aug 22 10:04:09 2018 +0100

    Fix AArch64 stub layout algorithm to allow for the fact that section layut might change a stub's target location.
    
    	PR 23560
    	* elfnn-aarch64.c (elfNN_aarch64_size_stubs): Always update the
    	stub's target, since it may have been changed after the layout.
Comment 2 Nick Clifton 2018-08-22 09:43:43 UTC
Hi Rafael,

  Thanks for the bug report and patch.  I have applied your patch to the
  mainstream sources.

Cheers
  Nick
Comment 3 Sourceware Commits 2020-01-13 12:16:43 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a788aedd86da983faf0afef3cb41461118a2e9f2

commit a788aedd86da983faf0afef3cb41461118a2e9f2
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Jan 13 22:30:46 2020 +1030

    PR23560, PR23561, readelf memory leaks
    
    	PR 23560
    	PR 23561
    	* dwarf.c (display_debug_frames): Move fde_fc earlier.  Free
    	fde_fc col_type and col_offset.
    	* readelf.c (apply_relocations): Move symsec check earlier.
    	(free_debug_section): Free reloc_info.
    	(process_notes_at): Free pnotes on error path.
    	(process_object): Free dump_sects here..
    	(process_archive): ..not here.