On Fri, 7 Mar 2025, Jeremy Drake via Mingw-w64-public wrote:

> On Fri, 7 Mar 2025, Jeremy Drake via Mingw-w64-public wrote:
>
> > On Fri, 7 Mar 2025, Jeremy Drake via Mingw-w64-public wrote:
> >
> > > That bug was avoided, due to the fact that the code that tries to
> > > garbage-collect unused stubs only looks at .idata sections, and delayloads
> > > are now in .didat sections.
> > >
> > > However, this patch is probably overkill.  This puts the whole of the
> > > delay load stuff into .didat, while only the IAT needs to be there
> > > (writable).  I will try just moving .idata$5 into .didat$5 and see what
> > > happens.
> >
> > I tried the attached patch, and it works, but brings back the bug I
> > referenced for 32-bit.
> >
> > > Also, I noticed in objdump that the Delay import directory entry in the
> > > optional header is 0.  This may have been the case before, I'm not seeing
> > > any code to fill it in.
> >
> > This needs some symbols or sections for the delay import directory table.
> > Right now, it is put into .text$2, which seems like a hack for the fact
> > that putting it into .idata$2 would have messed up the normal import
> > directory.
> >
> > I am confused by what LLD is doing though. It is putting the functions and
> > modules into .data, and the read-only stuff into .didat.  The way I read
> > the docs suggested to use .didat to hold the function pointers so that the
> > guard flags could allow the OS to change protection as needed without
> > affecting other data.
>
>
> OK, apparently I forgot to attach the patch last time.  Oh well, here's a
> new one!

The list is eating my attachment.  Trying again with .txt extension

>
> This patch unfortunately does a few different things at this point:
> * moves delay load directory table into .didat$2 section, and puts this
> into .idata(!)
> * fills in the delay import descriptor table data directory entry
> * fills in the load config table data directory entry if _load_config_used
> is present (it isn't unless it's actually referenced by an object)
> * moves delay load IAT into .dadat$5 section, which goes into new .didat
> section
> * fixes https://sourceware.org/bugzilla/show_bug.cgi?id=14339 by excluding
> delay import stubs from being excluded
>
> I've only tested this in MINGW32, but it works even when hex editing the
> load config guard flags to make Windows protect the delay load IAT (this
> still wants the default flags for the section to be read/write, and
> Windows will take away write access at load time).  This is more than can
> be said for LLD at this point, because it puts the IAT itself in the .data
> section it blows up early if Windows takes away write access from pages in
> it.  Martin, do you know anything about this?
>
>
> I'm not at all convinced that your initial idea to put all of the delay
> load stuff into the new .didat section isn't the way to go.  It seemed to
> me like only the IAT needed to go in the section where its protection
> changed.  The module handle is still in .data, do you think it was
> intended to put that in .didat also so it also gets write protected?  The
> docs do say:
> Delayload import table in its own .didat section (with nothing else in it)
> that can be freely reprotected.
>
> #define IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION 0x00002000
>
> Which is what this patch currently does.
>
>
> Feel free to pick this up and continue working on it.
> _______________________________________________
> Mingw-w64-public mailing list
> Mingw-w64-public@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
diff -ur binutils-2.44.ORIG/bfd/coffgen.c binutils-2.44/bfd/coffgen.c
--- binutils-2.44.ORIG/bfd/coffgen.c    2025-03-07 11:08:40.756680100 -0800
+++ binutils-2.44/bfd/coffgen.c 2025-03-07 11:08:50.489285700 -0800
@@ -3120,6 +3120,7 @@
          else if (startswith (o->name, ".idata")
                   || startswith (o->name, ".pdata")
                   || startswith (o->name, ".xdata")
+                  || startswith (o->name, ".didat")
                   || startswith (o->name, ".rsrc"))
            o->gc_mark = 1;
 
