]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 33453 linker generated .eh_frame
authorAlan Modra <amodra@gmail.com>
Wed, 26 Nov 2025 22:35:03 +0000 (09:05 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 26 Nov 2025 22:42:07 +0000 (09:12 +1030)
This is the final piece to fix the PR33453 testcase.  It makes use of
the extended size final link buffer when writing linker generated
.eh_frame.

PR 33453
* elf-bfd.h (_bfd_elf_write_linker_section_eh_frame): Declare.
* elf-eh-frame.c (_bfd_elf_write_linker_section_eh_frame): New.
* elf32-ppc.c (ppc_elf_finish_dynamic_sections): Use new function.
* elf64-ppc.c (ppc64_elf_finish_dynamic_sections): Likewise.
* elf64-s390.c (elf_s390_finish_dynamic_sections): Likewise.
* elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): Likewise.

bfd/elf-bfd.h
bfd/elf-eh-frame.c
bfd/elf32-ppc.c
bfd/elf64-ppc.c
bfd/elf64-s390.c
bfd/elfxx-x86.c

index d1368ece9016a11f44950b3ec91dcc9e349357c5..5f08d1a4dfb49368e512232bfb4f5a92c73afccc 100644 (file)
@@ -2553,7 +2553,9 @@ extern bfd_vma _bfd_elf_eh_frame_section_offset
   (bfd *, struct bfd_link_info *, asection *, bfd_vma) ATTRIBUTE_HIDDEN;
 extern bool _bfd_elf_write_section_eh_frame
   (bfd *, struct bfd_link_info *, asection *, bfd_byte *) ATTRIBUTE_HIDDEN;
-bool _bfd_elf_write_section_eh_frame_entry
+extern bool _bfd_elf_write_linker_section_eh_frame
+  (bfd *, struct bfd_link_info *, asection *, bfd_byte *) ATTRIBUTE_HIDDEN;
+extern bool _bfd_elf_write_section_eh_frame_entry
   (bfd *, struct bfd_link_info *, asection *, bfd_byte *) ATTRIBUTE_HIDDEN;
 extern bool _bfd_elf_fixup_eh_frame_hdr
   (struct bfd_link_info *) ATTRIBUTE_HIDDEN;
index 91d08bb9e30ebbf8a7c92fd09e28a7adbb02436f..cc2a5033cc6cc86e722120ad67488b678b6b110c 100644 (file)
@@ -2294,6 +2294,34 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
                                   sec->size);
 }
 
+/* A handy wrapper for writing linker generated .eh_frame sections
+   with contents that may need to be extended beyond the initial size
+   allocated.  */
+
+bool
+_bfd_elf_write_linker_section_eh_frame (bfd *obfd, struct bfd_link_info *info,
+                                       asection *sec, bfd_byte *bigbuf)
+{
+  bfd_size_type initial_size = sec->rawsize != 0 ? sec->rawsize : sec->size;
+  memcpy (bigbuf, sec->contents, initial_size);
+  if (!_bfd_elf_write_section_eh_frame (obfd, info, sec, bigbuf))
+    return false;
+  if (sec->size > initial_size)
+    {
+      if (sec->alloced)
+       sec->contents = bfd_alloc (sec->owner, sec->size);
+      else
+       {
+         free (sec->contents);
+         sec->contents = bfd_malloc (sec->size);
+       }
+      if (sec->contents == NULL)
+       return false;
+    }
+  memcpy (sec->contents, bigbuf, sec->size);
+  return true;
+}
+
 /* Helper function used to sort .eh_frame_hdr search table by increasing
    VMA of FDE initial location.  */
 
index 6ed220d572c5a4a1adbdaadbf86e1e4cd069a1d6..753cb22baea13ebd8bb4d2257399d96daa115f68 100644 (file)
@@ -9921,7 +9921,7 @@ ppc_elf_reloc_type_class (const struct bfd_link_info *info,
 static bool
 ppc_elf_finish_dynamic_sections (bfd *output_bfd,
                                 struct bfd_link_info *info,
-                                bfd_byte *buf ATTRIBUTE_UNUSED)
+                                bfd_byte *buf)
 {
   asection *sdyn;
   struct ppc_elf_link_hash_table *htab;
@@ -10345,9 +10345,9 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
       bfd_put_32 (htab->elf.dynobj, val, p);
 
       if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
-         && !_bfd_elf_write_section_eh_frame (output_bfd, info,
-                                              htab->glink_eh_frame,
-                                              htab->glink_eh_frame->contents))
+         && !_bfd_elf_write_linker_section_eh_frame (output_bfd, info,
+                                                     htab->glink_eh_frame,
+                                                     buf))
        return false;
     }
 
