aboutsummaryrefslogtreecommitdiff
path: root/bfd/peXXigen.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/peXXigen.c')
-rw-r--r--bfd/peXXigen.c87
1 files changed, 75 insertions, 12 deletions
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 9938108..e6686dc 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -289,7 +289,7 @@ _bfd_XXi_swap_aux_in (bfd * abfd,
/* PR 17521: Make sure that all fields in the aux structure
are initialised. */
- memset (in, 0, sizeof * in);
+ memset (in, 0, sizeof (*in));
switch (in_class)
{
case C_FILE:
@@ -299,6 +299,9 @@ _bfd_XXi_swap_aux_in (bfd * abfd,
in->x_file.x_n.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
}
else
+#if FILNMLEN != E_FILNMLEN
+#error we need to cope with truncating or extending x_fname
+#endif
memcpy (in->x_file.x_n.x_fname, ext->x_file.x_fname, FILNMLEN);
return;
@@ -373,7 +376,10 @@ _bfd_XXi_swap_aux_out (bfd * abfd,
H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset, ext->x_file.x_n.x_offset);
}
else
- memcpy (ext->x_file.x_fname, in->x_file.x_n.x_fname, sizeof (ext->x_file.x_fname));
+#if FILNMLEN != E_FILNMLEN
+#error we need to cope with truncating or extending x_fname
+#endif
+ memcpy (ext->x_file.x_fname, in->x_file.x_n.x_fname, E_FILNMLEN);
return AUXESZ;
@@ -593,7 +599,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 +607,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 +658,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;
@@ -911,7 +919,8 @@ _bfd_XX_only_swap_filehdr_out (bfd * abfd, void * in, void * out)
}
unsigned int
-_bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
+_bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out,
+ const asection *section)
{
struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
SCNHDR *scnhdr_ext = (SCNHDR *) out;
@@ -980,9 +989,8 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set
(this is especially important when dealing with the .idata section since
the addresses for routines from .dlls must be overwritten). If .reloc
- section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE
- (0x02000000). Also, the resource data should also be read and
- writable. */
+ section data is ever generated, we generally need to add
+ IMAGE_SCN_MEM_DISCARDABLE (0x02000000). */
/* FIXME: Alignment is also encoded in this field, at least on
ARM-WINCE. Although - how do we get the original alignment field
@@ -995,12 +1003,13 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
}
pe_required_section_flags;
- pe_required_section_flags known_sections [] =
+ static const pe_required_section_flags known_sections [] =
{
{ ".CRT", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
{ ".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 },
@@ -1012,7 +1021,7 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
{ ".xdata", IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA },
};
- pe_required_section_flags * p;
+ const pe_required_section_flags * p;
/* We have defaulted to adding the IMAGE_SCN_MEM_WRITE flag, but now
we know exactly what this specific section wants so we remove it
@@ -1027,10 +1036,16 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
p++)
if (memcmp (scnhdr_int->s_name, p->section_name, SCNNMLEN) == 0)
{
+ unsigned long must_have = p->must_have;
+
if (memcmp (scnhdr_int->s_name, ".text", sizeof ".text")
|| (bfd_get_file_flags (abfd) & WP_TEXT))
scnhdr_int->s_flags &= ~IMAGE_SCN_MEM_WRITE;
- scnhdr_int->s_flags |= p->must_have;
+ /* Avoid forcing in the discardable flag if the section itself is
+ allocated. */
+ if (section->flags & SEC_ALLOC)
+ must_have &= ~IMAGE_SCN_MEM_DISCARDABLE;
+ scnhdr_int->s_flags |= must_have;
break;
}
@@ -3112,9 +3127,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;
@@ -4543,6 +4560,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);