Add ability to change linker warning messages into errors when reporting executable...
[binutils-gdb.git] / bfd / elflink.c
index 89dcf26108c55a4a1b04af0fb5387bfdecac8dc1..49ea222ec77e3fe4305a5ff08344987050f5d9ab 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2022 Free Software Foundation, Inc.
+   Copyright (C) 1995-2023 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -2651,7 +2651,7 @@ elf_link_read_relocs_from_section (bfd *abfd,
     return false;
 
   /* Read the relocations.  */
-  if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
+  if (bfd_read (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
     return false;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -3586,10 +3586,19 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
       abfd = abfd->plugin_dummy_bfd;
       hdr = &elf_tdata (abfd)->symtab_hdr;
     }
-  else if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
-    hdr = &elf_tdata (abfd)->symtab_hdr;
   else
-    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+    {
+      if (elf_use_dt_symtab_p (abfd))
+       {
+         bfd_set_error (bfd_error_wrong_format);
+         return false;
+       }
+
+      if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+       hdr = &elf_tdata (abfd)->symtab_hdr;
+      else
+       hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+    }
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
 
@@ -4233,6 +4242,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
 
+  if (elf_use_dt_symtab_p (abfd))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
   if ((abfd->flags & DYNAMIC) == 0)
     dynamic = false;
   else
@@ -4386,7 +4401,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                       | DYN_NO_NEEDED)) == 0;
 
       s = bfd_get_section_by_name (abfd, ".dynamic");
-      if (s != NULL && s->size != 0)
+      if (s != NULL && s->size != 0 && (s->flags & SEC_HAS_CONTENTS) != 0)
        {
          bfd_byte *dynbuf;
          bfd_byte *extdyn;
@@ -5302,10 +5317,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                  else
                    _bfd_error_handler
                      /* xgettext:c-format */
-                     (_("warning: alignment %u of symbol `%s' in %pB"
-                        " is smaller than %u in %pB"),
+                     (_("warning: alignment %u of normal symbol `%s' in %pB"
+                        " is smaller than %u used by the common definition in %pB"),
                       1 << normal_align, name, normal_bfd,
                       1 << common_align, common_bfd);
+
+                 /* PR 30499: make sure that users understand that this warning is serious.  */
+                 _bfd_error_handler
+                   (_("warning: NOTE: alignment discrepancies can cause real problems.  Investigation is advised."));
                }
            }
 
@@ -5317,12 +5336,18 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              if (h->size != 0
                  && h->size != isym->st_size
                  && ! size_change_ok)
-               _bfd_error_handler
-                 /* xgettext:c-format */
-                 (_("warning: size of symbol `%s' changed"
-                    " from %" PRIu64 " in %pB to %" PRIu64 " in %pB"),
-                  name, (uint64_t) h->size, old_bfd,
-                  (uint64_t) isym->st_size, abfd);
+               {
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("warning: size of symbol `%s' changed"
+                      " from %" PRIu64 " in %pB to %" PRIu64 " in %pB"),
+                    name, (uint64_t) h->size, old_bfd,
+                    (uint64_t) isym->st_size, abfd);
+
+                 /* PR 30499: make sure that users understand that this warning is serious.  */
+                 _bfd_error_handler
+                   (_("warning: NOTE: size discrepancies can cause real problems.  Investigation is advised."));
+               }
 
              h->size = isym->st_size;
            }
@@ -5382,7 +5407,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
            }
 
