Make the assembler generate an error if there is an attempt to define a section with...
[deliverable/binutils-gdb.git] / gas / config / obj-elf.c
index ae9b2e18dfee67fcd71e4f340975b17595e5d3c9..7cf921c051f62b4cd73b867e7d203cc3fec284fe 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF object file format
-   Copyright (C) 1992-2018 Free Software Foundation, Inc.
+   Copyright (C) 1992-2020 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -23,7 +23,6 @@
 #include "safe-ctype.h"
 #include "subsegs.h"
 #include "obstack.h"
-#include "struc-symbol.h"
 #include "dwarf2dbg.h"
 
 #ifndef ECOFF_DEBUGGING
@@ -34,6 +33,7 @@
 
 #ifdef NEED_ECOFF_DEBUG
 #include "ecoff.h"
+#include "bfd/ecoff-bfd.h"
 #endif
 
 #ifdef TC_ALPHA
 #include "elf/ppc.h"
 #endif
 
-#ifdef TC_I370
-#include "elf/i370.h"
-#endif
-
 #ifdef TC_I386
 #include "elf/x86-64.h"
 #endif
@@ -117,8 +113,8 @@ static const pseudo_typeS elf_pseudo_table[] =
   {"subsection", obj_elf_subsection, 0},
 
   /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
