S/390: Add support for pgste marker
[deliverable/binutils-gdb.git] / bfd / elf64-s390.c
index 601aa4374d54ea0a4f972949499576c86528b290..1af1200f6cdf4cc6653f1de2e1586b1092338b4d 100644 (file)
@@ -1,6 +1,5 @@
 /* IBM S/390-specific support for 64-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2000-2017 Free Software Foundation, Inc.
    Contributed Martin Schwidefsky (schwidefsky@de.ibm.com).
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -26,6 +25,8 @@
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/s390.h"
+#include "elf-s390.h"
+#include <stdarg.h>
 
 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
    from smaller values.  Start with zero, widen, *then* decrement.  */
@@ -43,7 +44,7 @@ static reloc_howto_type elf_howto_table[] =
 {
   HOWTO (R_390_NONE,           /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
+        3,                     /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -338,10 +339,10 @@ elf_s390_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
        && strcasecmp (elf_howto_table[i].name, r_name) == 0)
       return &elf_howto_table[i];
 
-    if (strcasecmp (elf64_s390_vtinherit_howto.name, r_name) == 0)
-      return &elf64_s390_vtinherit_howto;
-    if (strcasecmp (elf64_s390_vtentry_howto.name, r_name) == 0)
-      return &elf64_s390_vtentry_howto;
+  if (strcasecmp (elf64_s390_vtinherit_howto.name, r_name) == 0)
+    return &elf64_s390_vtinherit_howto;
+  if (strcasecmp (elf64_s390_vtentry_howto.name, r_name) == 0)
+    return &elf64_s390_vtentry_howto;
 
   return NULL;
 }
@@ -368,8 +369,9 @@ elf_s390_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
     default:
       if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
        {
-         (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-                                abfd, (int) r_type);
+         /* xgettext:c-format */
+         _bfd_error_handler (_("%B: invalid relocation type %d"),
+                             abfd, (int) r_type);
          r_type = R_390_NONE;
        }
       cache_ptr->howto = &elf_howto_table[r_type];
@@ -493,8 +495,8 @@ elf_s390_is_local_label_name (bfd *abfd, const char *name)
 
    The GOT holds the address in the PLT to be executed.
    The loader then gets:
-   24(15) =  Pointer to the structure describing the object.
-   28(15) =  Offset in symbol table
+   48(15) =  Pointer to the structure describing the object.
+   56(15) =  Offset in symbol table
    The loader  must  then find the module where the function is
    and insert the address in the GOT.
 
@@ -650,8 +652,6 @@ struct elf_s390_link_hash_table
   struct elf_link_hash_table elf;
 
   /* Short-cuts to get to dynamic linker sections.  */
-  asection *sdynbss;
-  asection *srelbss;
   asection *irelifunc;
 
   union {
@@ -661,13 +661,16 @@ struct elf_s390_link_hash_table
 
   /* Small local sym cache.  */
   struct sym_cache sym_cache;
+
+  /* Options passed from the linker.  */
+  struct s390_elf_params *params;
 };
 
 /* Get the s390 ELF linker hash table from a link_info structure.  */
 
-#define elf_s390_hash_table(p) \
-  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
-  == S390_ELF_DATA ? ((struct elf_s390_link_hash_table *) ((p)->hash)) : NULL)
+#define elf_s390_hash_table(p)                                         \
+  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash))      \
+   == S390_ELF_DATA ? ((struct elf_s390_link_hash_table *) ((p)->hash)) : NULL)
 
 #define ELF64 1
 #include "elf-s390-common.c"
@@ -729,63 +732,6 @@ elf_s390_link_hash_table_create (bfd *abfd)
   return &ret->elf.root;
 }
 
-/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
-   shortcuts to them in our hash table.  */
-
-static bfd_boolean
-create_got_section (bfd *dynobj,
-                   struct bfd_link_info *info)
-{
-  struct elf_s390_link_hash_table *htab;
-
-  if (! _bfd_elf_create_got_section (dynobj, info))
-    return FALSE;
-
-  htab = elf_s390_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  htab->elf.sgot = bfd_get_linker_section (dynobj, ".got");
-  htab->elf.sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
-  htab->elf.srelgot = bfd_get_linker_section (dynobj, ".rela.got");
-  if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot)
-    abort ();
-  return TRUE;
-}
-
-/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
-   .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
-   hash table.  */
-
-static bfd_boolean
-elf_s390_create_dynamic_sections (bfd *dynobj,
-                                 struct bfd_link_info *info)
-{
-  struct elf_s390_link_hash_table *htab;
-
-  htab = elf_s390_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  if (!htab->elf.sgot && !create_got_section (dynobj, info))
-    return FALSE;
-
-  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
-    return FALSE;
-
-  htab->elf.splt = bfd_get_linker_section (dynobj, ".plt");
-  htab->elf.srelplt = bfd_get_linker_section (dynobj, ".rela.plt");
-  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
-  if (!info->shared)
-    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
-  if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
-      || (!info->shared && !htab->srelbss))
-    abort ();
-
-  return TRUE;
-}
-
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
@@ -843,7 +789,8 @@ elf_s390_copy_indirect_symbol (struct bfd_link_info *info,
       /* If called to transfer flags for a weakdef during processing
         of elf_adjust_dynamic_symbol, don't copy non_got_ref.
         We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
-      dir->ref_dynamic |= ind->ref_dynamic;
+      if (dir->versioned != versioned_hidden)
+       dir->ref_dynamic |= ind->ref_dynamic;
       dir->ref_regular |= ind->ref_regular;
       dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
       dir->needs_plt |= ind->needs_plt;
@@ -857,7 +804,7 @@ elf_s390_tls_transition (struct bfd_link_info *info,
                         int r_type,
                         int is_local)
 {
-  if (info->shared)
+  if (bfd_link_pic (info))
     return r_type;
 
   switch (r_type)
@@ -897,7 +844,7 @@ elf_s390_check_relocs (bfd *abfd,
   bfd_signed_vma *local_got_refcounts;
   int tls_type, old_tls_type;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   BFD_ASSERT (is_s390_elf (abfd));
@@ -924,9 +871,9 @@ elf_s390_check_relocs (bfd *abfd,
 
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
        {
-         (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
-                                abfd,
-                                r_symndx);
+         /* xgettext:c-format */
+         _bfd_error_handler (_("%B: bad symbol index: %d"),
+                             abfd, r_symndx);
          return FALSE;
        }
 
