aboutsummaryrefslogtreecommitdiff
path: root/bfd/peXXigen.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/peXXigen.c')
-rw-r--r--bfd/peXXigen.c164
1 files changed, 146 insertions, 18 deletions
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 2901268..c337fc5 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, didat2, tls, loadcfg;
sa = extra->SectionAlignment;
fa = extra->FileAlignment;
@@ -601,7 +601,9 @@ _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];
if (aouthdr_in->tsize)
{
@@ -650,7 +652,9 @@ _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;
if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0)
/* Until other .idata fixes are made (pending patch), the entry for
@@ -999,6 +1003,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 },
@@ -3110,9 +3115,11 @@ bool
_bfd_XX_bfd_copy_private_section_data (bfd *ibfd,
asection *isec,
bfd *obfd,
- asection *osec)
+ asection *osec,
+ struct bfd_link_info *link_info)
{
- if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour
+ if (link_info != NULL
+ || bfd_get_flavour (ibfd) != bfd_target_coff_flavour
|| bfd_get_flavour (obfd) != bfd_target_coff_flavour)
return true;
@@ -4403,6 +4410,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.
@@ -4430,8 +4438,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;
}
@@ -4450,8 +4458,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;
}
@@ -4471,8 +4479,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;
}
@@ -4491,8 +4499,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;
}
}
@@ -4533,17 +4541,62 @@ _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;
}
}
}
+ /* The delay import directory. This is .didat$2 */
h1 = coff_link_hash_lookup (coff_hash_table (info),
- (bfd_get_symbol_leading_char (abfd) != 0
- ? "__tls_used" : "_tls_used"),
- false, false, true);
+ "__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);
if (h1 != NULL)
{
if ((h1->root.type == bfd_link_hash_defined
@@ -4558,8 +4611,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
@@ -4573,6 +4626,81 @@ _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. */
+ 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_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"),
+ 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))