diff options
Diffstat (limited to 'bfd/peXXigen.c')
-rw-r--r-- | bfd/peXXigen.c | 87 |
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); |