gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf64-sparc.c
index 65e39070447ac4f9dc7e8480a2adeee85b497730..8d352252b63aba8278f8764f5e4d746e1edf5b5e 100644 (file)
@@ -1,7 +1,5 @@
 /* SPARC-specific support for 64-bit ELF
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1993-2020 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -21,6 +19,7 @@
    MA 02110-1301, USA.  */
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 static long
 elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 {
+#if SIZEOF_LONG == SIZEOF_INT
+  if (sec->reloc_count >= LONG_MAX / 2 / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
+#endif
   return (sec->reloc_count * 2 + 1) * sizeof (arelent *);
 }
 
 static long
 elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
-  return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2;
+  long ret = _bfd_elf_get_dynamic_reloc_upper_bound (abfd);
+  if (ret > LONG_MAX / 2)
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      ret = -1;
+    }
+  else if (ret > 0)
+    ret *= 2;
+  return ret;
 }
 
 /* Read  relocations for ASECT from REL_HDR.  There are RELOC_COUNT of
@@ -65,13 +79,11 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect,
   bfd_size_type count;
   arelent *relents;
 
-  allocated = bfd_malloc (rel_hdr->sh_size);
+  if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0)
+    return FALSE;
+  allocated = _bfd_malloc_and_read (abfd, rel_hdr->sh_size, rel_hdr->sh_size);
   if (allocated == NULL)
-    goto error_return;
-
-  if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
-      || bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size)
-    goto error_return;
+    return FALSE;
 
   native_relocs = (bfd_byte *) allocated;
 
@@ -101,6 +113,18 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect,
 
       if (ELF64_R_SYM (rela.r_info) == STN_UNDEF)
        relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+      else if (/* PR 17512: file: 996185f8.  */
+              ELF64_R_SYM (rela.r_info) > (dynamic
+                                           ? bfd_get_dynamic_symcount (abfd)
+                                           : bfd_get_symcount (abfd)))
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB(%pA): relocation %d has invalid symbol index %ld"),
+            abfd, asect, i, (long) ELF64_R_SYM (rela.r_info));
+         bfd_set_error (bfd_error_bad_value);
+         relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+       }
       else
        {
          asymbol **ps, *s;
@@ -120,27 +144,28 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect,
       r_type = ELF64_R_TYPE_ID (rela.r_info);
       if (r_type == R_SPARC_OLO10)
        {
-         relent->howto = _bfd_sparc_elf_info_to_howto_ptr (R_SPARC_LO10);
+         relent->howto = _bfd_sparc_elf_info_to_howto_ptr (abfd, R_SPARC_LO10);
          relent[1].address = relent->address;
          relent++;
          relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
          relent->addend = ELF64_R_TYPE_DATA (rela.r_info);
-         relent->howto = _bfd_sparc_elf_info_to_howto_ptr (R_SPARC_13);
+         relent->howto = _bfd_sparc_elf_info_to_howto_ptr (abfd, R_SPARC_13);
        }
       else
-       relent->howto = _bfd_sparc_elf_info_to_howto_ptr (r_type);
+       {
+         relent->howto = _bfd_sparc_elf_info_to_howto_ptr (abfd, r_type);
+         if (relent->howto == NULL)
+           goto error_return;
+       }
     }
 
   canon_reloc_count (asect) += relent - relents;
 
-  if (allocated != NULL)
-    free (allocated);
-
+  free (allocated);
   return TRUE;
 
  error_return:
-  if (allocated != NULL)
-    free (allocated);
+  free (allocated);
   return FALSE;
 }
 
@@ -276,6 +301,18 @@ elf64_sparc_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage,
   return ret;
 }
 
+/* Install a new set of internal relocs.  */
+
+static void
+elf64_sparc_set_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+                      asection *asect,
+                      arelent **location,
+                      unsigned int count)
+{
+  asect->orelocation = location;
+  canon_reloc_count (asect) = count;
+}
+
 /* Write out the relocs.  */
 
 static void
@@ -300,14 +337,14 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data)
      reloc_count field to zero to inhibit writing them here.  Also,
      sometimes the SEC_RELOC flag gets set even when there aren't any
      relocs.  */
-  if (sec->reloc_count == 0)
+  if (canon_reloc_count (sec) == 0)
     return;
 
   /* We can combine two relocs that refer to the same address
      into R_SPARC_OLO10 if first one is R_SPARC_LO10 and the
      latter is R_SPARC_13 with no associated symbol.  */
   count = 0;