-  {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
-  {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},
+  {"vtable_inherit", obj_elf_vtable_inherit, 0},
+  {"vtable_entry", obj_elf_vtable_entry, 0},
 
   /* A GNU extension for object attributes.  */
   {"gnu_attribute", obj_elf_gnu_attribute, 0},
@@ -128,7 +124,7 @@ static const pseudo_typeS elf_pseudo_table[] =
   {"4byte", cons, 4},
   {"8byte", cons, 8},
   /* These are used for dwarf2.  */
-  { "file", (void (*) (int)) dwarf2_directive_file, 0 },
+  { "file", dwarf2_directive_file, 0 },
   { "loc",  dwarf2_directive_loc,  0 },
   { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
 
@@ -265,10 +261,12 @@ elf_sec_sym_ok_for_reloc (asection *sec)
 void
 elf_file_symbol (const char *s, int appfile)
 {
+  asymbol *bsym;
+
   if (!appfile
       || symbol_rootP == NULL
-      || symbol_rootP->bsym == NULL
-      || (symbol_rootP->bsym->flags & BSF_FILE) == 0)
+      || (bsym = symbol_get_bfdsym (symbol_rootP)) == NULL
+      || (bsym->flags & BSF_FILE) == 0)
     {
       symbolS *sym;
       size_t name_length;
@@ -288,8 +286,8 @@ elf_file_symbol (const char *s, int appfile)
       symbol_get_bfdsym (sym)->flags |= BSF_FILE;
 
       if (symbol_rootP != sym
-         && (symbol_rootP->bsym == NULL
-             || !(symbol_rootP->bsym->flags & BSF_FILE)))
+         && ((bsym = symbol_get_bfdsym (symbol_rootP)) == NULL
+             || (bsym->flags & BSF_FILE) == 0))
        {
          symbol_remove (sym, &symbol_rootP, &symbol_lastP);
          symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
@@ -709,9 +707,6 @@ obj_elf_change_section (const char *name,
        attr |= ssect->attr;
     }
 
-  if ((attr & (SHF_ALLOC | SHF_GNU_MBIND)) == SHF_GNU_MBIND)
-    as_fatal (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name);
-
   /* Convert ELF type and flags to BFD flags.  */
   flags = (SEC_RELOC
           | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
@@ -743,7 +738,7 @@ obj_elf_change_section (const char *name,
       if (type == SHT_NOBITS)
        seg_info (sec)->bss = 1;
 
-      bfd_set_section_flags (stdoutput, sec, flags);
+      bfd_set_section_flags (sec, flags);
       if (flags & SEC_MERGE)
        sec->entsize = entsize;
       elf_group_name (sec) = group_name;
@@ -788,7 +783,8 @@ obj_elf_change_section (const char *name,
 }
 
 static bfd_vma
-obj_elf_parse_section_letters (char *str, size_t len, bfd_boolean *is_clone)
+obj_elf_parse_section_letters (char *str, size_t len,
+                              bfd_boolean *is_clone, bfd_vma *gnu_attr)
 {
   bfd_vma attr = 0;
   *is_clone = FALSE;
@@ -822,7 +818,7 @@ obj_elf_parse_section_letters (char *str, size_t len, bfd_boolean *is_clone)
          attr |= SHF_TLS;
          break;
        case 'd':
-         attr |= SHF_GNU_MBIND;
+         *gnu_attr |= SHF_GNU_MBIND;
          break;
        case '?':
          *is_clone = TRUE;
@@ -1014,12 +1010,12 @@ obj_elf_section (int push)
   char *beg;
   int type, dummy;
   bfd_vma attr;
+  bfd_vma gnu_attr;
   int entsize;
   int linkonce;
   subsegT new_subsection = -1;
   unsigned int info = 0;
 
-#ifndef TC_I370
   if (flag_mri)
     {
       char mri_type;
@@ -1039,13 +1035,25 @@ obj_elf_section (int push)
 
       return;
     }
-#endif /* ! defined (TC_I370) */
 
   name = obj_elf_section_name ();
   if (name == NULL)
     return;
+
+  symbolS * sym;
+  if ((sym = symbol_find (name)) != NULL
+      && ! symbol_section_p (sym)
+      && S_IS_DEFINED (sym)
+      && ! S_IS_VOLATILE (sym)
+      && ! S_CAN_BE_REDEFINED (sym))
+    {
+      as_bad (_("section name '%s' already defined as another symbol"), name);
+      ignore_rest_of_line ();
+      return;
+    }
   type = SHT_NULL;
   attr = 0;
+  gnu_attr = 0;
   group_name = NULL;
   entsize = 0;
   linkonce = 0;
@@ -1082,7 +1090,8 @@ obj_elf_section (int push)
              ignore_rest_of_line ();
              return;
            }
-         attr |= obj_elf_parse_section_letters (beg, strlen (beg), &is_clone);
+         attr |= obj_elf_parse_section_letters (beg, strlen (beg),
+                                                &is_clone, &gnu_attr);
 
          SKIP_WHITESPACE ();
          if (*input_line_pointer == ',')
@@ -1108,14 +1117,14 @@ obj_elf_section (int push)
                  ++input_line_pointer;
 
                  if (ISDIGIT (* input_line_pointer))
-                   {
-                     type = strtoul (input_line_pointer, & input_line_pointer, 0);
-                   }
+                   type = strtoul (input_line_pointer, &input_line_pointer, 0);
                  else
                    {
                      c = get_symbol_name (& beg);
                      (void) restore_line_pointer (c);
-                     type = obj_elf_section_type (beg, input_line_pointer - beg, TRUE);
+                     type = obj_elf_section_type (beg,
+                                                  input_line_pointer - beg,
+                                                  TRUE);
                    }
                }
              else
@@ -1182,7 +1191,7 @@ obj_elf_section (int push)
                }
            }
 
-         if ((attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
+         if ((gnu_attr & SHF_GNU_MBIND) != 0 && *input_line_pointer == ',')
            {
              ++input_line_pointer;
              SKIP_WHITESPACE ();
@@ -1216,7 +1225,8 @@ obj_elf_section (int push)
              c = get_symbol_name (& beg);
              (void) restore_line_pointer (c);
 
-             attr |= obj_elf_section_word (beg, input_line_pointer - beg, & type);
+             attr |= obj_elf_section_word (beg, input_line_pointer - beg,
+                                           &type);
 
              SKIP_WHITESPACE ();
            }
@@ -1231,6 +1241,24 @@ done:
   obj_elf_change_section (name, type, info, attr, entsize, group_name,
                          linkonce, push);
 
+  if ((gnu_attr & SHF_GNU_MBIND) != 0)
+    {
+      struct elf_backend_data *bed;
+
+      if ((attr & SHF_ALLOC) == 0)
+       as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name);
+
+      bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
+      if (bed->elf_osabi == ELFOSABI_NONE)
+       bed->elf_osabi = ELFOSABI_GNU;
+      else if (bed->elf_osabi != ELFOSABI_GNU
+              && bed->elf_osabi != ELFOSABI_FREEBSD)
+       as_bad (_("GNU_MBIND section is supported only by GNU "
+                 "and FreeBSD targets"));
+      elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind;
+    }
+  elf_section_flags (now_seg) |= gnu_attr;
+
   if (push && new_subsection != -1)
     subseg_set (now_seg, new_subsection);
 }
@@ -1460,7 +1488,7 @@ obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
    syntax is ".vtable_inherit CHILDNAME, PARENTNAME".  */
 
 struct fix *
-obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
+obj_elf_get_vtable_inherit (void)
 {
   char *cname, *pname;
   symbolS *csym, *psym;
@@ -1524,12 +1552,21 @@ obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
                  0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
 }
 
+/* This is a version of obj_elf_get_vtable_inherit() that is
+   suitable for use in struct _pseudo_type tables.  */
+
+void
+obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
+{
+  (void) obj_elf_get_vtable_inherit ();
+}
+
 /* This handles the .vtable_entry pseudo-op, which is used to indicate
    to the linker that a vtable slot was used.  The syntax is
    ".vtable_entry tablename, offset".  */
 
 struct fix *
-obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
+obj_elf_get_vtable_entry (void)
 {
   symbolS *sym;
   offsetT offset;
@@ -1557,6 +1594,15 @@ obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
                  BFD_RELOC_VTABLE_ENTRY);
 }
 
+/* This is a version of obj_elf_get_vtable_entry() that is
+   suitable for use in struct _pseudo_type tables.  */
+
+void
+obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
+{
+  (void) obj_elf_get_vtable_entry ();
+}
+
 #define skip_whitespace(str)  do { if (*(str) == ' ') ++(str); } while (0)
 
 static inline int
@@ -1826,9 +1872,7 @@ obj_elf_version (int ignore ATTRIBUTE_UNUSED)
 
       /* Create the .note section.  */
       note_secp = subseg_new (".note", 0);
-      bfd_set_section_flags (stdoutput,
-                            note_secp,
-                            SEC_HAS_CONTENTS | SEC_READONLY);
+      bfd_set_section_flags (note_secp, SEC_HAS_CONTENTS | SEC_READONLY);
       record_alignment (note_secp, 2);
 
       /* Process the version string.  */
@@ -2019,15 +2063,16 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED)
           || strcmp (type_name, "10") == 0
           || strcmp (type_name, "STT_GNU_IFUNC") == 0)
     {
-      const struct elf_backend_data *bed;
-
-      bed = get_elf_backend_data (stdoutput);
-      if (!(bed->elf_osabi == ELFOSABI_GNU
-           || bed->elf_osabi == ELFOSABI_FREEBSD
-           /* GNU is still using the default value 0.  */
-           || bed->elf_osabi == ELFOSABI_NONE))
-       as_bad (_("symbol type \"%s\" is supported only by GNU and FreeBSD targets"),
-               type_name);
+      struct elf_backend_data *bed;
+
+      bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
+      if (bed->elf_osabi == ELFOSABI_NONE)
+       bed->elf_osabi = ELFOSABI_GNU;
+      else if (bed->elf_osabi != ELFOSABI_GNU
+              && bed->elf_osabi != ELFOSABI_FREEBSD)
+       as_bad (_("symbol type \"%s\" is supported only by GNU "
+                 "and FreeBSD targets"), type_name);
+      elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
       type = BSF_FUNCTION | BSF_GNU_INDIRECT_FUNCTION;
     }
   else if (strcmp (type_name, "gnu_unique_object") == 0)
