binutils: backport upstream commits

This fixes #23577,
https://sourceware.org/bugzilla/show_bug.cgi?id=14339, and
https://sourceware.org/bugzilla/show_bug.cgi?id=32675 at least.  Also
backport support for filling in the load config directory with
_load_config_used.  This is not directly a bugfix, but avoided a
conflict with the other patches.
This commit is contained in:
Jeremy Drake
2025-06-13 11:16:45 -07:00
parent 66c94fb01b
commit cef453db44
9 changed files with 1169 additions and 2 deletions

View File

@@ -0,0 +1,54 @@
From 9d5eb91175c5ddb601ec24d3249ad23e81f92619 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Mon, 7 Apr 2025 13:18:46 +0200
Subject: [PATCH 5000/5007] bfd: properly use bfd_get_symbol_leading_char() in
peXXigen
This function returns the leading char to use, so we cannot just assume
it will always be '_' or '\0'.
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
bfd/peXXigen.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 29012688adf..561f8585766 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -4403,6 +4403,7 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
struct coff_link_hash_entry *h1;
struct bfd_link_info *info = pfinfo->info;
bool result = true;
+ char name[20];
/* There are a few fields that need to be filled in now while we
have symbol table access.
@@ -4540,10 +4541,9 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
}
}
- h1 = coff_link_hash_lookup (coff_hash_table (info),
- (bfd_get_symbol_leading_char (abfd) != 0
- ? "__tls_used" : "_tls_used"),
- false, false, true);
+ name[0] = bfd_get_symbol_leading_char (abfd);
+ strcpy (name + !!name[0], "_tls_used");
+ h1 = coff_link_hash_lookup (coff_hash_table (info), name, false, false, true);
if (h1 != NULL)
{
if ((h1->root.type == bfd_link_hash_defined
@@ -4558,8 +4558,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
else
{
_bfd_error_handler
- (_("%pB: unable to fill in DataDictionary[9] because __tls_used is missing"),
- abfd);
+ (_("%pB: unable to fill in DataDirectory[%d]: %s not defined correctly"),
+ abfd, PE_TLS_TABLE, name);
result = false;
}
/* According to PECOFF sepcifications by Microsoft version 8.2
--
2.49.0.windows.1

View File

@@ -0,0 +1,76 @@
From 75fde30d74a8d415cc8f642d3c560079245c1ca3 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Mon, 7 Apr 2025 13:19:10 +0200
Subject: [PATCH 5001/5007] bfd: adjust a few error messages
Rationalize the error messages in _bfd_XXi_final_link_postscript().
They now all correctly refer to DataDirectory instead of DataDictionary,
and use unified format strings, so fewer translations are needed.
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
bfd/peXXigen.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 561f8585766..7ca57831a94 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -4431,8 +4431,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
else
{
_bfd_error_handler
- (_("%pB: unable to fill in DataDictionary[1] because .idata$2 is missing"),
- abfd);
+ (_("%pB: unable to fill in DataDirectory[%d]: %s is missing"),
+ abfd, PE_IMPORT_TABLE, ".idata$2");
result = false;
}
@@ -4451,8 +4451,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
else
{
_bfd_error_handler
- (_("%pB: unable to fill in DataDictionary[1] because .idata$4 is missing"),
- abfd);
+ (_("%pB: unable to fill in DataDirectory[%d]: %s is missing"),
+ abfd, PE_IMPORT_TABLE, ".idata$4");
result = false;
}
@@ -4472,8 +4472,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
else
{
_bfd_error_handler
- (_("%pB: unable to fill in DataDictionary[12] because .idata$5 is missing"),
- abfd);
+ (_("%pB: unable to fill in DataDirectory[%d]: %s is missing"),
+ abfd, PE_IMPORT_ADDRESS_TABLE, ".idata$5");
result = false;
}
@@ -4492,8 +4492,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
else
{
_bfd_error_handler
- (_("%pB: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] because .idata$6 is missing"),
- abfd);
+ (_("%pB: unable to fill in DataDirectory[%d]: %s is missing"),
+ abfd, PE_IMPORT_ADDRESS_TABLE, ".idata$6");
result = false;
}
}
@@ -4534,8 +4534,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
else
{
_bfd_error_handler
- (_("%pB: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE(12)]"
- " because .idata$6 is missing"), abfd);
+ (_("%pB: unable to fill in DataDirectory[%d]: %s not defined correctly"),
+ abfd, PE_IMPORT_ADDRESS_TABLE, "__IAT_end__");
result = false;
}
}
--
2.49.0.windows.1

View File

@@ -0,0 +1,119 @@
From 8df2060980184a5762d774d95425c6fccaaba382 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Mon, 7 Apr 2025 13:19:19 +0200
Subject: [PATCH 5002/5007] bfd: fill in PE load config directory entry
This is filled in with the rva of _load_config_used if defined (much
like _tls_used), and the size is the first 32-bit value at that symbol.
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
bfd/peXXigen.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 7ca57831a94..f63a7b6f11a 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -593,7 +593,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out;
bfd_vma sa, fa, ib;
- IMAGE_DATA_DIRECTORY idata2, idata5, tls;
+ IMAGE_DATA_DIRECTORY idata2, idata5, tls, loadcfg;
sa = extra->SectionAlignment;
fa = extra->FileAlignment;
@@ -602,6 +602,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE];
idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE];
tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE];
+ loadcfg = pe->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE];
if (aouthdr_in->tsize)
{
@@ -651,6 +652,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
extra->DataDirectory[PE_IMPORT_TABLE] = idata2;
extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5;
extra->DataDirectory[PE_TLS_TABLE] = tls;
+ extra->DataDirectory[PE_LOAD_CONFIG_TABLE] = loadcfg;
if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0)
/* Until other .idata fixes are made (pending patch), the entry for
@@ -4573,6 +4575,73 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
#endif
}
+ name[0] = bfd_get_symbol_leading_char (abfd);
+ strcpy (name + !!name[0], "_load_config_used");
+ h1 = coff_link_hash_lookup (coff_hash_table (info), name, false, false, true);
+ if (h1 != NULL)
+ {
+ char data[4];
+ if ((h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ {
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset
+ - pe_data (abfd)->pe_opthdr.ImageBase);
+
+ if (pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].VirtualAddress
+ & (bfd_arch_bits_per_address (abfd) / bfd_arch_bits_per_byte (abfd)
+ - 1))
+ {
+ _bfd_error_handler
+ (_("%pB: unable to fill in DataDirectory[%d]: %s not properly aligned"),
+ abfd, PE_LOAD_CONFIG_TABLE, name);
+ 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. */
+ 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))
+ {
+ 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_error_handler
+ (_("%pB: unable to fill in DataDirectory[%d]: size too large for the containing section"),
+ abfd, PE_LOAD_CONFIG_TABLE);
+ result = false;
+ }
+ }
+ else
+ {
+ _bfd_error_handler
+ (_("%pB: unable to fill in DataDirectory[%d]: size can't be read from %s"),
+ abfd, PE_LOAD_CONFIG_TABLE, name);
+ result = false;
+ }
+ }
+ else
+ {
+ _bfd_error_handler
+ (_("%pB: unable to fill in DataDirectory[%d]: %s not defined correctly"),
+ abfd, PE_LOAD_CONFIG_TABLE, name);
+ result = false;
+ }
+ }
+
/* If there is a .pdata section and we have linked pdata finally, we
need to sort the entries ascending. */
#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined (COFF_WITH_peRiscV64))
--
2.49.0.windows.1

