* remote.c (struct packet_reg): Declare.
[deliverable/binutils-gdb.git] / gas / config / obj-elf.c
index f29849888363e2cc2aea94240de461208f212532..3c4531e77cae092d452f17e8d640c4dc047e5ef8 100644 (file)
@@ -21,6 +21,7 @@
 
 #define OBJ_HEADER "obj-elf.h"
 #include "as.h"
+#include "safe-ctype.h"
 #include "subsegs.h"
 #include "obstack.h"
 
@@ -57,6 +58,7 @@ static void elf_s_set_align PARAMS ((symbolS *, bfd_vma));
 static void elf_s_set_other PARAMS ((symbolS *, int));
 static int elf_sec_sym_ok_for_reloc PARAMS ((asection *));
 static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
+static void build_group_lists PARAMS ((bfd *, asection *, PTR));
 static int elf_separate_stab_sections PARAMS ((void));
 static void elf_init_stab_section PARAMS ((segT));
 
@@ -73,6 +75,12 @@ static void obj_elf_ident PARAMS ((int));
 static void obj_elf_weak PARAMS ((int));
 static void obj_elf_local PARAMS ((int));
 static void obj_elf_visibility PARAMS ((int));
+static void obj_elf_change_section
+  PARAMS ((const char *, int, int, int, const char *, int));
+static int obj_elf_parse_section_letters PARAMS ((char *, size_t));
+static int obj_elf_section_word PARAMS ((char *, size_t));
+static char *obj_elf_section_name PARAMS ((void));
+static int obj_elf_section_type PARAMS ((char *, size_t));
 static void obj_elf_symver PARAMS ((int));
 static void obj_elf_subsection PARAMS ((int));
 static void obj_elf_popsection PARAMS ((int));
@@ -297,7 +305,7 @@ obj_elf_common (is_common)
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_bad (_("Expected comma after symbol-name"));
+      as_bad (_("expected comma after symbol-name"));
       ignore_rest_of_line ();
       return;
     }
@@ -314,7 +322,7 @@ obj_elf_common (is_common)
   *p = c;
   if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
     {
-      as_bad (_("Ignoring attempt to re-define symbol"));
+      as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
       ignore_rest_of_line ();
       return;
     }
@@ -322,7 +330,7 @@ obj_elf_common (is_common)
     {
       if (S_GET_VALUE (symbolP) != (valueT) size)
        {
-         as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+         as_warn (_("length of .comm \"%s\" is already %ld; not changed to %d"),
                   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
        }
     }
@@ -345,7 +353,7 @@ obj_elf_common (is_common)
          if (temp < 0)
            {
              temp = 0;
-             as_warn (_("Common alignment negative; 0 assumed"));
+             as_warn (_("common alignment negative; 0 assumed"));
            }
        }
       if (symbol_get_obj (symbolP)->local)
@@ -364,7 +372,7 @@ obj_elf_common (is_common)
              for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
              if (temp != 1)
                {
-                 as_bad (_("Common alignment not a power of 2"));
+                 as_bad (_("common alignment not a power of 2"));
                  ignore_rest_of_line ();
                  return;
                }
@@ -611,10 +619,14 @@ static struct special_section const special_sections[] =
   { NULL,      0,              0                               }
 };
 
-void
-obj_elf_change_section (name, type, attr, entsize, push)
-     char *name;
-     int type, attr, entsize, push;
+static void
+obj_elf_change_section (name, type, attr, entsize, group_name, push)
+     const char *name;
+     int type;
+     int attr;
+     int entsize;
+     const char *group_name;
+     int push;
 {
   asection *old_sec;
   segT sec;
@@ -653,11 +665,11 @@ obj_elf_change_section (name, type, attr, entsize, push)
          {
            if (old_sec == NULL)
              {
-               as_warn (_("Setting incorrect section type for %s"), name);
+               as_warn (_("setting incorrect section type for %s"), name);
              }
            else
              {
-               as_warn (_("Ignoring incorrect section type for %s"), name);
+               as_warn (_("ignoring incorrect section type for %s"), name);
                type = special_sections[i].type;
              }
          }
@@ -670,7 +682,7 @@ obj_elf_change_section (name, type, attr, entsize, push)
               file.  */
            if (strcmp (name, ".note") != 0
                || attr != SHF_ALLOC)
-             as_warn (_("Setting incorrect section attributes for %s"),
+             as_warn (_("setting incorrect section attributes for %s"),
                       name);
          }
        attr |= special_sections[i].attributes;
@@ -700,6 +712,7 @@ obj_elf_change_section (name, type, attr, entsize, push)
       bfd_set_section_flags (stdoutput, sec, flags);
       if (flags & SEC_MERGE)
        sec->entsize = entsize;
+      elf_group_name (sec) = group_name;
 
       /* Add a symbol for this section to the symbol table.  */
       secsym = symbol_find (name);
@@ -716,9 +729,12 @@ obj_elf_change_section (name, type, attr, entsize, push)
       if ((old_sec->flags ^ flags)
          & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
             | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS))