@@ -2035,14 +2080,13 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED)
       struct elf_backend_data *bed;
 
       bed = (struct elf_backend_data *) get_elf_backend_data (stdoutput);
-      if (!(bed->elf_osabi == ELFOSABI_GNU
-           /* GNU is still using the default value 0.  */
-           || bed->elf_osabi == ELFOSABI_NONE))
+      if (bed->elf_osabi == ELFOSABI_NONE)
+       bed->elf_osabi = ELFOSABI_GNU;
+      else if (bed->elf_osabi != ELFOSABI_GNU)
        as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
                type_name);
+      elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
       type = BSF_OBJECT | BSF_GNU_UNIQUE;
-      /* PR 10549: Always set OSABI field to GNU for objects containing unique symbols.  */
-      bed->elf_osabi = ELFOSABI_GNU;
     }
 #ifdef md_elf_symbol_type
   else if ((type = md_elf_symbol_type (type_name, sym, elfsym)) != -1)
@@ -2056,7 +2100,38 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED)
   if (*input_line_pointer == '"')
     ++input_line_pointer;
 
-  elfsym->symbol.flags |= type;
+#ifdef md_elf_symbol_type_change
+  if (!md_elf_symbol_type_change (sym, elfsym, type))
+#endif
+    {
+      flagword mask = BSF_FUNCTION | BSF_OBJECT;
+
+      if (type != BSF_FUNCTION)
+       mask |= BSF_GNU_INDIRECT_FUNCTION;
+      if (type != BSF_OBJECT)
+       {
+         mask |= BSF_GNU_UNIQUE | BSF_THREAD_LOCAL;
+
+         if (S_IS_COMMON (sym))
+           {
+             as_bad (_("cannot change type of common symbol '%s'"),
+                     S_GET_NAME (sym));
+             mask = type = 0;
+           }
+       }
+
+      /* Don't warn when changing to STT_NOTYPE.  */
+      if (type)
+       {
+         flagword new = (elfsym->symbol.flags & ~mask) | type;
+
+         if (new != (elfsym->symbol.flags | type))
+           as_warn (_("symbol '%s' already has its type set"), S_GET_NAME (sym));
+         elfsym->symbol.flags = new;
+       }
+      else
+       elfsym->symbol.flags &= ~mask;
+    }
 
   demand_empty_rest_of_line ();
 }