-         if (definition && !dynamic)
+         /* Don't add indirect symbols for .symver x, x@FOO aliases
+            in IR.  Since all data or text symbols in IR have the
+            same type, value and section, we can't tell if a symbol
+            is an alias of another symbol by their types, values and
+            sections.  */
+         if (definition
+             && !dynamic
+             && (abfd->flags & BFD_PLUGIN) == 0)
            {
              char *p = strchr (name, ELF_VER_CHR);
              if (p != NULL && p[1] != ELF_VER_CHR)
@@ -7120,9 +7152,20 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       /* If the user has explicitly requested warnings, then generate one even
         though the choice is the result of another command line option.  */
       if (info->warn_execstack == 1)
-       _bfd_error_handler
-         (_("\
+       {
+         if (info->error_execstack)
+           {
+             _bfd_error_handler
+               (_("\
+error: creating an executable stack because of -z execstack command line option"));
+             return false;
+           }
+
+         _bfd_error_handler
+           (_("\
 warning: enabling an executable stack because of -z execstack command line option"));
+       }
+
       elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
     }
   else if (info->noexecstack)
@@ -7178,11 +7221,29 @@ warning: enabling an executable stack because of -z execstack command line optio
                     being enabled despite the fact that it was not requested
                     on the command line.  */
                  if (noteobj)
-                   _bfd_error_handler (_("\
+                   {
+                     if (info->error_execstack)
+                       {
+                         _bfd_error_handler (_("\
+error: %s: is triggering the generation of an executable stack (because it has an executable .note.GNU-stack section)"),
+                                             bfd_get_filename (noteobj));
+                         return false;
+                       }
+
+                     _bfd_error_handler (_("\
 warning: %s: requires executable stack (because the .note.GNU-stack section is executable)"),
                       bfd_get_filename (noteobj));
+                   }
                  else if (emptyobj)
                    {
+                     if (info->error_execstack)
+                       {
+                         _bfd_error_handler (_("\
+error: %s: is triggering the generation of an executable stack because it does not have a .note.GNU-stack section"),
+                                             bfd_get_filename (emptyobj));
+                         return false;
+                       }
+
                      _bfd_error_handler (_("\
 warning: %s: missing .note.GNU-stack section implies executable stack"),
                                          bfd_get_filename (emptyobj));
@@ -8204,7 +8265,7 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
     return true;
 
   s = bfd_get_section_by_name (abfd, ".dynamic");
-  if (s == NULL || s->size == 0)
+  if (s == NULL || s->size == 0 || (s->flags & SEC_HAS_CONTENTS) == 0)
     return true;
 
   if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
@@ -9995,9 +10056,7 @@ elf_link_output_symstrtab (void *finf,
   if (ELF_ST_BIND (elfsym->st_info) == STB_GNU_UNIQUE)
     elf_tdata (flinfo->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_unique;
 
-  if (name == NULL
-      || *name == '\0'
-      || (input_sec->flags & SEC_EXCLUDE))
+  if (name == NULL || *name == '\0')
     elfsym->st_name = (unsigned long) -1;
   else
     {
@@ -10161,7 +10220,7 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
   pos = hdr->sh_offset + hdr->sh_size;
   amt = bed->s->sizeof_sym * flinfo->output_bfd->symcount;
   if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) == 0
-      && bfd_bwrite (symbuf, amt, flinfo->output_bfd) == amt)
+      && bfd_write (symbuf, amt, flinfo->output_bfd) == amt)
     {
       hdr->sh_size += amt;
       ret = true;
@@ -10899,6 +10958,7 @@ elf_section_ignore_discarded_relocs (asection *sec)
     case SEC_INFO_TYPE_STABS:
     case SEC_INFO_TYPE_EH_FRAME:
     case SEC_INFO_TYPE_EH_FRAME_ENTRY:
+    case SEC_INFO_TYPE_SFRAME:
       return true;
     default:
       break;
@@ -10924,12 +10984,22 @@ elf_section_ignore_discarded_relocs (asection *sec)
 unsigned int
 _bfd_elf_default_action_discarded (asection *sec)
 {
+  const struct elf_backend_data *bed;
+  bed = get_elf_backend_data (sec->owner);
+
   if (sec->flags & SEC_DEBUGGING)
     return PRETEND;
 
   if (strcmp (".eh_frame", sec->name) == 0)
     return 0;
 
+  if (bed->elf_backend_can_make_multiple_eh_frame
+      && strncmp (sec->name, ".eh_frame.", 10) == 0)
+    return 0;
+
+  if (strcmp (".sframe", sec->name) == 0)
+    return 0;
+
   if (strcmp (".gcc_except_table", sec->name) == 0)
     return 0;
 
@@ -11142,22 +11212,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
       /* If this symbol is defined in a section which we are
         discarding, we don't need to keep it.  */
-      if (isym->st_shndx != SHN_UNDEF
-         && isym->st_shndx < SHN_LORESERVE
-         && isec->output_section == NULL
-         && flinfo->info->non_contiguous_regions
-         && flinfo->info->non_contiguous_regions_warnings)
-       {
-         _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
-                               "discards section `%s' from '%s'\n"),
-                             isec->name, bfd_get_filename (isec->owner));
-         continue;
-       }
-
-      if (isym->st_shndx != SHN_UNDEF
-         && isym->st_shndx < SHN_LORESERVE
-         && bfd_section_removed_from_list (output_bfd,
-                                           isec->output_section))
+      if (isym->st_shndx < SHN_LORESERVE
+         && (isec->output_section == NULL
+             || bfd_section_removed_from_list (output_bfd,
+                                               isec->output_section)))
        continue;
 
       /* Get the name of the symbol.  */
@@ -11364,6 +11422,13 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              contents = flinfo->contents;
            }
        }
+      else if (!(o->flags & SEC_RELOC)
+              && !bed->elf_backend_write_section
+              && o->sec_info_type == SEC_INFO_TYPE_MERGE)
+       /* A MERGE section that has no relocations doesn't need the
+          contents anymore, they have been recorded earlier.  Except
+          if the backend has special provisions for writing sections.  */
+       contents = NULL;
       else
        {
          contents = flinfo->contents;
@@ -11863,6 +11928,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              return false;
          }
          break;
+       case SEC_INFO_TYPE_SFRAME:
+           {
+             /* Merge .sframe sections into the ctf frame encoder
+                context of the output_bfd's section.  The final .sframe
+                output section will be written out later.  */
+             if (!_bfd_elf_merge_section_sframe (output_bfd, flinfo->info,
+                                                 o, contents))
+               return false;
+           }
+           break;
        default:
          {
            if (! (o->flags & SEC_EXCLUDE))
@@ -12540,7 +12615,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
             later.  Use bfd_malloc since it will be freed by
             bfd_compress_section_contents.  */
          unsigned char *contents = esdo->this_hdr.contents;
-         if ((o->flags & SEC_ELF_COMPRESS) == 0 || contents != NULL)
+         if (contents != NULL)
            abort ();
          contents
            = (unsigned char *) bfd_malloc (esdo->this_hdr.sh_size);
@@ -12855,8 +12930,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   /* If backend needs to output some local symbols not present in the hash
      table, do it now.  */
-  if (bed->elf_backend_output_arch_local_syms
-      && (info->strip != strip_all || emit_relocs))
+  if (bed->elf_backend_output_arch_local_syms)
     {
       if (! ((*bed->elf_backend_output_arch_local_syms)
             (abfd, info, &flinfo, elf_link_output_symstrtab)))
@@ -13029,7 +13103,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                                                               off, true);
 
              if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
-                 || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt))
+                 || (bfd_write (flinfo.symshndxbuf, amt, abfd) != amt))
                {
                  ret = false;
                  goto return_local_hash_table;
@@ -13446,6 +13520,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
     goto error_return;
 
+  if (! _bfd_elf_write_section_sframe (abfd, info))
+    goto error_return;
+
   if (info->callbacks->emit_ctf)
       info->callbacks->emit_ctf ();
 
@@ -13662,7 +13739,7 @@ elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
       /* Return the local debug definition section.  */
       asection *isec = bfd_section_from_elf_index (sec->owner,
                                                   sym->st_shndx);
-      if ((isec->flags & SEC_DEBUGGING) != 0)
+      if (isec != NULL && (isec->flags & SEC_DEBUGGING) != 0)
        return isec;
     }
 
@@ -14901,6 +14978,41 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
                                _bfd_elf_adjust_eh_frame_global_symbol, NULL);
     }
 
+  o = bfd_get_section_by_name (output_bfd, ".sframe");
+  if (o != NULL)
+    {
+      asection *i;
+
+      for (i = o->map_head.s; i != NULL; i = i->map_head.s)
+       {
+         if (i->size == 0)
+           continue;
+
+         abfd = i->owner;
+         if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+           continue;
+
+         if (!init_reloc_cookie_for_section (&cookie, info, i))
+           return -1;
+
+         if (_bfd_elf_parse_sframe (abfd, info, i, &cookie))
+           {
+             if (_bfd_elf_discard_section_sframe (i,
+                                                  bfd_elf_reloc_symbol_deleted_p,
+                                                  &cookie))
+               {
+                 if (i->size != i->rawsize)
+                   changed = 1;
+               }
+           }
+         fini_reloc_cookie_for_section (&cookie, i);
+       }
+      /* Update the reference to the output .sframe section.  Used to
+        determine later if PT_GNU_SFRAME segment is to be generated.  */
+      if (!_bfd_elf_set_section_sframe (output_bfd, info))
+       return -1;
+    }
+
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
     {
       const struct elf_backend_data *bed;