[binutils-gdb] PR 33453 linker generated .eh_frame
Alan Modra
amodra@sourceware.org
Wed Nov 26 22:42:52 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bd7c19dff4b424b7328ebad67a09d7deb2eeef56
commit bd7c19dff4b424b7328ebad67a09d7deb2eeef56
Author: Alan Modra <amodra@gmail.com>
Date: Thu Nov 27 09:05:03 2025 +1030
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:
---
bfd/elf-bfd.h | 4 +++-
bfd/elf-eh-frame.c | 28 ++++++++++++++++++++++++++++
bfd/elf32-ppc.c | 8 ++++----
bfd/elf64-ppc.c | 7 +++----
bfd/elf64-s390.c | 13 +++++--------
bfd/elfxx-x86.c | 38 +++++++++++++++-----------------------
6 files changed, 58 insertions(+), 40 deletions(-)
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
More information about the Binutils-cvs
mailing list