-  for (idx = 0; idx < sec->reloc_count; idx++)
+  for (idx = 0; idx < canon_reloc_count (sec); idx++)
     {
       bfd_vma addr;
 
@@ -315,7 +352,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data)
 
       addr = sec->orelocation[idx]->address;
       if (sec->orelocation[idx]->howto->type == R_SPARC_LO10
-         && idx < sec->reloc_count - 1)
+         && idx < canon_reloc_count (sec) - 1)
        {
          arelent *r = sec->orelocation[idx + 1];
 
@@ -352,7 +389,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data)
   outbound_relocas = (Elf64_External_Rela *) rela_hdr->contents;
   src_rela = outbound_relocas;
 
-  for (idx = 0; idx < sec->reloc_count; idx++)
+  for (idx = 0; idx < canon_reloc_count (sec); idx++)
     {
       Elf_Internal_Rela dst_rela;
       arelent *ptr;
@@ -386,7 +423,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data)
        }
 
       if (ptr->howto->type == R_SPARC_LO10
-         && idx < sec->reloc_count - 1)
+         && idx < canon_reloc_count (sec) - 1)
        {
          arelent *r = sec->orelocation[idx + 1];
 
@@ -426,11 +463,6 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
 {
   static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
 
-  if ((abfd->flags & DYNAMIC) == 0
-      && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
-         || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
-    elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
-
   if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
     {
       int reg;
@@ -442,31 +474,32 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
        case 2: reg -= 2; break;
        case 6: reg -= 4; break;
        default:
-          (*_bfd_error_handler)
-            (_("%B: Only registers %%g[2367] can be declared using STT_REGISTER"),
-             abfd);
+         _bfd_error_handler
+           (_("%pB: only registers %%g[2367] can be declared using STT_REGISTER"),
+            abfd);
          return FALSE;
        }
 
       if (info->output_bfd->xvec != abfd->xvec
          || (abfd->flags & DYNAMIC) != 0)
-        {
+       {
          /* STT_REGISTER only works when linking an elf64_sparc object.
             If STT_REGISTER comes from a dynamic object, don't put it into
             the output bfd.  The dynamic linker will recheck it.  */
          *namep = NULL;
          return TRUE;
-        }
+       }
 
       p = _bfd_sparc_elf_hash_table(info)->app_regs + reg;
 
       if (p->name != NULL && strcmp (p->name, *namep))
        {
-          (*_bfd_error_handler)
-            (_("Register %%g%d used incompatibly: %s in %B, previously %s in %B"),
-             abfd, p->abfd, (int) sym->st_value,
-             **namep ? *namep : "#scratch",
-             *p->name ? p->name : "#scratch");
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("register %%g%d used incompatibly: %s in %pB,"
+              " previously %s in %pB"),
+            (int) sym->st_value, **namep ? *namep : "#scratch", abfd,
+            *p->name ? p->name : "#scratch", p->abfd);
          return FALSE;
        }
 
@@ -485,9 +518,11 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
 
                  if (type > STT_FUNC)
                    type = 0;
-                 (*_bfd_error_handler)
-                   (_("Symbol `%s' has differing types: REGISTER in %B, previously %s in %B"),
-                    abfd, p->abfd, *namep, stt_types[type]);
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("symbol `%s' has differing types: REGISTER in %pB,"
+                      " previously %s in %pB"),
+                    *namep, abfd, stt_types[type], p->abfd);
                  return FALSE;
                }
 
@@ -530,9 +565,11 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
 
            if (type > STT_FUNC)
              type = 0;
-           (*_bfd_error_handler)
-             (_("Symbol `%s' has differing types: %s in %B, previously REGISTER in %B"),
-              abfd, p->abfd, *namep, stt_types[type]);
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("Symbol `%s' has differing types: %s in %pB,"
+                " previously REGISTER in %pB"),
+              *namep, stt_types[type], abfd, p->abfd);
            return FALSE;
          }
     }
@@ -556,29 +593,6 @@ elf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED,
     _bfd_sparc_elf_hash_table(info)->app_regs;
   Elf_Internal_Sym sym;
 
