Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
[deliverable/binutils-gdb.git] / bfd / elf32-s390.c
index 170a450bd43eacc538dd9aebc124013fa7c4a0a2..ce5c98be869a95af3104b6badb39c3401af6a253 100644 (file)
@@ -1,5 +1,5 @@
 /* IBM S/390-specific support for 32-bit ELF
-   Copyright (C) 2000-2016 Free Software Foundation, Inc.
+   Copyright (C) 2000-2017 Free Software Foundation, Inc.
    Contributed by Carl B. Pedersen and Martin Schwidefsky.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -25,6 +25,7 @@
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/s390.h"
+#include <stdarg.h>
 
 static bfd_reloc_status_type
 s390_tls_reloc (bfd *, arelent *, asymbol *, void *,
@@ -341,8 +342,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];
@@ -736,8 +738,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
@@ -816,56 +816,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);
-  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->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 (!bfd_link_pic (info))
-    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
-  if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
-      || (!bfd_link_pic (info) && !htab->srelbss))
-    abort ();
-
-  return TRUE;
-}
-
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
@@ -923,7 +873,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;
@@ -994,15 +945,16 @@ elf_s390_check_relocs (bfd *abfd,
   for (rel = relocs; rel < rel_end; rel++)
     {
       unsigned int r_type;
-      unsigned long r_symndx;
+      unsigned int r_symndx;
       struct elf_link_hash_entry *h;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
       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;
        }
 
@@ -1044,7 +996,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
@@ -1087,7 +1039,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;
            }
        }
@@ -1123,6 +1075,7 @@ elf_s390_check_relocs (bfd *abfd,
        case R_390_GOTOFF32:
          if (h == NULL || !s390_is_ifunc_symbol_p (h) || !h->def_regular)
            break;
+         /* Fall through.  */
 
        case R_390_PLT12DBL:
        case R_390_PLT16DBL:
@@ -1230,7 +1183,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;
@@ -1447,180 +1401,6 @@ elf_s390_gc_mark_hook (asection *sec,
 
 }
 