@@ -968,7 +915,7 @@ elf_s390_check_relocs (bfd *abfd,
 
          /* PR15323, ref flags aren't set for references in the same
             object.  */
-         h->root.non_ir_ref = 1;
+         h->root.non_ir_ref_regular = 1;
        }
 
       /* Create got section and local_got_refcounts array if they
@@ -1015,7 +962,7 @@ elf_s390_check_relocs (bfd *abfd,
            {
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
-             if (!create_got_section (htab->elf.dynobj, info))
+             if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
                return FALSE;
            }
        }
@@ -1041,9 +988,6 @@ elf_s390_check_relocs (bfd *abfd,
 
       switch (r_type)
        {
-       case R_390_GOTOFF16:
-       case R_390_GOTOFF32:
-       case R_390_GOTOFF64:
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
          /* These relocs do not need a GOT slot.  They just load the
@@ -1051,6 +995,12 @@ elf_s390_check_relocs (bfd *abfd,
             the GOT.  Since the GOT pointer has been set up above we
             are done.  */
          break;
+       case R_390_GOTOFF16:
+       case R_390_GOTOFF32:
+       case R_390_GOTOFF64:
+         if (h == NULL || !s390_is_ifunc_symbol_p (h) || !h->def_regular)
+           break;
+         /* Fall through.  */
 
        case R_390_PLT12DBL:
        case R_390_PLT16DBL:
@@ -1110,7 +1060,7 @@ elf_s390_check_relocs (bfd *abfd,
        case R_390_TLS_GOTIE20:
        case R_390_TLS_GOTIE64:
        case R_390_TLS_IEENT:
-         if (info->shared)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
          /* Fall through */
 
@@ -1162,7 +1112,8 @@ elf_s390_check_relocs (bfd *abfd,
            {
              if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                    (_("%B: `%s' accessed both as normal and thread local symbol"),
                     abfd, h->root.root.string);
                  return FALSE;
@@ -1184,7 +1135,13 @@ elf_s390_check_relocs (bfd *abfd,
          /* Fall through */
 
        case R_390_TLS_LE64:
-         if (!info->shared)
+         /* For static linking and executables this reloc will be
+            calculated at linktime otherwise a TLS_TPOFF runtime
+            reloc will be generated.  */
+         if (r_type == R_390_TLS_LE64 && bfd_link_pie (info))
+           break;
+
+         if (!bfd_link_pic (info))
            break;
          info->flags |= DF_STATIC_TLS;
          /* Fall through */
@@ -1200,7 +1157,7 @@ elf_s390_check_relocs (bfd *abfd,
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC64:
-         if (h != NULL)
+         if (h != NULL && bfd_link_executable (info))
            {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
@@ -1210,7 +1167,7 @@ elf_s390_check_relocs (bfd *abfd,
                 adjust_dynamic_symbol.  */
              h->non_got_ref = 1;
 
-             if (!info->shared)
+             if (!bfd_link_pic (info))
                {
                  /* We may need a .plt entry if the function this reloc
                     refers to is in a shared lib.  */
@@ -1239,7 +1196,7 @@ elf_s390_check_relocs (bfd *abfd,
             may need to keep relocations for symbols satisfied by a
             dynamic library if we manage to avoid copy relocs for the
             symbol.  */
-         if ((info->shared
+         if ((bfd_link_pic (info)
               && (sec->flags & SEC_ALLOC) != 0
               && ((ELF64_R_TYPE (rel->r_info) != R_390_PC16
                    && ELF64_R_TYPE (rel->r_info) != R_390_PC12DBL
@@ -1253,7 +1210,7 @@ elf_s390_check_relocs (bfd *abfd,
                           || h->root.type == bfd_link_hash_defweak
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
+                 && !bfd_link_pic (info)
                  && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
@@ -1390,7 +1347,7 @@ elf_s390_gc_sweep_hook (bfd *abfd,
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   htab = elf_s390_hash_table (info);
@@ -1457,6 +1414,18 @@ elf_s390_gc_sweep_hook (bfd *abfd,
          if (htab->tls_ldm_got.refcount > 0)
            htab->tls_ldm_got.refcount -= 1;
          break;
+       case R_390_GOTOFF16:
+       case R_390_GOTOFF32:
+       case R_390_GOTOFF64:
+         if (h != NULL && s390_is_ifunc_symbol_p (h) && h->def_regular)
+           {
+             h->plt.refcount--;
+             break;
+           }
+
+       case R_390_GOTPC:
+       case R_390_GOTPCDBL:
+         break;
 
        case R_390_TLS_GD64:
        case R_390_TLS_IE64:
@@ -1469,11 +1438,6 @@ elf_s390_gc_sweep_hook (bfd *abfd,
        case R_390_GOT20:
        case R_390_GOT32:
        case R_390_GOT64:
-       case R_390_GOTOFF16:
-       case R_390_GOTOFF32:
-       case R_390_GOTOFF64:
-       case R_390_GOTPC:
-       case R_390_GOTPCDBL:
        case R_390_GOTENT:
          if (h != NULL)
            {
@@ -1500,7 +1464,7 @@ elf_s390_gc_sweep_hook (bfd *abfd,
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC64:
-         if (info->shared)
+         if (bfd_link_pic (info))
            break;
          /* Fall through */
 
@@ -1582,11 +1546,51 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h)
 {
   struct elf_s390_link_hash_table *htab;
-  asection *s;
+  asection *s, *srel;
 
   /* STT_GNU_IFUNC symbol must go through PLT. */
   if (s390_is_ifunc_symbol_p (h))
-    return TRUE;
+    {
+      /* All local STT_GNU_IFUNC references must be treated as local
+        calls via local PLT.  */
+      if (h->ref_regular && SYMBOL_CALLS_LOCAL (info, h))
+       {
+         bfd_size_type pc_count = 0, count = 0;
+         struct elf_dyn_relocs **pp;
+         struct elf_s390_link_hash_entry *eh;
+         struct elf_dyn_relocs *p;
+
+         eh = (struct elf_s390_link_hash_entry *) h;
+         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+           {
+             pc_count += p->pc_count;
+             p->count -= p->pc_count;
+             p->pc_count = 0;
+             count += p->count;
+             if (p->count == 0)
+               *pp = p->next;
+             else
+               pp = &p->next;
+           }
+
+         if (pc_count || count)
+           {
+             h->needs_plt = 1;
+             h->non_got_ref = 1;
+             if (h->plt.refcount <= 0)
+               h->plt.refcount = 1;
+             else
+               h->plt.refcount += 1;
+           }
+       }
+
+      if (h->plt.refcount <= 0)
+       {
+         h->plt.offset = (bfd_vma) -1;
+         h->needs_plt = 0;
+       }
+      return TRUE;
+    }
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later
@@ -1640,7 +1644,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
-  if (info->shared)
+  if (bfd_link_pic (info))
     return TRUE;
 
   /* If there are no references to this symbol that do not use the
@@ -1694,15 +1698,23 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* We must generate a R_390_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  */
+  if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+    {
+      s = htab->elf.sdynrelro;
+      srel = htab->elf.sreldynrelro;
+    }
+  else
+    {
+      s = htab->elf.sdynbss;
+      srel = htab->elf.srelbss;
+    }
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
-      htab->srelbss->size += sizeof (Elf64_External_Rela);
+      srel->size += sizeof (Elf64_External_Rela);
       h->needs_copy = 1;
     }
 
-  s = htab->sdynbss;
-
-  return _bfd_elf_adjust_dynamic_copy (h, s);
+  return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
@@ -1728,8 +1740,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
      here if it is defined and referenced in a non-shared object.  */
   if (s390_is_ifunc_symbol_p (h) && h->def_regular)
-    return s390_elf_allocate_ifunc_dyn_relocs (info, h,
-                                              &eh->dyn_relocs);
+    return s390_elf_allocate_ifunc_dyn_relocs (info, h);
   else if (htab->elf.dynamic_sections_created
           && h->plt.refcount > 0)
     {
@@ -1742,7 +1753,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
            return FALSE;
        }
 
-      if (info->shared
+      if (bfd_link_pic (info)
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
          asection *s = htab->elf.splt;
@@ -1759,7 +1770,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
             location in the .plt.  This is required to make function
             pointers compare as equal between the normal executable and
             the shared library.  */
-         if (! info->shared
+         if (! bfd_link_pic (info)
              && !h->def_regular)
            {
              h->root.u.def.section = s;
@@ -1795,7 +1806,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
      to R_390_TLS_LE64 requiring no TLS entry. For GOTIE12 and IEENT
      we can save the dynamic TLS relocation.  */
   if (h->got.refcount > 0
-      && !info->shared
+      && !bfd_link_pic (info)
       && h->dynindx == -1
       && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE)
     {
@@ -1841,7 +1852,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
        htab->elf.srelgot->size += 2 * sizeof (Elf64_External_Rela);
       else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                || h->root.type != bfd_link_hash_undefweak)
-              && (info->shared
+              && (bfd_link_pic (info)
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
        htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
     }
@@ -1857,7 +1868,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h,
      space for pc-relative relocs that have become local due to symbol
      visibility changes.  */
 
-  if (info->shared)
+  if (bfd_link_pic (info))
     {
       if (SYMBOL_CALLS_LOCAL (info, h))
        {
@@ -1984,7 +1995,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
@@ -1996,7 +2007,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
@@ -2052,7 +2063,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              s->size += GOT_ENTRY_SIZE;
              if (*local_tls_type == GOT_TLS_GD)
                s->size += GOT_ENTRY_SIZE;
-             if (info->shared)
+             if (bfd_link_pic (info))
                srela->size += sizeof (Elf64_External_Rela);
            }
          else
@@ -2100,7 +2111,8 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (s == htab->elf.splt
          || s == htab->elf.sgot
          || s == htab->elf.sgotplt
-         || s == htab->sdynbss
+         || s == htab->elf.sdynbss
+         || s == htab->elf.sdynrelro
          || s == htab->elf.iplt
          || s == htab->elf.igotplt
          || s == htab->irelifunc)
@@ -2162,7 +2174,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (info->executable)
+      if (bfd_link_executable (info))
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -2240,7 +2252,8 @@ invalid_tls_insn (bfd *input_bfd,
   reloc_howto_type *howto;
 
   howto = elf_howto_table + ELF64_R_TYPE (rel->r_info);
-  (*_bfd_error_handler)
+  _bfd_error_handler
+    /* xgettext:c-format */
     (_("%B(%A+0x%lx): invalid instruction for TLS relocation %s"),
      input_bfd,
      input_section,
@@ -2386,7 +2399,7 @@ elf_s390_relocate_section (bfd *output_bfd,
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
                                         rel, 1, relend, howto, 0, contents);
 
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        continue;
 
       switch (r_type)
@@ -2426,7 +2439,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                    PLT_ENTRY_SIZE;
 
                  /* Offset in GOT is PLT index plus GOT headers(3)
-                    times 4, addr & GOT addr.  */
+                    times 8, addr & GOT addr.  */
                  relocation = (plt_index + 3) * GOT_ENTRY_SIZE;
                  if (r_type == R_390_GOTPLTENT)
                    relocation += htab->elf.sgot->output_section->vma;
@@ -2471,8 +2484,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                         finish_dynamic_symbol.  */
                    }
                }
-             else if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-                      || (info->shared
+             else if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+                                                         bfd_link_pic (info),
+                                                         h)
+                      || (bfd_link_pic (info)
                           && SYMBOL_REFERENCES_LOCAL (info, h))
                       || (ELF_ST_VISIBILITY (h->other)
                           && h->root.type == bfd_link_hash_undefweak))
@@ -2499,7 +2514,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                    }
 
                  if ((h->def_regular
-                      && info->shared
+                      && bfd_link_pic (info)
                       && SYMBOL_REFERENCES_LOCAL (info, h))
                      /* lgrl rx,sym@GOTENT -> larl rx, sym */
                      && ((r_type == R_390_GOTENT
@@ -2549,7 +2564,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                  bfd_put_64 (output_bfd, relocation,
                              htab->elf.sgot->contents + off);
 
-                 if (info->shared)
+                 if (bfd_link_pic (info))
                    {
                      asection *s;
                      Elf_Internal_Rela outrel;
@@ -2594,6 +2609,18 @@ elf_s390_relocate_section (bfd *output_bfd,
          /* Relocation is relative to the start of the global offset
             table.  */
 
+         if (h != NULL
+             && s390_is_ifunc_symbol_p (h)
+             && h->def_regular
+             && !bfd_link_executable (info))
+           {
+             relocation = (htab->elf.iplt->output_section->vma
+                           + htab->elf.iplt->output_offset
+                           + h->plt.offset
+                           - htab->elf.sgot->output_section->vma);
+             goto do_relocation;
+           }
+
          /* Note that sgot->output_offset is not involved in this
             calculation.  We always want the start of .got.  If we
             defined _GLOBAL_OFFSET_TABLE in a different way, as is
@@ -2671,10 +2698,6 @@ elf_s390_relocate_section (bfd *output_bfd,
          unresolved_reloc = FALSE;
          break;
 
-       case R_390_8:
-       case R_390_16:
-       case R_390_32:
-       case R_390_64:
        case R_390_PC16:
        case R_390_PC12DBL:
        case R_390_PC16DBL:
@@ -2682,15 +2705,47 @@ elf_s390_relocate_section (bfd *output_bfd,
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC64:
+         if (h != NULL
+             && bfd_link_pie (info)
+             && !h->def_regular)
+           {
+             _bfd_error_handler (_("%B: `%s' non-PLT reloc for symbol defined "
+                                   "in shared library and accessed "
+                                   "from executable "
+                                   "(rebuild file with -fPIC ?)"),
+                                 input_bfd, h->root.root.string);
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
+         /* The target of these relocs are instruction operands
+            residing in read-only sections.  We cannot emit a runtime
+            reloc for it.  */
+         if (h != NULL
+             && s390_is_ifunc_symbol_p (h)
+             && h->def_regular
+             && bfd_link_pic (info))
+           {
+             relocation = (htab->elf.iplt->output_section->vma
+                           + htab->elf.iplt->output_offset
+                           + h->plt.offset);
+             goto do_relocation;
+           }
+         /* Fall through.  */
+
+       case R_390_8:
+       case R_390_16:
+       case R_390_32:
+       case R_390_64:
 
          if (h != NULL
              && s390_is_ifunc_symbol_p (h)
              && h->def_regular)
            {
-             if (!info->shared || !h->non_got_ref)
+             if (!bfd_link_pic (info))
                {
-                 /* For a non-shared object STT_GNU_IFUNC symbol must
-                    go through PLT.  */
+                 /* For a non-shared object the symbol will not
+                    change.  Hence we can write the address of the
+                    target IPLT slot now.  */
                  relocation = (htab->elf.iplt->output_section->vma
                                + htab->elf.iplt->output_offset
                                + h ->plt.offset);
@@ -2718,7 +2773,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
                  if (h->dynindx == -1
                      || h->forced_local
-                     || info->executable)
+                     || bfd_link_executable (info))
                    {
                      /* This symbol is resolved locally.  */
                      outrel.r_info = ELF64_R_INFO (0, R_390_IRELATIVE);
@@ -2747,7 +2802,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          if ((input_section->flags & SEC_ALLOC) == 0)
            break;
 
-         if ((info->shared
+         if ((bfd_link_pic (info)
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                   || h->root.type != bfd_link_hash_undefweak)
@@ -2760,7 +2815,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                    && r_type != R_390_PC64)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
+                 && !bfd_link_pic (info)
                  && h != NULL
                  && h->dynindx != -1
                  && !h->non_got_ref
@@ -2802,7 +2857,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                           || r_type == R_390_PC32
                           || r_type == R_390_PC32DBL
                           || r_type == R_390_PC64
-                          || !info->shared
+                          || !bfd_link_pic (info)
                           || !SYMBOLIC_BIND (info, h)
                           || !h->def_regular))
                {
@@ -2874,7 +2929,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          /* Relocations for tls literal pool entries.  */
        case R_390_TLS_IE64:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              Elf_Internal_Rela outrel;
              asection *sreloc;
@@ -2902,7 +2957,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          else if (h != NULL)
            {
              tls_type = elf_s390_hash_entry(h)->tls_type;
-             if (!info->shared && h->dynindx == -1 && tls_type >= GOT_TLS_IE)
+             if (!bfd_link_pic (info) && h->dynindx == -1 && tls_type >= GOT_TLS_IE)
                r_type = R_390_TLS_LE64;
            }
          if (r_type == R_390_TLS_GD64 && tls_type >= GOT_TLS_IE)
@@ -3013,14 +3068,14 @@ elf_s390_relocate_section (bfd *output_bfd,
              if (local_got_offsets == NULL)
                abort();
              off = local_got_offsets[r_symndx];
-             if (info->shared)
+             if (bfd_link_pic (info))
                goto emit_tls_relocs;
            }
          else
            {
              off = h->got.offset;
              tls_type = elf_s390_hash_entry(h)->tls_type;
-             if (info->shared || h->dynindx != -1 || tls_type < GOT_TLS_IE)
+             if (bfd_link_pic (info) || h->dynindx != -1 || tls_type < GOT_TLS_IE)
                goto emit_tls_relocs;
            }
 
@@ -3037,7 +3092,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          break;
 
        case R_390_TLS_LDM64:
-         if (! info->shared)
+         if (! bfd_link_pic (info))
            /* The literal pool entry this relocation refers to gets ignored
               by the optimized code of the local exec model. Do nothing
               and the value will turn out zero.  */
@@ -3075,7 +3130,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          break;
 
        case R_390_TLS_LE64:
-         if (info->shared)
+         if (bfd_link_dll (info))
            {
              /* Linking a shared library with non-fpic code requires
                 a R_390_TLS_TPOFF relocation.  */
@@ -3112,7 +3167,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          continue;
 
        case R_390_TLS_LDO64:
-         if (info->shared || (input_section->flags & SEC_DEBUGGING))
+         if (bfd_link_pic (info) || (input_section->flags & SEC_DEBUGGING))
            relocation -= dtpoff_base (info);
          else
            /* When converting LDO to LE, we must negate.  */
@@ -3134,7 +3189,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          if (r_type == R_390_TLS_LOAD)
            {
-             if (!info->shared && (h == NULL || h->dynindx == -1))
+             if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1))
                {
                  /* IE->LE transition. Four valid cases:
                     lg %rx,(0,%ry)    -> sllg %rx,%ry,0
@@ -3146,8 +3201,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                  insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4);
                  if (insn1 != 0x0004)
-                   invalid_tls_insn (input_bfd, input_section, rel);
-                 ry = 0;
+                   {
+                     invalid_tls_insn (input_bfd, input_section, rel);
+                     return FALSE;
+                   }
                  if ((insn0 & 0xff00f000) == 0xe3000000)
                    /* lg %rx,0(%ry,0) -> sllg %rx,%ry,0  */
                    ry = (insn0 & 0x000f0000);
@@ -3161,7 +3218,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                    /* lg %rx,0(%r12,%ry) -> sllg %rx,%ry,0  */
                    ry = (insn0 & 0x0000f000) << 4;
                  else
-                   invalid_tls_insn (input_bfd, input_section, rel);
+                   {
+                     invalid_tls_insn (input_bfd, input_section, rel);
+                     return FALSE;
+                   }
                  insn0 = 0xeb000000 | (insn0 & 0x00f00000) | ry;
                  insn1 = 0x000d;
                  bfd_put_32 (output_bfd, insn0, contents + rel->r_offset);
@@ -3175,8 +3235,11 @@ elf_s390_relocate_section (bfd *output_bfd,
              insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset);
              insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4);
              if ((insn0 & 0xffff0000) != 0xc0e50000)
-               invalid_tls_insn (input_bfd, input_section, rel);
-             if (!info->shared && (h == NULL || h->dynindx == -1))
+               {
+                 invalid_tls_insn (input_bfd, input_section, rel);
+                 return FALSE;
+               }
+             if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1))
                {
                  /* GD->LE transition.
                     brasl %r14,__tls_get_addr@plt -> brcl 0,. */
@@ -3195,14 +3258,17 @@ elf_s390_relocate_section (bfd *output_bfd,
            }
          else if (r_type == R_390_TLS_LDCALL)
            {
-             if (!info->shared)
+             if (!bfd_link_pic (info))
                {
                  unsigned int insn0, insn1;
 
                  insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4);
                  if ((insn0 & 0xffff0000) != 0xc0e50000)
-                   invalid_tls_insn (input_bfd, input_section, rel);
+                   {
+                     invalid_tls_insn (input_bfd, input_section, rel);
+                     return FALSE;
+                   }
                  /* LD->LE transition.
                     brasl %r14,__tls_get_addr@plt -> brcl 0,. */
                  insn0 = 0xc0040000;
@@ -3225,7 +3291,8 @@ elf_s390_relocate_section (bfd *output_bfd,
               && h->def_dynamic)
          && _bfd_elf_section_offset (output_bfd, info, input_section,
                                      rel->r_offset) != (bfd_vma) -1)
-       (*_bfd_error_handler)
+       _bfd_error_handler
+         /* xgettext:c-format */
          (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
           input_section,
@@ -3276,17 +3343,13 @@ elf_s390_relocate_section (bfd *output_bfd,
            }
 
          if (r == bfd_reloc_overflow)
-           {
-
-             if (! ((*info->callbacks->reloc_overflow)
-                    (info, (h ? &h->root : NULL), name, howto->name,
-                     (bfd_vma) 0, input_bfd, input_section,
-                     rel->r_offset)))
-               return FALSE;
-           }
+           (*info->callbacks->reloc_overflow)
+             (info, (h ? &h->root : NULL), name, howto->name,
+              (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
          else
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B(%A+0x%lx): reloc against `%s': error %d"),
                 input_bfd, input_section,
                 (long) rel->r_offset, name, (int) r);
@@ -3365,7 +3428,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
 
   if (!h
       || h->dynindx == -1
-      || ((info->executable
+      || ((bfd_link_executable (info)
           || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
          && h->def_regular))
     {
@@ -3409,17 +3472,16 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
 
       /* This symbol has an entry in the procedure linkage table.  Set
         it up.  */
-      if (s390_is_ifunc_symbol_p (h))
+      if (s390_is_ifunc_symbol_p (h) && h->def_regular)
        {
-         /* If we can resolve the IFUNC symbol locally we generate an
-            IRELATIVE reloc.  */
-         elf_s390_finish_ifunc_symbol (output_bfd, info, h, htab, h->plt.offset,
-                                       eh->ifunc_resolver_address +
-                                       eh->ifunc_resolver_section->output_offset +
-                                       eh->ifunc_resolver_section->output_section->vma);
-                                ;
-         /* Fallthrough.  Handling of explicit GOT slots of IFUNC
-            symbols is below.  */
+         elf_s390_finish_ifunc_symbol (output_bfd, info, h,
+           htab, h->plt.offset,
+           eh->ifunc_resolver_address +
+           eh->ifunc_resolver_section->output_offset +
+           eh->ifunc_resolver_section->output_section->vma);
+
+         /* Do not return yet.  Handling of explicit GOT slots of
+            IFUNC symbols is below.  */
        }
       else
        {
@@ -3507,7 +3569,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
 
       if (h->def_regular && s390_is_ifunc_symbol_p (h))
        {
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              /* An explicit GOT slot usage needs GLOB_DAT.  If the
                 symbol references local the implicit got.iplt slot
@@ -3527,8 +3589,8 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
              return TRUE;
            }
        }
-      else if (info->shared
-         && SYMBOL_REFERENCES_LOCAL (info, h))
+      else if (bfd_link_pic (info)
+              && SYMBOL_REFERENCES_LOCAL (info, h))
        {
          /* If this is a static link, or it is a -Bsymbolic link and
             the symbol is defined locally or was forced to be local
@@ -3536,7 +3598,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
             RELATIVE reloc.  The entry in the global offset table
             will already have been initialized in the
             relocate_section function.  */
-         if (!h->def_regular)
+         if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
            return FALSE;
          BFD_ASSERT((h->got.offset & 1) != 0);
          rela.r_info = ELF64_R_INFO (0, R_390_RELATIVE);
@@ -3547,7 +3609,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
       else
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
-do_glob_dat:
+       do_glob_dat:
          bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + h->got.offset);
          rela.r_info = ELF64_R_INFO (h->dynindx, R_390_GLOB_DAT);
          rela.r_addend = 0;
@@ -3561,6 +3623,7 @@ do_glob_dat:
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
+      asection *s;
       bfd_byte *loc;
 
       /* This symbols needs a copy reloc.  Set it up.  */
@@ -3568,7 +3631,7 @@ do_glob_dat:
       if (h->dynindx == -1
          || (h->root.type != bfd_link_hash_defined
              && h->root.type != bfd_link_hash_defweak)
-         || htab->srelbss == NULL)
+         || htab->elf.srelbss == NULL)
        abort ();
 
       rela.r_offset = (h->root.u.def.value
@@ -3576,8 +3639,11 @@ do_glob_dat:
                       + h->root.u.def.section->output_offset);
       rela.r_info = ELF64_R_INFO (h->dynindx, R_390_COPY);
       rela.r_addend = 0;
-      loc = htab->srelbss->contents;
-      loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
+      if (h->root.u.def.section == htab->elf.sdynrelro)
+       s = htab->elf.sreldynrelro;
+      else
+       s = htab->elf.srelbss;
+      loc = s->contents + s->reloc_count++ * sizeof (Elf64_External_Rela);
       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
     }
 
@@ -3598,6 +3664,23 @@ elf_s390_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
                           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 elf_s390_link_hash_table *htab = elf_s390_hash_table (info);
+  unsigned long r_symndx = ELF64_R_SYM (rela->r_info);
+  Elf_Internal_Sym sym;
+
+  if (htab->elf.dynsym == NULL
+      || !bed->s->swap_symbol_in (abfd,
+                                 (htab->elf.dynsym->contents
+                                  + r_symndx * bed->s->sizeof_sym),
+                                 0, &sym))
+    abort ();
+
+  /* Check relocation against STT_GNU_IFUNC symbol.  */
+  if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+    return reloc_class_ifunc;
+
   switch ((int) ELF64_R_TYPE (rela->r_info))
     {
     case R_390_RELATIVE:
@@ -3652,16 +3735,17 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
              continue;
 
            case DT_PLTGOT:
-             dyn.d_un.d_ptr = htab->elf.sgot->output_section->vma;
+             s = htab->elf.sgotplt;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_JMPREL:
-             dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
+             s = htab->elf.srelplt;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_PLTRELSZ:
-             s = htab->elf.srelplt->output_section;
-             dyn.d_un.d_val = s->size;
+             dyn.d_un.d_val = htab->elf.srelplt->size + htab->elf.irelplt->size;
              break;
 
            case DT_RELASZ:
@@ -3672,8 +3756,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
                 linker script arranges for .rela.plt to follow all
                 other relocation sections, we don't have to worry
                 about changing the DT_RELA entry.  */
-             s = htab->elf.srelplt->output_section;
-             dyn.d_un.d_val -= s->size;
+             dyn.d_un.d_val -= htab->elf.srelplt->size + htab->elf.irelplt->size;
              break;
            }
 
@@ -3688,9 +3771,10 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
                  PLT_FIRST_ENTRY_SIZE);
          /* Fixup relative address to start of GOT */
          bfd_put_32 (output_bfd,
-                     (htab->elf.sgotplt->output_section->vma +
-                      htab->elf.sgotplt->output_offset
-                      - htab->elf.splt->output_section->vma - 6)/2,
+                     (htab->elf.sgotplt->output_section->vma
+                      + htab->elf.sgotplt->output_offset
+                      - htab->elf.splt->output_section->vma
+                      - htab->elf.splt->output_offset - 6)/2,
                      htab->elf.splt->contents + 8);
        }
       if (elf_section_data (htab->elf.splt->output_section) != NULL)
@@ -3710,7 +3794,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
          /* One entry for shared object struct ptr.  */
          bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 8);
          /* One entry for _dl_runtime_resolve.  */
-         bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 12);
+         bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 16);
        }
 
       elf_section_data (htab->elf.sgot->output_section)
@@ -3718,7 +3802,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
     }
 
   /* Finish dynamic symbol for local IFUNC symbols.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       struct plt_entry *local_plt;
       Elf_Internal_Sym *isym;
@@ -3750,7 +3834,120 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
 
   return TRUE;
 }
+\f
+/* Support for core dump NOTE sections.  */
+
+static bfd_boolean
+elf_s390_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
+{
+  int offset;
+  size_t size;
+
+  switch (note->descsz)
+    {
+    default:
+      return FALSE;
+
+    case 336:                  /* sizeof(struct elf_prstatus) on s390x */
+      /* pr_cursig */
+      elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
+
+      /* pr_pid */
+      elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32);
+
+      /* pr_reg */
+      offset = 112;
+      size = 216;
+      break;
+    }
 
+  /* Make a ".reg/999" section.  */
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+                                         size, note->descpos + offset);
+}
+
+static bfd_boolean
+elf_s390_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+  switch (note->descsz)
+    {
+    default:
+      return FALSE;
+
+    case 136:                  /* sizeof(struct elf_prpsinfo) on s390x */
+      elf_tdata (abfd)->core->pid
+       = bfd_get_32 (abfd, note->descdata + 24);
+      elf_tdata (abfd)->core->program
+       = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
+      elf_tdata (abfd)->core->command
+       = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
+    }
+
+  /* Note that for some reason, a spurious space is tacked
+     onto the end of the args in some (at least one anyway)
+     implementations, so strip it off if it exists.  */
+
+  {
+    char *command = elf_tdata (abfd)->core->command;
+    int n = strlen (command);
+
+    if (0 < n && command[n - 1] == ' ')
+      command[n - 1] = '\0';
+  }
+
+  return TRUE;
+}
+
+static char *
+elf_s390_write_core_note (bfd *abfd, char *buf, int *bufsiz,
+                         int note_type, ...)
+{
+  va_list ap;
+
+  switch (note_type)
+    {
+    default:
+      return NULL;
+
+    case NT_PRPSINFO:
+      {
+       char data[136] = { 0 };
+       const char *fname, *psargs;
+
+       va_start (ap, note_type);
+       fname = va_arg (ap, const char *);
+       psargs = va_arg (ap, const char *);
+       va_end (ap);
+
+       strncpy (data + 40, fname, 16);
+       strncpy (data + 56, psargs, 80);
+       return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type,
+                                  &data, sizeof (data));
+      }
+
+    case NT_PRSTATUS:
+      {
+       char data[336] = { 0 };
+       long pid;
+       int cursig;
+       const void *gregs;
+
+       va_start (ap, note_type);
+       pid = va_arg (ap, long);
+       cursig = va_arg (ap, int);
+       gregs = va_arg (ap, const void *);
+       va_end (ap);
+
+       bfd_put_16 (abfd, cursig, data + 12);
+       bfd_put_32 (abfd, pid, data + 32);
+       memcpy (data + 112, gregs, 216);
+       return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type,
+                                  &data, sizeof (data));
+      }
+    }
+  /* NOTREACHED */
+}
+\f
 /* Return address for Ith PLT stub in section PLT, for relocation REL
    or (bfd_vma) -1 if it should not be included.  */
 
@@ -3761,6 +3958,82 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt,
   return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
 }
 
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+elf64_s390_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
+{
+  if (!is_s390_elf (ibfd) || !is_s390_elf (info->output_bfd))
+    return TRUE;
+
+  return elf_s390_merge_obj_attributes (ibfd, info);
+}
+
+/* We may add a PT_S390_PGSTE program header.  */
+
+static int
+elf_s390_additional_program_headers (bfd *abfd ATTRIBUTE_UNUSED,
+                                    struct bfd_link_info *info)
+{
+  struct elf_s390_link_hash_table *htab;
+
+  htab = elf_s390_hash_table (info);
+  return htab->params->pgste;
+}
+
+
+/* Add the PT_S390_PGSTE program header.  */
+
+static bfd_boolean
+elf_s390_modify_segment_map (bfd *abfd ATTRIBUTE_UNUSED,
+                            struct bfd_link_info *info)
+{
+  struct elf_s390_link_hash_table *htab;
+  struct elf_segment_map *m, *pm = NULL;
+
+  htab = elf_s390_hash_table (info);
+  if (!htab->params->pgste)
+    return TRUE;
+
+  /* If there is already a PT_S390_PGSTE header, avoid adding
+     another.  */
+  m = elf_seg_map (abfd);
+  while (m && m->p_type != PT_S390_PGSTE)
+    {
+      pm = m;
+      m = m->next;
+    }
+
+  if (m)
+    return TRUE;
+
+  m = (struct elf_segment_map *)
+    bfd_zalloc (abfd, sizeof (struct elf_segment_map));
+  if (m == NULL)
+    return FALSE;
+  m->p_type = PT_S390_PGSTE;
+  m->count = 0;
+  m->next = NULL;
+  if (pm)
+    pm->next = m;
+
+  return TRUE;
+}
+
+bfd_boolean
+bfd_elf_s390_set_options (struct bfd_link_info *info,
+                         struct s390_elf_params *params)
+{
+  struct elf_s390_link_hash_table *htab;
+
+  htab = elf_s390_hash_table (info);
+  htab->params = params;
+
+  return TRUE;
+}
+
+
 /* Why was the hash table entry size definition changed from
    ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and
    this is the only reason for the s390_elf64_size_info structure.  */
@@ -3796,7 +4069,7 @@ const struct elf_size_info s390_elf64_size_info =
   bfd_elf64_swap_reloca_out
 };
 
-#define TARGET_BIG_SYM bfd_elf64_s390_vec
+#define TARGET_BIG_SYM s390_elf64_vec
 #define TARGET_BIG_NAME        "elf64-s390"
 #define ELF_ARCH       bfd_arch_s390
 #define ELF_TARGET_ID  S390_ELF_DATA
@@ -3812,6 +4085,7 @@ const struct elf_size_info s390_elf64_size_info =
 #define elf_backend_plt_readonly       1
 #define elf_backend_want_plt_sym       0
 #define elf_backend_got_header_size    24
+#define elf_backend_want_dynrelro      1
 #define elf_backend_rela_normal                1
 
 #define elf_info_to_howto              elf_s390_info_to_howto
@@ -3819,12 +4093,13 @@ const struct elf_size_info s390_elf64_size_info =
 #define bfd_elf64_bfd_is_local_label_name     elf_s390_is_local_label_name
 #define bfd_elf64_bfd_link_hash_table_create  elf_s390_link_hash_table_create
 #define bfd_elf64_bfd_reloc_type_lookup              elf_s390_reloc_type_lookup
-#define bfd_elf64_bfd_reloc_name_lookup elf_s390_reloc_name_lookup
+#define bfd_elf64_bfd_reloc_name_lookup       elf_s390_reloc_name_lookup
+#define bfd_elf64_bfd_merge_private_bfd_data  elf64_s390_merge_private_bfd_data
 
 #define elf_backend_adjust_dynamic_symbol     elf_s390_adjust_dynamic_symbol
 #define elf_backend_check_relocs             elf_s390_check_relocs
 #define elf_backend_copy_indirect_symbol      elf_s390_copy_indirect_symbol
-#define elf_backend_create_dynamic_sections   elf_s390_create_dynamic_sections
+#define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
 #define elf_backend_finish_dynamic_sections   elf_s390_finish_dynamic_sections
 #define elf_backend_finish_dynamic_symbol     elf_s390_finish_dynamic_symbol
 #define elf_backend_gc_mark_hook             elf_s390_gc_mark_hook
@@ -3833,25 +4108,16 @@ const struct elf_size_info s390_elf64_size_info =
 #define elf_backend_relocate_section         elf_s390_relocate_section
 #define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
 #define elf_backend_init_index_section       _bfd_elf_init_1_index_section
+#define elf_backend_grok_prstatus            elf_s390_grok_prstatus
+#define elf_backend_grok_psinfo                      elf_s390_grok_psinfo
+#define elf_backend_write_core_note          elf_s390_write_core_note
 #define elf_backend_plt_sym_val                      elf_s390_plt_sym_val
 #define elf_backend_add_symbol_hook           elf_s390_add_symbol_hook
+#define elf_backend_sort_relocs_p             elf_s390_elf_sort_relocs_p
+#define elf_backend_additional_program_headers elf_s390_additional_program_headers
+#define elf_backend_modify_segment_map       elf_s390_modify_segment_map
 
 #define bfd_elf64_mkobject             elf_s390_mkobject
 #define elf_backend_object_p           elf_s390_object_p
 
-/* Enable ELF64 archive functions.  */
-#define bfd_elf64_archive_functions
-extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
-extern bfd_boolean bfd_elf64_archive_write_armap (bfd *, unsigned int, struct orl *, unsigned int, int);
-
-#define bfd_elf64_archive_slurp_extended_name_table    _bfd_archive_coff_slurp_extended_name_table
-#define bfd_elf64_archive_construct_extended_name_table _bfd_archive_coff_construct_extended_name_table
-#define bfd_elf64_archive_truncate_arname              _bfd_archive_coff_truncate_arname
-#define bfd_elf64_archive_read_ar_hdr                  _bfd_archive_coff_read_ar_hdr
-#define bfd_elf64_archive_write_ar_hdr                 _bfd_archive_coff_write_ar_hdr
-#define bfd_elf64_archive_openr_next_archived_file     _bfd_archive_coff_openr_next_archived_file
-#define bfd_elf64_archive_get_elt_at_index             _bfd_archive_coff_get_elt_at_index
-#define bfd_elf64_archive_generic_stat_arch_elt        _bfd_archive_coff_generic_stat_arch_elt
-#define bfd_elf64_archive_update_armap_timestamp       _bfd_archive_coff_update_armap_timestamp
-
 #include "elf64-target.h"
This page took 0.042147 seconds and 4 git commands to generate.