-  /* We arranged in size_dynamic_sections to put the STT_REGISTER entries
-     at the end of the dynlocal list, so they came at the end of the local
-     symbols in the symtab.  Except that they aren't STB_LOCAL, so we need
-     to back up symtab->sh_info.  */
-  if (elf_hash_table (info)->dynlocal)
-    {
-      bfd * dynobj = elf_hash_table (info)->dynobj;
-      asection *dynsymsec = bfd_get_linker_section (dynobj, ".dynsym");
-      struct elf_link_local_dynamic_entry *e;
-
-      for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
-       if (e->input_indx == -1)
-         break;
-      if (e)
-       {
-         elf_section_data (dynsymsec->output_section)->this_hdr.sh_info
-           = e->dynindx;
-       }
-    }
-
-  if (info->strip == strip_all)
-    return TRUE;
-
   for (reg = 0; reg < 4; reg++)
     if (app_regs [reg].name != NULL)
       {
@@ -636,8 +650,9 @@ elf64_sparc_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym)
    object file when linking.  */
 
 static bfd_boolean
-elf64_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 {
+  bfd *obfd = info->output_bfd;
   bfd_boolean error;
   flagword new_flags, old_flags;
   int new_mm, old_mm;
@@ -658,7 +673,7 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
   else if (new_flags == old_flags)      /* Compatible flags are ok */
     ;
 
-  else                                  /* Incompatible flags */
+  else                                 /* Incompatible flags */
     {
       error = FALSE;
 
@@ -683,8 +698,8 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
              && (old_flags & EF_SPARC_HAL_R1))
            {
              error = TRUE;
-             (*_bfd_error_handler)
-               (_("%B: linking UltraSPARC specific with HAL specific code"),
+             _bfd_error_handler
+               (_("%pB: linking UltraSPARC specific with HAL specific code"),
                 ibfd);
            }
          /* Choose the most restrictive memory ordering.  */
@@ -700,22 +715,23 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 
       /* Warn about any other mismatches */
       if (new_flags != old_flags)
-        {
-          error = TRUE;
-          (*_bfd_error_handler)
-            (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
-             ibfd, (long) new_flags, (long) old_flags);
-        }
+       {
+         error = TRUE;
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB: uses different e_flags (%#x) fields than previous modules (%#x)"),
+            ibfd, new_flags, old_flags);
+       }
 
       elf_elfheader (obfd)->e_flags = old_flags;
 
       if (error)
-        {
-          bfd_set_error (bfd_error_bad_value);
-          return FALSE;
-        }
+       {
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
     }
-  return _bfd_sparc_elf_merge_private_bfd_data (ibfd, obfd);
+  return _bfd_sparc_elf_merge_private_bfd_data (ibfd, info);
 }
 
 /* MARCO: Set the correct entry size for the .stab section.  */
@@ -727,7 +743,7 @@ elf64_sparc_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
 {
   const char *name;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
 
   if (strcmp (name, ".stab") == 0)
     {
@@ -756,21 +772,52 @@ elf64_sparc_print_symbol_all (bfd *abfd ATTRIBUTE_UNUSED, void * filep,
   fprintf (file, "REG_%c%c%11s%c%c    R", "GOLI" [reg / 8], '0' + (reg & 7), "",
                 ((type & BSF_LOCAL)
                  ? (type & BSF_GLOBAL) ? '!' : 'l'
-                 : (type & BSF_GLOBAL) ? 'g' : ' '),
-                (type & BSF_WEAK) ? 'w' : ' ');
+                 : (type & BSF_GLOBAL) ? 'g' : ' '),
+                (type & BSF_WEAK) ? 'w' : ' ');
   if (symbol->name == NULL || symbol->name [0] == '\0')
     return "#scratch";
   else
     return symbol->name;
 }
 \f
+/* Used to decide how to sort relocs in an optimal manner for the
+   dynamic linker, before writing them out.  */
+
 static enum elf_reloc_type_class
-elf64_sparc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+elf64_sparc_reloc_type_class (const struct bfd_link_info *info,
                              const asection *rel_sec ATTRIBUTE_UNUSED,
                              const Elf_Internal_Rela *rela)
 {
+  bfd *abfd = info->output_bfd;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct _bfd_sparc_elf_link_hash_table *htab
+    = _bfd_sparc_elf_hash_table (info);
+  BFD_ASSERT (htab != NULL);
+
+  if (htab->elf.dynsym != NULL
+      && htab->elf.dynsym->contents != NULL)
+    {
+      /* Check relocation against STT_GNU_IFUNC symbol if there are
+        dynamic symbols.  */
+      unsigned long r_symndx = htab->r_symndx (rela->r_info);
+      if (r_symndx != STN_UNDEF)
+       {
+         Elf_Internal_Sym sym;
+         if (!bed->s->swap_symbol_in (abfd,
+                                      (htab->elf.dynsym->contents
+                                       + r_symndx * bed->s->sizeof_sym),
+                                      0, &sym))
+           abort ();
+
+         if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+           return reloc_class_ifunc;
+       }
+    }
+
   switch ((int) ELF64_R_TYPE (rela->r_info))
     {
+    case R_SPARC_IRELATIVE:
+      return reloc_class_ifunc;
     case R_SPARC_RELATIVE:
       return reloc_class_relative;
     case R_SPARC_JMP_SLOT:
@@ -823,7 +870,7 @@ const struct elf_size_info elf64_sparc_size_info =
   bfd_elf64_swap_reloca_out
 };
 
-#define TARGET_BIG_SYM bfd_elf64_sparc_vec
+#define TARGET_BIG_SYM sparc_elf64_vec
 #define TARGET_BIG_NAME        "elf64-sparc"
 #define ELF_ARCH       bfd_arch_sparc
 #define ELF_MAXPAGESIZE 0x100000
@@ -845,6 +892,8 @@ const struct elf_size_info elf64_sparc_size_info =
   elf64_sparc_canonicalize_reloc
 #define bfd_elf64_canonicalize_dynamic_reloc \
   elf64_sparc_canonicalize_dynamic_reloc
+#define bfd_elf64_set_reloc \
+  elf64_sparc_set_reloc
 #define elf_backend_add_symbol_hook \
   elf64_sparc_add_symbol_hook
 #define elf_backend_get_symbol_type \
@@ -866,8 +915,6 @@ const struct elf_size_info elf64_sparc_size_info =
   _bfd_sparc_elf_plt_sym_val
 #define bfd_elf64_bfd_link_hash_table_create \
   _bfd_sparc_elf_link_hash_table_create
-#define bfd_elf64_bfd_link_hash_table_free \
-  _bfd_sparc_elf_link_hash_table_free
 #define elf_info_to_howto \
   _bfd_sparc_elf_info_to_howto
 #define elf_backend_copy_indirect_symbol \
@@ -899,6 +946,8 @@ const struct elf_size_info elf64_sparc_size_info =
   _bfd_sparc_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
   _bfd_sparc_elf_finish_dynamic_sections
+#define elf_backend_fixup_symbol \
+  _bfd_sparc_elf_fixup_symbol
 
 #define bfd_elf64_mkobject \
   _bfd_sparc_elf_mkobject
@@ -906,8 +955,6 @@ const struct elf_size_info elf64_sparc_size_info =
   _bfd_sparc_elf_object_p
 #define elf_backend_gc_mark_hook \
   _bfd_sparc_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook \
-  _bfd_sparc_elf_gc_sweep_hook
 #define elf_backend_init_index_section \
   _bfd_elf_init_1_index_section
 
@@ -917,18 +964,17 @@ const struct elf_size_info elf64_sparc_size_info =
 #define elf_backend_plt_readonly 0
 #define elf_backend_want_plt_sym 1
 #define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
 #define elf_backend_rela_normal 1
 
 /* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table.  */
 #define elf_backend_plt_alignment 8
 
-#define elf_backend_post_process_headers       _bfd_elf_set_osabi
-
 #include "elf64-target.h"
 
 /* FreeBSD support */
 #undef  TARGET_BIG_SYM
-#define TARGET_BIG_SYM bfd_elf64_sparc_freebsd_vec
+#define TARGET_BIG_SYM sparc_elf64_fbsd_vec
 #undef  TARGET_BIG_NAME
 #define TARGET_BIG_NAME "elf64-sparc-freebsd"
 #undef ELF_OSABI
@@ -942,7 +988,7 @@ const struct elf_size_info elf64_sparc_size_info =
 /* Solaris 2.  */
 
 #undef TARGET_BIG_SYM
-#define        TARGET_BIG_SYM                          bfd_elf64_sparc_sol2_vec
+#define        TARGET_BIG_SYM                          sparc_elf64_sol2_vec
 #undef TARGET_BIG_NAME
 #define        TARGET_BIG_NAME                         "elf64-sparc-sol2"
 
This page took 0.029572 seconds and 4 git commands to generate.