-       as_warn (_("Ignoring changed section attributes for %s"), name);
-      else if ((flags & SEC_MERGE) && old_sec->entsize != entsize)
-       as_warn (_("Ignoring changed section entity size for %s"), name);
+       as_warn (_("ignoring changed section attributes for %s"), name);
+      else if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
+       as_warn (_("ignoring changed section entity size for %s"), name);
+      else if ((attr & SHF_GROUP) != 0
+              && strcmp (elf_group_name (old_sec), group_name) != 0)
+       as_warn (_("ignoring new section group for %s"), name);
     }
 
 #ifdef md_elf_section_change_hook
@@ -726,7 +742,7 @@ obj_elf_change_section (name, type, attr, entsize, push)
 #endif
 }
 
-int
+static int
 obj_elf_parse_section_letters (str, len)
      char *str;
      size_t len;
@@ -746,15 +762,30 @@ obj_elf_parse_section_letters (str, len)
        case 'x':
          attr |= SHF_EXECINSTR;
          break;
-       case 'm':
+       case 'M':
          attr |= SHF_MERGE;
          break;
-       case 's':
+       case 'S':
          attr |= SHF_STRINGS;
          break;
+       case 'G':
+         attr |= SHF_GROUP;
+         break;
+       /* Compatibility.  */
+       case 'm':
+         if (*(str - 1) == 'a')
+           {
+             attr |= SHF_MERGE;
+             if (len > 1 && str[1] == 's')
+               {
+                 attr |= SHF_STRINGS;
+                 str++, len--;
+               }
+             break;
+           }
        default:
          {
-           char *bad_msg = _("Unrecognized .section attribute: want a,m,s,w,x");
+           char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G");
 #ifdef md_elf_section_letter
            int md_attr = md_elf_section_letter (*str, &bad_msg);
            if (md_attr >= 0)
@@ -774,7 +805,7 @@ obj_elf_parse_section_letters (str, len)
   return attr;
 }
 
-int
+static int
 obj_elf_section_word (str, len)
      char *str;
      size_t len;
@@ -794,11 +825,11 @@ obj_elf_section_word (str, len)
   }
 #endif
 
-  as_warn (_("Unrecognized section attribute"));
+  as_warn (_("unrecognized section attribute"));
   return 0;
 }
 
-int
+static int
 obj_elf_section_type (str, len)
      char *str;
      size_t len;
@@ -816,15 +847,55 @@ obj_elf_section_type (str, len)
   }
 #endif
 
-  as_warn (_("Unrecognized section type"));
+  as_warn (_("unrecognized section type"));
   return 0;
 }
 
+/* Get name of section.  */
+static char *
+obj_elf_section_name ()
+{
+  char *name;
+
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer == '"')
+    {
+      int dummy;
+
+      name = demand_copy_C_string (&dummy);
+      if (name == NULL)
+       {
+         ignore_rest_of_line ();
+         return NULL;
+       }
+    }
+  else
+    {
+      char *end = input_line_pointer;
+
+      while (0 == strchr ("\n\t,; ", *end))
+       end++;
+      if (end == input_line_pointer)
+       {
+         as_warn (_("missing name"));
+         ignore_rest_of_line ();
+         return NULL;
+       }
+
+      name = xmalloc (end - input_line_pointer + 1);
+      memcpy (name, input_line_pointer, end - input_line_pointer);
+      name[end - input_line_pointer] = '\0';
+      input_line_pointer = end;
+    }
+  SKIP_WHITESPACE ();
+  return name;
+}
+
 void
 obj_elf_section (push)
      int push;
 {
-  char *name, *beg, *end;
+  char *name, *group_name, *beg;
   int type, attr, dummy;
   int entsize;
 
@@ -850,38 +921,12 @@ obj_elf_section (push)
     }
 #endif /* ! defined (TC_I370) */
 