diff -ur binutils-2.44.ORIG/bfd/pe-aarch64.c binutils-2.44/bfd/pe-aarch64.c
--- binutils-2.44.ORIG/bfd/pe-aarch64.c 2025-03-07 11:08:40.362193200 -0800
+++ binutils-2.44/bfd/pe-aarch64.c      2025-03-07 11:08:50.508464400 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pe-arm.c binutils-2.44/bfd/pe-arm.c
--- binutils-2.44.ORIG/bfd/pe-arm.c     2025-03-07 11:08:40.377852200 -0800
+++ binutils-2.44/bfd/pe-arm.c  2025-03-07 11:08:50.520989900 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pe-i386.c binutils-2.44/bfd/pe-i386.c
--- binutils-2.44.ORIG/bfd/pe-i386.c    2025-03-07 11:08:40.377852200 -0800
+++ binutils-2.44/bfd/pe-i386.c 2025-03-07 11:08:50.536642100 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pei-aarch64.c binutils-2.44/bfd/pei-aarch64.c
--- binutils-2.44.ORIG/bfd/pei-aarch64.c        2025-03-07 11:08:40.393906100 
-0800
+++ binutils-2.44/bfd/pei-aarch64.c     2025-03-07 11:08:50.599389900 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pei-arm.c binutils-2.44/bfd/pei-arm.c
--- binutils-2.44.ORIG/bfd/pei-arm.c    2025-03-07 11:08:40.409549500 -0800
+++ binutils-2.44/bfd/pei-arm.c 2025-03-07 11:08:50.615458600 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pei-i386.c binutils-2.44/bfd/pei-i386.c
--- binutils-2.44.ORIG/bfd/pei-i386.c   2025-03-07 11:08:40.724374700 -0800
+++ binutils-2.44/bfd/pei-i386.c        2025-03-07 11:08:50.631119800 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pei-loongarch64.c 
binutils-2.44/bfd/pei-loongarch64.c
--- binutils-2.44.ORIG/bfd/pei-loongarch64.c    2025-03-07 11:08:40.409549500 
-0800
+++ binutils-2.44/bfd/pei-loongarch64.c 2025-03-07 11:08:50.646727400 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pei-riscv64.c binutils-2.44/bfd/pei-riscv64.c
--- binutils-2.44.ORIG/bfd/pei-riscv64.c        2025-03-07 11:08:40.409549500 
-0800
+++ binutils-2.44/bfd/pei-riscv64.c     2025-03-07 11:08:50.646727400 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pei-x86_64.c binutils-2.44/bfd/pei-x86_64.c
--- binutils-2.44.ORIG/bfd/pei-x86_64.c 2025-03-07 11:08:40.409549500 -0800
+++ binutils-2.44/bfd/pei-x86_64.c      2025-03-07 11:08:50.662359400 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/pe-x86_64.c binutils-2.44/bfd/pe-x86_64.c
--- binutils-2.44.ORIG/bfd/pe-x86_64.c  2025-03-07 11:08:40.377852200 -0800
+++ binutils-2.44/bfd/pe-x86_64.c       2025-03-07 11:08:50.568095000 -0800
@@ -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 -ur binutils-2.44.ORIG/bfd/peXXigen.c binutils-2.44/bfd/peXXigen.c
--- binutils-2.44.ORIG/bfd/peXXigen.c   2025-03-07 11:08:40.393906100 -0800
+++ binutils-2.44/bfd/peXXigen.c        2025-03-07 16:13:04.699583800 -0800
@@ -593,7 +593,7 @@
   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, didat2, tls;
 
   sa = extra->SectionAlignment;
   fa = extra->FileAlignment;
@@ -601,6 +601,7 @@
 
   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];
 
   if (aouthdr_in->tsize)
@@ -650,6 +651,7 @@
      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;
 
   if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0)
@@ -999,6 +1001,7 @@
        { ".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 },
@@ -4540,6 +4543,84 @@
        }
     }
 
