[PATCH v2 0/4] PE delay import fixes
Jeremy Drake
sourceware-bugzilla@jdrake.com
Tue May 6 06:05:45 GMT 2025
Jeremy Drake (3):
ld,dlltool: move read-only delayimp data into .rdata
dlltool: respect use-nul-prefixed-import-tables option for delaylib
bfd: populate delay import directory in PE header.
LIU Hao (1):
bfd,ld,dlltool: Emit delay-load import data into its own section
bfd/coffgen.c | 14 +++++++
bfd/pe-aarch64.c | 2 +
bfd/pe-arm.c | 2 +
bfd/pe-i386.c | 2 +
bfd/pe-x86_64.c | 2 +
bfd/peXXigen.c | 51 +++++++++++++++++++++-
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 | 98 ++++++++++++++++++++++++++++++++++++-------
ld/scripttempl/pe.sc | 29 ++++++++++++-
ld/scripttempl/pep.sc | 31 +++++++++++++-
16 files changed, 225 insertions(+), 19 deletions(-)
Range-diff against v1:
1: 5d7d252aacd ! 1: 8ac56d5a735 bfd,ld,dlltool: Emit delay-load import data into its own section
@@ Commit message
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.
+ faults when functions from delay-import library were called. This is
+ PR 32675.
- This commit makes DLLTOOL emit delay-import IAT into `.didata`, as specified
+ 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.
+ section is writeable. As a side-effect of this, PR 14339 is also fixed.
Using this DEF:
@@ Commit message
```
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 ##
+@@ bfd/coffgen.c: 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)
+ {
@@ bfd/coffgen.c: 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")
-+ || startswith (o->name, ".didat")
++ || is_subsection (o->name, ".didat")
|| startswith (o->name, ".rsrc"))
o->gc_mark = 1;
2: bd2cee94dfc ! 2: c39f04640ac move read-only delayimp data into .rdata
@@ Metadata
Author: Jeremy Drake <sourceware-bugzilla@jdrake.com>
## Commit message ##
- move read-only delayimp data into .rdata
+ 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
@@ binutils/dlltool.c: make_delay_head (void)
fprintf (f, "__DELAY_IMPORT_DESCRIPTOR_%s:\n", imp_name_lab);
fprintf (f, "\t%s 1\t%s grAttrs\n", ASM_LONG, ASM_C);
@@ binutils/dlltool.c: 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);
+ 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");
-+ 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);
}
-: ----------- > 3: 5bc5c6f71fa dlltool: respect use-nul-prefixed-import-tables option for delaylib
3: 685e88d6db4 ! 4: 12302e5cc33 bfd: populate delay import directory in PE header.
@@ bfd/peXXigen.c: _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_li
+ h1 = coff_link_hash_lookup (coff_hash_table (info),
+ "__DELAY_IMPORT_DIRECTORY_start__", false, false,
+ true);
-+ if (h1 != NULL)
++ 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)
+ {
-+ if ((h1->root.type == bfd_link_hash_defined
++ 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)
+ {
-+ 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;
-+ }
++ 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;
+ }
+ }
+
--
2.49.0.windows.1
More information about the Binutils
mailing list