PATCH: x86_64 large data sections support

H. J. Lu hjl@lucon.org
Sun Jul 24 15:27:00 GMT 2005


On Sun, Jul 24, 2005 at 01:38:04PM +0200, Jan Hubicka wrote:
> Hi,
> not sure if I told you, but your implementation of x86-64 lcommon seems
> to work flawlessly for me now, so it would be very nice if you pushed it
> into mainline binutils tree ;)
> 
> Thanks a lot for help!
> Honza

There are 2 patches for x86_64 large data section support. They have
been tested on x86_64, ia32 and ia64. There are no regressions. Other
backends can use the frame work provided here to improve large/small
common symbol support if needed.  Are there any objections to check
them in?



H.J.
-------------- next part --------------
2005-06-27  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (elf_backend_data): Add special_section,
	common_definition, common_section_index, common_section,
	and merge_symbol.
	(_bfd_elf_common_definition): New.
	(_bfd_elf_common_section_index): New.
	(_bfd_elf_common_section): New.

	* elf.c (elf_fake_sections): Don't clear sh_flags.

	* elflink.c (_bfd_elf_merge_symbol): Call backend merge_symbol
	if it is available.
	(is_global_data_symbol_definition): Call backend
	common_definition instead of checking SHN_COMMON.
	(elf_link_add_object_symbols): Likewise.
	(elf_link_output_extsym): Call backend common_section_index
	for common section index.
	(elf_link_input_bfd): Call backend special_section for unknown
	special section indices.
	(_bfd_elf_common_definition): New.
	(_bfd_elf_common_section_index): New.
	(_bfd_elf_common_section): New.

	* elfxx-target.h (elf_backend_common_definition): New.
	(elf_backend_common_section_index): New.
	(elf_backend_common_section): New.
	(elf_backend_special_section): New.
	(elf_backend_merge_symbol): New.
	(elfNN_bed): Initialize special_section, common_definition,
	common_section_index, common_section, and merge_symbol.

	* section.c (BFD_FAKE_SECTION): New.
	(STD_SECTION): Use it.
	* bfd-in2.h: Regenerated.

--- bfd/elf-bfd.h.common	2005-07-18 11:35:01.397432713 -0700
+++ bfd/elf-bfd.h	2005-07-18 11:35:01.441425461 -0700
@@ -974,6 +974,33 @@ struct elf_backend_data
      see elf.c.  */
   bfd_vma (*plt_sym_val) (bfd_vma, const asection *, const arelent *);
 
+  /* Return the special section where symbol is defined.  */
+  asection *(*special_section) (Elf_Internal_Sym *);
+
+  /* Is symbol defined in common section?  */
+  bfd_boolean (*common_definition) (Elf_Internal_Sym *);
+
+  /* Return a common section index for section.  */
+  unsigned int (*common_section_index) (asection *);
+
+  /* Return a common section for section.  */
+  asection *(*common_section) (asection *);
+
+  /* Return TRUE if we can merge 2 definitions.  */
+  bfd_boolean (*merge_symbol) (struct bfd_link_info *,
+			       struct elf_link_hash_entry **,
+			       struct elf_link_hash_entry *,
+			       Elf_Internal_Sym *, asection **,
+			       bfd_vma *, unsigned int *,
+			       bfd_boolean *, bfd_boolean *,
+			       bfd_boolean *, bfd_boolean *,
+			       bfd_boolean *, bfd_boolean *,
+			       bfd_boolean *, bfd_boolean *,
+			       bfd *, asection **,
+			       bfd_boolean *, bfd_boolean *,
+			       bfd_boolean *, bfd_boolean *,
+			       bfd *, asection **);
+
   /* Used to handle bad SHF_LINK_ORDER input.  */
   bfd_error_handler_type link_order_error_handler;
 
@@ -1749,6 +1776,15 @@ extern int bfd_elf_link_record_local_dyn
 extern bfd_boolean _bfd_elf_close_and_cleanup
   (bfd *);
 
+extern bfd_boolean _bfd_elf_common_definition
+  (Elf_Internal_Sym *);
+
+extern unsigned int _bfd_elf_common_section_index
+  (asection *);
+
+extern asection *_bfd_elf_common_section
+  (asection *);
+
 extern void _bfd_dwarf2_cleanup_debug_info
   (bfd *);
 
--- bfd/elf.c.common	2005-07-18 11:35:01.402431889 -0700
+++ bfd/elf.c	2005-07-18 11:35:01.445424802 -0700
@@ -2618,7 +2618,7 @@ elf_fake_sections (bfd *abfd, asection *
       return;
     }
 
-  this_hdr->sh_flags = 0;
+  /* Don't clear sh_flags. Assembler may set additional bits.  */
 
   if ((asect->flags & SEC_ALLOC) != 0
       || asect->user_set_vma)
--- bfd/elflink.c.common	2005-07-18 11:35:01.129476881 -0700
+++ bfd/elflink.c	2005-07-18 11:47:05.791028513 -0700
@@ -782,6 +782,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
   bfd_boolean newweak, oldweak;
+  const struct elf_backend_data *bed;
 
   *skip = FALSE;
   *override = FALSE;
