x86-64 large data sections updated

Jan Hubicka jh@suse.cz
Tue Jun 14 22:13:00 GMT 2005


Hi,
I am attaching my current updated patch.  I am now going to test it more
toroughly but it seems to basically work and since there was so many
comments (sorry for being exceptionally dense this time!) I think it
would make sense to ensure that we are now in sync.

The patch change section ordering per Richard's comment and adds the
alignments before and after readonly segment.  (I am getting this
probably wrong since I want the DATA_SEGMENT_ALIGN instead of the normal
align becuase of pagesizes and I probably want to avoid alignment when
lrodata is empty, I am just looking into this issue).

I've also added the special sections with proper flags per Dj's comment
new SHF_X86_64_LARGE flag should be now set for large sections per
pending ABI change proposal.  with gas one can use 'l' in the .section
command to set it.

There is new .largecomm keyword that is equivalent to .comm except for
creating SHN_X86_64_LCOMMON (per current ABI change proposal).

So hope that I am gettting closer to solving this issue and thanks for
patience with previous thread ;)

Honza

Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.300
diff -c -3 -p -r1.300 elf.c
*** bfd/elf.c	6 Jun 2005 14:28:30 -0000	1.300
--- bfd/elf.c	14 Jun 2005 21:50:20 -0000
*************** get_program_header_size (bfd *abfd)
*** 4593,4598 ****
--- 4593,4607 ----
        segs += 2;
      }
  
+   if (bfd_get_section_by_name (abfd, ".ldata") != NULL
+       || bfd_get_section_by_name (abfd, ".lrodata") != NULL
+       || bfd_get_section_by_name (abfd, ".lbss") != NULL)
+ 
+     {
+       /* We need a large data area segment.  */
+       ++segs;
+     }
+ 
    if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
      {
        /* We need a PT_DYNAMIC segment.  */
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.95
diff -c -3 -p -r1.95 elf64-x86-64.c
*** bfd/elf64-x86-64.c	17 May 2005 16:43:02 -0000	1.95
--- bfd/elf64-x86-64.c	14 Jun 2005 21:50:20 -0000
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 975,980 ****
--- 991,1028 ----
    return TRUE;
  }
  
+ /* Hook called by the linker routine which adds symbols from an object
+    file.  We use it to put .comm items in .lbss, and not .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)
+ {
+   if (sym->st_shndx == SHN_X86_64_LCOMMON)
+     {
+ 
+       asection *lcomm = bfd_get_section_by_name (abfd, ".lbss");
+ 
+       if (lcomm == NULL)
+ 	{
+ 	  lcomm = bfd_make_section (abfd, ".lbss");
+ 	  if (lcomm == NULL
+ 	      || !bfd_set_section_flags (abfd, lcomm, (SEC_ALLOC
+ 						       | SEC_IS_COMMON
+ 						       | SEC_LINKER_CREATED)))
+ 	    return FALSE;
+ 	}
+ 
+       *secp = lcomm;
+       *valp = sym->st_size;
+     }
+ 
+   return TRUE;
+ }
+ 
+ 
  /* Return the section that should be marked against GC for a given
     relocation.	*/
  
*************** elf64_x86_64_section_from_shdr (bfd *abf
*** 2839,2844 ****
--- 2912,2985 ----
    return TRUE;
  }
  
