[v6,3/3] bfd: add load config size workaround for i386 XP and earlier.

Message ID c0558e1c-846e-00f7-c2e9-e142bb59cd03@jdrake.com
State New
Headers
Series [v6,1/3] bfd: properly use bfd_get_symbol_leading_char in peXXigen. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Jeremy Drake April 3, 2025, 6:14 p.m. UTC
  Per the Microsoft PE documentation, XP and earlier on i686 require the
Size field to be 64, rather than the actual size as required on other
architectures.  I have confirmed Windows 11 accepts either 64 or the
actual size for i386 images, but only the actual size for x86_64 images.

Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
I noticed and followed the convention of putting the operator at the
beginning rather than then end of the line when wrapping an expression.

 bfd/peXXigen.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)
  

Patch

diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 7c80a665247..2a4dea583b5 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -4602,21 +4602,29 @@  _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
 	      result = false;
 	    }

-	  /* The size is stored as the first 4 bytes at _load_config_used.
-	     The Microsoft PE format documentation says for compatibility with
-	     Windows XP and earlier, the size must be 64 for x86 images.  If
-	     anyone cares about those versions, the size should be overridden
-	     for i386.  */
+	  /* The size is stored as the first 4 bytes at _load_config_used.  */
 	  if (bfd_get_section_contents (abfd,
 		h1->root.u.def.section->output_section, data,
 		h1->root.u.def.section->output_offset + h1->root.u.def.value,
 		4))
 	    {
+	      uint32_t size = bfd_get_32 (abfd, data);
+	      /* The Microsoft PE format documentation says for compatibility
+		 with Windows XP and earlier, the size must be 64 for x86
+		 images.  */
 	      pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].Size =
-		bfd_get_32 (abfd, data);
-
-	      if (pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].Size >
-		  h1->root.u.def.section->size - h1->root.u.def.value)
+		(bfd_get_arch (abfd) == bfd_arch_i386
+		 && (bfd_get_mach (abfd) & ~bfd_mach_i386_intel_syntax)
+		 == bfd_mach_i386_i386
+		 && (pe_data (abfd)->pe_opthdr.Subsystem
+		   == IMAGE_SUBSYSTEM_WINDOWS_GUI
+		   || pe_data (abfd)->pe_opthdr.Subsystem
+		   == IMAGE_SUBSYSTEM_WINDOWS_CUI)
+		 && pe_data (abfd)->pe_opthdr.MajorSubsystemVersion * 256
+		 + pe_data (abfd)->pe_opthdr.MinorSubsystemVersion <= 0x0501)
+		? 64 : size;
+
+	      if (size > h1->root.u.def.section->size - h1->root.u.def.value)
 		{
 		  _bfd_error_handler
 		    (_("%pB: unable to fill in DataDirectory[%d]: size too large for the containing section"),