@@ -2076,9 +2151,8 @@ obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
     {
       char *p;
       comment_section = subseg_new (".comment", 0);
-      bfd_set_section_flags (stdoutput, comment_section,
-                            SEC_READONLY | SEC_HAS_CONTENTS
-                            | SEC_MERGE | SEC_STRINGS);
+      bfd_set_section_flags (comment_section, (SEC_READONLY | SEC_HAS_CONTENTS
+                                              | SEC_MERGE | SEC_STRINGS));
       comment_section->entsize = 1;
 #ifdef md_elf_section_change_hook
       md_elf_section_change_hook ();
@@ -2106,7 +2180,7 @@ obj_elf_init_stab_section (segT seg)
 
   /* Force the section to align to a longword boundary.  Without this,
      UnixWare ar crashes.  */
-  bfd_set_section_alignment (stdoutput, seg, 2);
+  bfd_set_section_alignment (seg, 2);
 
   /* Make space for this first symbol.  */
   p = frag_more (12);
@@ -2114,7 +2188,7 @@ obj_elf_init_stab_section (segT seg)
   memset (p, 0, 12);
   file = as_where (NULL);
   stabstr_name = concat (segment_name (seg), "str", (char *) NULL);
-  stroff = get_stab_string_offset (file, stabstr_name);
+  stroff = get_stab_string_offset (file, stabstr_name, TRUE);
   know (stroff == 1 || (stroff == 0 && file[0] == '\0'));
   md_number_to_chars (p, stroff, 4);
   seg_info (seg)->stabu.p = p;
@@ -2140,10 +2214,10 @@ adjust_stab_sections (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   name = concat (sec->name, "str", NULL);
   strsec = bfd_get_section_by_name (abfd, name);
   if (strsec)
-    strsz = bfd_section_size (abfd, strsec);
+    strsz = bfd_section_size (strsec);
   else
     strsz = 0;
-  nsyms = bfd_section_size (abfd, sec) / 12 - 1;
+  nsyms = bfd_section_size (sec) / 12 - 1;
 
   p = seg_info (sec)->stabu.p;
   gas_assert (p != 0);
@@ -2325,23 +2399,6 @@ elf_frob_symbol (symbolS *symp, int *puntp)
        as_bad (_("symbol `%s' can not be both weak and common"),
                S_GET_NAME (symp));
     }
-
-#ifdef TC_MIPS
-  /* The Irix 5 and 6 assemblers set the type of any common symbol and
-     any undefined non-function symbol to STT_OBJECT.  We try to be
-     compatible, since newer Irix 5 and 6 linkers care.  However, we
-     only set undefined symbols to be STT_OBJECT if we are on Irix,
-     because that is the only time gcc will generate the necessary
-     .global directives to mark functions.  */
-
-  if (S_IS_COMMON (symp))
-    symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
-
-  if (strstr (TARGET_OS, "irix") != NULL
-      && ! S_IS_DEFINED (symp)
-      && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0)
-    symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;
-#endif
 }
 
 struct group_list