-  /* Get name of section.  */
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer == '"')
-    {
-      name = demand_copy_C_string (&dummy);
-      if (name == NULL)
-       {
-         ignore_rest_of_line ();
-         return;
-       }
-    }
-  else
-    {
-      end = input_line_pointer;
-      while (0 == strchr ("\n\t,; ", *end))
-       end++;
-      if (end == input_line_pointer)
-       {
-         as_warn (_("Missing section name"));
-         ignore_rest_of_line ();
-         return;
-       }
-
-      name = xmalloc (end - input_line_pointer + 1);
-      memcpy (name, input_line_pointer, end - input_line_pointer);
-      name[end - input_line_pointer] = '\0';
-      input_line_pointer = end;
-    }
-  SKIP_WHITESPACE ();
-
+  name = obj_elf_section_name ();
+  if (name == NULL)
+    return;
   type = SHT_NULL;
   attr = 0;
+  group_name = NULL;
   entsize = 0;
 
   if (*input_line_pointer == ',')
@@ -904,6 +949,8 @@ obj_elf_section (push)
          if (*input_line_pointer == ',')
            {
              char c;
+             char *save = input_line_pointer;
+
              ++input_line_pointer;
              SKIP_WHITESPACE ();
              c = *input_line_pointer;
@@ -924,21 +971,42 @@ obj_elf_section (push)
                  *input_line_pointer = c;
                  type = obj_elf_section_type (beg, input_line_pointer - beg);
                }
+             else
+               input_line_pointer = save;
            }
 
          SKIP_WHITESPACE ();
-         if ((attr & SHF_MERGE) && *input_line_pointer == ',')
+         if ((attr & SHF_MERGE) != 0 && *input_line_pointer == ',')
            {
              ++input_line_pointer;
              SKIP_WHITESPACE ();
              entsize = get_absolute_expression ();
+             SKIP_WHITESPACE ();
              if (entsize < 0)
                {
-                 as_warn (_("Bad .section directive - invalid merge entity size"));
+                 as_warn (_("invalid merge entity size"));
                  attr &= ~SHF_MERGE;
                  entsize = 0;
                }
            }
+         else if ((attr & SHF_MERGE) != 0)
+           {
+             as_warn (_("entity size for SHF_MERGE not specified"));
+             attr &= ~SHF_MERGE;
+           }
+
+         if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
+           {
+             ++input_line_pointer;
+             group_name = obj_elf_section_name ();
+             if (group_name == NULL)
+               attr &= ~SHF_GROUP;
+           }
+         else if ((attr & SHF_GROUP) != 0)
+           {
+             as_warn (_("group name for SHF_GROUP not specified"));
+             attr &= ~SHF_GROUP;
+           }
        }
       else
        {
@@ -949,7 +1017,7 @@ obj_elf_section (push)
              SKIP_WHITESPACE ();
              if (*input_line_pointer != '#')
                {
-                 as_warn (_("Bad .section directive - character following name is not '#'"));
+                 as_warn (_("character following name is not '#'"));
                  ignore_rest_of_line ();
                  return;
                }
@@ -968,13 +1036,7 @@ obj_elf_section (push)
 
   demand_empty_rest_of_line ();
 
-  if ((attr & SHF_MERGE) && entsize == 0)
-    {
-      as_warn (_("Entity size for SHF_MERGE not specified.\nSpecify entity size as 4th argument"));
-      attr &= SHF_MERGE;
-    }
-
-  obj_elf_change_section (name, type, attr, entsize, push);
+  obj_elf_change_section (name, type, attr, entsize, group_name, push);
 }
 
 /* Change to the .data section.  */
@@ -1056,7 +1118,7 @@ obj_elf_previous (ignore)
 
   if (previous_section == 0)
     {
-      as_bad (_(".previous without corresponding .section; ignored"));
+      as_warn (_(".previous without corresponding .section; ignored"));
       return;
     }
 
@@ -1083,7 +1145,7 @@ obj_elf_popsection (xxx)
 
   if (top == NULL)
     {
-      as_bad (_(".popsection without corresponding .pushsection; ignored"));
+      as_warn (_(".popsection without corresponding .pushsection; ignored"));
       return;
     }
 
