diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/obj-elf.c | 20 | ||||
-rw-r--r-- | gas/config/obj-elf.h | 3 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 72 | ||||
-rw-r--r-- | gas/config/tc-i386.h | 6 |
4 files changed, 99 insertions, 2 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index d015dab..43e0c97 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -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_pseudo_table[] = /* 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 appfile) /* 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_UNUSED, symbolS *symbolP, addressT size) 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) diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h index 01c1598..629fc00 100644 --- a/gas/config/obj-elf.h +++ b/gas/config/obj-elf.h @@ -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 */ diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 514ff4bf..df3a35b 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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 *symbol, unsigned int size) 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 */ diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 0bd0660..3796ae1 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -501,6 +501,12 @@ extern void tc_x86_frame_initial_instructions PARAMS ((void)); #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 |