@@ -1123,6 +1124,19 @@ _bfd_elf_merge_symbol (bfd *abfd,
   else
     olddyncommon = FALSE;
 
+  /* We now know everything about the old and new symbols.  We ask the
+     backend to check if we can merge them.  */
+  bed = get_elf_backend_data (abfd);
+  if (bed->merge_symbol
+      && !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue,
+			     pold_alignment, skip, override,
+			     type_change_ok, size_change_ok,
+			     &newdyn, &newdef, &newdyncommon, &newweak,
+			     abfd, &sec,
+			     &olddyn, &olddef, &olddyncommon, &oldweak,
+			     oldbfd, &oldsec))
+    return FALSE;
+
   /* If both the old and the new symbols look like common symbols in a
      dynamic object, set the size of the symbol to the larger of the
      two.  */
@@ -1199,7 +1213,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       newdef = FALSE;
       newdyncommon = FALSE;
       *pvalue = sym->st_size;
-      *psec = sec = bfd_com_section_ptr;
+      *psec = sec = bed->common_section (oldsec);
       *size_change_ok = TRUE;
     }
 
@@ -2661,6 +2675,8 @@ static bfd_boolean
 is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
 				  Elf_Internal_Sym *sym)
 {
+  const struct elf_backend_data *bed;
+
   /* Local symbols do not count, but target specific ones might.  */
   if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL
       && ELF_ST_BIND (sym->st_info) < STB_LOOS)
