From 167ad85bf06582759e8dfe021aac9da79b81340d Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Mon, 2 Dec 2013 14:30:32 +0100 Subject: [PATCH] Add pe/x86_64 bigobj file format. bfd/ * peicode.h (pe_ILF_object_p): Adjust, as the version number has been read. (pe_bfd_object_p): Also read version number to detect ILF. * pe-x86_64.c (COFF_WITH_PE_BIGOBJ): Define. (x86_64pe_bigobj_vec): Define * coffcode.h (bfd_coff_backend_data): Add _bfd_coff_max_nscns field. (bfd_coff_max_nscns): New macro. (coff_compute_section_file_positions): Use unsigned int for target_index. Compare with bfd_coff_max_nscns. (bfd_coff_std_swap_table, ticoff0_swap_table, ticoff1_swap_table): Set a value for _bfd_coff_max_nscns. (header_bigobj_classid): New constant. (coff_bigobj_swap_filehdr_in, coff_bigobj_swap_filehdr_out) (coff_bigobj_swap_sym_in, coff_bigobj_swap_sym_out) (coff_bigobj_swap_aux_in, coff_bigobj_swap_aux_out): New functions. (bigobj_swap_table): New table. * libcoff.h: Regenerate. * coff-sh.c (bfd_coff_small_swap_table): Likewise. * coff-alpha.c (alpha_ecoff_backend_data): Add value for _bfd_coff_max_nscns. * coff-mips.c (mips_ecoff_backend_data): Likewise. * coff-rs6000.c (bfd_xcoff_backend_data) (bfd_pmac_xcoff_backend_data): Likewise. * coff64-rs6000.c (bfd_xcoff_backend_data) (bfd_xcoff_aix5_backend_data): Likewise. * targets.c (x86_64pe_bigobj_vec): Declare. * configure.in (x86_64pe_bigobj_vec): New vector. * configure: Regenerate. * config.bfd: Add bigobj object format for Windows targets. gas/ * config/tc-i386.c (use_big_obj): Declare. (OPTION_MBIG_OBJ): Define. (md_longopts): Add -mbig-obj option. (md_parse_option): Handle it. (md_show_usage): Display help for this option. (i386_target_format): Use bigobj for x86-64 if -mbig-obj. * doc/c-i386.texi: Document the option. gas/testsuite/ * gas/pe/big-obj.d, gas/pe/big-obj.s: Add test. * gas/pe/pe.exp: Add test. include/coff/ * pe.h (struct external_ANON_OBJECT_HEADER_BIGOBJ): Declare. (FILHSZ_BIGOBJ): Define. (struct external_SYMBOL_EX): Declare. (SYMENT_BIGOBJ, SYMESZ_BIGOBJ): Define. (union external_AUX_SYMBOL_EX): Declare. (AUXENT_BIGOBJ, AUXESZ_BIGOBJ): Define. * internal.h (struct internal_filehdr): Change type of f_nscns. --- bfd/ChangeLog | 33 +++++ bfd/coff-alpha.c | 2 +- bfd/coff-mips.c | 2 +- bfd/coff-rs6000.c | 2 + bfd/coff-sh.c | 1 + bfd/coff64-rs6000.c | 2 + bfd/coffcode.h | 258 ++++++++++++++++++++++++++++++++- bfd/config.bfd | 2 +- bfd/configure | 1 + bfd/configure.in | 1 + bfd/libcoff.h | 4 + bfd/pe-x86_64.c | 54 +++++++ bfd/peicode.h | 19 ++- bfd/targets.c | 2 + gas/ChangeLog | 10 ++ gas/config/tc-i386.c | 24 ++- gas/doc/c-i386.texi | 5 + gas/testsuite/ChangeLog | 5 + gas/testsuite/gas/pe/big-obj.d | 11 ++ gas/testsuite/gas/pe/big-obj.s | 16 ++ gas/testsuite/gas/pe/pe.exp | 8 + include/coff/ChangeLog | 11 ++ include/coff/internal.h | 2 +- include/coff/pe.h | 79 ++++++++++ 24 files changed, 537 insertions(+), 17 deletions(-) create mode 100644 gas/testsuite/gas/pe/big-obj.d create mode 100644 gas/testsuite/gas/pe/big-obj.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7ecaed68137..168c84f428c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,36 @@ +2014-03-13 Tristan Gingold + + * peicode.h (pe_ILF_object_p): Adjust, as the version number + has been read. + (pe_bfd_object_p): Also read version number to detect ILF. + * pe-x86_64.c (COFF_WITH_PE_BIGOBJ): Define. + (x86_64pe_bigobj_vec): Define + * coffcode.h (bfd_coff_backend_data): Add _bfd_coff_max_nscns field. + (bfd_coff_max_nscns): New macro. + (coff_compute_section_file_positions): Use unsigned int for + target_index. Compare with bfd_coff_max_nscns. + (bfd_coff_std_swap_table, ticoff0_swap_table, ticoff1_swap_table): + Set a value for _bfd_coff_max_nscns. + (header_bigobj_classid): New constant. + (coff_bigobj_swap_filehdr_in, coff_bigobj_swap_filehdr_out) + (coff_bigobj_swap_sym_in, coff_bigobj_swap_sym_out) + (coff_bigobj_swap_aux_in, coff_bigobj_swap_aux_out): New + functions. + (bigobj_swap_table): New table. + * libcoff.h: Regenerate. + * coff-sh.c (bfd_coff_small_swap_table): Likewise. + * coff-alpha.c (alpha_ecoff_backend_data): Add value for + _bfd_coff_max_nscns. + * coff-mips.c (mips_ecoff_backend_data): Likewise. + * coff-rs6000.c (bfd_xcoff_backend_data) + (bfd_pmac_xcoff_backend_data): Likewise. + * coff64-rs6000.c (bfd_xcoff_backend_data) + (bfd_xcoff_aix5_backend_data): Likewise. + * targets.c (x86_64pe_bigobj_vec): Declare. + * configure.in (x86_64pe_bigobj_vec): New vector. + * configure: Regenerate. + * config.bfd: Add bigobj object format for Windows targets. + 2014-03-12 Nick Clifton PR ld/16671 diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index a7a977cdbbd..8c68b56a80f 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -2241,7 +2241,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = alpha_ecoff_swap_filehdr_out, alpha_ecoff_swap_aouthdr_out, alpha_ecoff_swap_scnhdr_out, FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, - ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, + ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, 32768, alpha_ecoff_swap_filehdr_in, alpha_ecoff_swap_aouthdr_in, alpha_ecoff_swap_scnhdr_in, NULL, alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c index 454f89a230e..3a30d83f0f0 100644 --- a/bfd/coff-mips.c +++ b/bfd/coff-mips.c @@ -1254,7 +1254,7 @@ static const struct ecoff_backend_data mips_ecoff_backend_data = mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out, mips_ecoff_swap_scnhdr_out, FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, - ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, + ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, 32768, mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in, mips_ecoff_swap_scnhdr_in, NULL, mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 06ee721477b..d0b8eaf1804 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -4105,6 +4105,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data = 3, /* _bfd_coff_default_section_alignment_power */ FALSE, /* _bfd_coff_force_symnames_in_strings */ 2, /* _bfd_coff_debug_string_prefix_length */ + 32768, /* _bfd_coff_max_nscns */ coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in, @@ -4285,6 +4286,7 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data = 3, /* _bfd_coff_default_section_alignment_power */ FALSE, /* _bfd_coff_force_symnames_in_strings */ 2, /* _bfd_coff_debug_string_prefix_length */ + 32768, /* _bfd_coff_max_nscns */ coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in, diff --git a/bfd/coff-sh.c b/bfd/coff-sh.c index aca2b8b46d4..1bf3f21fc9e 100644 --- a/bfd/coff-sh.c +++ b/bfd/coff-sh.c @@ -3090,6 +3090,7 @@ static bfd_coff_backend_data bfd_coff_small_swap_table = #else 2, #endif + 32768, coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in, coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c index 4bc7ea8e872..d660e3a5267 100644 --- a/bfd/coff64-rs6000.c +++ b/bfd/coff64-rs6000.c @@ -2542,6 +2542,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data = 3, /* _bfd_coff_default_section_alignment_power */ TRUE, /* _bfd_coff_force_symnames_in_strings */ 4, /* _bfd_coff_debug_string_prefix_length */ + 32768, /* _bfd_coff_max_nscns */ coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in, @@ -2801,6 +2802,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data = 3, /* _bfd_coff_default_section_alignment_power */ TRUE, /* _bfd_coff_force_symnames_in_strings */ 4, /* _bfd_coff_debug_string_prefix_length */ + 32768, /* _bfd_coff_max_nscns */ coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in, diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 11e70a51784..d6fe39f1572 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -1393,6 +1393,7 @@ Special entry points for gdb to swap in coff symbol table parts: . unsigned int _bfd_coff_default_section_alignment_power; . bfd_boolean _bfd_coff_force_symnames_in_strings; . unsigned int _bfd_coff_debug_string_prefix_length; +. unsigned int _bfd_coff_max_nscns; . . void (*_bfd_coff_swap_filehdr_in) . (bfd *, void *, void *); @@ -1530,6 +1531,9 @@ Special entry points for gdb to swap in coff symbol table parts: . ((coff_backend_info (abfd)->_bfd_coff_set_long_section_names) (abfd, enable)) .#define bfd_coff_default_section_alignment_power(abfd) \ . (coff_backend_info (abfd)->_bfd_coff_default_section_alignment_power) +.#define bfd_coff_max_nscns(abfd) \ +. (coff_backend_info (abfd)->_bfd_coff_max_nscns) +. .#define bfd_coff_swap_filehdr_in(abfd, i,o) \ . ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o)) . @@ -3136,7 +3140,7 @@ coff_compute_section_file_positions (bfd * abfd) asection *current; file_ptr sofar = bfd_coff_filhsz (abfd); bfd_boolean align_adjust; - int target_index; + unsigned int target_index; #ifdef ALIGN_SECTIONS_IN_FILE asection *previous = NULL; file_ptr old_sofar; @@ -3304,7 +3308,7 @@ coff_compute_section_file_positions (bfd * abfd) } #endif /* ! COFF_IMAGE_WITH_PE */ - if (target_index >= 32768) + if (target_index >= bfd_coff_max_nscns (abfd)) { bfd_set_error (bfd_error_file_too_big); (*_bfd_error_handler) @@ -5497,6 +5501,7 @@ static bfd_coff_backend_data bfd_coff_std_swap_table ATTRIBUTE_UNUSED = #else 2, #endif + 32768, coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, coff_SWAP_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, @@ -5537,6 +5542,7 @@ static bfd_coff_backend_data ticoff0_swap_table = #else 2, #endif + 32768, coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, coff_SWAP_reloc_in, ticoff0_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, @@ -5578,6 +5584,7 @@ static bfd_coff_backend_data ticoff1_swap_table = #else 2, #endif + 32768, coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, coff_SWAP_reloc_in, ticoff1_bad_format_hook, coff_set_arch_mach_hook, coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, @@ -5591,6 +5598,253 @@ static bfd_coff_backend_data ticoff1_swap_table = }; #endif +#ifdef COFF_WITH_PE_BIGOBJ +/* The UUID for bigobj files. */ + +static const char header_bigobj_classid[16] = +{ + 0xC7, 0xA1, 0xBA, 0xD1, + 0xEE, 0xBA, + 0xa9, 0x4b, + 0xAF, 0x20, + 0xFA, 0xF6, 0x6A, 0xA4, 0xDC, 0xB8 +}; + +/* Swap routines. */ + +static void +coff_bigobj_swap_filehdr_in (bfd * abfd, void * src, void * dst) +{ + struct external_ANON_OBJECT_HEADER_BIGOBJ *filehdr_src = + (struct external_ANON_OBJECT_HEADER_BIGOBJ *) src; + struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst; + + filehdr_dst->f_magic = H_GET_16 (abfd, filehdr_src->Machine); + filehdr_dst->f_nscns = H_GET_32 (abfd, filehdr_src->NumberOfSections); + filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src->TimeDateStamp); + filehdr_dst->f_symptr = + GET_FILEHDR_SYMPTR (abfd, filehdr_src->PointerToSymbolTable); + filehdr_dst->f_nsyms = H_GET_32 (abfd, filehdr_src->NumberOfSymbols); + filehdr_dst->f_opthdr = 0; + filehdr_dst->f_flags = 0; + + /* Check other magic numbers. */ + if (H_GET_16 (abfd, filehdr_src->Sig1) != IMAGE_FILE_MACHINE_UNKNOWN + || H_GET_16 (abfd, filehdr_src->Sig2) != 0xffff + || H_GET_16 (abfd, filehdr_src->Version) != 2 + || memcmp (filehdr_src->ClassID, header_bigobj_classid, 16) != 0) + filehdr_dst->f_opthdr = 0xffff; + + /* Note that CLR metadata are ignored. */ +} + +static unsigned int +coff_bigobj_swap_filehdr_out (bfd *abfd, void * in, void * out) +{ + struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in; + struct external_ANON_OBJECT_HEADER_BIGOBJ *filehdr_out = + (struct external_ANON_OBJECT_HEADER_BIGOBJ *) out; + + memset (filehdr_out, 0, sizeof (*filehdr_out)); + + H_PUT_16 (abfd, IMAGE_FILE_MACHINE_UNKNOWN, filehdr_out->Sig1); + H_PUT_16 (abfd, 0xffff, filehdr_out->Sig2); + H_PUT_16 (abfd, 2, filehdr_out->Version); + memcpy (filehdr_out->ClassID, header_bigobj_classid, 16); + H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->Machine); + H_PUT_32 (abfd, filehdr_in->f_nscns, filehdr_out->NumberOfSections); + H_PUT_32 (abfd, filehdr_in->f_timdat, filehdr_out->TimeDateStamp); + PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, + filehdr_out->PointerToSymbolTable); + H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->NumberOfSymbols); + + return bfd_coff_filhsz (abfd); +} + +static void +coff_bigobj_swap_sym_in (bfd * abfd, void * ext1, void * in1) +{ + SYMENT_BIGOBJ *ext = (SYMENT_BIGOBJ *) ext1; + struct internal_syment *in = (struct internal_syment *) in1; + + if (ext->e.e_name[0] == 0) + { + in->_n._n_n._n_zeroes = 0; + in->_n._n_n._n_offset = H_GET_32 (abfd, ext->e.e.e_offset); + } + else + { +#if SYMNMLEN != E_SYMNMLEN +#error we need to cope with truncating or extending SYMNMLEN +#else + memcpy (in->_n._n_name, ext->e.e_name, SYMNMLEN); +#endif + } + + in->n_value = H_GET_32 (abfd, ext->e_value); + in->n_scnum = H_GET_32 (abfd, ext->e_scnum); + in->n_type = H_GET_16 (abfd, ext->e_type); + in->n_sclass = H_GET_8 (abfd, ext->e_sclass); + in->n_numaux = H_GET_8 (abfd, ext->e_numaux); +} + +static unsigned int +coff_bigobj_swap_sym_out (bfd * abfd, void * inp, void * extp) +{ + struct internal_syment *in = (struct internal_syment *) inp; + SYMENT_BIGOBJ *ext = (SYMENT_BIGOBJ *) extp; + + if (in->_n._n_name[0] == 0) + { + H_PUT_32 (abfd, 0, ext->e.e.e_zeroes); + H_PUT_32 (abfd, in->_n._n_n._n_offset, ext->e.e.e_offset); + } + else + { +#if SYMNMLEN != E_SYMNMLEN +#error we need to cope with truncating or extending SYMNMLEN +#else + memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN); +#endif + } + + H_PUT_32 (abfd, in->n_value, ext->e_value); + H_PUT_32 (abfd, in->n_scnum, ext->e_scnum); + + H_PUT_16 (abfd, in->n_type, ext->e_type); + H_PUT_8 (abfd, in->n_sclass, ext->e_sclass); + H_PUT_8 (abfd, in->n_numaux, ext->e_numaux); + + return SYMESZ_BIGOBJ; +} + +static void +coff_bigobj_swap_aux_in (bfd *abfd, + void * ext1, + int type, + int in_class, + int indx, + int numaux, + void * in1) +{ + AUXENT_BIGOBJ *ext = (AUXENT_BIGOBJ *) ext1; + union internal_auxent *in = (union internal_auxent *) in1; + + switch (in_class) + { + case C_FILE: + if (numaux > 1) + { + if (indx == 0) + memcpy (in->x_file.x_fname, ext->File.Name, + numaux * sizeof (AUXENT_BIGOBJ)); + } + else + memcpy (in->x_file.x_fname, ext->File.Name, sizeof (ext->File.Name)); + break; + + case C_STAT: + case C_LEAFSTAT: + case C_HIDDEN: + if (type == T_NULL) + { + in->x_scn.x_scnlen = H_GET_32 (abfd, ext->Section.Length); + in->x_scn.x_nreloc = + H_GET_16 (abfd, ext->Section.NumberOfRelocations); + in->x_scn.x_nlinno = + H_GET_16 (abfd, ext->Section.NumberOfLinenumbers); + in->x_scn.x_checksum = H_GET_32 (abfd, ext->Section.Checksum); + in->x_scn.x_associated = H_GET_16 (abfd, ext->Section.Number) + | (H_GET_16 (abfd, ext->Section.HighNumber) << 16); + in->x_scn.x_comdat = H_GET_8 (abfd, ext->Section.Selection); + return; + } + break; + + default: + in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->Sym.WeakDefaultSymIndex); + /* Characteristics is ignored. */ + break; + } +} + +static unsigned int +coff_bigobj_swap_aux_out (bfd * abfd, + void * inp, + int type, + int in_class, + int indx ATTRIBUTE_UNUSED, + int numaux ATTRIBUTE_UNUSED, + void * extp) +{ + union internal_auxent * in = (union internal_auxent *) inp; + AUXENT_BIGOBJ *ext = (AUXENT_BIGOBJ *) extp; + + memset (ext, 0, AUXESZ); + + switch (in_class) + { + case C_FILE: + memcpy (ext->File.Name, in->x_file.x_fname, sizeof (ext->File.Name)); + + return AUXESZ; + + case C_STAT: + case C_LEAFSTAT: + case C_HIDDEN: + if (type == T_NULL) + { + H_PUT_32 (abfd, in->x_scn.x_scnlen, ext->Section.Length); + H_PUT_16 (abfd, in->x_scn.x_nreloc, + ext->Section.NumberOfRelocations); + H_PUT_16 (abfd, in->x_scn.x_nlinno, + ext->Section.NumberOfLinenumbers); + H_PUT_32 (abfd, in->x_scn.x_checksum, ext->Section.Checksum); + H_PUT_16 (abfd, in->x_scn.x_associated & 0xffff, + ext->Section.Number); + H_PUT_16 (abfd, (in->x_scn.x_associated >> 16), + ext->Section.HighNumber); + H_PUT_8 (abfd, in->x_scn.x_comdat, ext->Section.Selection); + return AUXESZ; + } + break; + } + + H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->Sym.WeakDefaultSymIndex); + H_PUT_32 (abfd, 1, ext->Sym.WeakSearchType); + + return AUXESZ; +} + +static bfd_coff_backend_data bigobj_swap_table = +{ + coff_bigobj_swap_aux_in, coff_bigobj_swap_sym_in, coff_SWAP_lineno_in, + coff_bigobj_swap_aux_out, coff_bigobj_swap_sym_out, + coff_SWAP_lineno_out, coff_SWAP_reloc_out, + coff_bigobj_swap_filehdr_out, coff_SWAP_aouthdr_out, + coff_SWAP_scnhdr_out, + FILHSZ_BIGOBJ, AOUTSZ, SCNHSZ, SYMESZ_BIGOBJ, AUXESZ_BIGOBJ, + RELSZ, LINESZ, FILNMLEN_BIGOBJ, + TRUE, + COFF_DEFAULT_LONG_SECTION_NAMES, + COFF_DEFAULT_SECTION_ALIGNMENT_POWER, + FALSE, + 2, + 1U << 31, + coff_bigobj_swap_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in, + coff_SWAP_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook, + coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook, + coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook, + coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate, + coff_classify_symbol, coff_compute_section_file_positions, + coff_start_final_link, coff_relocate_section, coff_rtype_to_howto, + coff_adjust_symndx, coff_link_add_one_symbol, + coff_link_output_has_begun, coff_final_link_postscript, + bfd_pe_print_pdata /* huh */ +}; + +#endif /* COFF_WITH_PE_BIGOBJ */ + #ifndef coff_close_and_cleanup #define coff_close_and_cleanup _bfd_generic_close_and_cleanup #endif diff --git a/bfd/config.bfd b/bfd/config.bfd index 59b9f64db15..147954a6de1 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -676,7 +676,7 @@ case "${targ}" in ;; x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) targ_defvec=x86_64pe_vec - targ_selvecs="x86_64pe_vec x86_64pei_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec i386pe_vec i386pei_vec bfd_elf32_i386_vec" + targ_selvecs="x86_64pe_vec x86_64pei_vec x86_64pe_bigobj_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec i386pe_vec i386pei_vec bfd_elf32_i386_vec" want64=true targ_underscore=no ;; diff --git a/bfd/configure b/bfd/configure index bef72959802..fbf5f44f52b 100755 --- a/bfd/configure +++ b/bfd/configure @@ -15453,6 +15453,7 @@ do i386pei_vec) tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;; x86_64pe_vec) tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;; x86_64pei_vec) tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;; + x86_64pe_bigobj_vec) tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;; i860coff_vec) tb="$tb coff-i860.lo cofflink.lo" ;; icoff_big_vec) tb="$tb coff-i960.lo cofflink.lo" ;; icoff_little_vec) tb="$tb coff-i960.lo cofflink.lo" ;; diff --git a/bfd/configure.in b/bfd/configure.in index da8c6dcec83..f1ec9656fa4 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -942,6 +942,7 @@ do i386pei_vec) tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;; x86_64pe_vec) tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;; x86_64pei_vec) tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;; + x86_64pe_bigobj_vec) tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;; i860coff_vec) tb="$tb coff-i860.lo cofflink.lo" ;; icoff_big_vec) tb="$tb coff-i960.lo cofflink.lo" ;; icoff_little_vec) tb="$tb coff-i960.lo cofflink.lo" ;; diff --git a/bfd/libcoff.h b/bfd/libcoff.h index b5a98527a05..36c9829bde1 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -736,6 +736,7 @@ typedef struct unsigned int _bfd_coff_default_section_alignment_power; bfd_boolean _bfd_coff_force_symnames_in_strings; unsigned int _bfd_coff_debug_string_prefix_length; + unsigned int _bfd_coff_max_nscns; void (*_bfd_coff_swap_filehdr_in) (bfd *, void *, void *); @@ -873,6 +874,9 @@ typedef struct ((coff_backend_info (abfd)->_bfd_coff_set_long_section_names) (abfd, enable)) #define bfd_coff_default_section_alignment_power(abfd) \ (coff_backend_info (abfd)->_bfd_coff_default_section_alignment_power) +#define bfd_coff_max_nscns(abfd) \ + (coff_backend_info (abfd)->_bfd_coff_max_nscns) + #define bfd_coff_swap_filehdr_in(abfd, i,o) \ ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o)) diff --git a/bfd/pe-x86_64.c b/bfd/pe-x86_64.c index 26bb99d384e..16b13ecc93d 100644 --- a/bfd/pe-x86_64.c +++ b/bfd/pe-x86_64.c @@ -27,6 +27,7 @@ #define TARGET_NAME "pe-x86-64" #define COFF_WITH_PE #define COFF_WITH_pex64 +#define COFF_WITH_PE_BIGOBJ #define PCRELOFFSET TRUE #if defined (USE_MINGW64_LEADING_UNDERSCORES) #define TARGET_UNDERSCORE '_' @@ -58,3 +59,56 @@ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 } #include "coff-x86_64.c" + +/* Entry for big object files. */ + +const bfd_target +x86_64pe_bigobj_vec = +{ + "pe-bigobj-x86-64", /* Name. */ + bfd_target_coff_flavour, + BFD_ENDIAN_LITTLE, /* Data byte order is little. */ + BFD_ENDIAN_LITTLE, /* Header byte order is little. */ + + (HAS_RELOC | EXEC_P | /* Object flags. */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS), + + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */ + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING + | SEC_CODE | SEC_DATA | SEC_EXCLUDE ), + + TARGET_UNDERSCORE, /* Leading underscore. */ + '/', /* Ar_pad_char. */ + 15, /* Ar_max_namelen. */ + 0, /* match priority. */ + + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ + + /* Note that we allow an object file to be treated as a core file as well. */ + { _bfd_dummy_target, amd64coff_object_p, /* BFD_check_format. */ + bfd_generic_archive_p, amd64coff_object_p }, + { bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format. */ + bfd_false }, + { bfd_false, coff_write_object_contents, /* bfd_write_contents. */ + _bfd_write_archive_contents, bfd_false }, + + BFD_JUMP_TABLE_GENERIC (coff), + BFD_JUMP_TABLE_COPY (coff), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), + BFD_JUMP_TABLE_SYMBOLS (coff), + BFD_JUMP_TABLE_RELOCS (coff), + BFD_JUMP_TABLE_WRITE (coff), + BFD_JUMP_TABLE_LINK (coff), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + NULL, + + &bigobj_swap_table +}; diff --git a/bfd/peicode.h b/bfd/peicode.h index 8fd689c38ec..157879b478a 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -1077,7 +1077,7 @@ pe_ILF_build_a_bfd (bfd * abfd, static const bfd_target * pe_ILF_object_p (bfd * abfd) { - bfd_byte buffer[16]; + bfd_byte buffer[14]; bfd_byte * ptr; char * symbol_name; char * source_dll; @@ -1087,17 +1087,13 @@ pe_ILF_object_p (bfd * abfd) unsigned int types; unsigned int magic; - /* Upon entry the first four buyes of the ILF header have + /* Upon entry the first six bytes of the ILF header have already been read. Now read the rest of the header. */ - if (bfd_bread (buffer, (bfd_size_type) 16, abfd) != 16) + if (bfd_bread (buffer, (bfd_size_type) 14, abfd) != 14) return NULL; ptr = buffer; - /* We do not bother to check the version number. - version = H_GET_16 (abfd, ptr); */ - ptr += 2; - machine = H_GET_16 (abfd, ptr); ptr += 2; @@ -1251,7 +1247,7 @@ pe_ILF_object_p (bfd * abfd) static const bfd_target * pe_bfd_object_p (bfd * abfd) { - bfd_byte buffer[4]; + bfd_byte buffer[6]; struct external_PEI_DOS_hdr dos_hdr; struct external_PEI_IMAGE_hdr image_hdr; struct internal_filehdr internal_f; @@ -1260,15 +1256,18 @@ pe_bfd_object_p (bfd * abfd) file_ptr offset; /* Detect if this a Microsoft Import Library Format element. */ + /* First read the beginning of the header. */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 - || bfd_bread (buffer, (bfd_size_type) 4, abfd) != 4) + || bfd_bread (buffer, (bfd_size_type) 6, abfd) != 6) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } - if (H_GET_32 (abfd, buffer) == 0xffff0000) + /* Then check the magic and the version (only 0 is supported). */ + if (H_GET_32 (abfd, buffer) == 0xffff0000 + && H_GET_16 (abfd, buffer + 4) == 0) return pe_ILF_object_p (abfd); if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 diff --git a/bfd/targets.c b/bfd/targets.c index f502eeccfdf..058ab777812 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -896,6 +896,7 @@ extern const bfd_target w65_vec; extern const bfd_target we32kcoff_vec; extern const bfd_target x86_64pe_vec; extern const bfd_target x86_64pei_vec; +extern const bfd_target x86_64pe_bigobj_vec; extern const bfd_target x86_64coff_vec; extern const bfd_target z80coff_vec; extern const bfd_target z8kcoff_vec; @@ -1231,6 +1232,7 @@ static const bfd_target * const _bfd_target_vector[] = &x86_64coff_vec, &x86_64pe_vec, &x86_64pei_vec, + &x86_64pe_bigobj_vec, #endif &i860coff_vec, &icoff_big_vec, diff --git a/gas/ChangeLog b/gas/ChangeLog index 6851b8c4bb4..ab4036fa6d1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2014-03-13 Tristan Gingold + + * config/tc-i386.c (use_big_obj): Declare. + (OPTION_MBIG_OBJ): Define. + (md_longopts): Add -mbig-obj option. + (md_parse_option): Handle it. + (md_show_usage): Display help for this option. + (i386_target_format): Use bigobj for x86-64 if -mbig-obj. + * doc/c-i386.texi: Document the option. + 2014-03-12 Nick Clifton PR gas/16688 diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index f6283a685e5..734935adebe 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -513,6 +513,11 @@ enum x86_elf_abi static enum x86_elf_abi x86_elf_abi = I386_ABI; #endif +#if defined (TE_PE) || defined (TE_PEP) +/* Use big object file format. */ +static int use_big_obj = 0; +#endif + /* 1 for intel syntax, 0 if att syntax. */ static int intel_syntax = 0; @@ -9497,6 +9502,7 @@ const char *md_shortopts = "qn"; #define OPTION_MADD_BND_PREFIX (OPTION_MD_BASE + 15) #define OPTION_MEVEXLIG (OPTION_MD_BASE + 16) #define OPTION_MEVEXWIG (OPTION_MD_BASE + 17) +#define OPTION_MBIG_OBJ (OPTION_MD_BASE + 18) struct option md_longopts[] = { @@ -9523,6 +9529,9 @@ struct option md_longopts[] = {"madd-bnd-prefix", no_argument, NULL, OPTION_MADD_BND_PREFIX}, {"mevexlig", required_argument, NULL, OPTION_MEVEXLIG}, {"mevexwig", required_argument, NULL, OPTION_MEVEXWIG}, +# if defined (TE_PE) || defined (TE_PEP) + {"mbig-obj", no_argument, NULL, OPTION_MBIG_OBJ}, +#endif {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -9804,6 +9813,12 @@ md_parse_option (int c, char *arg) as_fatal (_("invalid -mevexwig= option: `%s'"), arg); break; +# if defined (TE_PE) || defined (TE_PEP) + case OPTION_MBIG_OBJ: + use_big_obj = 1; + break; +#endif + default: return 0; } @@ -9956,6 +9971,10 @@ md_show_usage (FILE *stream) -mold-gcc support old (<= 2.8.1) versions of gcc\n")); fprintf (stream, _("\ -madd-bnd-prefix add BND prefix for all valid branches\n")); +# if defined (TE_PE) || defined (TE_PEP) + fprintf (stream, _("\ + -mbig-obj generate big object files\n")); +#endif } #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ @@ -9994,7 +10013,10 @@ i386_target_format (void) #if defined (OBJ_MAYBE_COFF) || defined (OBJ_COFF) # if defined (TE_PE) || defined (TE_PEP) case bfd_target_coff_flavour: - return flag_code == CODE_64BIT ? "pe-x86-64" : "pe-i386"; + if (flag_code == CODE_64BIT) + return use_big_obj ? "pe-bigobj-x86-64" : "pe-x86-64"; + else + return "pe-i386"; # elif defined (TE_GO32) case bfd_target_coff_flavour: return "coff-go32"; diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index 18bd96ae608..1952cee78bd 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -283,6 +283,11 @@ The @code{.att_syntax} and @code{.intel_syntax} directives will take precedent. This option forces the assembler to add BND prefix to all branches, even if such prefix was not explicitly specified in the source code. +@cindex @samp{-mbig-obj} option, x86-64 +@item -mbig-obj +On x86-64 PE/COFF target this option forces the use of big object file +format, which allows more than 32768 sections. + @end table @c man end diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 9e87cc02aa5..161d49ec100 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-03-13 Tristan Gingold + + * gas/pe/big-obj.d, gas/pe/big-obj.s: Add test. + * gas/pe/pe.exp: Add test. + 2014-03-12 Nick Clifton PR gas/16688 diff --git a/gas/testsuite/gas/pe/big-obj.d b/gas/testsuite/gas/pe/big-obj.d new file mode 100644 index 00000000000..95ff1d82883 --- /dev/null +++ b/gas/testsuite/gas/pe/big-obj.d @@ -0,0 +1,11 @@ +#as: -mbig-obj +#objdump: -h +#name: PE x64 big obj + +.*: *file format pe-bigobj-.* + +Sections: +#... +5000. \.data\$a49999 .* + CONTENTS, ALLOC, LOAD, DATA + diff --git a/gas/testsuite/gas/pe/big-obj.s b/gas/testsuite/gas/pe/big-obj.s new file mode 100644 index 00000000000..07edc9133a7 --- /dev/null +++ b/gas/testsuite/gas/pe/big-obj.s @@ -0,0 +1,16 @@ + .file "big-obj.s" + + .irp n,0,1,2,3,4 + .irp m,0,1,2,3,4,5,6,7,8,9 + .irp c,0,1,2,3,4,5,6,7,8,9 + .irp d,0,1,2,3,4,5,6,7,8,9 + .irp u,0,1,2,3,4,5,6,7,8,9 + .globl a\n\m\c\d\u + .section .data$a\n\m\c\d\u,"w" +a\n\m\c\d\u : + .byte 1 + .endr + .endr + .endr + .endr + .endr diff --git a/gas/testsuite/gas/pe/pe.exp b/gas/testsuite/gas/pe/pe.exp index 0b70ee68067..c1c5f499237 100644 --- a/gas/testsuite/gas/pe/pe.exp +++ b/gas/testsuite/gas/pe/pe.exp @@ -48,3 +48,11 @@ if ([istarget "x86_64-*-mingw*"]) then { run_dump_test "peseh-x64-5" run_dump_test "peseh-x64-6" } + +# Big obj + + +if ([istarget "x86_64-*-mingw*"]) then { + # Currently only supported on x86_64 + run_dump_test "big-obj" +} diff --git a/include/coff/ChangeLog b/include/coff/ChangeLog index 0d90f5a91bf..2ee6361f828 100644 --- a/include/coff/ChangeLog +++ b/include/coff/ChangeLog @@ -1,3 +1,14 @@ +2014-03-13 Tristan Gingold + + * pe.h (struct external_ANON_OBJECT_HEADER_BIGOBJ): Declare. + (FILHSZ_BIGOBJ): Define. + (struct external_SYMBOL_EX): Declare. + (SYMENT_BIGOBJ, SYMESZ_BIGOBJ): Define. + (union external_AUX_SYMBOL_EX): Declare. + (AUXENT_BIGOBJ, AUXESZ_BIGOBJ): Define. + * internal.h (struct internal_filehdr): Change type + of f_nscns. + 2014-03-05 Alan Modra Update copyright years. diff --git a/include/coff/internal.h b/include/coff/internal.h index 4f99f2f95ea..b34e5c6c348 100644 --- a/include/coff/internal.h +++ b/include/coff/internal.h @@ -73,7 +73,7 @@ struct internal_filehdr /* Standard coff internal info. */ unsigned short f_magic; /* magic number */ - unsigned short f_nscns; /* number of sections */ + unsigned int f_nscns; /* number of sections */ long f_timdat; /* time & date stamp */ bfd_vma f_symptr; /* file pointer to symtab */ long f_nsyms; /* number of symtab entries */ diff --git a/include/coff/pe.h b/include/coff/pe.h index 0093398bea2..3166531097f 100644 --- a/include/coff/pe.h +++ b/include/coff/pe.h @@ -358,6 +358,85 @@ typedef struct #define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 #define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 +/* Bigobj header. */ +struct external_ANON_OBJECT_HEADER_BIGOBJ +{ + /* ANON_OBJECT_HEADER_V2 header. */ + char Sig1[2]; + char Sig2[2]; + char Version[2]; + char Machine[2]; + char TimeDateStamp[4]; + char ClassID[16]; + char SizeOfData[4]; + char Flags[4]; + char MetaDataSize[4]; + char MetaDataOffset[4]; + + /* BIGOBJ specific. */ + char NumberOfSections[4]; + char PointerToSymbolTable[4]; + char NumberOfSymbols[4]; +}; + +#define FILHSZ_BIGOBJ (14 * 4) + +struct external_SYMBOL_EX +{ + union + { + char e_name[E_SYMNMLEN]; + + struct + { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + + char e_value[4]; + char e_scnum[4]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +} ATTRIBUTE_PACKED ; + +#define SYMENT_BIGOBJ struct external_SYMBOL_EX +#define SYMESZ_BIGOBJ 20 + +#define FILNMLEN_BIGOBJ 20 + +union external_AUX_SYMBOL_EX +{ + struct + { + char WeakDefaultSymIndex[4]; + char WeakSearchType[4]; + char rgbReserved[12]; + } Sym; + + struct + { + char Name[FILNMLEN_BIGOBJ]; + } File; + + struct + { + char Length[4]; /* section length */ + char NumberOfRelocations[2]; /* # relocation entries */ + char NumberOfLinenumbers[2]; /* # line numbers */ + char Checksum[4]; /* section COMDAT checksum */ + char Number[2]; /* COMDAT associated section index */ + char Selection[1]; /* COMDAT selection number */ + char bReserved[1]; + char HighNumber[2]; /* High bits of COMDAT associated sec. */ + char rgbReserved[2]; + } Section; +} ATTRIBUTE_PACKED; + +#define AUXENT_BIGOBJ union external_AUX_SYMBOL_EX +#define AUXESZ_BIGOBJ 20 + /* .pdata/.xdata defines and structures for x64 PE+ for exception handling. */ /* .pdata in exception directory. */ -- 2.30.2