]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
bfd: add load config size workaround for i386 XP and earlier
authorJeremy Drake <sourceware-bugzilla@jdrake.com>
Mon, 7 Apr 2025 11:19:28 +0000 (13:19 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 7 Apr 2025 11:19:28 +0000 (13:19 +0200)
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>
bfd/peXXigen.c

index f63a7b6f11a5064850644e0f7a4ea0f3a436cf56..9938108ce6b86c6c24b3514a10b5539282c5216c 100644 (file)
@@ -4602,22 +4602,30 @@ _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 ((bfd_vma) 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"),