+  /* The delay import directory.  This is .didat$2 */
+  h1 = coff_link_hash_lookup (coff_hash_table (info),
+                             "__DELAY_DIRECTORY_start__", false, false, true);
+  if (h1 != NULL)
+    {
+      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)
+       {
+         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_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 
DataDictionary[PE_DELAY_IMPORT_DESCRIPTOR(13)]"
+                  " because .didat$2 is missing"), abfd);
+             result = false;
+           }
+       }
+    }
+
+  h1 = coff_link_hash_lookup (coff_hash_table (info),
+                             (bfd_get_symbol_leading_char (abfd) != 0
+                              ? "__load_config_used" : "_load_config_used"),
+                             false, false, true);
+  if (h1 != NULL)
+    {
+      char sz[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);
+      else
+       {
+         _bfd_error_handler
+           (_("%pB: unable to fill in DataDictionary[10] because 
__load_config_used is missing"),
+            abfd);
+         result = false;
+       }
+      if (!bfd_get_section_contents (abfd, 
h1->root.u.def.section->output_section,
+                             sz, h1->root.u.def.section->output_offset, 4))
+       {
+         _bfd_error_handler
+           (_("%pB: unable to fill in DataDictionary[10] because we can't read 
the size"),
+            abfd);
+         result = false;
+       }
+      pe_data (abfd)->pe_opthdr.DataDirectory[PE_LOAD_CONFIG_TABLE].Size = 
H_GET_32 (abfd, sz);
+    }
+
   h1 = coff_link_hash_lookup (coff_hash_table (info),
                              (bfd_get_symbol_leading_char (abfd) != 0
                               ? "__tls_used" : "_tls_used"),
diff -ur binutils-2.44.ORIG/bfd/syms.c binutils-2.44/bfd/syms.c
--- binutils-2.44.ORIG/bfd/syms.c       2025-03-07 11:08:40.692211500 -0800
+++ binutils-2.44/bfd/syms.c    2025-03-07 11:08:50.693791800 -0800
@@ -594,6 +594,7 @@
    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 -ur binutils-2.44.ORIG/binutils/dlltool.c binutils-2.44/binutils/dlltool.c
--- binutils-2.44.ORIG/binutils/dlltool.c       2025-03-07 11:07:53.114156900 
-0800
+++ binutils-2.44/binutils/dlltool.c    2025-03-07 12:16:09.844181400 -0800
@@ -2268,7 +2268,7 @@
 #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 @@
   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, ".idata$7", SEC_HAS_CONTENTS, 2),
+  INIT_SEC_DATA (IDATA5, ".didat$5", SEC_HAS_CONTENTS, 2),
+  INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2),
+  INIT_SEC_DATA (IDATA6, ".idata$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 @@
 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);
@@ -2807,7 +2819,7 @@
 
   /* 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);
@@ -2835,7 +2847,7 @@
 
   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);
@@ -2854,8 +2866,6 @@
       fprintf (f, "__INT_%s:\n", imp_name_lab);
     }
 
-  fprintf (f, "\t.section\t.idata$2\n");
-
   fclose (f);
 
   assemble_file (TMP_HEAD_S, TMP_HEAD_O);
@@ -2921,6 +2931,57 @@
   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.idata$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.idata$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 +3017,13 @@
   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 -ur binutils-2.44.ORIG/ld/emultempl/pe.em binutils-2.44/ld/emultempl/pe.em
--- binutils-2.44.ORIG/ld/emultempl/pe.em       2025-03-07 11:08:37.530839700 
-0800
+++ binutils-2.44/ld/emultempl/pe.em    2025-03-07 17:42:42.902585800 -0800
@@ -1827,7 +1827,7 @@
       {
        if (is->the_bfd->my_archive)
          {
-           int is_imp = 0;
+           int is_imp = 0, is_delayimp = 0;
            asection *sec, *stub_sec = NULL;
 
            /* See if this is an import library thunk.  */
@@ -1835,13 +1835,17 @@
              {
                if (strncmp (sec->name, ".idata\$", 7) == 0)
                  is_imp = 1;
+               else if (strncmp (sec->name, ".didat\$", 7) == 0)
+                 is_delayimp = 1;
                /* The section containing the jmp stub has code
                   and has a reloc.  */
                if ((sec->flags & SEC_CODE) && sec->reloc_count)
                  stub_sec = sec;
              }
 
-           if (is_imp && stub_sec)
+           /* delay imports need the stub section: it is referenced by the
+              default __imp_ pointer: PR 14339 */
+           if (is_imp && !is_delayimp && stub_sec)
              {
                asymbol **symbols;
                long nsyms, src_count;
diff -ur binutils-2.44.ORIG/ld/scripttempl/pe.sc 
binutils-2.44/ld/scripttempl/pe.sc
--- binutils-2.44.ORIG/ld/scripttempl/pe.sc     2025-03-07 11:08:37.641333200 
-0800
+++ binutils-2.44/ld/scripttempl/pe.sc  2025-03-07 12:41:46.385459200 -0800
@@ -14,7 +14,7 @@
 # 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,8 @@
   R_IDATA67='
     KEEP (SORT(*)(.idata$6))
     KEEP (SORT(*)(.idata$7))'
+  R_DIDAT2='KEEP (SORT(*)(.didat$2))'
+  R_DIDAT5='KEEP (SORT(*)(.didat$5))'
   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 +63,7 @@
   R_IDATA234=
   R_IDATA5=
   R_IDATA67=
+  R_DIDAT5=
   R_CRT_XC=
   R_CRT_XI=
   R_CRT_XL=
@@ -242,6 +245,18 @@
     ${R_IDATA5}
     ${RELOCATING+__IAT_end__ = .;}
     ${R_IDATA67}
+    ${RELOCATING+__DELAY_DIRECTORY_start__ = .;}
+    ${R_DIDAT2}
+    ${RELOCATING+__DELAY_DIRECTORY_end__ = .;}
+  }
+
+  .didat ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* This cannot currently be handled with grouped sections.
+       See pe.em:sort_sections.  */
+    ${RELOCATING+__DELAY_IAT_start__ = .;}
+    ${R_DIDAT5}
+    ${RELOCATING+__DELAY_IAT_end__ = .;}
   }
 
   /* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be
diff -ur binutils-2.44.ORIG/ld/scripttempl/pep.sc 
binutils-2.44/ld/scripttempl/pep.sc
--- binutils-2.44.ORIG/ld/scripttempl/pep.sc    2025-03-07 11:08:37.641333200 
-0800
+++ binutils-2.44/ld/scripttempl/pep.sc 2025-03-07 12:45:46.771734700 -0800
@@ -14,7 +14,7 @@
 # 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,8 @@
   R_IDATA67='
     KEEP (SORT(*)(.idata$6))
     KEEP (SORT(*)(.idata$7))'
+  R_DIDAT2='KEEP (SORT(*)(.didat$2))'
+  R_DIDAT5='SORT(*)(.didat$5)'
   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 +64,7 @@
   R_IDATA234=
   R_IDATA5=
   R_IDATA67=
+  R_DIDAT5=
   R_CRT_XC=
   R_CRT_XI=
   R_CRT_XL=
@@ -249,6 +252,18 @@
     ${R_IDATA5}
     ${RELOCATING+__IAT_end__ = .;}
     ${R_IDATA67}
+    ${RELOCATING+__DELAY_DIRECTORY_start__ = .;}
+    ${R_DIDAT2}
+    ${RELOCATING+__DELAY_DIRECTORY_end__ = .;}
+  }
+
+  .didat ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* This cannot currently be handled with grouped sections.
+       See pep.em:sort_sections.  */
+    ${RELOCATING+__DELAY_IAT_start__ = .;}
+    ${R_DIDAT5}
+    ${RELOCATING+__DELAY_IAT_end__ = .;}
   }
 
   /* Windows TLS expects .tls\$AAA to be at the start and .tls\$ZZZ to be
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to