@@ -2676,7 +2692,8 @@ is_global_data_symbol_definition (bfd *a
 
   /* If the symbol is defined in the common section, then
      it is a common definition and so does not count.  */
-  if (sym->st_shndx == SHN_COMMON)
+  bed = get_elf_backend_data (abfd);
+  if (bed->common_definition (sym))
     return FALSE;
 
   /* If the symbol is in a target specific section then we
@@ -3568,6 +3585,7 @@ elf_link_add_object_symbols (bfd *abfd, 
       bfd_boolean type_change_ok;
       bfd_boolean new_weakdef;
       bfd_boolean override;
+      bfd_boolean common;
       unsigned int old_alignment;
       bfd *old_bfd;
 
@@ -3577,6 +3595,7 @@ elf_link_add_object_symbols (bfd *abfd, 
       sec = NULL;
       value = isym->st_value;
       *sym_hash = NULL;
+      common = bed->common_definition (isym);
 
       bind = ELF_ST_BIND (isym->st_info);
       if (bind == STB_LOCAL)
@@ -3589,8 +3608,7 @@ elf_link_add_object_symbols (bfd *abfd, 
 	}
       else if (bind == STB_GLOBAL)
 	{
-	  if (isym->st_shndx != SHN_UNDEF
-	      && isym->st_shndx != SHN_COMMON)
+	  if (isym->st_shndx != SHN_UNDEF && !common)
 	    flags = BSF_GLOBAL;
 	}
       else if (bind == STB_WEAK)
@@ -3881,13 +3899,12 @@ elf_link_add_object_symbols (bfd *abfd, 
 	}
 
       /* Set the alignment of a common symbol.  */
-      if ((isym->st_shndx == SHN_COMMON
-	   || bfd_is_com_section (sec))
+      if ((common || bfd_is_com_section (sec))
 	  && h->root.type == bfd_link_hash_common)
 	{
 	  unsigned int align;
 
-	  if (isym->st_shndx == SHN_COMMON)
+	  if (common)
 	    align = bfd_log2 (isym->st_value);
 	  else
 	    {
@@ -3913,7 +3930,7 @@ elf_link_add_object_symbols (bfd *abfd, 
 	     definition or a common symbol is ignored due to the old
 	     normal definition. We need to make sure the maximum
 	     alignment is maintained.  */
-	  if ((old_alignment || isym->st_shndx == SHN_COMMON)
+	  if ((old_alignment || common)
 	      && h->root.type != bfd_link_hash_common)
 	    {
 	      unsigned int common_align;
@@ -6526,7 +6543,7 @@ elf_link_output_extsym (struct elf_link_
 
     case bfd_link_hash_common:
       input_sec = h->root.u.c.p->section;
-      sym.st_shndx = SHN_COMMON;
+      sym.st_shndx = bed->common_section_index (input_sec);
       sym.st_value = 1 << h->root.u.c.p->alignment_power;
       break;
 
@@ -6880,6 +6897,8 @@ elf_link_input_bfd (struct elf_final_lin
 	isec = bfd_abs_section_ptr;
       else if (isym->st_shndx == SHN_COMMON)
 	isec = bfd_com_section_ptr;
+      else if (bed->special_section)
+	isec = bed->special_section (isym);
       else
 	{
 	  /* Who knows?  */
@@ -9928,3 +9947,21 @@ _bfd_elf_fix_excluded_sec_syms (bfd *obf
 {
   bfd_link_hash_traverse (info->hash, fix_syms, obfd);
 }
+
+bfd_boolean
+_bfd_elf_common_definition (Elf_Internal_Sym *sym)
+{
+  return sym->st_shndx == SHN_COMMON;
+}
+
+unsigned int
+_bfd_elf_common_section_index (asection *sec ATTRIBUTE_UNUSED)
+{
+  return SHN_COMMON;
+}
+
+asection *
+_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED)
+{
+  return bfd_com_section_ptr;
+}
--- bfd/elfxx-target.h.common	2005-07-18 11:35:01.410430570 -0700
+++ bfd/elfxx-target.h	2005-07-18 11:35:01.454423319 -0700
@@ -525,6 +525,26 @@
 #define elf_backend_link_order_error_handler _bfd_default_error_handler
 #endif
 
+#ifndef elf_backend_common_definition
+#define elf_backend_common_definition _bfd_elf_common_definition
+#endif
+
+#ifndef elf_backend_common_section_index
+#define elf_backend_common_section_index _bfd_elf_common_section_index
+#endif
+
+#ifndef elf_backend_common_section
+#define elf_backend_common_section _bfd_elf_common_section
+#endif
+
+#ifndef elf_backend_special_section
+#define elf_backend_special_section NULL
+#endif
+
+#ifndef elf_backend_merge_symbol
+#define elf_backend_merge_symbol NULL
+#endif
+
 extern const struct elf_size_info _bfd_elfNN_size_info;
 
 #ifndef INCLUDED_TARGET_FILE
@@ -595,6 +615,11 @@ static const struct elf_backend_data elf
   elf_backend_ecoff_debug_swap,
   elf_backend_bfd_from_remote_memory,
   elf_backend_plt_sym_val,
+  elf_backend_special_section,
+  elf_backend_common_definition,
+  elf_backend_common_section_index,
+  elf_backend_common_section,
+  elf_backend_merge_symbol,
   elf_backend_link_order_error_handler,
   elf_backend_relplt_name,
   ELF_MACHINE_ALT1,
--- bfd/section.c.common	2005-06-29 21:46:11.000000000 -0700
+++ bfd/section.c	2005-07-18 11:35:01.460422330 -0700
@@ -635,6 +635,47 @@ CODE_FRAGMENT
 .#define bfd_section_removed_from_list(ABFD, S) \
 .  ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
 .
+.#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, SYM_PTR, NAME, IDX)		\
+.  {* name, id,  index, next, prev, flags, user_set_vma,            *}	\
+.  { NAME,  IDX, 0,     NULL, NULL, FLAGS, 0,				\
+.									\
+.  {* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      *}	\
+.     0,           0,                1,       0,			\
+.									\
+.  {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       *}	\
+.     0,            0,             0,          0,			\
+.									\
+.  {* has_gp_reloc, need_finalize_relax, reloc_done,                *}	\
+.     0,            0,                   0,				\
+.									\
+.  {* vma, lma, size, rawsize                                       *}	\
+.     0,   0,   0,    0,						\
+.									\
+.  {* output_offset, output_section,              alignment_power,  *}	\
+.     0,             (struct bfd_section *) &SEC, 0,			\
+.									\
+.  {* relocation, orelocation, reloc_count, filepos, rel_filepos,   *}	\
+.     NULL,       NULL,        0,           0,       0,			\
+.									\
+.  {* line_filepos, userdata, contents, lineno, lineno_count,       *}	\
+.     0,            NULL,     NULL,     NULL,   0,			\
+.									\
+.  {* entsize, kept_section, moving_line_filepos,		     *}	\
+.     0,       NULL,	      0,					\
+.									\
+.  {* target_index, used_by_bfd, constructor_chain, owner,          *}	\
+.     0,            NULL,        NULL,              NULL,		\
+.									\
+.  {* symbol,                                                       *}	\
+.     (struct bfd_symbol *) SYM,					\
+.									\
+.  {* symbol_ptr_ptr,                                               *}	\
+.     (struct bfd_symbol **) SYM_PTR,					\
+.									\
+.  {* map_head, map_tail                                            *}	\
+.     { NULL }, { NULL }						\
+.    }
+.
 */
 
 /* We use a macro to initialize the static asymbol structures because
@@ -662,46 +703,8 @@ static const asymbol global_syms[] =
 
 #define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX)				\
   const asymbol * const SYM = (asymbol *) &global_syms[IDX]; 		\
-  asection SEC =							\
-    /* name, id,  index, next, prev, flags, user_set_vma,            */	\
-    { NAME,  IDX, 0,     NULL, NULL, FLAGS, 0,				\
-									\
-    /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */	\
-       0,           0,                1,       0,			\
-									\
-    /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */	\
-       0,            0,             0,          0,			\
-									\
-    /* has_gp_reloc, need_finalize_relax, reloc_done,                */	\
-       0,            0,                   0,				\
-									\
-    /* vma, lma, size, rawsize                                       */	\
-       0,   0,   0,    0,						\
-									\
-    /* output_offset, output_section,              alignment_power,  */	\
-       0,             (struct bfd_section *) &SEC, 0,			\
-									\
-    /* relocation, orelocation, reloc_count, filepos, rel_filepos,   */	\
-       NULL,       NULL,        0,           0,       0,		\
-									\
-    /* line_filepos, userdata, contents, lineno, lineno_count,       */	\
-       0,            NULL,     NULL,     NULL,   0,			\
-									\
-    /* entsize, kept_section, moving_line_filepos,                   */	\
-       0,       NULL,         0,					\
-									\
-    /* target_index, used_by_bfd, constructor_chain, owner,          */	\
-       0,            NULL,        NULL,              NULL,		\
-									\
-    /* symbol,                                                       */	\
-       (struct bfd_symbol *) &global_syms[IDX],				\
-									\
-    /* symbol_ptr_ptr,                                               */	\
-       (struct bfd_symbol **) &SYM,					\
-									\
-    /* map_head, map_tail                                            */	\
-       { NULL }, { NULL }						\
-    }
+  asection SEC = BFD_FAKE_SECTION(SEC, FLAGS, &global_syms[IDX], &SYM,	\
+				  NAME, IDX)
 
 STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol,
 	     BFD_COM_SECTION_NAME, 0);
-------------- next part --------------
bfd/

2005-06-27  Jan Hubicka  <jh@suse.cz>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (_bfd_elf_large_com_section): New.
	* elf.c (_bfd_elf_large_com_section): New. Defined.

	* elf64-x86-64.c (elf64_x86_64_add_symbol_hook): New.
	(elf64_x86_64_elf_section_from_bfd_section): New.
	(elf64_x86_64_symbol_processing): New.
	(elf64_x86_64_common_definition): New.
	(elf64_x86_64_common_section_index): New.
	(elf64_x86_64_common_section): New.
	(elf64_x86_64_merge_symbol): New.
	(elf64_x86_64_additional_program_headers): New.
	(elf64_x86_64_special_sections): New.
	(elf_backend_section_from_bfd_section): New. Defined.
	(elf_backend_add_symbol_hook): Likewise.
	(elf_backend_common_section_index): Likewise.
	(elf_backend_common_section): Likewise.
	(elf_backend_common_definition): Likewise.
	(elf_backend_merge_symbol): Likewise.
	(elf_backend_special_sections): Likewise.
	(elf_backend_additional_program_headers): Likewise.

binutils/

2005-06-27  H.J. Lu  <hongjiu.lu@intel.com>

	* readelf.c (dump_relocations): Handle SHN_X86_64_LCOMMON.
	(get_symbol_index_type): Likewise.
	(get_elf_section_flags): Handle SHF_X86_64_LARGE.

gas/

2005-06-27  Jan Hubicka  <jh@suse.cz>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* config/obj-elf.c: Include "elf/x86-64.h" if TC_I386 is
	defined.
	(elf_com_section_ptr): New.
	(elf_begin): Set elf_com_section_ptr to bfd_com_section_ptr.
	(elf_common_parse): Make it global. Use elf_com_section_ptr
	instead of bfd_com_section_ptr.
	(obj_elf_change_section): Handle x86-64 large bss sections.

	* config/obj-elf.h (elf_com_section_ptr): New.
	(elf_common_parse): New.

	* config/tc-i386.c (handle_large_common): New.
	(md_pseudo_table): Add "largecomm".
	(x86_64_section_letter): New.
	(x86_64_section_word): New.

	* config/tc-i386.h (x86_64_section_word): New.
	(x86_64_section_letter): New.
	(md_elf_section_letter): New. Defined.
	(md_elf_section_word): Likewise.

include/elf/

2005-06-27  Jan Hubicka  <jh@suse.cz>

	* x86-64.h (SHN_X86_64_LCOMMON): New.
	(SHF_X86_64_LARGE): New.

ld/

2005-06-27  Jan Hubicka  <jh@suse.cz>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* emulparams/elf_x86_64.sh (LARGE_SECTIONS): New.

	* scripttempl/elf.sc: Updated for large section support.

--- binutils/bfd/elf-bfd.h.large	2005-07-18 13:10:12.860526432 -0700
+++ binutils/bfd/elf-bfd.h	2005-07-18 14:49:04.723471171 -0700
@@ -1845,6 +1845,9 @@ extern bfd *_bfd_elf64_bfd_from_remote_m
   (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep,
    int (*target_read_memory) (bfd_vma, bfd_byte *, int));
 
+/* Large common section.  */
+extern asection _bfd_elf_large_com_section;
+
 /* SH ELF specific routine.  */
 
 extern bfd_boolean _sh_elf_set_mach_from_flags
--- binutils/bfd/elf.c.large	2005-07-18 13:10:12.865525608 -0700
+++ binutils/bfd/elf.c	2005-07-18 14:49:04.728470344 -0700
@@ -8459,3 +8459,9 @@ done:
 
   return result;
 }
+
+/* It is only used by x86-64 so far.  */
+asection _bfd_elf_large_com_section
+  = BFD_FAKE_SECTION (_bfd_elf_large_com_section,
+		      SEC_IS_COMMON, NULL, NULL, "LARGE_COMMON",
+		      0);
--- binutils/bfd/elf64-x86-64.c.large	2005-07-18 13:10:12.845528905 -0700
+++ binutils/bfd/elf64-x86-64.c	2005-07-18 16:33:26.944589571 -0700
@@ -2906,6 +2906,181 @@ elf64_x86_64_section_from_shdr (bfd *abf
   return TRUE;
 }
 
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We use it to put SHN_X86_64_LCOMMON items in .lbss, instead
+   of .bss.  */
+
+static bfd_boolean
+elf64_x86_64_add_symbol_hook (bfd *abfd,
+			      struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			      Elf_Internal_Sym *sym,
+			      const char **namep ATTRIBUTE_UNUSED,
+			      flagword *flagsp ATTRIBUTE_UNUSED,
+			      asection **secp, bfd_vma *valp)
+{
+  asection *lcomm;
+
+  switch (sym->st_shndx)
+    {
+    case SHN_X86_64_LCOMMON:
+      lcomm = bfd_get_section_by_name (abfd, "LARGE_COMMON");
+      if (lcomm == NULL)
+	{
+	  lcomm = bfd_make_section_with_flags (abfd,
+					       "LARGE_COMMON",
+					       (SEC_ALLOC
+						| SEC_IS_COMMON
+						| SEC_LINKER_CREATED));
+	  if (lcomm == NULL)
+	    return FALSE;
+	  elf_section_flags (lcomm) |= SHF_X86_64_LARGE;
+	}
+      *secp = lcomm;
+      *valp = sym->st_size;
+      break;
+    }
+  return TRUE;
+}
+
+
+/* Given a BFD section, try to locate the corresponding ELF section
+   index.  */
+
+static bfd_boolean
+elf64_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+					   asection *sec, int *index)
+{
+  if (sec == &_bfd_elf_large_com_section)
+    {
+      *index = SHN_X86_64_LCOMMON;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+/* Process a symbol.  */
+
+static void
+elf64_x86_64_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
+				asymbol *asym)
+{
+  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
+
+  switch (elfsym->internal_elf_sym.st_shndx)
+    {
+    case SHN_X86_64_LCOMMON:
+      asym->section = &_bfd_elf_large_com_section;
+      asym->value = elfsym->internal_elf_sym.st_size;
+      /* Common symbol doesn't set BSF_GLOBAL.  */
+      asym->flags &= ~BSF_GLOBAL;
+      break;
+    }
+}
+
+static bfd_boolean
+elf64_x86_64_common_definition (Elf_Internal_Sym *sym)
+{
+  return (sym->st_shndx == SHN_COMMON
+	  || sym->st_shndx == SHN_X86_64_LCOMMON);
+}
+
+static unsigned int
+elf64_x86_64_common_section_index (asection *sec)
+{
+  if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
+    return SHN_COMMON;
+  else
+    return SHN_X86_64_LCOMMON;
+}
+
+static asection *
+elf64_x86_64_common_section (asection *sec)
+{
+  if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
+    return bfd_com_section_ptr;
+  else
+    return &_bfd_elf_large_com_section;
+}
+
+static bfd_boolean
+elf64_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			   struct elf_link_hash_entry **sym_hash ATTRIBUTE_UNUSED,
+			   struct elf_link_hash_entry *h,
+			   Elf_Internal_Sym *sym,
+			   asection **psec ATTRIBUTE_UNUSED,
+			   bfd_vma *pvalue ATTRIBUTE_UNUSED,
+			   unsigned int *pold_alignment ATTRIBUTE_UNUSED,
+			   bfd_boolean *skip ATTRIBUTE_UNUSED,
+			   bfd_boolean *override ATTRIBUTE_UNUSED,
+			   bfd_boolean *type_change_ok ATTRIBUTE_UNUSED,
+			   bfd_boolean *size_change_ok ATTRIBUTE_UNUSED,
+			   bfd_boolean *newdef ATTRIBUTE_UNUSED,
+			   bfd_boolean *newdyn,
+			   bfd_boolean *newdyncommon ATTRIBUTE_UNUSED,
+			   bfd_boolean *newweak ATTRIBUTE_UNUSED,
+			   bfd *abfd ATTRIBUTE_UNUSED,
+			   asection **sec,
+			   bfd_boolean *olddef ATTRIBUTE_UNUSED,
+			   bfd_boolean *olddyn,
+			   bfd_boolean *olddyncommon ATTRIBUTE_UNUSED,
+			   bfd_boolean *oldweak ATTRIBUTE_UNUSED,
+			   bfd *oldbfd ATTRIBUTE_UNUSED,
+			   asection **oldsec)
+{
+  /* A normal common symbol and a large common symbol result in a
+     normal common symbol.  If we see the normal symbol first, we
+     do nothing since the first one will be used.  If we see the
+     large common symbol first, we need to change the large common
+     symbol to the normal common symbol.  */
+  if (!*olddyn
+      && h->root.type == bfd_link_hash_common
+      && !*newdyn
+      && bfd_is_com_section (*sec)
+      && *oldsec != *sec
+      && sym->st_shndx == SHN_COMMON
+      && (elf_section_flags (*oldsec) & SHF_X86_64_LARGE) != 0)
+    {
+      h->root.u.c.p->section = bfd_make_section_old_way (abfd,
+							 "COMMON");
+      h->root.u.c.p->section->flags = SEC_ALLOC;
+    }
+
+  return TRUE;
+}
+
+static int
+elf64_x86_64_additional_program_headers (bfd *abfd)
+{
+  asection *s;
+  int count = 0; 
+
+  /* Check to see if we need a large readonly segment.  */
+  s = bfd_get_section_by_name (abfd, ".lrodata");
+  if (s && (s->flags & SEC_LOAD))
+    count++;
+
+  /* Check to see if we need a large data segment.  Since .lbss sections
+     is placed right after the .bss section, there should be no need for
+     a large data segment just because of .lbss.  */
+  s = bfd_get_section_by_name (abfd, ".ldata");
+  if (s && (s->flags & SEC_LOAD))
+    count++;
+
+  return count;
+}
+
+static const struct bfd_elf_special_section 
+  elf64_x86_64_special_sections[]=
+{
+  { ".gnu.linkonce.lb",	16, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+  { ".gnu.linkonce.lr",	16, -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
+  { ".gnu.linkonce.lt",	16, -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR + SHF_X86_64_LARGE},
+  { ".lbss",	5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+  { ".ldata",	6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+  { ".lrodata",	8, -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
+  { NULL,	0,  0, 0,            0 }
+};
+
 #define TARGET_LITTLE_SYM		    bfd_elf64_x86_64_vec
 #define TARGET_LITTLE_NAME		    "elf64-x86-64"
 #define ELF_ARCH			    bfd_arch_i386
@@ -2947,4 +3122,23 @@ elf64_x86_64_section_from_shdr (bfd *abf
 #define elf_backend_section_from_shdr \
 	elf64_x86_64_section_from_shdr
 
+#define elf_backend_section_from_bfd_section \
+  elf64_x86_64_elf_section_from_bfd_section
+#define elf_backend_add_symbol_hook \
+  elf64_x86_64_add_symbol_hook
+#define elf_backend_symbol_processing \
+  elf64_x86_64_symbol_processing
+#define elf_backend_common_section_index \
+  elf64_x86_64_common_section_index
+#define elf_backend_common_section \
+  elf64_x86_64_common_section
+#define elf_backend_common_definition \
+  elf64_x86_64_common_definition
+#define elf_backend_merge_symbol \
+  elf64_x86_64_merge_symbol
+#define elf_backend_special_sections \
+  elf64_x86_64_special_sections
+#define elf_backend_additional_program_headers \
+  elf64_x86_64_additional_program_headers
+
 #include "elf64-target.h"
--- binutils/binutils/readelf.c.large	2005-07-18 09:51:47.000000000 -0700
+++ binutils/binutils/readelf.c	2005-07-18 14:49:04.747467202 -0700
@@ -1355,6 +1355,9 @@ dump_relocations (FILE *file,
 			sec_name = "ABS";
 		      else if (psym->st_shndx == SHN_COMMON)
 			sec_name = "COMMON";
+		      else if (elf_header.e_machine == EM_X86_64
+			       && psym->st_shndx == SHN_X86_64_LCOMMON)
+			sec_name = "LARGE_COMMON";
 		      else if (elf_header.e_machine == EM_IA_64
 			       && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
 			       && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
@@ -3789,7 +3792,10 @@ get_elf_section_flags (bfd_vma sh_flags)
 	case SHF_TLS:		   *p = 'T'; break;
 
 	default:
-	  if (flag & SHF_MASKOS)
+	  if (elf_header.e_machine == EM_X86_64
+	      && flag == SHF_X86_64_LARGE)
+	    *p = 'l';
+	  else if (flag & SHF_MASKOS)
 	    {
 	      *p = 'o';
 	      sh_flags &= ~ SHF_MASKOS;
@@ -6698,6 +6704,9 @@ get_symbol_index_type (unsigned int type
 	  && elf_header.e_machine == EM_IA_64
 	  && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
 	return "ANSI_COM";
+      else if (elf_header.e_machine == EM_X86_64
+	       && type == SHN_X86_64_LCOMMON)
+	return "LARGE_COM";
       else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
 	sprintf (buff, "PRC[0x%04x]", type);
       else if (type >= SHN_LOOS && type <= SHN_HIOS)
--- binutils/gas/config/obj-elf.c.large	2005-07-06 08:45:41.000000000 -0700
+++ binutils/gas/config/obj-elf.c	2005-07-18 14:49:04.748467036 -0700
@@ -53,6 +53,10 @@
 #include "elf/i370.h"
 #endif
 
+#ifdef TC_I386
+#include "elf/x86-64.h"
+#endif
+
 static void obj_elf_line (int);
 static void obj_elf_size (int);
 static void obj_elf_type (int);
@@ -174,6 +178,8 @@ static const pseudo_typeS ecoff_debug_ps
 
 /* This is called when the assembler starts.  */
 
+asection *elf_com_section_ptr;
+
 void
 elf_begin (void)
 {
@@ -186,6 +192,7 @@ elf_begin (void)
   symbol_table_insert (section_symbol (s));
   s = bfd_get_section_by_name (stdoutput, BSS_SECTION_NAME);
   symbol_table_insert (section_symbol (s));
+  elf_com_section_ptr = bfd_com_section_ptr;
 }
 
 void
@@ -270,7 +277,7 @@ elf_file_symbol (const char *s, int appf
 /* Called from read.c:s_comm after we've parsed .comm symbol, size.
    Parse a possible alignment value.  */
 
-static symbolS *
+symbolS *
 elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
 {
   addressT align = 0;
@@ -334,7 +341,7 @@ elf_common_parse (int ignore ATTRIBUTE_U
       S_SET_VALUE (symbolP, size);
       S_SET_ALIGN (symbolP, align);
       S_SET_EXTERNAL (symbolP);
-      S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+      S_SET_SEGMENT (symbolP, elf_com_section_ptr);
     }
 
   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
@@ -569,7 +576,16 @@ obj_elf_change_section (const char *name
 		 .section .init_array,"aw",@progbits
 
 		 for __attribute__ ((section (".init_array"))).
+		 "@progbits" is incorrect.  Also for x86-64 large bss
+		 sections, gcc, as of 2005-07-06, will emit
+
+		 .section .lbss,"aw",@progbits
+
 		 "@progbits" is incorrect.  */
+#ifdef TC_I386
+	      && (bed->s->arch_size != 64
+		  || !(ssect->attr & SHF_X86_64_LARGE))
+#endif
 	      && ssect->type != SHT_INIT_ARRAY
 	      && ssect->type != SHT_FINI_ARRAY
 	      && ssect->type != SHT_PREINIT_ARRAY)
--- binutils/gas/config/obj-elf.h.large	2005-07-08 08:42:37.000000000 -0700
+++ binutils/gas/config/obj-elf.h	2005-07-18 13:10:12.895520663 -0700
@@ -244,5 +244,8 @@ extern void elf_pop_insert (void);
 struct ecoff_extr;
 extern void elf_ecoff_set_ext (symbolS *, struct ecoff_extr *);
 #endif
+extern asection *elf_com_section_ptr;
+extern symbolS * elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP,
+				   addressT size);
 
 #endif /* _OBJ_ELF_H */
--- binutils/gas/config/tc-i386.c.large	2005-07-18 09:51:59.000000000 -0700
+++ binutils/gas/config/tc-i386.c	2005-07-18 13:10:12.899520004 -0700
@@ -305,6 +305,7 @@ static int allow_naked_reg = 0;
    leave, push, and pop instructions so that gcc has the same stack
    frame as in 32 bit mode.  */
 static char stackop_size = '\0';
+static void handle_large_common (int small ATTRIBUTE_UNUSED);
 
 /* Non-zero to optimize code alignment.  */
 int optimize_align_code = 1;
@@ -467,6 +468,9 @@ const pseudo_typeS md_pseudo_table[] =
   {"att_syntax", set_intel_syntax, 0},
   {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
   {"loc", dwarf2_directive_loc, 0},
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+  {"largecomm", handle_large_common, 0},
+#endif
 #ifdef TE_PE
   {"secrel32", pe_directive_secrel, 0},
 #endif
@@ -6990,3 +6994,71 @@ tc_pe_dwarf2_emit_offset (symbolS *symbo
   emit_expr (&expr, size);
 }
 #endif
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+/* For ELF on x86-64, add support for SHF_X86_64_LARGE.  */
+
+int
+x86_64_section_letter (int letter, char **ptr_msg)
+{
+  if (flag_code == CODE_64BIT)
+    {
+      if (letter == 'l')
+	return SHF_X86_64_LARGE;
+
+      *ptr_msg = _("Bad .section directive: want a,l,w,x,M,S,G,T in string");
+     }
+  else
+   *ptr_msg = _("Bad .section directive: want a,w,x,M,S,G,T in string");
+  return -1;
+}
+
+int
+x86_64_section_word (char *str, size_t len)
+{
+  if (len == 5 && flag_code == CODE_64BIT && strncmp (str, "large", 5) == 0)
+    return SHF_X86_64_LARGE;
+
+  return -1;
+}
+
+static void
+handle_large_common (int small ATTRIBUTE_UNUSED)
+{
+  if (flag_code != CODE_64BIT)
+    {
+      s_comm_internal (0, elf_common_parse);
+      as_warn (_(".largecomm supported only in 64bit mode, producing .comm"));
+    }
+  else
+    {
+      static segT lbss_section;
+      asection *saved_com_section_ptr = elf_com_section_ptr;
+      asection *saved_bss_section = bss_section;
+
+      if (lbss_section == NULL)
+	{
+	  flagword applicable;
+	  segT seg = now_seg;
+	  subsegT subseg = now_subseg;
+
+	  /* The .lbss section is for local .largecomm symbols.  */
+	  lbss_section = subseg_new (".lbss", 0);
+	  applicable = bfd_applicable_section_flags (stdoutput);
+	  bfd_set_section_flags (stdoutput, lbss_section,
+				 applicable & SEC_ALLOC);
+	  seg_info (lbss_section)->bss = 1;
+
+	  subseg_set (seg, subseg);
+	}
+
+      elf_com_section_ptr = &_bfd_elf_large_com_section;
+      bss_section = lbss_section;
+
+      s_comm_internal (0, elf_common_parse);
+
+      elf_com_section_ptr = saved_com_section_ptr;
+      bss_section = saved_bss_section;
+    }
+}
+#endif /* OBJ_ELF || OBJ_MAYBE_ELF */
--- binutils/gas/config/tc-i386.h.large	2005-07-18 09:51:59.000000000 -0700
+++ binutils/gas/config/tc-i386.h	2005-07-18 13:10:12.900519839 -0700
@@ -501,6 +501,12 @@ extern void tc_x86_frame_initial_instruc
 #define md_elf_section_type(str,len) i386_elf_section_type (str, len)
 extern int i386_elf_section_type PARAMS ((const char *, size_t len));
 
+/* Support for SHF_X86_64_LARGE */
+extern int x86_64_section_word PARAMS ((char *, size_t));
+extern int x86_64_section_letter PARAMS ((int letter, char **ptr_msg));
+#define md_elf_section_letter(LETTER, PTR_MSG)	x86_64_section_letter (LETTER, PTR_MSG)
+#define md_elf_section_word(STR, LEN)		x86_64_section_word (STR, LEN)
+
 #ifdef TE_PE
 
 #define O_secrel O_md1
--- binutils/include/elf/x86-64.h.large	2005-06-17 15:26:45.000000000 -0700
+++ binutils/include/elf/x86-64.h	2005-07-18 13:10:12.900519839 -0700
@@ -61,4 +61,9 @@ END_RELOC_NUMBERS (R_X86_64_max)
 
 #define SHT_X86_64_UNWIND	0x70000001	/* unwind information */
 
+/* Like SHN_COMMON but the symbol will be allocated in the .lbss
+   section.  */
+#define SHN_X86_64_LCOMMON 	0xff02
+
+#define SHF_X86_64_LARGE	0x10000000
 #endif
--- binutils/ld/emulparams/elf_x86_64.sh.large	2005-07-18 13:10:12.852527751 -0700
+++ binutils/ld/emulparams/elf_x86_64.sh	2005-07-18 13:10:12.901519674 -0700
@@ -12,6 +12,7 @@ TEMPLATE_NAME=elf32
 GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
+LARGE_SECTIONS=yes
 SEPARATE_GOTPLT=24
 
 if [ "x${host}" = "x${target}" ]; then
--- binutils/ld/scripttempl/elf.sc.large	2005-06-30 22:11:04.000000000 -0700
+++ binutils/ld/scripttempl/elf.sc	2005-07-18 14:49:04.751466540 -0700
@@ -78,6 +78,9 @@
 #  .debug_info	.gnu.linkonce.wi.foo
 #  .tdata	.gnu.linkonce.td.foo
 #  .tbss	.gnu.linkonce.tb.foo
+#  .lrodata	.gnu.linkonce.lr.foo
+#  .ldata	.gnu.linkonce.l.foo
+#  .lbss	.gnu.linkonce.lb.foo
 #
 #  Each of these can also have corresponding .rel.* and .rela.* sections.
 
@@ -157,6 +160,31 @@ if test -z "${SDATA_GOT}"; then
     SDATA_GOT=" "
   fi
 fi
+if test -n "${LARGE_SECTIONS}"; then
+  LBSS="
+  .lbss ${RELOCATING-0} :
+  {
+   *(.dynlbss)
+   *(.lbss${RELOCATING+ .lbss.* .gnu.linkonce.lb.*})
+   *(LARGE_COMMON)
+  }"
+  LARGE_SECTIONS="
+  .lrodata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} :
+  {
+   *(.lrodata${RELOCATING+ .lrodata.* .gnu.linkonce.lr.*})
+  }
+  .ldata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} :
+  {
+   *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*})
+   ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
+  }"
+  REL_LDATA=".rel.ldata    ${RELOCATING-0} : { *(.rel.ldata${RELOCATING+ .rel.ldata.* .rel.gnu.linkonce.l.*}) }
+  .rela.ldata   ${RELOCATING-0} : { *(.rela.ldata${RELOCATING+ .rela.ldata.* .rela.gnu.linkonce.l.*}) }"
+  REL_LBSS=".rel.lbss     ${RELOCATING-0} : { *(.rel.lbss${RELOCATING+ .rel.lbss.* .rel.gnu.linkonce.lb.*}) }
+  .rela.lbss    ${RELOCATING-0} : { *(.rela.lbss${RELOCATING+ .rela.lbss.* .rela.gnu.linkonce.lb.*}) }"
+  REL_LRODATA=".rel.lrodata       ${RELOCATING-0} : { *(.rel.lrodata${RELOCATING+ .rel.lrodata.* .rel.gnu.linkonce.lr.*}) }
+  .rela.lrodata       ${RELOCATING-0} : { *(.rela.lrodata${RELOCATING+ .rela.lrodata.* .rela.gnu.linkonce.lr.*}) }"
+fi
 test -n "$SEPARATE_GOTPLT" && SEPARATE_GOTPLT=" "
 CTOR=".ctors        ${CONSTRUCTING-0} : 
   {
@@ -274,6 +302,9 @@ eval $COMBRELOCCAT <<EOF
   ${REL_SBSS2}
   .rel.bss      ${RELOCATING-0} : { *(.rel.bss${RELOCATING+ .rel.bss.* .rel.gnu.linkonce.b.*}) }
   .rela.bss     ${RELOCATING-0} : { *(.rela.bss${RELOCATING+ .rela.bss.* .rela.gnu.linkonce.b.*}) }
+  ${REL_LDATA}
+  ${REL_LBSS}
+  ${REL_LRODATA}
 EOF
 if [ -n "$COMBRELOC" ]; then
 cat <<EOF
@@ -397,13 +428,17 @@ cat <<EOF
    *(COMMON)
    /* Align here to ensure that the .bss section occupies space up to
       _end.  Align after .bss to ensure correct alignment even if the
-      .bss section disappears because there are no input sections.  */
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
    ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
   }
+  ${LBSS}
   ${OTHER_BSS_SECTIONS}
+  ${RELOCATING+${OTHER_BSS_END_SYMBOLS}}
+  ${LARGE_SECTIONS}
   ${RELOCATING+. = ALIGN(${ALIGNMENT});}
   ${RELOCATING+_end = .;}
-  ${RELOCATING+${OTHER_BSS_END_SYMBOLS}}
   ${RELOCATING+PROVIDE (end = .);}
   ${RELOCATING+${DATA_SEGMENT_END}}
 


More information about the Binutils mailing list