@@ -1232,7 +1294,7 @@ obj_elf_vtable_inherit (ignore)
 
   if (input_line_pointer[0] == '0'
       && (input_line_pointer[1] == '\0'
-         || isspace ((unsigned char) input_line_pointer[1])))
+         || ISSPACE (input_line_pointer[1])))
     {
       psym = section_symbol (absolute_section);
       ++input_line_pointer;
@@ -1330,23 +1392,23 @@ void
 elf_copy_symbol_attributes (dest, src)
      symbolS *dest, *src;
 {
-  struct elf_obj_sy *srcelf = symbol_get_obj (src);            
-  struct elf_obj_sy *destelf = symbol_get_obj (dest);          
-  if (srcelf->size)                                            
-    {                                                          
-      if (destelf->size == NULL)                               
-       destelf->size =                                 
-         (expressionS *) xmalloc (sizeof (expressionS));       
-      *destelf->size = *srcelf->size;                          
-    }                                                          
-  else                                                 
-    {                                                          
-      if (destelf->size != NULL)                               
-       free (destelf->size);                                   
-      destelf->size = NULL;                                    
-    }                                                          
-  S_SET_SIZE (dest, S_GET_SIZE (src));                 
-  S_SET_OTHER (dest, S_GET_OTHER (src));                       
+  struct elf_obj_sy *srcelf = symbol_get_obj (src);
+  struct elf_obj_sy *destelf = symbol_get_obj (dest);
+  if (srcelf->size)
+    {
+      if (destelf->size == NULL)
+       destelf->size =
+         (expressionS *) xmalloc (sizeof (expressionS));
+      *destelf->size = *srcelf->size;
+    }
+  else
+    {
+      if (destelf->size != NULL)
+       free (destelf->size);
+      destelf->size = NULL;
+    }
+  S_SET_SIZE (dest, S_GET_SIZE (src));
+  S_SET_OTHER (dest, S_GET_OTHER (src));
 }
 
 void
@@ -1355,14 +1417,13 @@ obj_elf_version (ignore)
 {
   char *name;
   unsigned int c;
-  char ch;
   char *p;
   asection *seg = now_seg;
   subsegT subseg = now_subseg;
   Elf_Internal_Note i_note;
   Elf_External_Note e_note;
   asection *note_secp = (asection *) NULL;
-  int i, len;
+  int len;
 
   SKIP_WHITESPACE ();
   if (*input_line_pointer == '\"')
@@ -1392,26 +1453,21 @@ obj_elf_version (ignore)
       i_note.descsz = 0;       /* no description */
       i_note.type = NT_VERSION;
       p = frag_more (sizeof (e_note.namesz));
-      md_number_to_chars (p, (valueT) i_note.namesz, 4);
+      md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz));
       p = frag_more (sizeof (e_note.descsz));
-      md_number_to_chars (p, (valueT) i_note.descsz, 4);
+      md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz));
       p = frag_more (sizeof (e_note.type));
-      md_number_to_chars (p, (valueT) i_note.type, 4);
+      md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type));
+      p = frag_more (len + 1);
+      strcpy (p, name);
 
-      for (i = 0; i < len; i++)
-       {
-         ch = *(name + i);
-         {
-           FRAG_APPEND_1_CHAR (ch);
-         }
-       }
       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 ();
 }
@@ -1449,7 +1505,14 @@ obj_elf_size (ignore)
   sym = symbol_find_or_make (name);
   *p = c;
   if (exp.X_op == O_constant)
