* read.c (potable): Add string8, string16, string32 and string64. Add bit size for...
[binutils-gdb.git] / gas / config / obj-elf.c
index 7bd62d769d4e60df9884fac9cfd7baf6ef866153..8f696d77202325d7af4c3efc188cc4bad448d5e9 100644 (file)
@@ -1,12 +1,13 @@
 /* ELF object file format
    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
 /* ELF object file format
    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2,
+   published by the Free Software Foundation; either version 3,
    or (at your option) any later version.
 
    GAS is distributed in the hope that it will be useful, but
    or (at your option) any later version.
 
    GAS is distributed in the hope that it will be useful, but
@@ -16,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 #define OBJ_HEADER "obj-elf.h"
 #include "as.h"
 
 #define OBJ_HEADER "obj-elf.h"
 #include "as.h"
 #include "elf/i370.h"
 #endif
 
 #include "elf/i370.h"
 #endif
 
+#ifdef TC_I386
+#include "elf/x86-64.h"
+#endif
+
+#ifdef TC_MEP
+#include "elf/mep.h"
+#endif
+
 static void obj_elf_line (int);
 static void obj_elf_size (int);
 static void obj_elf_type (int);
 static void obj_elf_line (int);
 static void obj_elf_size (int);
 static void obj_elf_type (int);
@@ -65,6 +74,7 @@ static void obj_elf_subsection (int);
 static void obj_elf_popsection (int);
 static void obj_elf_tls_common (int);
 static void obj_elf_lcomm (int);
 static void obj_elf_popsection (int);
 static void obj_elf_tls_common (int);
 static void obj_elf_lcomm (int);
+static void obj_elf_struct (int);
 
 static const pseudo_typeS elf_pseudo_table[] =
 {
 
 static const pseudo_typeS elf_pseudo_table[] =
 {
@@ -110,9 +120,12 @@ static const pseudo_typeS elf_pseudo_table[] =
   /* These are used for dwarf2.  */
   { "file", (void (*) (int)) dwarf2_directive_file, 0 },
   { "loc",  dwarf2_directive_loc,  0 },
   /* These are used for dwarf2.  */
   { "file", (void (*) (int)) dwarf2_directive_file, 0 },
   { "loc",  dwarf2_directive_loc,  0 },
+  { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
 
   /* We need to trap the section changing calls to handle .previous.  */
   {"data", obj_elf_data, 0},
 
   /* We need to trap the section changing calls to handle .previous.  */
   {"data", obj_elf_data, 0},
+  {"offset", obj_elf_struct, 0},
+  {"struct", obj_elf_struct, 0},
   {"text", obj_elf_text, 0},
 
   {"tls_common", obj_elf_tls_common, 0},
   {"text", obj_elf_text, 0},
 
   {"tls_common", obj_elf_tls_common, 0},
@@ -171,6 +184,8 @@ static const pseudo_typeS ecoff_debug_pseudo_table[] =
 
 /* This is called when the assembler starts.  */
 
 
 /* This is called when the assembler starts.  */
 
+asection *elf_com_section_ptr;
+
 void
 elf_begin (void)
 {
 void
 elf_begin (void)
 {
@@ -183,6 +198,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));
   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
 }
 
 void
@@ -236,32 +252,38 @@ elf_sec_sym_ok_for_reloc (asection *sec)
 }
 
 void
 }
 
 void