View File

@@ -0,0 +1,64 @@
From eb4f86f44322c7969e01fe41597a26fbbf033dab Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Mon, 7 Apr 2025 13:19:28 +0200
Subject: [PATCH 5003/5007] bfd: add load config size workaround for i386 XP
and earlier
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 | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index f63a7b6f11a..9938108ce6b 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -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"),
--
2.49.0.windows.1

View File

@@ -0,0 +1,573 @@
From 31ed2c87d3ef91159f8262e93ea24cc75722b9ab Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Fri, 13 Jun 2025 07:52:29 +0200
Subject: [PATCH 5004/5007] bfd,ld,dlltool: Emit delay-load import data into
its own section
A delay-import symbol (of a function) is resolved when a call to it is made.
The delay loader may overwrite the `__imp_` pointer to the actual function
after it has been resolved, which requires the pointer itself be in a
writeable section.
Previously it was placed in the ordinary Import Address Table (IAT), which
is emitted into the `.idata` section, which had been changed to read-only
in db00f6c3aceabbf03acdb69e74b59b2d2b043cd7, which caused segmentation
faults when functions from delay-import library were called. This is
PR 32675.
This commit makes DLLTOOL emit delay-import IAT into `.didat`, as specified
by Microsoft. Most of the code is copied from `.idata`, except that this
section is writeable. As a side-effect of this, PR 14339 is also fixed.
Using this DEF:
```
; ws2_32.def
LIBRARY "WS2_32.DLL"
EXPORTS
WSAGetLastError
```
and this C program:
```
// delay.c
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <stdio.h>
/////////////////////////////////////////////////////////
// User code
/////////////////////////////////////////////////////////
DWORD WINAPI WSAGetLastError(void);
extern PVOID __imp_WSAGetLastError;
int
main(void)
{
fprintf(stderr, "before delay load, __imp_WSAGetLastError = %p\n", __imp_WSAGetLastError);
SetLastError(123);
fprintf(stderr, "WSAGetLastError() = %d\n", WSAGetLastError());
fprintf(stderr, "after delay load, __imp_WSAGetLastError = %p\n", __imp_WSAGetLastError);
__imp_WSAGetLastError = (PVOID) 1234567;
fprintf(stderr, "after plain write, __imp_WSAGetLastError = %p\n", __imp_WSAGetLastError);
}
/////////////////////////////////////////////////////////
// Overridden `__delayLoadHelper2` facility
/////////////////////////////////////////////////////////
extern char __ImageBase[];
PVOID WINAPI ResolveDelayLoadedAPI(PVOID ParentModuleBase, LPCVOID DelayloadDescriptor,
PVOID FailureDllHook, PVOID FailureSystemHook,
FARPROC* ThunkAddress, ULONG Flags);
FARPROC WINAPI DelayLoadFailureHook(LPCSTR name, LPCSTR function);
FARPROC WINAPI __delayLoadHelper2(LPCVOID pidd, FARPROC* ppfnIATEntry)
{
return ResolveDelayLoadedAPI(&__ImageBase, pidd, NULL, (PVOID) DelayLoadFailureHook,
ppfnIATEntry, 0);
}
```
This program used to crash:
```
$ dlltool -nn -d ws2_32.def -y delay_ws2_32.a
$ gcc -g delay.c delay_ws2_32.a -o delay.exe
$ ./delay.exe
before delay load, __imp_WSAGetLastError = 00007FF6937215C6
Segmentation fault
```
After this commit, it loads and calls `WSAGetLastError()` properly, and
`__imp_WSAGetLastError` is writeable:
```
$ dlltool -nn -d ws2_32.def -y delay_ws2_32.a
$ gcc -g delay.c delay_ws2_32.a -o delay.exe
$ ./delay.exe
before delay load, __imp_WSAGetLastError = 00007FF76E2215C6
WSAGetLastError() = 123
after delay load, __imp_WSAGetLastError = 00007FFF191FA720
after plain write, __imp_WSAGetLastError = 000000000012D687
```
Reference: https://learn.microsoft.com/en-us/windows/win32/secbp/pe-metadata#import-handling
Co-authored-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
bfd/coffgen.c | 15 +++++++++
bfd/pe-aarch64.c | 2 ++
bfd/pe-arm.c | 2 ++
bfd/pe-i386.c | 2 ++
bfd/pe-x86_64.c | 2 ++
bfd/peXXigen.c | 1 +
bfd/pei-aarch64.c | 2 ++
bfd/pei-arm.c | 2 ++
bfd/pei-i386.c | 2 ++
bfd/pei-loongarch64.c | 2 ++
bfd/pei-riscv64.c | 2 ++
bfd/pei-x86_64.c | 2 ++
bfd/syms.c | 1 +
binutils/dlltool.c | 76 +++++++++++++++++++++++++++++++++++++++----
ld/scripttempl/pe.sc | 26 ++++++++++++++-
ld/scripttempl/pep.sc | 27 ++++++++++++++-
16 files changed, 158 insertions(+), 8 deletions(-)
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index d8c60e26342..8a01b7fdef8 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -43,6 +43,7 @@
#include "coff/internal.h"
#include "libcoff.h"
#include "hashtab.h"
+#include "safe-ctype.h"
/* Extract a long section name at STRINDEX and copy it to the bfd objstack.
Return NULL in case of error. */
@@ -3099,6 +3100,19 @@ coff_gc_sweep_symbol (struct coff_link_hash_entry *h,
typedef bool (*gc_sweep_hook_fn)
(bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *);
+static inline bool
+is_subsection (const char *str, const char *prefix)
+{
+ size_t n = strlen (prefix);
+ if (strncmp (str, prefix, n) != 0)
+ return false;
+ if (str[n] == 0)
+ return true;
+ else if (str[n] != '$')
+ return false;
+ return ISDIGIT (str[n + 1]) && str[n + 2] == 0;
+}
+
static bool
coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{
@@ -3120,6 +3134,7 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
else if (startswith (o->name, ".idata")
|| startswith (o->name, ".pdata")
|| startswith (o->name, ".xdata")
+ || is_subsection (o->name, ".didat")
|| startswith (o->name, ".rsrc"))
o->gc_mark = 1;
diff --git a/bfd/pe-aarch64.c b/bfd/pe-aarch64.c
index 64975d19f67..2204a51c509 100644
--- a/bfd/pe-aarch64.c
+++ b/bfd/pe-aarch64.c
@@ -48,6 +48,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pe-arm.c b/bfd/pe-arm.c
index fe4e18e7e06..5efa559a353 100644
--- a/bfd/pe-arm.c
+++ b/bfd/pe-arm.c
@@ -43,6 +43,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pe-i386.c b/bfd/pe-i386.c
index 07f674342cf..3742fd8feb4 100644
--- a/bfd/pe-i386.c
+++ b/bfd/pe-i386.c
@@ -36,6 +36,8 @@
#define COFF_SECTION_ALIGNMENT_ENTRIES \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pe-x86_64.c b/bfd/pe-x86_64.c
index d56d75dabd0..9151aac5792 100644
--- a/bfd/pe-x86_64.c
+++ b/bfd/pe-x86_64.c
@@ -57,6 +57,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 9938108ce6b..7dfa82ee43e 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -1001,6 +1001,7 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
{ ".arch", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_ALIGN_8BYTES },
{ ".bss", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
{ ".data", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
+ { ".didat", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE },
{ ".edata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
{ ".idata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
{ ".pdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
diff --git a/bfd/pei-aarch64.c b/bfd/pei-aarch64.c
index 3d7f5b376a6..00f38e0f9bb 100644
--- a/bfd/pei-aarch64.c
+++ b/bfd/pei-aarch64.c
@@ -49,6 +49,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pei-arm.c b/bfd/pei-arm.c
index 2abc14de025..07cebb510ef 100644
--- a/bfd/pei-arm.c
+++ b/bfd/pei-arm.c
@@ -45,6 +45,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pei-i386.c b/bfd/pei-i386.c
index 676a824877b..a26f1702b3b 100644
--- a/bfd/pei-i386.c
+++ b/bfd/pei-i386.c
@@ -35,6 +35,8 @@
#define COFF_SECTION_ALIGNMENT_ENTRIES \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pei-loongarch64.c b/bfd/pei-loongarch64.c
index 4b3a30d4ddc..f22498cab21 100644
--- a/bfd/pei-loongarch64.c
+++ b/bfd/pei-loongarch64.c
@@ -49,6 +49,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pei-riscv64.c b/bfd/pei-riscv64.c
index e87aa429350..c4ae7bfb89a 100644
--- a/bfd/pei-riscv64.c
+++ b/bfd/pei-riscv64.c
@@ -49,6 +49,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/pei-x86_64.c b/bfd/pei-x86_64.c
index 3f8f255af33..a5c2fd85f06 100644
--- a/bfd/pei-x86_64.c
+++ b/bfd/pei-x86_64.c
@@ -51,6 +51,8 @@
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
+ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
diff --git a/bfd/syms.c b/bfd/syms.c
index 95017ba4f11..df2229b3fa3 100644
--- a/bfd/syms.c
+++ b/bfd/syms.c
@@ -594,6 +594,7 @@ struct section_to_type
adding entries. Since it is so short, a linear search is used. */
static const struct section_to_type stt[] =
{
+ {".didat", 'i'}, /* MSVC's .didat (delay import) section */
{".drectve", 'i'}, /* MSVC's .drective section */
{".edata", 'e'}, /* MSVC's .edata (export) section */
{".idata", 'i'}, /* MSVC's .idata (import) section */
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index d32bf2062b4..371d61fc484 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -2268,7 +2268,7 @@ typedef struct
#define DATA_SEC_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_DATA)
#define BSS_SEC_FLAGS SEC_ALLOC
-static sinfo secdata[NSECS] =
+static sinfo secdata_plain[NSECS] =
{
INIT_SEC_DATA (TEXT, ".text", TEXT_SEC_FLAGS, 2),
INIT_SEC_DATA (DATA, ".data", DATA_SEC_FLAGS, 2),
@@ -2279,6 +2279,17 @@ static sinfo secdata[NSECS] =
INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1)
};
+static sinfo secdata_delay[NSECS] =
+{
+ INIT_SEC_DATA (TEXT, ".text", TEXT_SEC_FLAGS, 2),
+ INIT_SEC_DATA (DATA, ".data", DATA_SEC_FLAGS, 2),
+ INIT_SEC_DATA (BSS, ".bss", BSS_SEC_FLAGS, 2),
+ INIT_SEC_DATA (IDATA7, ".didat$7", SEC_HAS_CONTENTS, 2),
+ INIT_SEC_DATA (IDATA5, ".didat$5", SEC_HAS_CONTENTS, 2),
+ INIT_SEC_DATA (IDATA4, ".didat$4", SEC_HAS_CONTENTS, 2),
+ INIT_SEC_DATA (IDATA6, ".didat$6", SEC_HAS_CONTENTS, 1)
+};
+
/* This is what we're trying to make. We generate the imp symbols with
both single and double underscores, for compatibility.
@@ -2341,6 +2352,7 @@ make_imp_label (const char *prefix, const char *name)
static bfd *
make_one_lib_file (export_type *exp, int i, int delay)
{
+ sinfo *const secdata = delay ? secdata_delay : secdata_plain;
char *outname = TMP_STUB;
size_t name_len = strlen (outname);
sprintf (outname + name_len - 7, "%05d.o", i);
@@ -2835,7 +2847,7 @@ make_delay_head (void)
if (!no_idata5)
{
- fprintf (f, "\t.section\t.idata$5\n");
+ fprintf (f, "\t.section\t.didat$5\n");
/* NULL terminating list. */
if (create_for_pep)
fprintf (f, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
@@ -2846,15 +2858,15 @@ make_delay_head (void)
if (!no_idata4)
{
- fprintf (f, "\t.section\t.idata$4\n");
+ fprintf (f, "\t.section\t.didat$4\n");
fprintf (f, "\t%s\t0\n", ASM_LONG);
if (create_for_pep)
fprintf (f, "\t%s\t0\n", ASM_LONG);
- fprintf (f, "\t.section\t.idata$4\n");
+ fprintf (f, "\t.section\t.didat$4\n");
fprintf (f, "__INT_%s:\n", imp_name_lab);
}
- fprintf (f, "\t.section\t.idata$2\n");
+ fprintf (f, "\t.section\t.didat$2\n");
fclose (f);
@@ -2921,6 +2933,57 @@ make_tail (void)
return abfd;
}
+static bfd *
+make_delay_tail (void)
+{
+ FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
+ bfd *abfd;
+
+ if (f == NULL)
+ {
+ fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
+ return NULL;
+ }
+
+ temp_file_to_remove[TEMP_TAIL_FILE] = TMP_TAIL_S;
+
+ if (!no_idata4)
+ {
+ fprintf (f, "\t.section\t.didat$4\n");
+ if (create_for_pep)
+ fprintf (f, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
+ else
+ fprintf (f, "\t%s\t0\n", ASM_LONG); /* NULL terminating list. */
+ }
+
+ if (!no_idata5)
+ {
+ fprintf (f, "\t.section\t.didat$5\n");
+ if (create_for_pep)
+ fprintf (f, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
+ else
+ fprintf (f, "\t%s\t0\n", ASM_LONG); /* NULL terminating list. */
+ }
+
+ fprintf (f, "\t.section\t.didat$7\n");
+ fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
+ fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
+ imp_name_lab, ASM_TEXT, dll_name);
+
+ fclose (f);
+
+ assemble_file (TMP_TAIL_S, TMP_TAIL_O);
+
+ abfd = bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET);
+ if (abfd == NULL)
+ /* xgettext:c-format */
+ fatal (_("failed to open temporary tail file: %s: %s"),
+ TMP_TAIL_O, bfd_get_errmsg ());
+
+ temp_file_to_remove[TEMP_TAIL_O_FILE] = TMP_TAIL_O;
+ return abfd;
+}
+
static void
gen_lib_file (int delay)
{
@@ -2956,12 +3019,13 @@ gen_lib_file (int delay)
if (delay)
{
ar_head = make_delay_head ();
+ ar_tail = make_delay_tail();
}
else
{
ar_head = make_head ();
+ ar_tail = make_tail();
}
- ar_tail = make_tail();
if (ar_head == NULL || ar_tail == NULL)
return;
diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc
index 96a47515444..108c6fb2cdf 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -14,7 +14,7 @@ fi
# substitution, so we do this instead.
# Sorting of the .foo$* sections is required by the definition of
# grouped sections in PE.
-# Sorting of the file names in R_IDATA is required by the
+# Sorting of the file names in R_IDATA and R_DIDAT is required by the
# current implementation of dlltool (this could probably be changed to
# use grouped sections instead).
if test "${RELOCATING}"; then
@@ -39,6 +39,18 @@ if test "${RELOCATING}"; then
R_IDATA67='
KEEP (SORT(*)(.idata$6))
KEEP (SORT(*)(.idata$7))'
+ R_DIDAT234='
+ __DELAY_IMPORT_DIRECTORY_start__ = .;
+ KEEP (SORT(*)(.didat$2))
+ KEEP (SORT(*)(.didat$3))
+ __DELAY_IMPORT_DIRECTORY_end__ = .;
+ /* These zeroes mark the end of the import list. */
+ . += (__DELAY_IMPORT_DIRECTORY_end__ - __DELAY_IMPORT_DIRECTORY_start__) ? 8*4 : 0;
+ KEEP (SORT(*)(.didat$4))'
+ R_DIDAT5='KEEP (SORT(*)(.didat$5))'
+ R_DIDAT67='
+ KEEP (SORT(*)(.didat$6))
+ KEEP (SORT(*)(.didat$7))'
R_CRT_XC='KEEP (*(SORT(.CRT$XC*))) /* C initialization */'
R_CRT_XI='KEEP (*(SORT(.CRT$XI*))) /* C++ initialization */'
R_CRT_XL='KEEP (*(SORT(.CRT$XL*))) /* TLS callbacks */'
@@ -61,6 +73,9 @@ else
R_IDATA234=
R_IDATA5=
R_IDATA67=
+ R_DIDAT234=
+ R_DIDAT5=
+ R_DIDAT67=
R_CRT_XC=
R_CRT_XI=
R_CRT_XL=
@@ -244,6 +259,15 @@ SECTIONS
${R_IDATA67}
}
+ .didat ${RELOCATING+BLOCK(__section_alignment__)} :
+ {
+ /* This cannot currently be handled with grouped sections.
+ See pe.em:sort_sections. */
+ ${R_DIDAT234}
+ ${R_DIDAT5}
+ ${R_DIDAT67}
+ }
+
/* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be
at the end of section. This is important because _tls_start MUST
be at the beginning of the section to enable SECREL32 relocations with TLS
diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc
index e2c6c2cedd2..f508ebe5585 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -14,7 +14,7 @@ fi
# substitution, so we do this instead.
# Sorting of the .foo$* sections is required by the definition of
# grouped sections in PE.
-# Sorting of the file names in R_IDATA is required by the
+# Sorting of the file names in R_IDATA and R_DIDAT is required by the
# current implementation of dlltool (this could probably be changed to
# use grouped sections instead).
if test "${RELOCATING}"; then
@@ -40,6 +40,19 @@ if test "${RELOCATING}"; then
R_IDATA67='
KEEP (SORT(*)(.idata$6))
KEEP (SORT(*)(.idata$7))'
+ R_DIDAT234='
+ __DELAY_IMPORT_DIRECTORY_start__ = .;
+ KEEP (SORT(*)(.didat$2))
+ KEEP (SORT(*)(.didat$3))
+ __DELAY_IMPORT_DIRECTORY_end__ = .;
+ /* These zeroes mark the end of the import list. */
+ . += (__DELAY_IMPORT_DIRECTORY_end__ - __DELAY_IMPORT_DIRECTORY_start__) ? 8*4 : 0;
+ . = ALIGN(8);
+ KEEP (SORT(*)(.didat$4))'
+ R_DIDAT5='SORT(*)(.didat$5)'
+ R_DIDAT67='
+ KEEP (SORT(*)(.didat$6))
+ KEEP (SORT(*)(.didat$7))'
R_CRT_XC='KEEP (*(SORT(.CRT$XC*))) /* C initialization */'
R_CRT_XI='KEEP (*(SORT(.CRT$XI*))) /* C++ initialization */'
R_CRT_XL='KEEP (*(SORT(.CRT$XL*))) /* TLS callbacks */'
@@ -62,6 +75,9 @@ else
R_IDATA234=
R_IDATA5=
R_IDATA67=
+ R_DIDAT234=
+ R_DIDAT5=
+ R_DIDAT67=
R_CRT_XC=
R_CRT_XI=
R_CRT_XL=
@@ -251,6 +267,15 @@ SECTIONS
${R_IDATA67}
}
+ .didat ${RELOCATING+BLOCK(__section_alignment__)} :
+ {
+ /* This cannot currently be handled with grouped sections.
+ See pep.em:sort_sections. */
+ ${R_DIDAT234}
+ ${R_DIDAT5}
+ ${R_DIDAT67}
+ }
+
/* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be
at the end of the .tls section. This is important because _tls_start MUST
be at the beginning of the section to enable SECREL32 relocations with TLS
--
2.49.0.windows.1

View File

@@ -0,0 +1,99 @@
From 247eb6f63e697b30b42c9c3df6d6a2c99525f4e2 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Fri, 13 Jun 2025 07:52:47 +0200
Subject: [PATCH 5005/5007] ld,dlltool: move read-only delayimp data into
.rdata
This allows the delay IAT to be in its own section with nothing else, as
required by IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION, documented at
https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#load-configuration-layout
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
binutils/dlltool.c | 5 +----
ld/scripttempl/pe.sc | 7 +++++--
ld/scripttempl/pep.sc | 8 ++++++--
3 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index 371d61fc484..5b038dba8c5 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -2819,7 +2819,7 @@ make_delay_head (void)
/* Output the delay import descriptor */
fprintf (f, "\n%s DELAY_IMPORT_DESCRIPTOR\n", ASM_C);
- fprintf (f, ".section\t.text$2\n");
+ fprintf (f, ".section\t.didat$2\n");
fprintf (f, "%s __DELAY_IMPORT_DESCRIPTOR_%s\n", ASM_GLOBAL,imp_name_lab);
fprintf (f, "__DELAY_IMPORT_DESCRIPTOR_%s:\n", imp_name_lab);
fprintf (f, "\t%s 1\t%s grAttrs\n", ASM_LONG, ASM_C);
@@ -2862,12 +2862,9 @@ make_delay_head (void)
fprintf (f, "\t%s\t0\n", ASM_LONG);
if (create_for_pep)
fprintf (f, "\t%s\t0\n", ASM_LONG);
- fprintf (f, "\t.section\t.didat$4\n");
fprintf (f, "__INT_%s:\n", imp_name_lab);
}
- fprintf (f, "\t.section\t.didat$2\n");
-
fclose (f);
assemble_file (TMP_HEAD_S, TMP_HEAD_O);
diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc
index 108c6fb2cdf..8fb98b2c06e 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -146,6 +146,11 @@ SECTIONS
${RELOCATING+__rt_psrelocs_start = .;}
${RELOCATING+KEEP(*(.rdata_runtime_pseudo_reloc))}
${RELOCATING+__rt_psrelocs_end = .;}
+ /* read-only parts of .didat */
+ /* This cannot currently be handled with grouped sections.
+ See pe.em:sort_sections. */
+ ${R_DIDAT234}
+ ${R_DIDAT67}
/* .ctors & .dtors */
${CONSTRUCTING+
@@ -263,9 +268,7 @@ SECTIONS
{
/* This cannot currently be handled with grouped sections.
See pe.em:sort_sections. */
- ${R_DIDAT234}
${R_DIDAT5}
- ${R_DIDAT67}
}
/* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be
diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc
index f508ebe5585..841ee352f73 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -148,6 +148,12 @@ SECTIONS
${RELOCATING+__rt_psrelocs_start = .;}
${RELOCATING+KEEP(*(.rdata_runtime_pseudo_reloc))}
${RELOCATING+__rt_psrelocs_end = .;}
+ /* read-only parts of .didat */
+ /* This cannot currently be handled with grouped sections.
+ See pe.em:sort_sections. */
+ ${RELOCATING+. = ALIGN(8);}
+ ${R_DIDAT234}
+ ${R_DIDAT67}
/* .ctors & .dtors */
${CONSTRUCTING+. = ALIGN(8);}
@@ -271,9 +277,7 @@ SECTIONS
{
/* This cannot currently be handled with grouped sections.
See pep.em:sort_sections. */
- ${R_DIDAT234}
${R_DIDAT5}
- ${R_DIDAT67}
}
/* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be
--
2.49.0.windows.1

View File

@@ -0,0 +1,54 @@
From 592388aa50a52fb6c82002cd89e98d607680ab7c Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Fri, 13 Jun 2025 07:53:07 +0200
Subject: [PATCH 5006/5007] dlltool: respect use-nul-prefixed-import-tables
option for delaylib
Noticed the extra zeros while inspecting the output.
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
binutils/dlltool.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index 5b038dba8c5..d161140b1ba 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -2848,20 +2848,25 @@ make_delay_head (void)
if (!no_idata5)
{
fprintf (f, "\t.section\t.didat$5\n");
- /* NULL terminating list. */
- if (create_for_pep)
- fprintf (f, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
- else
- fprintf (f, "\t%s\t0\n", ASM_LONG);
+ if (use_nul_prefixed_import_tables)
+ {
+ if (create_for_pep)
+ fprintf (f, "\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
+ else
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ }
fprintf (f, "__IAT_%s:\n", imp_name_lab);
}
if (!no_idata4)
{
fprintf (f, "\t.section\t.didat$4\n");
- fprintf (f, "\t%s\t0\n", ASM_LONG);
- if (create_for_pep)
- fprintf (f, "\t%s\t0\n", ASM_LONG);
+ if (use_nul_prefixed_import_tables)
+ {
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ if (create_for_pep)
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ }
fprintf (f, "__INT_%s:\n", imp_name_lab);
}
--
2.49.0.windows.1

View File

@@ -0,0 +1,98 @@
From 175d5bf58d1c1f0fe6bdc75afd0cc98eb39f24ba Mon Sep 17 00:00:00 2001
From: Jeremy Drake <sourceware-bugzilla@jdrake.com>
Date: Fri, 13 Jun 2025 07:53:24 +0200
Subject: [PATCH 5007/5007] bfd: populate delay import directory in PE header
Previously, the delay import table was constructed but its rva and size
were never put into the PE optional header.
Signed-off-by: Jeremy Drake <sourceware-bugzilla@jdrake.com>
---
bfd/peXXigen.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 7dfa82ee43e..19f38a4ac1b 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -593,7 +593,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out;
bfd_vma sa, fa, ib;
- IMAGE_DATA_DIRECTORY idata2, idata5, tls, loadcfg;
+ IMAGE_DATA_DIRECTORY idata2, idata5, didat2, tls, loadcfg;
sa = extra->SectionAlignment;
fa = extra->FileAlignment;
@@ -601,6 +601,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE];
idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE];
+ didat2 = pe->pe_opthdr.DataDirectory[PE_DELAY_IMPORT_DESCRIPTOR];
tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE];
loadcfg = pe->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE];
@@ -651,6 +652,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
a final link is going to be performed, it can overwrite them. */
extra->DataDirectory[PE_IMPORT_TABLE] = idata2;
extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5;
+ extra->DataDirectory[PE_DELAY_IMPORT_DESCRIPTOR] = didat2;
extra->DataDirectory[PE_TLS_TABLE] = tls;
extra->DataDirectory[PE_LOAD_CONFIG_TABLE] = loadcfg;
@@ -4544,6 +4546,52 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
}
}
+ /* The delay import directory. This is .didat$2 */
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ "__DELAY_IMPORT_DIRECTORY_start__", false, false,
+ true);
+ if (h1 != NULL
+ && (h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ {
+ bfd_vma delay_va;
+
+ delay_va =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset);
+
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ "__DELAY_IMPORT_DIRECTORY_end__", false,
+ false, true);
+ if (h1 != NULL
+ && (h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ {
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_DELAY_IMPORT_DESCRIPTOR].Size =
+ ((h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset)
+ - delay_va);
+ if (pe_data (abfd)->pe_opthdr.DataDirectory[PE_DELAY_IMPORT_DESCRIPTOR].Size
+ != 0)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_DELAY_IMPORT_DESCRIPTOR].VirtualAddress =
+ delay_va - pe_data (abfd)->pe_opthdr.ImageBase;
+ }
+ else
+ {
+ _bfd_error_handler
+ (_("%pB: unable to fill in DataDirectory[%d]: %s not defined correctly"),
+ abfd, PE_DELAY_IMPORT_DESCRIPTOR,
+ "__DELAY_IMPORT_DIRECTORY_end__");
+ result = false;
+ }
+ }
+
name[0] = bfd_get_symbol_leading_char (abfd);
strcpy (name + !!name[0], "_tls_used");
h1 = coff_link_hash_lookup (coff_hash_table (info), name, false, false, true);
--
2.49.0.windows.1