index 48af990e9e4526cc3e7e2c9265edacb020b863a8..b39fe477dd8943e7f88f718d7a4ad67096bef8ac 100644 (file)
@@ -18249,7 +18249,7 @@ ppc64_elf_reloc_type_class (const struct bfd_link_info *info,
 static bool
 ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
                                   struct bfd_link_info *info,
-                                  bfd_byte *buf ATTRIBUTE_UNUSED)
+                                  bfd_byte *buf)
 {
   struct ppc_link_hash_table *htab;
   bfd *dynobj;
@@ -18387,9 +18387,8 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
   if (htab->glink_eh_frame != NULL
       && htab->glink_eh_frame->size != 0
       && htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
-      && !_bfd_elf_write_section_eh_frame (output_bfd, info,
-                                          htab->glink_eh_frame,
-                                          htab->glink_eh_frame->contents))
+      && !_bfd_elf_write_linker_section_eh_frame (output_bfd, info,
+                                                 htab->glink_eh_frame, buf))
     return false;
 
   /* We need to handle writing out multiple GOT sections ourselves,
index decd742a8d5431c8a4938ca88f6cdf4d1bb587fe..440e60af5be57528c41762f1bcb1dcefc91df2f6 100644 (file)
@@ -3842,7 +3842,7 @@ elf_s390_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
 static bool
 elf_s390_finish_dynamic_sections (bfd *output_bfd,
                                  struct bfd_link_info *info,
-                                 bfd_byte *buf ATTRIBUTE_UNUSED)
+                                 bfd_byte *buf)
 {
   struct elf_s390_link_hash_table *htab;
   bfd *dynobj;
@@ -4009,13 +4009,10 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
                             + PLT_FDE_START_OFFSET);
        }
 
-      if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_eh_frame,
-                                                htab->plt_eh_frame->contents))
-           return NULL;
-       }
+      if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_linker_section_eh_frame (output_bfd, info,
+                                                     htab->plt_eh_frame, buf))
+       return NULL;
     }
 
   /* Make any adjustment if necessary and merge .sframe section to
index 67fba0fa553041df00b12f09d40a8812075d6a3c..215a1569e9d4774c3272259b917052ab29487b53 100644 (file)
@@ -2763,7 +2763,7 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
 struct elf_x86_link_hash_table *
 _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
                                      struct bfd_link_info *info,
-                                     bfd_byte *buf ATTRIBUTE_UNUSED)
+                                     bfd_byte *buf)
 {
   struct elf_x86_link_hash_table *htab;
   const struct elf_backend_data *bed;
@@ -2924,13 +2924,10 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
                             + PLT_FDE_START_OFFSET);
        }
 
-      if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_eh_frame,
-                                                htab->plt_eh_frame->contents))
-           return NULL;
-       }
+      if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_linker_section_eh_frame (output_bfd, info,
+                                                     htab->plt_eh_frame, buf))
+       return NULL;
     }
 
   /* Adjust .eh_frame for .plt.got section.  */
@@ -2951,13 +2948,11 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
                             htab->plt_got_eh_frame->contents
                             + PLT_FDE_START_OFFSET);
        }
-      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_got_eh_frame,
-                                                htab->plt_got_eh_frame->contents))
-           return NULL;
-       }
+      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_linker_section_eh_frame (output_bfd, info,
+                                                     htab->plt_got_eh_frame,
+                                                     buf))
+       return NULL;
     }
 
   /* Adjust .eh_frame for the second PLT section.  */
@@ -2979,14 +2974,11 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
                             htab->plt_second_eh_frame->contents
                             + PLT_FDE_START_OFFSET);
        }
-      if (htab->plt_second_eh_frame->sec_info_type
-         == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_second_eh_frame,
-                                                htab->plt_second_eh_frame->contents))
-           return NULL;
-       }
+      if (htab->plt_second_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_linker_section_eh_frame (output_bfd, info,
+                                                     htab->plt_second_eh_frame,
+                                                     buf))
+       return NULL;
     }
 
   /* Make any adjustment if necessary and merge .sframe section to