-elf_file_symbol (const char *s)
+elf_file_symbol (const char *s, int appfile)
 {
 {
-  symbolS *sym;
+  if (!appfile
+      || symbol_rootP == NULL
+      || symbol_rootP->bsym == NULL
+      || (symbol_rootP->bsym->flags & BSF_FILE) == 0)
+    {
+      symbolS *sym;
 
 
-  sym = symbol_new (s, absolute_section, 0, NULL);
-  symbol_set_frag (sym, &zero_address_frag);
-  symbol_get_bfdsym (sym)->flags |= BSF_FILE;
+      sym = symbol_new (s, absolute_section, 0, NULL);
+      symbol_set_frag (sym, &zero_address_frag);
+      symbol_get_bfdsym (sym)->flags |= BSF_FILE;
 
 
-  if (symbol_rootP != sym)
-    {
-      symbol_remove (sym, &symbol_rootP, &symbol_lastP);
-      symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
+      if (symbol_rootP != sym)
+       {
+         symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+         symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
 #ifdef DEBUG
 #ifdef DEBUG
-      verify_symbol_chain (symbol_rootP, symbol_lastP);
+         verify_symbol_chain (symbol_rootP, symbol_lastP);
 #endif
 #endif
+       }
     }
 
 #ifdef NEED_ECOFF_DEBUG
     }
 
 #ifdef NEED_ECOFF_DEBUG
-  ecoff_new_file (s);
+  ecoff_new_file (s, appfile);
 #endif
 }
 
 /* Called from read.c:s_comm after we've parsed .comm symbol, size.
    Parse a possible alignment value.  */
 
 #endif
 }
 
 /* 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;
 elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
 {
   addressT align = 0;
@@ -325,7 +347,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_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;
     }
 
   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
@@ -511,6 +533,7 @@ obj_elf_change_section (const char *name,
   asection *old_sec;
   segT sec;
   flagword flags;
   asection *old_sec;
   segT sec;
   flagword flags;
+  const struct elf_backend_data *bed;
   const struct bfd_elf_special_section *ssect;
 
 #ifdef md_flush_pending_output
   const struct bfd_elf_special_section *ssect;
 
 #ifdef md_flush_pending_output
@@ -542,7 +565,8 @@ obj_elf_change_section (const char *name,
   else
     sec = subseg_force_new (name, 0);
 
   else
     sec = subseg_force_new (name, 0);
 
-  ssect = _bfd_elf_get_sec_type_attr (stdoutput, name);
+  bed = get_elf_backend_data (stdoutput);
+  ssect = (*bed->get_sec_type_attr) (stdoutput, sec);
 
   if (ssect != NULL)
     {
 
   if (ssect != NULL)
     {
@@ -558,7 +582,16 @@ obj_elf_change_section (const char *name,
                 .section .init_array,"aw",@progbits
 
                 for __attribute__ ((section (".init_array"))).
                 .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.  */
                 "@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)
              && ssect->type != SHT_INIT_ARRAY
              && ssect->type != SHT_FINI_ARRAY
              && ssect->type != SHT_PREINIT_ARRAY)
@@ -600,6 +633,15 @@ obj_elf_change_section (const char *name,
                       || strcmp (name, ".strtab") == 0
                       || strcmp (name, ".symtab") == 0))
            override = TRUE;
                       || strcmp (name, ".strtab") == 0
                       || strcmp (name, ".symtab") == 0))
            override = TRUE;
