aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/obj-elf.c20
-rw-r--r--gas/config/obj-elf.h3
-rw-r--r--gas/config/tc-i386.c72
-rw-r--r--gas/config/tc-i386.h6
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