View File

@@ -6,7 +6,7 @@ _realname=binutils
pkgbase=mingw-w64-${_realname}
pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}")
pkgver=2.44
pkgrel=3
pkgrel=4
pkgdesc="A set of programs to assemble and manipulate binary and object files (mingw-w64)"
arch=('any')
mingw_arch=('mingw32' 'mingw64' 'ucrt64')
@@ -33,6 +33,14 @@ source=(https://ftp.gnu.org/gnu/binutils/${_realname}-${pkgver}.tar.bz2{,.sig}
libiberty-unlink-handle-windows-nul.patch
3001-hack-libiberty-link-order.patch
4000-fix-DEBUG_S_INLINEELINES.patch
5000-bfd-properly-use-bfd_get_symbol_leading_char-in-peXX.patch
5001-bfd-adjust-a-few-error-messages.patch
5002-bfd-fill-in-PE-load-config-directory-entry.patch
5003-bfd-add-load-config-size-workaround-for-i386-XP-and-.patch
5004-bfd-ld-dlltool-Emit-delay-load-import-data-into-its-.patch
5005-ld-dlltool-move-read-only-delayimp-data-into-.rdata.patch
5006-dlltool-respect-use-nul-prefixed-import-tables-optio.patch
5007-bfd-populate-delay-import-directory-in-PE-header.patch
)
sha256sums=('f66390a661faa117d00fab2e79cf2dc9d097b42cc296bf3f8677d1e7b452dc3a'
'SKIP'
@@ -44,7 +52,15 @@ sha256sums=('f66390a661faa117d00fab2e79cf2dc9d097b42cc296bf3f8677d1e7b452dc3a'
'a094660ec95996c00b598429843b7869037732146442af567ada9f539bd40480'
'7ccbd418695733c50966068fa9755a6abb156f53af23701d2bc097c63e9e0030'
'604628156c08f3e361de60329af250fab6839e23e61e289f8369a7e18a04e277'
'5ed35a728b956ad49a5e196ae59f681666f2754f0a4903b9280a430d7a312ea8')
'5ed35a728b956ad49a5e196ae59f681666f2754f0a4903b9280a430d7a312ea8'
'0e04d2c174fd8faaf7982e049e0baa551b4fbfe49dca1a950625af50a71326b9'
'ea53673a3f4196f649d46e4adda54d3dfed77152204c51713790755d16b4f7e5'
'e36ab10562cefb8cae77ed06a7c91132ced6c90bda1a2d05c852b630f7a33089'
'f3a6f8d9ce48c165a3b9e32ab9cf61bccaa05ce3826f03cb04c7ebaaab3f726d'
'4214fdc959057c3c5ed576df2d61a649c8817f8323fc4d6d25606f0cd6445d7f'
'cf7f79840c6aace55fc5ea4638aaeb1cf07a13d07f5f7c1e2d86da3f0641ceff'
'928d283d86c66930167e2ef71f73e5222e9e3f878c5f57b5272dd12577fb82e1'
'9c5e3f13029e980e2ba98fd1bc6d5c5f738bc3680436848f4ef8a889f82a1f2d')
validpgpkeys=('EAF1C276A747E9ED86210CBAC3126D3B4AE55E93' # Tristan Gingold <gingold@adacore.com>
'3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F') # Nick Clifton <nickc@redhat.com>
@@ -95,6 +111,20 @@ prepare() {
# https://github.com/msys2/MINGW-packages/issues/24148
# https://sourceware.org/bugzilla/show_bug.cgi?id=32942
patch -p1 -i "${srcdir}/4000-fix-DEBUG_S_INLINEELINES.patch"
# https://github.com/msys2/MINGW-packages/issues/23577
# https://sourceware.org/bugzilla/show_bug.cgi?id=32675
# https://sourceware.org/bugzilla/show_bug.cgi?id=14339
# plus backport support for load config directory, to avoid a conflict
apply_patch_with_msg \
5000-bfd-properly-use-bfd_get_symbol_leading_char-in-peXX.patch \
5001-bfd-adjust-a-few-error-messages.patch \
5002-bfd-fill-in-PE-load-config-directory-entry.patch \
5003-bfd-add-load-config-size-workaround-for-i386-XP-and-.patch \
5004-bfd-ld-dlltool-Emit-delay-load-import-data-into-its-.patch \
5005-ld-dlltool-move-read-only-delayimp-data-into-.rdata.patch \
5006-dlltool-respect-use-nul-prefixed-import-tables-optio.patch \
5007-bfd-populate-delay-import-directory-in-PE-header.patch
}
build() {