-/* Update the got entry reference counts for the section being removed.  */
-
-static bfd_boolean
-elf_s390_gc_sweep_hook (bfd *abfd,
-                       struct bfd_link_info *info,
-                       asection *sec,
-                       const Elf_Internal_Rela *relocs)
-{
-  struct elf_s390_link_hash_table *htab;
-  Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes;
-  bfd_signed_vma *local_got_refcounts;
-  const Elf_Internal_Rela *rel, *relend;
-
-  if (bfd_link_relocatable (info))
-    return TRUE;
-
-  htab = elf_s390_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  elf_section_data (sec)->local_dynrel = NULL;
-
-  symtab_hdr = &elf_symtab_hdr (abfd);
-  sym_hashes = elf_sym_hashes (abfd);
-  local_got_refcounts = elf_local_got_refcounts (abfd);
-
-  relend = relocs + sec->reloc_count;
-  for (rel = relocs; rel < relend; rel++)
-    {
-      unsigned long r_symndx;
-      unsigned int r_type;
-      struct elf_link_hash_entry *h = NULL;
-
-      r_symndx = ELF32_R_SYM (rel->r_info);
-      if (r_symndx >= symtab_hdr->sh_info)
-       {
-         struct elf_s390_link_hash_entry *eh;
-         struct elf_dyn_relocs **pp;
-         struct elf_dyn_relocs *p;
-
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
-         eh = (struct elf_s390_link_hash_entry *) h;
-
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
-           if (p->sec == sec)
-             {
-               /* Everything must go for SEC.  */
-               *pp = p->next;
-               break;
-             }
-       }
-      else
-       {
-         Elf_Internal_Sym *isym;
-
-         /* A local symbol.  */
-         isym = bfd_sym_from_r_symndx (&htab->sym_cache,
-                                       abfd, r_symndx);
-         if (isym == NULL)
-           return FALSE;
-
-         if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
-           {
-             struct plt_entry *plt = elf_s390_local_plt (abfd);
-             if (plt[r_symndx].plt.refcount > 0)
-               plt[r_symndx].plt.refcount--;
-           }
-       }
-
-      r_type = ELF32_R_TYPE (rel->r_info);
-      r_type = elf_s390_tls_transition (info, r_type, h != NULL);
-      switch (r_type)
-       {
-       case R_390_TLS_LDM32:
-         if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
-           elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
-         break;
-
-       case R_390_GOTOFF16:
-       case R_390_GOTOFF32:
-         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_GD32:
-       case R_390_TLS_IE32:
-       case R_390_TLS_GOTIE12:
-       case R_390_TLS_GOTIE20:
-       case R_390_TLS_GOTIE32:
-       case R_390_TLS_IEENT:
-       case R_390_GOT12:
-       case R_390_GOT16:
-       case R_390_GOT20:
-       case R_390_GOT32:
-       case R_390_GOTENT:
-         if (h != NULL)
-           {
-             if (h->got.refcount > 0)
-               h->got.refcount -= 1;
-           }
-         else if (local_got_refcounts != NULL)
-           {
-             if (local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx] -= 1;
-           }
-         break;
-
-       case R_390_8:
-       case R_390_12:
-       case R_390_16:
-       case R_390_20:
-       case R_390_32:
-       case R_390_PC16:
-       case R_390_PC12DBL:
-       case R_390_PC16DBL:
-       case R_390_PC24DBL:
-       case R_390_PC32DBL:
-       case R_390_PC32:
-         if (bfd_link_pic (info))
-           break;
-         /* Fall through.  */
-
-       case R_390_PLT12DBL:
-       case R_390_PLT16DBL:
-       case R_390_PLT24DBL:
-       case R_390_PLT32DBL:
-       case R_390_PLT32:
-       case R_390_PLTOFF16:
-       case R_390_PLTOFF32:
-         if (h != NULL)
-           {
-             if (h->plt.refcount > 0)
-               h->plt.refcount -= 1;
-           }
-         break;
-
-       case R_390_GOTPLT12:
-       case R_390_GOTPLT16:
-       case R_390_GOTPLT20:
-       case R_390_GOTPLT32:
-       case R_390_GOTPLTENT:
-         if (h != NULL)
-           {
-             if (h->plt.refcount > 0)
-               {
-                 ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
-                 h->plt.refcount -= 1;
-               }
-           }
-         else if (local_got_refcounts != NULL)
-           {
-             if (local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx] -= 1;
-           }
-         break;
-
-       default:
-         break;
-       }
-    }
-
-  return TRUE;
-}
-
 /* Make sure we emit a GOT entry if the symbol was supposed to have a PLT
    entry but we found we will not create any.  Called when we find we will
    not have any PLT for this symbol, by for example
@@ -1654,7 +1434,7 @@ 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))
@@ -1804,14 +1584,22 @@ 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 (Elf32_External_Rela);
+      srel->size += sizeof (Elf32_External_Rela);
       h->needs_copy = 1;
     }
 
-  s = htab->sdynbss;
-
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
@@ -1985,7 +1773,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+             || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
            eh->dyn_relocs = NULL;
 
          /* Make sure undefined weak symbols are output as a dynamic
@@ -2203,7 +1992,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)
@@ -2342,11 +2132,12 @@ invalid_tls_insn (bfd *input_bfd,
   reloc_howto_type *howto;
 
   howto = elf_howto_table + ELF32_R_TYPE (rel->r_info);
-  (*_bfd_error_handler)
-    (_("%B(%A+0x%lx): invalid instruction for TLS relocation %s"),
+  _bfd_error_handler
+    /* xgettext:c-format */
+    (_("%B(%A+%#Lx): invalid instruction for TLS relocation %s"),
      input_bfd,
      input_section,
-     (long) rel->r_offset,
+     rel->r_offset,
      howto->name);
   bfd_set_error (bfd_error_bad_value);
 }
