]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Fix out-of-range branch veneers when --fix-cortex-a53-843419
authorRichard Earnshaw <rearnsha@arm.com>
Tue, 16 Dec 2025 14:08:10 +0000 (14:08 +0000)
committerRichard Earnshaw <rearnsha@arm.com>
Fri, 9 Jan 2026 10:21:09 +0000 (10:21 +0000)
The erratum mitigation support for the Cortex-A53 843419 erratum
inserts a new stub for every possible instance of the erratum.  Since
each stub ends up inserting 4k of space into the binary, in order to
avoid perturbing the alignment of other potential erratum sequences we
can end up adding substantially more space than the distance to the
next long-branch stub that we've prepared for.

The problem is, fundamentally a phase ordering problem, but that's
easily resolvable by running the 843419 erratum pass first and then
creating the stub groups once that is done.  In this way we take into
account the additional padding when forming the groups to ensure that
they remain within range.

bfd/elfnn-aarch64.c

index a3fd1dd75614ab63362f841251474abd51f99f1f..00a4f171cf131f85aa3c1db7e75cd9623e7c5513 100644 (file)
@@ -4772,49 +4772,55 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
       stub_group_size = 127 * 1024 * 1024;
     }
 
-  group_sections (htab, stub_group_size, stubs_always_before_branch);
-
-  (*htab->layout_sections_again) ();
-
-  if (htab->fix_erratum_835769)
+  /* The 843419 erratum fix inserts stub sections in place, not in
+     the section groups.  Running this after we have created the stub
+     groups can perturb the calculations and cause the stub groups
+     that have been created to be out of range.  Avoid this by running
+     this pass first and then creating the groups once we know how much
+     code this mitigation will insert.  */
+  if (htab->fix_erratum_843419 != ERRAT_NONE)
     {
       bfd *input_bfd;
 
       for (input_bfd = info->input_bfds;
-          input_bfd != NULL; input_bfd = input_bfd->link.next)
+          input_bfd != NULL;
+          input_bfd = input_bfd->link.next)
        {
+         asection *section;
+
          if (!is_aarch64_elf (input_bfd)
              || (input_bfd->flags & BFD_LINKER_CREATED) != 0)
            continue;
 
-         if (!_bfd_aarch64_erratum_835769_scan (input_bfd, info,
-                                                &num_erratum_835769_fixes))
-           return false;
+         for (section = input_bfd->sections;
+              section != NULL;
+              section = section->next)
+           if (!_bfd_aarch64_erratum_843419_scan (input_bfd, section, info))
+             return false;
        }
 
       _bfd_aarch64_resize_stubs (htab);
       (*htab->layout_sections_again) ();
     }
 
-  if (htab->fix_erratum_843419 != ERRAT_NONE)
+  group_sections (htab, stub_group_size, stubs_always_before_branch);
+
+  (*htab->layout_sections_again) ();
+
+  if (htab->fix_erratum_835769)
     {
       bfd *input_bfd;
 
       for (input_bfd = info->input_bfds;
-          input_bfd != NULL;
-          input_bfd = input_bfd->link.next)
+          input_bfd != NULL; input_bfd = input_bfd->link.next)
        {
-         asection *section;
-
          if (!is_aarch64_elf (input_bfd)
              || (input_bfd->flags & BFD_LINKER_CREATED) != 0)
            continue;
 
-         for (section = input_bfd->sections;
-              section != NULL;
-              section = section->next)
-           if (!_bfd_aarch64_erratum_843419_scan (input_bfd, section, info))
-             return false;
+         if (!_bfd_aarch64_erratum_835769_scan (input_bfd, info,
+                                                &num_erratum_835769_fixes))
+           return false;
        }
 
       _bfd_aarch64_resize_stubs (htab);