-    S_SET_SIZE (sym, exp.X_add_number);
+    {
+      S_SET_SIZE (sym, exp.X_add_number);
+      if (symbol_get_obj (sym)->size)
+       {
+         xfree (symbol_get_obj (sym)->size);
+         symbol_get_obj (sym)->size = NULL;
+       }
+    }
   else
     {
       symbol_get_obj (sym)->size =
@@ -1517,7 +1580,7 @@ obj_elf_type (ignore)
     ;
 #endif
   else
-    as_bad (_("ignoring unrecognized symbol type \"%s\""), typename);
+    as_bad (_("unrecognized symbol type \"%s\""), typename);
 
   *input_line_pointer = c;
 
@@ -1789,7 +1852,7 @@ elf_frob_symbol (symp, puntp)
   if (S_IS_WEAK (symp))
     {
       if (S_IS_COMMON (symp))
-       as_bad (_("Symbol `%s' can not be both weak and common"),
+       as_bad (_("symbol `%s' can not be both weak and common"),
                S_GET_NAME (symp));
     }
 
@@ -1822,11 +1885,101 @@ elf_frob_symbol (symp, puntp)
 #endif
 }
 
+struct group_list
+{
+  asection **head;             /* Section lists.  */
+  unsigned int *elt_count;     /* Number of sections in each list.  */
+  unsigned int num_group;      /* Number of lists.  */
+};
+
+/* Called via bfd_map_over_sections.  If SEC is a member of a group,
+   add it to a list of sections belonging to the group.  INF is a
+   pointer to a struct group_list, which is where we store the head of
+   each list.  */
+
+static void
+build_group_lists (abfd, sec, inf)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec;
+     PTR inf;
+{
+  struct group_list *list = (struct group_list *) inf;
+  const char *group_name = elf_group_name (sec);
+  unsigned int i;
+
+  if (group_name == NULL)
+    return;
+
+  /* If this group already has a list, add the section to the head of
+     the list.  */
+  for (i = 0; i < list->num_group; i++)
+    {
+      if (strcmp (group_name, elf_group_name (list->head[i])) == 0)
+       {
+         elf_next_in_group (sec) = list->head[i];
+         list->head[i] = sec;
+         list->elt_count[i] += 1;
+         return;
+       }
+    }
+
+  /* New group.  Make the arrays bigger in chunks to minimize calls to
+     realloc.  */
+  i = list->num_group;
+  if ((i & 127) == 0)
+    {
+      unsigned int newsize = i + 128;
+      list->head = xrealloc (list->head, newsize * sizeof (*list->head));
+      list->elt_count = xrealloc (list->elt_count,
+                                 newsize * sizeof (*list->elt_count));
+    }
+  list->head[i] = sec;
+  list->elt_count[i] = 1;
+  list->num_group += 1;
+}
+
 void
 elf_frob_file ()
 {
+  struct group_list list;
+  unsigned int i;
+
   bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
 
+  /* Go find section groups.  */
+  list.num_group = 0;
+  list.head = NULL;
+  list.elt_count = NULL;
+  bfd_map_over_sections (stdoutput, build_group_lists, (PTR) &list);
+
+  /* Make the SHT_GROUP sections that describe each section group.  We
+     can't set up the section contents here yet, because elf section
+     indices have yet to be calculated.  elf.c:set_group_contents does
+     the rest of the work.  */
+  for (i = 0; i < list.num_group; i++)
+    {
+      const char *group_name = elf_group_name (list.head[i]);
+      asection *s;
+      flagword flags;
+
+      s = subseg_force_new (group_name, 0);
+      flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
+      if (s == NULL
+         || !bfd_set_section_flags (stdoutput, s, flags)
+         || !bfd_set_section_alignment (stdoutput, s, 2))
+       {
+         as_fatal (_("can't create group: %s"),
+                   bfd_errmsg (bfd_get_error ()));
+       }
+
+      /* Pass a pointer to the first section in this group.  */
+      elf_next_in_group (s) = list.head[i];
+
+      s->_raw_size = 4 * (list.elt_count[i] + 1);
+      s->contents = frag_more (s->_raw_size);
+      frag_now->fr_fix = frag_now_fix_octets ();
+    }
+
 #ifdef elf_tc_final_processing
   elf_tc_final_processing ();
 #endif
@@ -1912,7 +2065,7 @@ elf_frob_file_after_relocs ()
       debug.external_ext = debug.external_ext_end = NULL;
       if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true,
                                       elf_get_extr, elf_set_index))
-       as_fatal (_("Failed to set up debugging information: %s"),
+       as_fatal (_("failed to set up debugging information: %s"),
                  bfd_errmsg (bfd_get_error ()));
 
       sec = bfd_get_section_by_name (stdoutput, ".mdebug");
@@ -1932,7 +2085,7 @@ elf_frob_file_after_relocs ()
          pointer will not be used.  */
       if (! bfd_set_section_contents (stdoutput, sec, (PTR) buf,
                                      (file_ptr) 0, (bfd_size_type) 0))
-       as_fatal (_("Can't start writing .mdebug section: %s"),
+       as_fatal (_("can't start writing .mdebug section: %s"),
                  bfd_errmsg (bfd_get_error ()));
 
       know (stdoutput->output_has_begun == true);
@@ -1940,7 +2093,7 @@ elf_frob_file_after_relocs ()
 
       if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
                                   sec->filepos))
-       as_fatal (_("Could not write .mdebug section: %s"),
+       as_fatal (_("could not write .mdebug section: %s"),
                  bfd_errmsg (bfd_get_error ()));
     }
 #endif /* NEED_ECOFF_DEBUG */
This page took 0.03194 seconds and 4 git commands to generate.