@@ -2393,6 +2184,7 @@ elf_s390_relocate_section (bfd *output_bfd,
       bfd_reloc_status_type r;
       int tls_type;
       asection *base_got = htab->elf.sgot;
+      bfd_boolean resolved_to_zero;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_390_GNU_VTINHERIT
@@ -2484,6 +2276,9 @@ elf_s390_relocate_section (bfd *output_bfd,
       if (bfd_link_relocatable (info))
        continue;
 
+      resolved_to_zero = (h != NULL
+                         && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+
       switch (r_type)
        {
        case R_390_GOTPLT12:
@@ -2801,6 +2596,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                            + h ->plt.offset);
              goto do_relocation;
            }
+         /* Fall through.  */
 
        case R_390_8:
        case R_390_16:
@@ -2809,7 +2605,7 @@ elf_s390_relocate_section (bfd *output_bfd,
              && s390_is_ifunc_symbol_p (h)
              && h->def_regular)
            {
-             if (!bfd_link_pic (info) || !h->non_got_ref)
+             if (!bfd_link_pic (info))
                {
                  /* For a non-shared object STT_GNU_IFUNC symbol must
                     go through PLT.  */
@@ -2871,7 +2667,8 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          if ((bfd_link_pic (info)
               && (h == NULL
-                  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                  || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                      && !resolved_to_zero)
                   || h->root.type != bfd_link_hash_undefweak)
               && ((r_type != R_390_PC16
                    && r_type != R_390_PC12DBL
@@ -3266,7 +3063,6 @@ elf_s390_relocate_section (bfd *output_bfd,
                  unsigned int insn, ry;
 
                  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                 ry = 0;
                  if ((insn & 0xff00f000) == 0x58000000)
                    /* l %rx,0(%ry,0) -> lr %rx,%ry + bcr 0,0  */
                    ry = (insn & 0x000f0000);
@@ -3280,7 +3076,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                    /* l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0  */
                    ry = (insn & 0x0000f000) << 4;
                  else
-                   invalid_tls_insn (input_bfd, input_section, rel);
+                   {
+                     invalid_tls_insn (input_bfd, input_section, rel);
+                     return FALSE;
+                   }
                  insn = 0x18000700 | (insn & 0x00f00000) | ry;
                  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
                }
@@ -3293,7 +3092,10 @@ elf_s390_relocate_section (bfd *output_bfd,
              if ((insn & 0xff000fff) != 0x4d000000 &&
                  (insn & 0xffff0000) != 0xc0e50000 &&
                  (insn & 0xff000000) != 0x0d000000)
-               invalid_tls_insn (input_bfd, input_section, rel);
+               {
+                 invalid_tls_insn (input_bfd, input_section, rel);
+                 return FALSE;
+               }
              if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1))
                {
                  if ((insn & 0xff000000) == 0x0d000000)
@@ -3322,7 +3124,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                  /* If basr is used in the pic case to invoke
                     _tls_get_offset, something went wrong before.  */
                  if ((insn & 0xff000000) == 0x0d000000)
-                   invalid_tls_insn (input_bfd, input_section, rel);
+                   {
+                     invalid_tls_insn (input_bfd, input_section, rel);
+                     return FALSE;
+                   }
 
                  if ((insn & 0xff000000) == 0x4d000000)
                    {
@@ -3352,7 +3157,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                  if ((insn & 0xff000fff) != 0x4d000000 &&
                      (insn & 0xffff0000) != 0xc0e50000 &&
                      (insn & 0xff000000) != 0x0d000000)
-                   invalid_tls_insn (input_bfd, input_section, rel);
+                   {
+                     invalid_tls_insn (input_bfd, input_section, rel);
+                     return FALSE;
+                   }
 
                  if ((insn & 0xff000000) == 0x0d000000)
                    {
@@ -3391,11 +3199,12 @@ 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)
-         (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+       _bfd_error_handler
+         /* xgettext:c-format */
+         (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
           input_section,
-          (long) rel->r_offset,
+          rel->r_offset,
           howto->name,
           h->root.root.string);
 
@@ -3447,10 +3256,11 @@ elf_s390_relocate_section (bfd *output_bfd,
               (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
          else
            {
-             (*_bfd_error_handler)
-               (_("%B(%A+0x%lx): reloc against `%s': error %d"),
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%B(%A+%#Lx): reloc against `%s': error %d"),
                 input_bfd, input_section,
-                (long) rel->r_offset, name, (int) r);
+                rel->r_offset, name, (int) r);
              return FALSE;
            }
        }
@@ -3818,7 +3628,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 = ELF32_R_INFO (0, R_390_RELATIVE);
@@ -3843,6 +3653,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
+      asection *s;
       bfd_byte *loc;
 
       /* This symbols needs a copy reloc.  Set it up.  */
@@ -3850,7 +3661,8 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
       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
+         || htab->elf.sreldynrelro == NULL)
        abort ();
 
       rela.r_offset = (h->root.u.def.value
@@ -3858,8 +3670,11 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
                       + h->root.u.def.section->output_offset);
       rela.r_info = ELF32_R_INFO (h->dynindx, R_390_COPY);
       rela.r_addend = 0;
-      loc = htab->srelbss->contents;
-      loc += htab->srelbss->reloc_count++ * sizeof (Elf32_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 (Elf32_External_Rela);
       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
     }
 
@@ -3958,7 +3773,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTRELSZ:
-             dyn.d_un.d_val = htab->elf.srelplt->size + htab->elf.irelplt->size;
+             dyn.d_un.d_val = htab->elf.srelplt->size;
+             if (htab->elf.irelplt)
+               dyn.d_un.d_val += htab->elf.irelplt->size;
              break;
            }
 
@@ -4016,6 +3833,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
 
       symtab_hdr = &elf_symtab_hdr (ibfd);
 
+      if (!is_s390_elf (ibfd))
+       continue;
+
       local_plt = elf_s390_local_plt (ibfd);
       if (local_plt != NULL)
        for (i = 0; i < symtab_hdr->sh_info; i++)
@@ -4039,6 +3859,8 @@ 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)
@@ -4069,6 +3891,89 @@ elf_s390_grok_prstatus (bfd * abfd, Elf_Internal_Note * note)
                                          size, note->descpos + offset);
 }
 
+static bfd_boolean
+elf_s390_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+  switch (note->descsz)
+    {
+    default:
+      return FALSE;
+
+    case 124:                  /* sizeof(struct elf_prpsinfo) on s390 */
+      elf_tdata (abfd)->core->pid
+       = bfd_get_32 (abfd, note->descdata + 12);
+      elf_tdata (abfd)->core->program
+       = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
+      elf_tdata (abfd)->core->command
+       = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
+      break;
+    }
+
+  /* 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[124] = { 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 + 28, fname, 16);
+       strncpy (data + 44, psargs, 80);
+       return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type,
+                                  &data, sizeof (data));
+      }
+
+    case NT_PRSTATUS:
+      {
+       char data[224] = { 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 + 24);
+       memcpy (data + 72, gregs, 144);
+       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.  */
 
@@ -4083,12 +3988,14 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt,
    object file when linking.  */
 
 static bfd_boolean
-elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+elf32_s390_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 {
+  bfd *obfd = info->output_bfd;
+
   if (!is_s390_elf (ibfd) || !is_s390_elf (obfd))
     return TRUE;
 
-  if (!elf_s390_merge_obj_attributes (ibfd, obfd))
+  if (!elf_s390_merge_obj_attributes (ibfd, info))
     return FALSE;
 
   elf_elfheader (obfd)->e_flags |= elf_elfheader (ibfd)->e_flags;
@@ -4110,6 +4017,7 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 #define elf_backend_plt_readonly       1
 #define elf_backend_want_plt_sym       0
 #define elf_backend_got_header_size    12
+#define elf_backend_want_dynrelro      1
 #define elf_backend_rela_normal                1
 
 #define elf_info_to_howto                    elf_s390_info_to_howto
@@ -4124,16 +4032,17 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 #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
-#define elf_backend_gc_sweep_hook            elf_s390_gc_sweep_hook
 #define elf_backend_reloc_type_class         elf_s390_reloc_type_class
 #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
@@ -4141,4 +4050,6 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 #define bfd_elf32_mkobject             elf_s390_mkobject
 #define elf_backend_object_p           elf_s390_object_p
 
+#define elf_backend_linux_prpsinfo32_ugid16    TRUE
+
 #include "elf32-target.h"
This page took 0.033944 seconds and 4 git commands to generate.