PATCH: Support x86-64 large data sections
H. J. Lu
hjl@lucon.org
Mon Jun 27 20:05:00 GMT 2005
On Fri, Jun 17, 2005 at 03:09:49PM +0200, Jan Hubicka wrote:
> > On Fri, Jun 17, 2005 at 11:08:52AM +0200, Jan Hubicka wrote:
> > >
> > > 1) I am unsure how to get page alignment only when .lrosegment is
> > > non-zero. I tried to play around with SIZEOF operator but I am not sure
> > > if I can apply SIZEOF to the alignment before .lrodata that might (in
> > > theory) change size of .lrodata due to alignments.
> > >
> >
> > I have implemented the similar thing for another project. I will take a
> > look after I fix the SHN issue.
> >
> > > 2) I am completely such with the SHN issue. I've dicussed this with
> >
> > I am working on it now. I will add a few functions to ELF backend to
> > deal with it. I hope to have something very soon.
>
> Thanks a lot! (I will try to cleanup the GCC part of changes in meantime.)
> Honza
Here are 2 patches for x86-64 large data section support. One is the
infrastructure for PS common symbols and the other is for x86-64
large data section.
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-06-27 10:05:29.908272947 -0700
+++ bfd/elf-bfd.h 2005-06-27 10:06:05.683368968 -0700
@@ -973,6 +973,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;
@@ -1747,6 +1774,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-06-27 10:05:29.913272122 -0700
+++ bfd/elf.c 2005-06-27 10:05:29.935268492 -0700
@@ -2626,7 +2626,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-06-27 10:05:29.885276742 -0700
+++ bfd/elflink.c 2005-06-27 10:06:05.689367978 -0700
@@ -783,6 +783,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;
@@ -960,6 +961,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
return FALSE;
}
+ 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;
+
/* We need to remember if a symbol has a definition in a dynamic
object or is weak in all dynamic objects. Internal and hidden
visibility will make it unavailable to dynamic objects. */
@@ -1200,7 +1212,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;
}
@@ -2664,6 +2676,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)
@@ -2679,7 +2693,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
@@ -3571,6 +3586,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;
@@ -3580,6 +3596,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)
@@ -3592,8 +3609,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)
@@ -3883,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
{
@@ -3915,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;
@@ -6528,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;
@@ -6882,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? */
@@ -9906,3 +9923,21 @@ _bfd_elf_provide_section_bound_symbols (
if (do_end)
bfd_elf_set_symbol (he, end_val);
}
+
+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-06-27 10:05:29.920270967 -0700
+++ bfd/elfxx-target.h 2005-06-27 10:05:29.943267172 -0700
@@ -522,6 +522,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
@@ -591,6 +611,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-05-18 10:37:28.000000000 -0700
+++ bfd/section.c 2005-06-27 10:05:29.945266842 -0700
@@ -634,6 +634,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, segment_mark, *} \
+. 0, 0, 1, 0, \
+. \
+. {* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc, *} \
+. 0, 0, 0, 0, \
+. \
+. {* need_finalize_relax, reloc_done, *} \
+. 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
@@ -661,46 +702,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, segment_mark, */ \
- 0, 0, 1, 0, \
- \
- /* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc, */ \
- 0, 0, 0, 0, \
- \
- /* need_finalize_relax, reloc_done, */ \
- 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_special_sections_l): New.
(elf64_special_sections_g): New.
(elf64_x86_64_elf_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 (elf_common_parse): Make it global.
* config/obj-elf.h (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-06-27 12:26:42.000000000 -0700
+++ binutils/bfd/elf-bfd.h 2005-06-27 12:26:42.000000000 -0700
@@ -1843,6 +1843,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-06-27 12:26:42.000000000 -0700
+++ binutils/bfd/elf.c 2005-06-27 12:26:42.000000000 -0700
@@ -8410,3 +8410,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-06-27 12:26:42.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c 2005-06-27 12:51:13.460476376 -0700
@@ -2900,6 +2900,209 @@ 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 ATTRIBUTE_UNUSED,
+ asection **psec,
+ 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 small common symbol and a large common symbol result in a small
+ common symbol. */
+ if (!*olddyn
+ && h->root.type == bfd_link_hash_common
+ && !*newdyn
+ && bfd_is_com_section (*sec)
+ && *oldsec != *sec)
+ *psec = *sec = bfd_com_section_ptr;
+
+ 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 struct bfd_elf_special_section const
+ elf64_special_sections_l[]=
+{
+ { ".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 }
+};
+static struct bfd_elf_special_section const
+ elf64_special_sections_g[]=
+{
+ { ".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},
+ { 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
@@ -2941,4 +3144,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_elf_special_sections
+#define elf_backend_additional_program_headers \
+ elf64_x86_64_additional_program_headers
+
#include "elf64-target.h"
--- binutils/binutils/readelf.c.large 2005-06-17 15:26:37.000000000 -0700
+++ binutils/binutils/readelf.c 2005-06-27 12:26:42.000000000 -0700
@@ -1348,6 +1348,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)
@@ -3781,7 +3784,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;
@@ -6690,6 +6696,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-05-05 07:44:47.000000000 -0700
+++ binutils/gas/config/obj-elf.c 2005-06-27 12:26:42.000000000 -0700
@@ -270,7 +270,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;
--- binutils/gas/config/obj-elf.h.large 2005-05-05 07:44:47.000000000 -0700
+++ binutils/gas/config/obj-elf.h 2005-06-27 12:26:42.000000000 -0700
@@ -246,5 +246,7 @@ struct ecoff_extr;
#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 */
--- binutils/gas/config/tc-i386.c.large 2005-06-26 08:24:15.000000000 -0700
+++ binutils/gas/config/tc-i386.c 2005-06-27 12:26:42.000000000 -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;
@@ -463,6 +464,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
@@ -6917,3 +6921,44 @@ 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)
+{
+ 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)
+ S_SET_SEGMENT (symbolP, &_bfd_elf_large_com_section);
+}
+#endif /* OBJ_ELF || OBJ_MAYBE_ELF */
--- binutils/gas/config/tc-i386.h.large 2005-06-08 07:12:41.000000000 -0700
+++ binutils/gas/config/tc-i386.h 2005-06-27 12:26:42.000000000 -0700
@@ -498,6 +498,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-06-27 12:26:42.000000000 -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-06-27 12:26:42.000000000 -0700
+++ binutils/ld/emulparams/elf_x86_64.sh 2005-06-27 12:26:42.000000000 -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-10 09:00:30.000000000 -0700
+++ binutils/ld/scripttempl/elf.sc 2005-06-27 12:26:42.000000000 -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