+         /* .note.GNU-stack can have SHF_EXECINSTR.  */
+         else if (attr == SHF_EXECINSTR
+                  && strcmp (name, ".note.GNU-stack") == 0)
+           override = TRUE;
+#ifdef TC_ALPHA
+         /* A section on Alpha may have SHF_ALPHA_GPREL.  */
+         else if ((attr & ~ssect->attr) == SHF_ALPHA_GPREL)
+           override = TRUE;
+#endif
          else
            {
              if (group_name == NULL)
          else
            {
              if (group_name == NULL)
@@ -612,11 +654,6 @@ obj_elf_change_section (const char *name,
        attr |= ssect->attr;
     }
 
        attr |= ssect->attr;
     }
 
-  if (type != SHT_NULL)
-    elf_section_type (sec) = type;
-  if (attr != 0)
-    elf_section_flags (sec) = attr;
-
   /* Convert ELF type and flags to BFD flags.  */
   flags = (SEC_RELOC
           | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
   /* Convert ELF type and flags to BFD flags.  */
   flags = (SEC_RELOC
           | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
@@ -637,6 +674,9 @@ obj_elf_change_section (const char *name,
     {
       symbolS *secsym;
 
     {
       symbolS *secsym;
 
+      elf_section_type (sec) = type;
+      elf_section_flags (sec) = attr;
+
       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
       if (type == SHT_NOBITS)
        seg_info (sec)->bss = 1;
       /* Prevent SEC_HAS_CONTENTS from being inadvertently set.  */
       if (type == SHT_NOBITS)
        seg_info (sec)->bss = 1;
@@ -653,19 +693,26 @@ obj_elf_change_section (const char *name,
       else
        symbol_table_insert (section_symbol (sec));
     }
       else
        symbol_table_insert (section_symbol (sec));
     }
-  else if (attr != 0)
+  else
     {
     {
-      /* If section attributes are specified the second time we see a
-        particular section, then check that they are the same as we
-        saw the first time.  */
-      if (((old_sec->flags ^ flags)
-          & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
-             | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
-             | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
-             | SEC_THREAD_LOCAL)))
-       as_warn (_("ignoring changed section attributes for %s"), name);
-      if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
-       as_warn (_("ignoring changed section entity size for %s"), name);
+      if (type != SHT_NULL
+         && (unsigned) type != elf_section_type (old_sec))
+       as_warn (_("ignoring changed section type for %s"), name);
+
+      if (attr != 0)
+       {
+         /* If section attributes are specified the second time we see a
+            particular section, then check that they are the same as we
+            saw the first time.  */
+         if (((old_sec->flags ^ flags)
+              & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+                 | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
+                 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
+                 | SEC_THREAD_LOCAL)))
+           as_warn (_("ignoring changed section attributes for %s"), name);
+         if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
+           as_warn (_("ignoring changed section entity size for %s"), name);
+       }
     }
 
 #ifdef md_elf_section_change_hook
     }
 
 #ifdef md_elf_section_change_hook
@@ -767,6 +814,12 @@ obj_elf_section_type (char *str, size_t len)
     return SHT_NOBITS;
   if (len == 4 && strncmp (str, "note", 4) == 0)
     return SHT_NOTE;
     return SHT_NOBITS;
   if (len == 4 && strncmp (str, "note", 4) == 0)
     return SHT_NOTE;
+  if (len == 10 && strncmp (str, "init_array", 10) == 0)
+    return SHT_INIT_ARRAY;
+  if (len == 10 && strncmp (str, "fini_array", 10) == 0)
+    return SHT_FINI_ARRAY;
+  if (len == 13 && strncmp (str, "preinit_array", 13) == 0)
+    return SHT_PREINIT_ARRAY;
 
 #ifdef md_elf_section_type
   {
 
 #ifdef md_elf_section_type
   {
@@ -1015,6 +1068,24 @@ obj_elf_text (int i)
 #endif
 }
 
 #endif
 }
 
+/* Change to the *ABS* section.  */
+
+void
+obj_elf_struct (int i)
+{
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  previous_section = now_seg;
+  previous_subsection = now_subseg;
+  s_struct (i);
+
+#ifdef md_elf_section_change_hook
+  md_elf_section_change_hook ();
+#endif
+}
+
 static void
 obj_elf_subsection (int ignore ATTRIBUTE_UNUSED)
 {
 static void
 obj_elf_subsection (int ignore ATTRIBUTE_UNUSED)
 {
@@ -1353,11 +1424,12 @@ obj_elf_version (int ignore ATTRIBUTE_UNUSED)
   Elf_Internal_Note i_note;
   Elf_External_Note e_note;
   asection *note_secp = NULL;
   Elf_Internal_Note i_note;
   Elf_External_Note e_note;
   asection *note_secp = NULL;
-  int len;
 
   SKIP_WHITESPACE ();
   if (*input_line_pointer == '\"')
     {
 
   SKIP_WHITESPACE ();
   if (*input_line_pointer == '\"')
     {
+      unsigned int len;
+
       ++input_line_pointer;    /* -> 1st char of string.  */
       name = input_line_pointer;
 
       ++input_line_pointer;    /* -> 1st char of string.  */
       name = input_line_pointer;
 
@@ -1368,19 +1440,19 @@ obj_elf_version (int ignore ATTRIBUTE_UNUSED)
       *(input_line_pointer - 1) = '\0';
       *input_line_pointer = c;
 
       *(input_line_pointer - 1) = '\0';
       *input_line_pointer = c;
 
-      /* create the .note section */
-
+      /* Create the .note section.  */
       note_secp = subseg_new (".note", 0);
       bfd_set_section_flags (stdoutput,
                             note_secp,
                             SEC_HAS_CONTENTS | SEC_READONLY);
 
       note_secp = subseg_new (".note", 0);
       bfd_set_section_flags (stdoutput,
                             note_secp,
                             SEC_HAS_CONTENTS | SEC_READONLY);
 
-      /* process the version string */
-
-      len = strlen (name);
+      /* Process the version string.  */
+      len = strlen (name) + 1;
 
 
-      i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
-      i_note.descsz = 0;       /* no description */
+      /* PR 3456: Although the name field is padded out to an 4-byte
+        boundary, the namesz field should not be adjusted.  */
+      i_note.namesz = len;
+      i_note.descsz = 0;       /* No description.  */
       i_note.type = NT_VERSION;
       p = frag_more (sizeof (e_note.namesz));
       md_number_to_chars (p, i_note.namesz, sizeof (e_note.namesz));
       i_note.type = NT_VERSION;
       p = frag_more (sizeof (e_note.namesz));
       md_number_to_chars (p, i_note.namesz, sizeof (e_note.namesz));
@@ -1388,17 +1460,16 @@ obj_elf_version (int ignore ATTRIBUTE_UNUSED)
       md_number_to_chars (p, i_note.descsz, sizeof (e_note.descsz));
       p = frag_more (sizeof (e_note.type));
       md_number_to_chars (p, i_note.type, sizeof (e_note.type));
       md_number_to_chars (p, i_note.descsz, sizeof (e_note.descsz));
       p = frag_more (sizeof (e_note.type));
       md_number_to_chars (p, i_note.type, sizeof (e_note.type));
-      p = frag_more (len + 1);
-      strcpy (p, name);
+      p = frag_more (len);
+      memcpy (p, name, len);
 
       frag_align (2, 0, 0);
 
       subseg_set (seg, subseg);
     }
   else
 
       frag_align (2, 0, 0);
 
       subseg_set (seg, subseg);
     }
   else
-    {
-      as_bad (_("expected quoted string"));
-    }
+    as_bad (_("expected quoted string"));
+
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
 
@@ -1547,7 +1618,7 @@ obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
     }
   else
     subseg_set (comment_section, 0);
     }
   else
     subseg_set (comment_section, 0);
-  stringer (1);
+  stringer (8 + 1);
   subseg_set (old_section, old_subsection);
 }
 
   subseg_set (old_section, old_subsection);
 }
 
@@ -1623,6 +1694,9 @@ adjust_stab_sections (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
    this at the moment, so we do it ourselves.  We save the information
    in the symbol.  */
 
    this at the moment, so we do it ourselves.  We save the information
    in the symbol.  */
 
+#ifdef OBJ_MAYBE_ELF
+static
+#endif
 void
 elf_ecoff_set_ext (symbolS *sym, struct ecoff_extr *ext)
 {
 void
 elf_ecoff_set_ext (symbolS *sym, struct ecoff_extr *ext)
 {
@@ -1794,17 +1868,6 @@ elf_frob_symbol (symbolS *symp, int *puntp)
       && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
 #endif
       && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
     symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
 #endif
-
-#if 0 /* TC_PPC */
-  /* If TC_PPC is defined, we used to force the type of a symbol to be
-     BSF_OBJECT if it was otherwise unset.  This was required by some
-     version of VxWorks.  Thomas de Lellis <tdel@windriver.com> says
-     that this is no longer needed, so it is now commented out.  */
-  if ((symbol_get_bfdsym (symp)->flags
-       & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0
-      && S_IS_DEFINED (symp))
-    symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
-#endif
 }
 
 struct group_list
 }
 
 struct group_list
@@ -1883,6 +1946,7 @@ elf_frob_file (void)
       flagword flags;
       struct symbol *sy;
       int has_sym;
       flagword flags;
       struct symbol *sy;
       int has_sym;
+      bfd_size_type size;
 
       flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
       for (s = list.head[i]; s != NULL; s = elf_next_in_group (s))
 
       flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
       for (s = list.head[i]; s != NULL; s = elf_next_in_group (s))
@@ -1923,9 +1987,11 @@ elf_frob_file (void)
       if (has_sym)
        elf_group_id (s) = sy->bsym;
 
       if (has_sym)
        elf_group_id (s) = sy->bsym;
 
-      s->_raw_size = 4 * (list.elt_count[i] + 1);
-      s->contents = frag_more (s->_raw_size);
+      size = 4 * (list.elt_count[i] + 1);
+      bfd_set_section_size (stdoutput, s, size);
+      s->contents = (unsigned char *) frag_more (size);
       frag_now->fr_fix = frag_now_fix_octets ();
       frag_now->fr_fix = frag_now_fix_octets ();
+      frag_wane (frag_now);
     }
 
 #ifdef elf_tc_final_processing
     }
 
 #ifdef elf_tc_final_processing
@@ -2033,7 +2099,8 @@ elf_frob_file_after_relocs (void)
         to force the ELF backend to allocate a file position, and then
         write out the data.  FIXME: Is this really the best way to do
         this?  */
         to force the ELF backend to allocate a file position, and then
         write out the data.  FIXME: Is this really the best way to do
         this?  */
-      sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap);
+      bfd_set_section_size
+       (stdoutput, sec, bfd_ecoff_debug_size (stdoutput, &debug, debug_swap));
 
       /* Pass BUF to bfd_set_section_contents because this will
         eventually become a call to fwrite, and ISO C prohibits
 
       /* Pass BUF to bfd_set_section_contents because this will
         eventually become a call to fwrite, and ISO C prohibits