From: Alan Modra Date: Wed, 26 Nov 2025 22:35:03 +0000 (+1030) Subject: PR 33453 linker generated .eh_frame X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bd7c19dff4b424b7328ebad67a09d7deb2eeef56;p=thirdparty%2Fbinutils-gdb.git PR 33453 linker generated .eh_frame 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. --- diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index d1368ece901..5f08d1a4dfb 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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; diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 91d08bb9e30..cc2a5033cc6 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -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. */ diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 6ed220d572c..753cb22baea 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -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; } diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 48af990e9e4..b39fe477dd8 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -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, diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index decd742a8d5..440e60af5be 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -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 diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 67fba0fa553..215a1569e9d 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -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