]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
bfd,ld,dlltool: Emit delay-load import data into its own section
authorLIU Hao <lh_mouse@126.com>
Fri, 13 Jun 2025 05:52:29 +0000 (07:52 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 13 Jun 2025 05:52:29 +0000 (07:52 +0200)
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>
16 files changed:
bfd/coffgen.c
bfd/pe-aarch64.c
bfd/pe-arm.c
bfd/pe-i386.c
bfd/pe-x86_64.c
bfd/peXXigen.c
bfd/pei-aarch64.c
bfd/pei-arm.c
bfd/pei-i386.c
bfd/pei-loongarch64.c
bfd/pei-riscv64.c
bfd/pei-x86_64.c
bfd/syms.c
binutils/dlltool.c
ld/scripttempl/pe.sc
ld/scripttempl/pep.sc

index ab4d790ad30b6e933a126a0f0b77175daa2330a1..c1811cbce1cd8877e89c846b9207122a11d70de0 100644 (file)
@@ -44,6 +44,7 @@
 #include "libcoff.h"
 #include "elf-bfd.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.  */
@@ -3120,6 +3121,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)
 {
@@ -3141,6 +3155,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;
 
index 64975d19f67a3425421f4e15a4a9ce8cf1a7c2f9..2204a51c50914555f2d7caa4dc55038d0ca21552 100644 (file)
@@ -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"), \
index fe4e18e7e066b4fccb9f1102dd6896724fc93334..5efa559a353a97279606b6328d2d625e693e6cc3 100644 (file)
@@ -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"), \
index 07f674342cfc83b398151b439cfd8c15c4a2aa4b..3742fd8feb446e836ccc02caaa42407584fe0e12 100644 (file)
@@ -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"), \
index d56d75dabd03432b69f0cf149713c9cef2f7ae02..9151aac5792e1ecbf8b236fb2298d619a8be5bac 100644 (file)
@@ -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"), \
index 9938108ce6b86c6c24b3514a10b5539282c5216c..7dfa82ee43eeaa38dc13780a30278a99af230758 100644 (file)
@@ -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 },
index 3d7f5b376a60024195756ff08bf5abe62e5664e1..00f38e0f9bbfbf47d831b20a2d6be568bff2dfe8 100644 (file)
@@ -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"), \
index 2abc14de025f27b313e8e9e170b4929125d9e9bc..07cebb510ef3bc9bb098414d3d160260e0558e45 100644 (file)
@@ -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"), \
index 676a824877bf888b6063d944dce584770d2dc479..a26f1702b3bc3abd8ec74a89186f6a402901bdc3 100644 (file)
@@ -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"), \
index 4b3a30d4ddc5bef124ac58294d8d609892cc4c36..f22498cab21919e99ac2833876ac5794102068d5 100644 (file)
@@ -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"), \
index e87aa4293507925133661d02246be49a73d1ac9a..c4ae7bfb89a511f66f682a5c16c6608e264eef6b 100644 (file)
@@ -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"), \
index 3f8f255af33324bd033311ec8b9e624bf942c62c..a5c2fd85f06e460e0ca1d77a5932b3f1426babad 100644 (file)
@@ -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"), \
index 95017ba4f11594e9d3eabdaa1b8121b17dc10cf3..df2229b3fa3f7485d5944c20fe8d5afaa4cf2de7 100644 (file)
@@ -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 */
index ef21423b06d6b30956dd44adee9df8325bb48aa0..0e0138305f4385c3492a35852dd533712db81fd3 100644 (file)
@@ -2250,7 +2250,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),
@@ -2261,6 +2261,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.
 
@@ -2323,6 +2334,7 @@ make_imp_label (bfd *abfd, 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);
@@ -2814,7 +2826,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);
@@ -2825,15 +2837,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);
 
@@ -2900,6 +2912,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)
 {
@@ -2935,12 +2998,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;
index 96a47515444a3a1e03a9e787287a518898e1ee87..108c6fb2cdff305826b0e1ff73abbd5312c585a5 100644 (file)
@@ -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
index e2c6c2cedd269b765e6f5c4c6ba5c38bdfd46b0b..f508ebe558531e0fbceea18431846a2392ba6d15 100644 (file)
@@ -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