+ /* Given a BFD section, try to locate the corresponding ELF section
+    index.  This is used by both the 32-bit and the 64-bit ABI.
+    Actually, it's not clear to me that the 64-bit ABI supports these,
+    but for non-PIC objects we will certainly want support for at least
+    the .scommon section.  */
+ 
+ static bfd_boolean
+ elf64_x86_64_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+ 					asection *sec, int *retval)
+ {
+   if (strcmp (bfd_get_section_name (abfd, sec), ".lcommon") == 0
+       || strcmp (bfd_get_section_name (abfd, sec), ".lbss") == 0)
+     {
+       *retval = SHN_X86_64_LCOMMON;
+       return TRUE;
+     }
+   return FALSE;
+ }
+ 
+ static struct bfd_elf_special_section const
+   elf64_special_sections_l[]=
+ {
+   { ".lbss",            4, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+   { ".ldata",           5, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+   { ".lrodata",         7, -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
+   { NULL,      0,  0, 0,              0 }
+ };
+ static struct bfd_elf_special_section const
+   elf64_special_sections_g[]=
+ {
+   { ".gnu.linkonce.lb",15, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
+   { ".gnu.linkonce.lr",15, -2, SHT_PROGBITS,   SHF_ALLOC},
+   { ".gnu.linkonce.l",15,  -2, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE },
+   { NULL,      0,  0, 0,              0 }
+ };
+ 
+ struct bfd_elf_special_section const *
+   elf64_x86_64_elf_special_sections[27] =
+ {
+   NULL,				/* 'a' */
+   NULL,				/* 'b' */
+   NULL,				/* 'c' */
+   NULL,				/* 'd' */
+   NULL,				/* 'e' */
+   NULL,				/* 'f' */
+   elf64_special_sections_g,	/* 'g' */
+   NULL,				/* 'h' */
+   NULL,				/* 'i' */
+   NULL,				/* 'j' */
+   NULL,				/* 'k' */
+   elf64_special_sections_l,	/* 'l' */
+   NULL,				/* 'm' */
+   NULL,				/* 'n' */
+   NULL,				/* 'o' */
+   NULL,				/* 'p' */
+   NULL,				/* 'q' */
+   NULL,				/* 'r' */
+   NULL,				/* 's' */
+   NULL,				/* 't' */
+   NULL,				/* 'u' */
+   NULL,				/* 'v' */
+   NULL,				/* 'w' */
+   NULL,				/* 'x' */
+   NULL,				/* 'y' */
+   NULL,				/* 'z' */
+   NULL				/* other */
+ };
+ 
  #define TARGET_LITTLE_SYM		    bfd_elf64_x86_64_vec
  #define TARGET_LITTLE_NAME		    "elf64-x86-64"
  #define ELF_ARCH			    bfd_arch_i386
*************** elf64_x86_64_section_from_shdr (bfd *abf
*** 2860,2865 ****
--- 3001,3007 ----
  #define bfd_elf64_bfd_reloc_type_lookup	    elf64_x86_64_reloc_type_lookup
  
  #define elf_backend_adjust_dynamic_symbol   elf64_x86_64_adjust_dynamic_symbol
+ #define elf_backend_add_symbol_hook         elf64_x86_64_add_symbol_hook
  #define elf_backend_check_relocs	    elf64_x86_64_check_relocs
  #define elf_backend_copy_indirect_symbol    elf64_x86_64_copy_indirect_symbol
  #define elf_backend_create_dynamic_sections elf64_x86_64_create_dynamic_sections
*************** elf64_x86_64_section_from_shdr (bfd *abf
*** 2874,2880 ****
--- 3016,3025 ----
  #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
  #define elf_backend_plt_sym_val		    elf64_x86_64_plt_sym_val
  #define elf_backend_object_p		    elf64_x86_64_elf_object_p
+ #define elf_backend_section_from_bfd_section \
+ 					    elf64_x86_64_elf_section_from_bfd_section
  #define bfd_elf64_mkobject		    elf64_x86_64_mkobject
+ #define elf_backend_special_sections	    elf64_x86_64_elf_special_sections
  
  #define elf_backend_section_from_shdr \
  	elf64_x86_64_section_from_shdr
Index: gas/config/obj-elf.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.c,v
retrieving revision 1.93
diff -c -3 -p -r1.93 obj-elf.c
*** gas/config/obj-elf.c	5 May 2005 09:12:52 -0000	1.93
--- gas/config/obj-elf.c	14 Jun 2005 21:50:20 -0000
*************** elf_file_symbol (const char *s, int appf
*** 270,276 ****
  /* Called from read.c:s_comm after we've parsed .comm symbol, size.
     Parse a possible alignment value.  */
  
! static symbolS *
  elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
  {
    addressT align = 0;
--- 270,276 ----
  /* Called from read.c:s_comm after we've parsed .comm symbol, size.
     Parse a possible alignment value.  */
  
! symbolS *
  elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
  {
    addressT align = 0;
Index: gas/config/obj-elf.h
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.h,v
retrieving revision 1.25
diff -c -3 -p -r1.25 obj-elf.h
*** gas/config/obj-elf.h	5 May 2005 09:12:53 -0000	1.25
--- gas/config/obj-elf.h	14 Jun 2005 21:50:20 -0000
*************** struct ecoff_extr;
*** 246,250 ****
--- 246,252 ----
  #endif
  extern void elf_ecoff_set_ext (symbolS *, struct ecoff_extr *);
  #endif
+ extern symbolS * elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP,
+ 				   addressT size);
  
  #endif /* _OBJ_ELF_H */
Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.181
diff -c -3 -p -r1.181 tc-i386.c
*** gas/config/tc-i386.c	7 Jun 2005 17:54:16 -0000	1.181
--- gas/config/tc-i386.c	14 Jun 2005 21:50:21 -0000
*************** static void s_bss PARAMS ((int));
*** 114,119 ****
--- 114,124 ----
  
  static const char *default_arch = DEFAULT_ARCH;
  
+ /* Stuff for .largecomm symbols.  */
+ static segT     lbss_section;
+ static asection lcom_section;
+ static asymbol  lcom_symbol;
+ 
  /* 'md_assemble ()' gathers together information and puts it into a
     i386_insn.  */
  
*************** static int allow_naked_reg = 0;
*** 305,310 ****
--- 310,316 ----
     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;
*************** const pseudo_typeS md_pseudo_table[] =
*** 463,468 ****
--- 469,477 ----
    {"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
*************** md_begin ()
*** 1035,1040 ****
--- 1044,1077 ----
        x86_dwarf2_return_column = 8;
        x86_cie_data_alignment = -4;
      }
+ #ifdef OBJ_ELF
+     if (flag_code == CODE_64BIT)
+       {
+ 	flagword applicable;
+ 	segT seg;
+ 	subsegT subseg;
+ 	/* The lbss section is for local .lcomm symbols.  */
+ 	lbss_section = subseg_new (".lbss", 0);
+ 	elf_section_flags (lbss_section) |= SHF_X86_64_LARGE;
+ 
+ 	seg    = now_seg;
+ 	subseg = now_subseg;
+ 	/* This is copied from perform_an_assembly_pass.  */
+ 	applicable = bfd_applicable_section_flags (stdoutput);
+ 	bfd_set_section_flags (stdoutput, lbss_section, applicable & SEC_ALLOC);
+ 
+ 	subseg_set (seg, subseg);
+ 
+ 	lcom_section                = bfd_com_section;
+ 	lcom_section.name           = ".lcommon";
+ 	lcom_section.output_section = & lcom_section;
+ 	lcom_section.symbol         = & lcom_symbol;
+ 	lcom_section.symbol_ptr_ptr = & lcom_section.symbol;
+ 	lcom_symbol                 = * bfd_com_section.symbol;
+ 	lcom_symbol.name            = ".lcommon";
+ 	lcom_symbol.section         = & lcom_section;
+       }
+ #endif
  }
  
  void
*************** tc_pe_dwarf2_emit_offset (symbolS *symbo
*** 6882,6884 ****
--- 6940,6994 ----
    emit_expr (&expr, size);
  }
  #endif
+ 
+ #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ /* For ELF on x86-64, add support for SHF_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;
+ }
+ 
+ /* The MRI COMMON pseudo-op.  We handle this by creating a common
+    symbol with the appropriate name.  We make s_space do the right
+    thing by increasing the size.  */
+ 
+ void
+ handle_large_common (int small ATTRIBUTE_UNUSED)
+ {
+   symbolS *symbolP = s_comm_internal (0, elf_common_parse);
+ 
+   if (flag_code != CODE_64BIT)
+     {
+       as_warn (_(".largecomm supported only in 64bit mode, producing .comm"));
+     }
+   else if (symbolP)
+     {
+       elf_symbol (symbol_get_bfdsym (symbolP))->internal_elf_sym.st_shndx
+ 	= SHN_X86_64_LCOMMON;
+       if (symbol_get_obj (symbolP)->local)
+         S_SET_SEGMENT (symbolP, lbss_section);
+       else
+         S_SET_SEGMENT (symbolP, &lcom_section);
+     }
+ }
+ #endif /* OBJ_ELF */
Index: gas/config/tc-i386.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.h,v
retrieving revision 1.55
diff -c -3 -p -r1.55 tc-i386.h
*** gas/config/tc-i386.h	7 Jun 2005 17:54:16 -0000	1.55
--- gas/config/tc-i386.h	14 Jun 2005 21:50:21 -0000
*************** extern void tc_x86_frame_initial_instruc
*** 498,503 ****
--- 498,509 ----
  #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
Index: include/elf/x86-64.h
===================================================================
RCS file: /cvs/src/src/include/elf/x86-64.h,v
retrieving revision 1.6
diff -c -3 -p -r1.6 x86-64.h
*** include/elf/x86-64.h	10 May 2005 10:21:10 -0000	1.6
--- include/elf/x86-64.h	14 Jun 2005 21:50:21 -0000
*************** START_RELOC_NUMBERS (elf_x86_64_reloc_ty
*** 51,60 ****
--- 51,64 ----
       RELOC_NUMBER (R_X86_64_TPOFF32,  23)     /* Offset in initial TLS block */
       RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
       RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
  END_RELOC_NUMBERS (R_X86_64_max)
  
  /* Processor specific section types.  */
  
  #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
Index: ld/scripttempl/elf.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/elf.sc,v
retrieving revision 1.59
diff -c -3 -p -r1.59 elf.sc
*** ld/scripttempl/elf.sc	10 Jun 2005 00:39:56 -0000	1.59
--- ld/scripttempl/elf.sc	14 Jun 2005 21:50:21 -0000
***************
*** 78,83 ****
--- 78,85 ----
  #  .debug_info	.gnu.linkonce.wi.foo
  #  .tdata	.gnu.linkonce.td.foo
  #  .tbss	.gnu.linkonce.tb.foo
+ #  .ldata	.gnu.linkonce.l.foo
+ #  .lbss	.gnu.linkonce.lb.foo
  #
  #  Each of these can also have corresponding .rel.* and .rela.* sections.
  
*************** if test -z "${SDATA_GOT}"; then
*** 157,162 ****
--- 159,189 ----
      SDATA_GOT=" "
    fi
  fi
+ if test -z "${NO_LARGE_DATA}"; then
+   LBSS=".lbss         ${RELOCATING-0} :
+   {
+     ${RELOCATING+PROVIDE (__lbss_start = .);}
+     ${RELOCATING+PROVIDE (___lbss_start = .);}
+     *(.dynlbss)
+     *(.lbss${RELOCATING+ .lbss.* .gnu.linkonce.lb.*})
+     *(.lcommon)
+     ${RELOCATING+PROVIDE (__lbss_end = .);}
+     ${RELOCATING+PROVIDE (___lbss_end = .);}
+   }"
+   LDATA="
+   .ldata        ${RELOCATING-0} : 
+   {
+     ${RELOCATING+${LDATA_START_SYMBOLS}}
+     *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*})
+   }"
+   LRODATA=".lrodata       ${RELOCATING-0} : { *(.lrodata${RELOCATING+ .lrodata.* .gnu.linkonce.lr.*}) }"
+   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.*}) }"
+ else
+   NO_LARGE_DATA=" "
+ fi
  test -n "$SEPARATE_GOTPLT" && SEPARATE_GOTPLT=" "
  CTOR=".ctors        ${CONSTRUCTING-0} : 
    {
*************** eval $COMBRELOCCAT <<EOF
*** 274,279 ****
--- 301,310 ----
    ${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_LDATA2}
+   ${REL_LBSS2}
  EOF
  if [ -n "$COMBRELOC" ]; then
  cat <<EOF
*************** cat <<EOF
*** 401,406 ****
--- 432,441 ----
     ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
    }
    ${OTHER_BSS_SECTIONS}
+   ${LBSS}
+   ${LDATA}
+   ${RELOCATING+. = ALIGN(${ALIGNMENT});}
+   ${LRODATA}
    ${RELOCATING+. = ALIGN(${ALIGNMENT});}
    ${RELOCATING+_end = .;}
    ${RELOCATING+${OTHER_BSS_END_SYMBOLS}}



More information about the Binutils mailing list