[binutils-gdb] bfd: section merging for PE/COFF images

Jan Beulich jbeulich@sourceware.org
Fri Oct 24 13:15:03 GMT 2025


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

commit a04b91a64199ba87ff07efb3b07c3d1ebeb2e8cf
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Oct 24 15:12:07 2025 +0200

    bfd: section merging for PE/COFF images
    
    Leverage the generalized section merging to enable it also when linking
    PE/COFF images (from ELF objects).
    
    Sadly the previous hack in bfd_generic_get_relocated_section_contents()
    (from "bfd: generalize _bfd_elf_merge_sections()") is getting yet more
    bogus.

Diff:
---
 bfd/coffgen.c  | 12 ++++++++++--
 bfd/cofflink.c | 11 ++++++++---
 bfd/merge.c    |  7 ++++---
 bfd/peicode.h  |  5 +++++
 4 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index c1811cbce1c..071ca0d133c 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1259,9 +1259,17 @@ coff_write_alien_symbol (bfd *abfd,
     }
   else
     {
+      asection *isec = symbol->section;
+
       native->u.syment.n_scnum = output_section->target_index;
-      native->u.syment.n_value = (symbol->value
-				  + symbol->section->output_offset);
+      native->u.syment.n_value = symbol->value;
+
+      if (isec->sec_info_type == SEC_INFO_TYPE_MERGE
+	  && !(symbol->flags & (BSF_SECTION_SYM | BSF_MERGE_RESOLVED)))
+	native->u.syment.n_value =
+	  _bfd_merged_section_offset (abfd, &isec, symbol->value);
+
+      native->u.syment.n_value += isec->output_offset;
       if (! obj_pe (abfd))
 	native->u.syment.n_value += output_section->vma;
 
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 2ce5a0273ae..d1658ac1e89 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -2608,13 +2608,18 @@ _bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data)
       {
 	asection *sec;
 
-	sec = h->root.u.def.section->output_section;
+	sec = h->root.u.def.section;
+	isym.n_value = h->root.u.def.value;
+	if (sec->sec_info_type == SEC_INFO_TYPE_MERGE)
+	  isym.n_value =
+	    _bfd_merged_section_offset (output_bfd, &sec, isym.n_value);
+	isym.n_value += sec->output_offset;
+
+	sec = sec->output_section;
 	if (bfd_is_abs_section (sec))
 	  isym.n_scnum = N_ABS;
 	else
 	  isym.n_scnum = sec->target_index;
-	isym.n_value = (h->root.u.def.value
-			+ h->root.u.def.section->output_offset);
 	if (! obj_pe (flaginfo->output_bfd))
 	  isym.n_value += sec->vma;
 #ifdef BFD64
diff --git a/bfd/merge.c b/bfd/merge.c
index 0de35da5cf4..b25d55d8539 100644
--- a/bfd/merge.c
+++ b/bfd/merge.c
@@ -1090,7 +1090,7 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec)
   struct sec_merge_sec_info *secinfo = sec->sec_info;
   file_ptr pos;
   unsigned char *contents;
-  Elf_Internal_Shdr *hdr;
+  Elf_Internal_Shdr *hdr = NULL;
 
   if (!secinfo)
     return false;
@@ -1099,8 +1099,9 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec)
     return true;
 
   /* FIXME: octets_per_byte.  */
-  hdr = &elf_section_data (sec->output_section)->this_hdr;
-  if (hdr->sh_offset == (file_ptr) -1)
+  if (bfd_get_flavour (output_bfd) == bfd_target_elf_flavour)
+    hdr = &elf_section_data (sec->output_section)->this_hdr;
+  if (hdr != NULL && hdr->sh_offset == (file_ptr) -1)
     {
       /* We must compress this section.  Write output to the
 	 buffer.  */
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 3a93e008799..8192bb9fa4b 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -82,6 +82,11 @@ static bool pe_bfd_copy_private_bfd_data (bfd *, bfd *);
 #define coff_mkobject_hook pe_mkobject_hook
 
 #ifdef COFF_IMAGE_WITH_PE
+
+/* For the case of linking ELF objects into a PE binary.  */
+#undef TARGET_MERGE_SECTIONS
+#define TARGET_MERGE_SECTIONS true
+
 /* This structure contains static variables used by the ILF code.  */
 typedef asection * asection_ptr;


More information about the Binutils-cvs mailing list