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

Message ID 4a73b2a3-632a-1b52-5697-9bd2315ea3e4@jdrake.com
State New
Headers
Series [v5,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 2, 2025, 10:56 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 decided to go ahead and send v5 of the patch series.  I figure you can
take or leave patch 3, depending on how convincing LIU Hao's argument for
supporting XP is.

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

Comments

LIU Hao April 3, 2025, 4:03 a.m. UTC | #1
在 2025-4-3 06:56, Jeremy Drake 写道:
> 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 decided to go ahead and send v5 of the patch series.  I figure you can
> take or leave patch 3, depending on how convincing LIU Hao's argument for
> supporting XP is.
> 
>   bfd/peXXigen.c | 26 +++++++++++++++++---------
>   1 file changed, 17 insertions(+), 9 deletions(-)
> 

These changes look good to me.

```
MINGW32 ~/Desktop
$ gcc hello.c -Wl,--subsystem,windows:5.1 -Wl,--undefined,__load_config_used \
 > && objdump -p a.exe | grep -Fi "load configuration directory"
Entry a 000042ec 00000040 Load Configuration Directory

MINGW32 ~/Desktop
$ gcc hello.c -Wl,--subsystem,windows:5.2 -Wl,--undefined,__load_config_used \
 > && objdump -p a.exe | grep -Fi "load configuration directory"
Entry a 000042ec 000000bc Load Configuration Directory

MINGW64 ~/Desktop
$ gcc hello.c -Wl,--subsystem,windows:5.1 -Wl,--undefined,_load_config_used \
 > && objdump -p a.exe | grep -Fi "load configuration directory"
Entry a 0000000000004348 00000138 Load Configuration Directory

MINGW64 ~/Desktop
$ gcc hello.c -Wl,--subsystem,windows:5.2 -Wl,--undefined,_load_config_used \
 > && objdump -p a.exe | grep -Fi "load configuration directory"
Entry a 0000000000004348 00000138 Load Configuration Directory
```




-- 
Best regards,
LIU Hao
  
Jan Beulich April 3, 2025, 8:51 a.m. UTC | #2
On 03.04.2025 00:56, Jeremy Drake wrote:
> 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 decided to go ahead and send v5 of the patch series.  I figure you can
> take or leave patch 3, depending on how convincing LIU Hao's argument for
> supporting XP is.

Since you've taken the time to write it, I don't see a reason to not put
it in: Okay.

Jan
  

Patch

diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 0dec04fcc3e..bbf7bfb5545 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -4601,21 +4601,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 DataDictionary[%d]: size too large for the containing section"),