Add pe/x86_64 bigobj file format.
authorTristan Gingold <gingold@adacore.com>
Mon, 2 Dec 2013 13:30:32 +0000 (14:30 +0100)
committerTristan Gingold <tristan.gingold@adacore.com>
Thu, 13 Mar 2014 08:33:07 +0000 (09:33 +0100)
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.

24 files changed:
bfd/ChangeLog
bfd/coff-alpha.c
bfd/coff-mips.c
bfd/coff-rs6000.c
bfd/coff-sh.c
bfd/coff64-rs6000.c
bfd/coffcode.h
bfd/config.bfd
bfd/configure
bfd/configure.in
bfd/libcoff.h
bfd/pe-x86_64.c
bfd/peicode.h
bfd/targets.c
gas/ChangeLog
gas/config/tc-i386.c
gas/doc/c-i386.texi
gas/testsuite/ChangeLog
gas/testsuite/gas/pe/big-obj.d [new file with mode: 0644]
gas/testsuite/gas/pe/big-obj.s [new file with mode: 0644]
gas/testsuite/gas/pe/pe.exp
include/coff/ChangeLog
include/coff/internal.h
include/coff/pe.h

index 7ecaed6..168c84f 100644 (file)
@@ -1,3 +1,36 @@
+2014-03-13  Tristan Gingold  <gingold@adacore.com>
+
+       * 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  <nickc@redhat.com>
 
        PR ld/16671
index a7a977c..8c68b56 100644 (file)
@@ -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,
index 454f89a..3a30d83 100644 (file)
@@ -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,
index 06ee721..d0b8eaf 100644 (file)
@@ -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,
index aca2b8b..1bf3f21 100644 (file)
@@ -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,
index 4bc7ea8..d660e3a 100644 (file)
@@ -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,
index 11e70a5..d6fe39f 100644 (file)
@@ -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
index 59b9f64..147954a 100644 (file)
@@ -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
     ;;
index bef7295..fbf5f44 100755 (executable)
@@ -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" ;;
index da8c6dc..f1ec965 100644 (file)
@@ -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" ;;
index b5a9852..36c9829 100644 (file)
@@ -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))
 
index 26bb99d..16b13ec 100644 (file)
@@ -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      '_'
   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
+};
index 8fd689c..157879b 100644 (file)
@@ -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
index f502eec..058ab77 100644 (file)
@@ -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,
index 6851b8c..ab4036f 100644 (file)
@@ -1,3 +1,13 @@
+2014-03-13  Tristan Gingold  <gingold@adacore.com>
+
+       * 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  <nickc@redhat.com>
 
        PR gas/16688
index f6283a6..734935a 100644 (file)
@@ -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";
index 18bd96a..1952cee 100644 (file)
@@ -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
 
index 9e87cc0..161d49e 100644 (file)
@@ -1,3 +1,8 @@
+2014-03-13  Tristan Gingold  <gingold@adacore.com>
+
+       * gas/pe/big-obj.d, gas/pe/big-obj.s: Add test.
+       * gas/pe/pe.exp: Add test.
+
 2014-03-12  Nick Clifton  <nickc@redhat.com>
 
        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 (file)
index 0000000..95ff1d8
--- /dev/null
@@ -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 (file)
index 0000000..07edc91
--- /dev/null
@@ -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
index 0b70ee6..c1c5f49 100644 (file)
@@ -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"
+}
index 0d90f5a..2ee6361 100644 (file)
@@ -1,3 +1,14 @@
+2014-03-13  Tristan Gingold  <gingold@adacore.com>
+
+       * 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  <amodra@gmail.com>
 
        Update copyright years.
index 4f99f2f..b34e5c6 100644 (file)
@@ -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     */
index 0093398..3166531 100644 (file)
@@ -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.  */