@@ -2443,8 +2500,8 @@ elf_adjust_symtab (void)
       sec_name = ".group";
       s = subseg_force_new (sec_name, 0);
       if (s == NULL
-         || !bfd_set_section_flags (stdoutput, s, flags)
-         || !bfd_set_section_alignment (stdoutput, s, 2))
+         || !bfd_set_section_flags (s, flags)
+         || !bfd_set_section_alignment (s, 2))
        {
          as_fatal (_("can't create group: %s"),
                    bfd_errmsg (bfd_get_error ()));
@@ -2457,10 +2514,7 @@ elf_adjust_symtab (void)
       /* Make sure that the signature symbol for the group has the
         name of the group.  */
       sy = symbol_find_exact (group_name);
-      if (!sy
-         || (sy != symbol_lastP
-             && (sy->sy_next == NULL
-                 || sy->sy_next->sy_previous != sy)))
+      if (!sy || !symbol_on_chain (sy, symbol_rootP, symbol_lastP))
        {
          /* Create the symbol now.  */
          sy = symbol_new (group_name, now_seg, (valueT) 0, frag_now);
@@ -2554,7 +2608,7 @@ elf_frob_file_after_relocs (void)
 
       group = elf_sec_group (head);
       subseg_set (group, 0);
-      bfd_set_section_size (stdoutput, group, size);
+      bfd_set_section_size (group, size);
       group->contents = (unsigned char *) frag_more (size);
       frag_now->fr_fix = frag_now_fix_octets ();
       frag_wane (frag_now);
@@ -2612,8 +2666,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?  */
-      bfd_set_section_size
-       (stdoutput, sec, bfd_ecoff_debug_size (stdoutput, &debug, debug_swap));
+      bfd_set_section_size (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
@@ -2634,103 +2688,6 @@ elf_frob_file_after_relocs (void)
 #endif /* NEED_ECOFF_DEBUG */
 }
 
-#ifdef SCO_ELF
-
-/* Heavily plagiarized from obj_elf_version.  The idea is to emit the
-   SCO specific identifier in the .notes section to satisfy the SCO
-   linker.
-
-   This looks more complicated than it really is.  As opposed to the
-   "obvious" solution, this should handle the cross dev cases
-   correctly.  (i.e, hosting on a 64 bit big endian processor, but
-   generating SCO Elf code) Efficiency isn't a concern, as there
-   should be exactly one of these sections per object module.
-
-   SCO OpenServer 5 identifies it's ELF modules with a standard ELF
-   .note section.
-
-   int_32 namesz  = 4 ;  Name size
-   int_32 descsz  = 12 ; Descriptive information
-   int_32 type    = 1 ;
-   char   name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
-   int_32 version = (major ver # << 16)  | version of tools ;
-   int_32 source  = (tool_id << 16 ) | 1 ;
-   int_32 info    = 0 ;    These are set by the SCO tools, but we
-                          don't know enough about the source
-                          environment to set them.  SCO ld currently
-                          ignores them, and recommends we set them
-                          to zero.  */
-
-#define SCO_MAJOR_VERSION 0x1
-#define SCO_MINOR_VERSION 0x1
-
-void
-sco_id (void)
-{
-
-  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 = NULL;
-  int i, len;
-
-  /* create the .note section */
-
-  note_secp = subseg_new (".note", 0);
-  bfd_set_section_flags (stdoutput,
-                        note_secp,
-                        SEC_HAS_CONTENTS | SEC_READONLY);
-
-  /* process the version string */
-
-  i_note.namesz = 4;
-  i_note.descsz = 12;          /* 12 descriptive bytes */
-  i_note.type = NT_VERSION;    /* Contains a version string */
-
-  p = frag_more (sizeof (i_note.namesz));
-  md_number_to_chars (p, i_note.namesz, 4);
-
-  p = frag_more (sizeof (i_note.descsz));
-  md_number_to_chars (p, i_note.descsz, 4);
-
-  p = frag_more (sizeof (i_note.type));
-  md_number_to_chars (p, i_note.type, 4);
-
-  p = frag_more (4);
-  strcpy (p, "SCO");
-
-  /* Note: this is the version number of the ELF we're representing */
-  p = frag_more (4);
-  md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
-
-  /* Here, we pick a magic number for ourselves (yes, I "registered"
-     it with SCO.  The bottom bit shows that we are compat with the
-     SCO ABI.  */
-  p = frag_more (4);
-  md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
-
-  /* If we knew (or cared) what the source language options were, we'd
-     fill them in here.  SCO has given us permission to ignore these
-     and just set them to zero.  */
-  p = frag_more (4);
-  md_number_to_chars (p, 0x0000, 4);
-
-  frag_align (2, 0, 0);
-
-  /* We probably can't restore the current segment, for there likely
-     isn't one yet...  */
-  if (seg && subseg)
-    subseg_set (seg, subseg);
-
-}
-
-#endif /* SCO_ELF */
-
 static void
 elf_generate_asm_lineno (void)
 {
This page took 0.03173 seconds and 4 git commands to generate.