+2005-07-25 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.
+
2005-07-25 H.J. Lu <hongjiu.lu@intel.com>
* elf-bfd.h (elf_backend_data): Add common_definition,
(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
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);
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
#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"
+2005-07-25 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.
+
2005-07-21 Eric Christopher <echristo@apple.com>
* MAINTAINERS: Change affiliation.
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)
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;
&& 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)
+2005-07-25 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.
+
2005-07-21 Ralf Corsepius <ralf.corsepius@rtems.org>
* configure.tgt: Remove i386-*-rtemself*.
#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);
/* This is called when the assembler starts. */
+asection *elf_com_section_ptr;
+
void
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
/* 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;
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;
.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)
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 */
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;
{"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
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 */
#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
+2005-07-25 Jan Hubicka <jh@suse.cz>
+
+ * x86-64.h (SHN_X86_64_LCOMMON): New.
+ (SHF_X86_64_LARGE): New.
+
2005-07-20 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com>
* m32r.h (R_M32R_REL32): Added.
#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
+2005-07-25 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.
+
2005-07-21 Ralf Corsepius <ralf.corsepius@rtems.org>
* configure.tgt: Remove i[3-7]86-*-rtemself*.
GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes
NO_SMALL_DATA=yes
+LARGE_SECTIONS=yes
SEPARATE_GOTPLT=24
if [ "x${host}" = "x${target}" ]; then
# .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.
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} :
{
${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
*(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}}