Handle R_X86_64_64 properly for x32
[deliverable/binutils-gdb.git] / bfd / elf64-s390.c
index fbe86683a5613da2c250ae2a4cfe85e5f5d98cb4..cc0e473119a0402497c44709caafe7219d5619cf 100644 (file)
@@ -1,6 +1,6 @@
 /* IBM S/390-specific support for 64-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011, 2012 Free Software Foundation, Inc.
    Contributed Martin Schwidefsky (schwidefsky@de.ibm.com).
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -493,7 +493,7 @@ elf_s390_is_local_label_name (abfd, name)
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
 
-#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
+#define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1"
 
 /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
    copying dynamic variables from a shared lib into an app's dynbss
@@ -540,31 +540,33 @@ elf_s390_is_local_label_name (abfd, name)
    RET1: BASR 1,0         # 2 bytes  Return from GOT 1st time
          LGF  1,12(1)     # 6 bytes  Load offset in symbl table in r1
          BRCL 15,-x       # 6 bytes  Jump to start of PLT
-         .long ?          # 4 bytes  offset into symbol table
+         .long ?          # 4 bytes  offset into .rela.plt
 
    Total = 32 bytes per PLT entry
    Fixup at offset 2: relative address to GOT entry
    Fixup at offset 22: relative branch to PLT0
-   Fixup at offset 28: 32 bit offset into symbol table
-
-   A 32 bit offset into the symbol table is enough. It allows for symbol
-   tables up to a size of 2 gigabyte. A single dynamic object (the main
-   program, any shared library) is limited to 4GB in size and I want to see
-   the program that manages to have a symbol table of more than 2 GB with a
-   total size of at max 4 GB.  */
-
-#define PLT_ENTRY_WORD0     (bfd_vma) 0xc0100000
-#define PLT_ENTRY_WORD1     (bfd_vma) 0x0000e310
-#define PLT_ENTRY_WORD2     (bfd_vma) 0x10000004
-#define PLT_ENTRY_WORD3     (bfd_vma) 0x07f10d10
-#define PLT_ENTRY_WORD4     (bfd_vma) 0xe310100c
-#define PLT_ENTRY_WORD5     (bfd_vma) 0x0014c0f4
-#define PLT_ENTRY_WORD6     (bfd_vma) 0x00000000
-#define PLT_ENTRY_WORD7     (bfd_vma) 0x00000000
+   Fixup at offset 28: 32 bit offset into .rela.plt
+
+   A 32 bit offset into the symbol table is enough. It allows for
+   .rela.plt sections up to a size of 2 gigabyte.  A single dynamic
+   object (the main program, any shared library) is limited to 4GB in
+   size.  Having a .rela.plt of 2GB would already make the .plt
+   section bigger than 8GB.  */
+
+static const bfd_byte elf_s390x_plt_entry[PLT_ENTRY_SIZE] =
+  {
+    0xc0, 0x10, 0x00, 0x00, 0x00, 0x00,     /* larl    %r1,.       */
+    0xe3, 0x10, 0x10, 0x00, 0x00, 0x04,     /* lg      %r1,0(%r1)  */
+    0x07, 0xf1,                             /* br      %r1         */
+    0x0d, 0x10,                             /* basr    %r1,%r0     */
+    0xe3, 0x10, 0x10, 0x0c, 0x00, 0x14,     /* lgf     %r1,12(%r1) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,     /* jg      first plt   */
+    0x00, 0x00, 0x00, 0x00                  /* .long   0x00000000  */
+  };
 
 /* The first PLT entry pushes the offset into the symbol table
-   from R1 onto the stack at 8(15) and the loader object info
-   at 12(15), loads the loader address in R1 and jumps to it.  */
+   from R1 onto the stack at 56(15) and the loader object info
+   at 48(15), loads the loader address in R1 and jumps to it.  */
 
 /* The first entry in the PLT:
 
@@ -577,34 +579,18 @@ elf_s390_is_local_label_name (abfd, name)
 
      Fixup at offset 8: relative address to start of GOT.  */
 
-#define PLT_FIRST_ENTRY_WORD0     (bfd_vma) 0xe310f038
-#define PLT_FIRST_ENTRY_WORD1     (bfd_vma) 0x0024c010
-#define PLT_FIRST_ENTRY_WORD2     (bfd_vma) 0x00000000
-#define PLT_FIRST_ENTRY_WORD3     (bfd_vma) 0xd207f030
-#define PLT_FIRST_ENTRY_WORD4     (bfd_vma) 0x1008e310
-#define PLT_FIRST_ENTRY_WORD5     (bfd_vma) 0x10100004
-#define PLT_FIRST_ENTRY_WORD6     (bfd_vma) 0x07f10700
-#define PLT_FIRST_ENTRY_WORD7     (bfd_vma) 0x07000700
-
-/* The s390 linker needs to keep track of the number of relocs that it
-   decides to copy as dynamic relocs in check_relocs for each symbol.
-   This is so that it can later discard them if they are found to be
-   unnecessary.  We store the information in a field extending the
-   regular ELF linker hash table.  */
-
-struct elf_s390_dyn_relocs
-{
-  struct elf_s390_dyn_relocs *next;
-
-  /* The input section of the reloc.  */
-  asection *sec;
+static const bfd_byte elf_s390x_first_plt_entry[PLT_FIRST_ENTRY_SIZE] =
+  {
+    0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24,     /* stg     %r1,56(%r15)      */
+    0xc0, 0x10, 0x00, 0x00, 0x00, 0x00,     /* larl    %r1,.             */
+    0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08,     /* mvc     48(8,%r15),8(%r1) */
+    0xe3, 0x10, 0x10, 0x10, 0x00, 0x04,     /* lg      %r1,16(%r1)       */
+    0x07, 0xf1,                             /* br      %r1               */
+    0x07, 0x00,                             /* nopr    %r0               */
+    0x07, 0x00,                             /* nopr    %r0               */
+    0x07, 0x00                              /* nopr    %r0               */
+  };
 
-  /* Total number of relocs copied for the input section.  */
-  bfd_size_type count;
-
-  /* Number of pc-relative relocs copied for the input section.  */
-  bfd_size_type pc_count;
-};
 
 /* s390 ELF linker hash entry.  */
 
@@ -613,7 +599,7 @@ struct elf_s390_link_hash_entry
   struct elf_link_hash_entry elf;
 
   /* Track dynamic relocs copied for this symbol.  */
-  struct elf_s390_dyn_relocs *dyn_relocs;
+  struct elf_dyn_relocs *dyn_relocs;
 
   /* Number of GOTPLT references for a function.  */
   bfd_signed_vma gotplt_refcount;
@@ -648,13 +634,13 @@ struct elf_s390_obj_tdata
 #define is_s390_elf(bfd)                               \
   (bfd_get_flavour (bfd) == bfd_target_elf_flavour     \
    && elf_tdata (bfd) != NULL                          \
-   && elf_object_id (bfd) == S390_ELF_TDATA)
+   && elf_object_id (bfd) == S390_ELF_DATA)
 
 static bfd_boolean
 elf_s390_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd, sizeof (struct elf_s390_obj_tdata),
-                                 S390_ELF_TDATA);
+                                 S390_ELF_DATA);
 }
 
 static bfd_boolean
@@ -672,11 +658,6 @@ struct elf_s390_link_hash_table
   struct elf_link_hash_table elf;
 
   /* Short-cuts to get to dynamic linker sections.  */
-  asection *sgot;
-  asection *sgotplt;
-  asection *srelgot;
-  asection *splt;
-  asection *srelplt;
   asection *sdynbss;
   asection *srelbss;
 
@@ -692,7 +673,8 @@ struct elf_s390_link_hash_table
 /* Get the s390 ELF linker hash table from a link_info structure.  */
 
 #define elf_s390_hash_table(p) \
-  ((struct elf_s390_link_hash_table *) ((p)->hash))
+  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+  == S390_ELF_DATA ? ((struct elf_s390_link_hash_table *) ((p)->hash)) : NULL)
 
 /* Create an entry in an s390 ELF linker hash table.  */
 
@@ -741,17 +723,18 @@ elf_s390_link_hash_table_create (abfd)
     return NULL;
 
   if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
-                                     sizeof (struct elf_s390_link_hash_entry)))
+                                     sizeof (struct elf_s390_link_hash_entry),
+                                     S390_ELF_DATA))
     {
       free (ret);
       return NULL;
     }
 
-  ret->sgot = NULL;
-  ret->sgotplt = NULL;
-  ret->srelgot = NULL;
-  ret->splt = NULL;
-  ret->srelplt = NULL;
+  ret->elf.sgot = NULL;
+  ret->elf.sgotplt = NULL;
+  ret->elf.srelgot = NULL;
+  ret->elf.splt = NULL;
+  ret->elf.srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
@@ -764,9 +747,8 @@ elf_s390_link_hash_table_create (abfd)
    shortcuts to them in our hash table.  */
 
 static bfd_boolean
-create_got_section (dynobj, info)
-     bfd *dynobj;
-     struct bfd_link_info *info;
+create_got_section (bfd *dynobj,
+                   struct bfd_link_info *info)
 {
   struct elf_s390_link_hash_table *htab;
 
@@ -774,10 +756,13 @@ create_got_section (dynobj, info)
     return FALSE;
 
   htab = elf_s390_hash_table (info);
-  htab->sgot = bfd_get_section_by_name (dynobj, ".got");
-  htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
-  htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
-  if (!htab->sgot || !htab->sgotplt || !htab->srelgot)
+  if (htab == NULL)
+    return FALSE;
+
+  htab->elf.sgot = bfd_get_section_by_name (dynobj, ".got");
+  htab->elf.sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+  htab->elf.srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+  if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot)
     abort ();
   return TRUE;
 }
@@ -787,26 +772,28 @@ create_got_section (dynobj, info)
    hash table.  */
 
 static bfd_boolean
-elf_s390_create_dynamic_sections (dynobj, info)
-     bfd *dynobj;
-     struct bfd_link_info *info;
+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->sgot && !create_got_section (dynobj, 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->splt = bfd_get_section_by_name (dynobj, ".plt");
-  htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+  htab->elf.splt = bfd_get_section_by_name (dynobj, ".plt");
+  htab->elf.srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
   htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
   if (!info->shared)
     htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
 
-  if (!htab->splt || !htab->srelplt || !htab->sdynbss
+  if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
       || (!info->shared && !htab->srelbss))
     abort ();
 
@@ -829,14 +816,14 @@ elf_s390_copy_indirect_symbol (info, dir, ind)
     {
       if (edir->dyn_relocs != NULL)
        {
-         struct elf_s390_dyn_relocs **pp;
-         struct elf_s390_dyn_relocs *p;
+         struct elf_dyn_relocs **pp;
+         struct elf_dyn_relocs *p;
 
          /* Add reloc counts against the indirect sym to the direct sym
             list.  Merge any entries against the same section.  */
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
            {
-             struct elf_s390_dyn_relocs *q;
+             struct elf_dyn_relocs *q;
 
              for (q = edir->dyn_relocs; q != NULL; q = q->next)
                if (q->sec == p->sec)
@@ -911,11 +898,10 @@ elf_s390_tls_transition (info, r_type, is_local)
    table.  */
 
 static bfd_boolean
-elf_s390_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+elf_s390_check_relocs (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;
@@ -932,6 +918,9 @@ elf_s390_check_relocs (abfd, info, sec, relocs)
   BFD_ASSERT (is_s390_elf (abfd));
 
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
   local_got_refcounts = elf_local_got_refcounts (abfd);
@@ -1012,7 +1001,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs)
        case R_390_GOTOFF64:
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
-         if (htab->sgot == NULL)
+         if (htab->elf.sgot == NULL)
            {
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
@@ -1229,8 +1218,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs)
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular)))
            {
-             struct elf_s390_dyn_relocs *p;
-             struct elf_s390_dyn_relocs **head;
+             struct elf_dyn_relocs *p;
+             struct elf_dyn_relocs **head;
 
              /* We must copy these reloc types into the output file.
                 Create a reloc section in dynobj and make room for
@@ -1272,14 +1261,14 @@ elf_s390_check_relocs (abfd, info, sec, relocs)
                    s = sec;
 
                  vpp = &elf_section_data (s)->local_dynrel;
-                 head = (struct elf_s390_dyn_relocs **) vpp;
+                 head = (struct elf_dyn_relocs **) vpp;
                }
 
              p = *head;
              if (p == NULL || p->sec != sec)
                {
                  bfd_size_type amt = sizeof *p;
-                 p = ((struct elf_s390_dyn_relocs *)
+                 p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
                  if (p == NULL)
                    return FALSE;
@@ -1353,6 +1342,7 @@ elf_s390_gc_sweep_hook (bfd *abfd,
                        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;
@@ -1361,6 +1351,10 @@ elf_s390_gc_sweep_hook (bfd *abfd,
   if (info->relocatable)
     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);
@@ -1378,8 +1372,8 @@ elf_s390_gc_sweep_hook (bfd *abfd,
       if (r_symndx >= symtab_hdr->sh_info)
        {
          struct elf_s390_link_hash_entry *eh;
-         struct elf_s390_dyn_relocs **pp;
-         struct elf_s390_dyn_relocs *p;
+         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
@@ -1401,8 +1395,8 @@ elf_s390_gc_sweep_hook (bfd *abfd,
       switch (r_type)
        {
        case R_390_TLS_LDM64:
-         if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
-           elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
+         if (htab->tls_ldm_got.refcount > 0)
+           htab->tls_ldm_got.refcount -= 1;
          break;
 
        case R_390_TLS_GD64:
@@ -1522,9 +1516,8 @@ elf_s390_adjust_gotplt (h)
    understand.  */
 
 static bfd_boolean
-elf_s390_adjust_dynamic_symbol (info, h)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
+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;
@@ -1599,7 +1592,7 @@ elf_s390_adjust_dynamic_symbol (info, h)
   if (ELIMINATE_COPY_RELOCS)
     {
       struct elf_s390_link_hash_entry * eh;
-      struct elf_s390_dyn_relocs *p;
+      struct elf_dyn_relocs *p;
 
       eh = (struct elf_s390_link_hash_entry *) h;
       for (p = eh->dyn_relocs; p != NULL; p = p->next)
@@ -1618,13 +1611,6 @@ elf_s390_adjust_dynamic_symbol (info, h)
        }
     }
 
-  if (h->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            h->root.root.string);
-      return TRUE;
-    }
-
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -1636,11 +1622,13 @@ elf_s390_adjust_dynamic_symbol (info, h)
      same memory location for the variable.  */
 
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   /* 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_ALLOC) != 0)
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
       htab->srelbss->size += sizeof (Elf64_External_Rela);
       h->needs_copy = 1;
@@ -1655,26 +1643,21 @@ elf_s390_adjust_dynamic_symbol (info, h)
    dynamic relocs.  */
 
 static bfd_boolean
-allocate_dynrelocs (h, inf)
-     struct elf_link_hash_entry *h;
-     PTR inf;
+allocate_dynrelocs (struct elf_link_hash_entry *h,
+                   void * inf)
 {
   struct bfd_link_info *info;
   struct elf_s390_link_hash_table *htab;
   struct elf_s390_link_hash_entry *eh;
-  struct elf_s390_dyn_relocs *p;
+  struct elf_dyn_relocs *p;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   info = (struct bfd_link_info *) inf;
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   if (htab->elf.dynamic_sections_created
       && h->plt.refcount > 0)
@@ -1691,7 +1674,7 @@ allocate_dynrelocs (h, inf)
       if (info->shared
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
-         asection *s = htab->splt;
+         asection *s = htab->elf.splt;
 
          /* If this is the first .plt entry, make room for the special
             first entry.  */
@@ -1717,10 +1700,10 @@ allocate_dynrelocs (h, inf)
 
          /* We also need to make an entry in the .got.plt section, which
             will be placed in the .got section by the linker script.  */
-         htab->sgotplt->size += GOT_ENTRY_SIZE;
+         htab->elf.sgotplt->size += GOT_ENTRY_SIZE;
 
          /* We also need to make an entry in the .rela.plt section.  */
-         htab->srelplt->size += sizeof (Elf64_External_Rela);
+         htab->elf.srelplt->size += sizeof (Elf64_External_Rela);
        }
       else
        {
@@ -1750,8 +1733,8 @@ allocate_dynrelocs (h, inf)
           to be stored somewhere. The immediate value in the instruction
           is not bit enough so the value is stored in the got.  */
        {
-         h->got.offset = htab->sgot->size;
-         htab->sgot->size += GOT_ENTRY_SIZE;
+         h->got.offset = htab->elf.sgot->size;
+         htab->elf.sgot->size += GOT_ENTRY_SIZE;
        }
       else
        h->got.offset = (bfd_vma) -1;
@@ -1771,7 +1754,7 @@ allocate_dynrelocs (h, inf)
            return FALSE;
        }
 
-      s = htab->sgot;
+      s = htab->elf.sgot;
       h->got.offset = s->size;
       s->size += GOT_ENTRY_SIZE;
       /* R_390_TLS_GD64 needs 2 consecutive GOT slots.  */
@@ -1782,14 +1765,14 @@ allocate_dynrelocs (h, inf)
         R_390_TLS_GD64 needs one if local symbol and two if global.  */
       if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
          || tls_type >= GOT_TLS_IE)
-       htab->srelgot->size += sizeof (Elf64_External_Rela);
+       htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
       else if (tls_type == GOT_TLS_GD)
-       htab->srelgot->size += 2 * sizeof (Elf64_External_Rela);
+       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
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
-       htab->srelgot->size += sizeof (Elf64_External_Rela);
+       htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
     }
   else
     h->got.offset = (bfd_vma) -1;
@@ -1808,7 +1791,7 @@ allocate_dynrelocs (h, inf)
     {
       if (SYMBOL_CALLS_LOCAL (info, h))
        {
-         struct elf_s390_dyn_relocs **pp;
+         struct elf_dyn_relocs **pp;
 
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
            {
@@ -1890,10 +1873,7 @@ readonly_dynrelocs (h, inf)
      PTR inf;
 {
   struct elf_s390_link_hash_entry *eh;
-  struct elf_s390_dyn_relocs *p;
-
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  struct elf_dyn_relocs *p;
 
   eh = (struct elf_s390_link_hash_entry *) h;
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
@@ -1916,9 +1896,8 @@ readonly_dynrelocs (h, inf)
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
-elf_s390_size_dynamic_sections (output_bfd, info)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+                               struct bfd_link_info *info)
 {
   struct elf_s390_link_hash_table *htab;
   bfd *dynobj;
@@ -1927,6 +1906,9 @@ elf_s390_size_dynamic_sections (output_bfd, info)
   bfd *ibfd;
 
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
   if (dynobj == NULL)
     abort ();
@@ -1960,7 +1942,7 @@ elf_s390_size_dynamic_sections (output_bfd, info)
 
       for (s = ibfd->sections; s != NULL; s = s->next)
        {
-         struct elf_s390_dyn_relocs *p;
+         struct elf_dyn_relocs *p;
 
          for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
            {
@@ -1990,8 +1972,8 @@ elf_s390_size_dynamic_sections (output_bfd, info)
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf_s390_local_got_tls_type (ibfd);
-      s = htab->sgot;
-      srela = htab->srelgot;
+      s = htab->elf.sgot;
+      srela = htab->elf.srelgot;
       for (; local_got < end_local_got; ++local_got, ++local_tls_type)
        {
          if (*local_got > 0)
@@ -2012,9 +1994,9 @@ elf_s390_size_dynamic_sections (output_bfd, info)
     {
       /* Allocate 2 got entries and 1 dynamic reloc for R_390_TLS_LDM64
         relocs.  */
-      htab->tls_ldm_got.offset = htab->sgot->size;
-      htab->sgot->size += 2 * GOT_ENTRY_SIZE;
-      htab->srelgot->size += sizeof (Elf64_External_Rela);
+      htab->tls_ldm_got.offset = htab->elf.sgot->size;
+      htab->elf.sgot->size += 2 * GOT_ENTRY_SIZE;
+      htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
     }
   else
     htab->tls_ldm_got.offset = -1;
@@ -2031,9 +2013,9 @@ elf_s390_size_dynamic_sections (output_bfd, info)
       if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
 
-      if (s == htab->splt
-         || s == htab->sgot
-         || s == htab->sgotplt
+      if (s == htab->elf.splt
+         || s == htab->elf.sgot
+         || s == htab->elf.sgotplt
          || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
@@ -2041,7 +2023,7 @@ elf_s390_size_dynamic_sections (output_bfd, info)
        }
       else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
        {
-         if (s->size != 0 && s != htab->srelplt)
+         if (s->size != 0 && s != htab->elf.srelplt)
            relocs = TRUE;
 
          /* We use the reloc_count field as a counter if we need
@@ -2099,7 +2081,7 @@ elf_s390_size_dynamic_sections (output_bfd, info)
            return FALSE;
        }
 
-      if (htab->splt->size != 0)
+      if (htab->elf.splt->size != 0)
        {
          if (!add_dynamic_entry (DT_PLTGOT, 0)
              || !add_dynamic_entry (DT_PLTRELSZ, 0)
@@ -2187,16 +2169,14 @@ invalid_tls_insn (input_bfd, input_section, rel)
 /* Relocate a 390 ELF section.  */
 
 static bfd_boolean
-elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
-                             contents, relocs, local_syms, local_sections)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     Elf_Internal_Rela *relocs;
-     Elf_Internal_Sym *local_syms;
-     asection **local_sections;
+elf_s390_relocate_section (bfd *output_bfd,
+                          struct bfd_link_info *info,
+                          bfd *input_bfd,
+                          asection *input_section,
+                          bfd_byte *contents,
+                          Elf_Internal_Rela *relocs,
+                          Elf_Internal_Sym *local_syms,
+                          asection **local_sections)
 {
   struct elf_s390_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
@@ -2208,6 +2188,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
   BFD_ASSERT (is_s390_elf (input_bfd));
 
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   symtab_hdr = &elf_symtab_hdr (input_bfd);
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
@@ -2261,16 +2244,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                                   unresolved_reloc, warned);
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
        continue;
@@ -2307,7 +2283,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              unresolved_reloc = FALSE;
 
              if (r_type == R_390_GOTPLTENT)
-               relocation += htab->sgot->output_section->vma;
+               relocation += htab->elf.sgot->output_section->vma;
              break;
            }
          /* Fall through.  */
@@ -2320,7 +2296,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_390_GOTENT:
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
-         if (htab->sgot == NULL)
+         if (htab->elf.sgot == NULL)
            abort ();
 
          if (h != NULL)
@@ -2352,7 +2328,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                  else
                    {
                      bfd_put_64 (output_bfd, relocation,
-                                 htab->sgot->contents + off);
+                                 htab->elf.sgot->contents + off);
                      h->got.offset |= 1;
                    }
                }
@@ -2374,7 +2350,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              else
                {
                  bfd_put_64 (output_bfd, relocation,
-                             htab->sgot->contents + off);
+                             htab->elf.sgot->contents + off);
 
                  if (info->shared)
                    {
@@ -2382,12 +2358,12 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                      Elf_Internal_Rela outrel;
                      bfd_byte *loc;
 
-                     s = htab->srelgot;
+                     s = htab->elf.srelgot;
                      if (s == NULL)
                        abort ();
 
-                     outrel.r_offset = (htab->sgot->output_section->vma
-                                        + htab->sgot->output_offset
+                     outrel.r_offset = (htab->elf.sgot->output_section->vma
+                                        + htab->elf.sgot->output_offset
                                         + off);
                      outrel.r_info = ELF64_R_INFO (0, R_390_RELATIVE);
                      outrel.r_addend = relocation;
@@ -2403,7 +2379,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
          if (off >= (bfd_vma) -2)
            abort ();
 
-         relocation = htab->sgot->output_offset + off;
+         relocation = htab->elf.sgot->output_offset + off;
 
          /* For @GOTENT the relocation is against the offset between
             the instruction and the symbols entry in the GOT and not
@@ -2411,7 +2387,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
             add the vma of the GOT to get the correct value.  */
          if (   r_type == R_390_GOTENT
              || r_type == R_390_GOTPLTENT)
-           relocation += htab->sgot->output_section->vma;
+           relocation += htab->elf.sgot->output_section->vma;
 
          break;
 
@@ -2426,13 +2402,13 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
             defined _GLOBAL_OFFSET_TABLE in a different way, as is
             permitted by the ABI, we might have to change this
             calculation.  */
-         relocation -= htab->sgot->output_section->vma;
+         relocation -= htab->elf.sgot->output_section->vma;
          break;
 
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
          /* Use global offset table as symbol value.  */
-         relocation = htab->sgot->output_section->vma;
+         relocation = htab->elf.sgot->output_section->vma;
          unresolved_reloc = FALSE;
          break;
 
@@ -2449,7 +2425,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
            break;
 
          if (h->plt.offset == (bfd_vma) -1
-             || htab->splt == NULL)
+             || htab->elf.splt == NULL)
            {
              /* We didn't make a PLT entry for this symbol.  This
                 happens when statically linking PIC code, or when
@@ -2457,8 +2433,8 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              break;
            }
 
-         relocation = (htab->splt->output_section->vma
-                       + htab->splt->output_offset
+         relocation = (htab->elf.splt->output_section->vma
+                       + htab->elf.splt->output_offset
                        + h->plt.offset);
          unresolved_reloc = FALSE;
          break;
@@ -2473,16 +2449,16 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
             this symbol resolve the symbol directly.  */
          if (   h == NULL
              || h->plt.offset == (bfd_vma) -1
-             || htab->splt == NULL)
+             || htab->elf.splt == NULL)
            {
-             relocation -= htab->sgot->output_section->vma;
+             relocation -= htab->elf.sgot->output_section->vma;
              break;
            }
 
-         relocation = (htab->splt->output_section->vma
-                       + htab->splt->output_offset
+         relocation = (htab->elf.splt->output_section->vma
+                       + htab->elf.splt->output_offset
                        + h->plt.offset
-                       - htab->sgot->output_section->vma);
+                       - htab->elf.sgot->output_section->vma);
          unresolved_reloc = FALSE;
          break;
 
@@ -2665,7 +2641,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              continue;
            }
 
-         if (htab->sgot == NULL)
+         if (htab->elf.sgot == NULL)
            abort ();
 
          if (h != NULL)
@@ -2688,11 +2664,11 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              bfd_byte *loc;
              int dr_type, indx;
 
-             if (htab->srelgot == NULL)
+             if (htab->elf.srelgot == NULL)
                abort ();
 
-             outrel.r_offset = (htab->sgot->output_section->vma
-                                + htab->sgot->output_offset + off);
+             outrel.r_offset = (htab->elf.sgot->output_section->vma
+                                + htab->elf.sgot->output_offset + off);
 
              indx = h && h->dynindx != -1 ? h->dynindx : 0;
              if (r_type == R_390_TLS_GD64)
@@ -2704,8 +2680,8 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              else
                outrel.r_addend = 0;
              outrel.r_info = ELF64_R_INFO (indx, dr_type);
-             loc = htab->srelgot->contents;
-             loc += htab->srelgot->reloc_count++
+             loc = htab->elf.srelgot->contents;
+             loc += htab->elf.srelgot->reloc_count++
                * sizeof (Elf64_External_Rela);
              bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 
@@ -2716,14 +2692,14 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                      BFD_ASSERT (! unresolved_reloc);
                      bfd_put_64 (output_bfd,
                                  relocation - dtpoff_base (info),
-                                 htab->sgot->contents + off + GOT_ENTRY_SIZE);
+                                 htab->elf.sgot->contents + off + GOT_ENTRY_SIZE);
                    }
                  else
                    {
                      outrel.r_info = ELF64_R_INFO (indx, R_390_TLS_DTPOFF);
                      outrel.r_offset += GOT_ENTRY_SIZE;
                      outrel.r_addend = 0;
-                     htab->srelgot->reloc_count++;
+                     htab->elf.srelgot->reloc_count++;
                      loc += sizeof (Elf64_External_Rela);
                      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
                    }
@@ -2739,14 +2715,14 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
            abort ();
          if (r_type == ELF64_R_TYPE (rel->r_info))
            {
-             relocation = htab->sgot->output_offset + off;
+             relocation = htab->elf.sgot->output_offset + off;
              if (r_type == R_390_TLS_IE64 || r_type == R_390_TLS_IEENT)
-               relocation += htab->sgot->output_section->vma;
+               relocation += htab->elf.sgot->output_section->vma;
              unresolved_reloc = FALSE;
            }
          else
            {
-             bfd_put_64 (output_bfd, htab->sgot->output_offset + off,
+             bfd_put_64 (output_bfd, htab->elf.sgot->output_offset + off,
                          contents + rel->r_offset);
              continue;
            }
@@ -2771,15 +2747,15 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                goto emit_tls_relocs;
            }
 
-         if (htab->sgot == NULL)
+         if (htab->elf.sgot == NULL)
            abort ();
 
          BFD_ASSERT (! unresolved_reloc);
          bfd_put_64 (output_bfd, -tpoff (info, relocation),
-                     htab->sgot->contents + off);
-         relocation = htab->sgot->output_offset + off;
+                     htab->elf.sgot->contents + off);
+         relocation = htab->elf.sgot->output_offset + off;
          if (r_type == R_390_TLS_IEENT)
-           relocation += htab->sgot->output_section->vma;
+           relocation += htab->elf.sgot->output_section->vma;
          unresolved_reloc = FALSE;
          break;
 
@@ -2790,7 +2766,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
               and the value will turn out zero.  */
            continue;
 
-         if (htab->sgot == NULL)
+         if (htab->elf.sgot == NULL)
            abort ();
 
          off = htab->tls_ldm_got.offset;
@@ -2801,23 +2777,23 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
 
-             if (htab->srelgot == NULL)
+             if (htab->elf.srelgot == NULL)
                abort ();
 
-             outrel.r_offset = (htab->sgot->output_section->vma
-                                + htab->sgot->output_offset + off);
+             outrel.r_offset = (htab->elf.sgot->output_section->vma
+                                + htab->elf.sgot->output_offset + off);
 
              bfd_put_64 (output_bfd, 0,
-                         htab->sgot->contents + off + GOT_ENTRY_SIZE);
+                         htab->elf.sgot->contents + off + GOT_ENTRY_SIZE);
              outrel.r_info = ELF64_R_INFO (0, R_390_TLS_DTPMOD);
              outrel.r_addend = 0;
-             loc = htab->srelgot->contents;
-             loc += htab->srelgot->reloc_count++
+             loc = htab->elf.srelgot->contents;
+             loc += htab->elf.srelgot->reloc_count++
                * sizeof (Elf64_External_Rela);
              bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
              htab->tls_ldm_got.offset |= 1;
            }
-         relocation = htab->sgot->output_offset + off;
+         relocation = htab->elf.sgot->output_offset + off;
          unresolved_reloc = FALSE;
          break;
 
@@ -2859,7 +2835,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
 
        case R_390_TLS_LDO64:
-         if (info->shared)
+         if (info->shared || (input_section->flags & SEC_DEBUGGING))
            relocation -= dtpoff_base (info);
          else
            /* When converting LDO to LE, we must negate.  */
@@ -2969,7 +2945,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
         not process them.  */
       if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
-              && h->def_dynamic))
+              && 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'"),
           input_bfd,
@@ -3038,15 +3016,16 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
    dynamic sections here.  */
 
 static bfd_boolean
-elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+                               struct bfd_link_info *info,
+                               struct elf_link_hash_entry *h,
+                               Elf_Internal_Sym *sym)
 {
   struct elf_s390_link_hash_table *htab;
 
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
@@ -3059,9 +3038,9 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
         it up.  */
 
       if (h->dynindx == -1
-         || htab->splt == NULL
-         || htab->sgotplt == NULL
-         || htab->srelplt == NULL)
+         || htab->elf.splt == NULL
+         || htab->elf.sgotplt == NULL
+         || htab->elf.srelplt == NULL)
        abort ();
 
       /* Calc. index no.
@@ -3073,52 +3052,39 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
       got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
 
       /* Fill in the blueprint of a PLT.  */
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0,
-                 htab->splt->contents + h->plt.offset);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1,
-                 htab->splt->contents + h->plt.offset + 4);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2,
-                 htab->splt->contents + h->plt.offset + 8);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD3,
-                 htab->splt->contents + h->plt.offset + 12);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD4,
-                 htab->splt->contents + h->plt.offset + 16);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD5,
-                 htab->splt->contents + h->plt.offset + 20);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD6,
-                 htab->splt->contents + h->plt.offset + 24);
-      bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD7,
-                 htab->splt->contents + h->plt.offset + 28);
+      memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390x_plt_entry,
+             PLT_ENTRY_SIZE);
+
       /* Fixup the relative address to the GOT entry */
       bfd_put_32 (output_bfd,
-                 (htab->sgotplt->output_section->vma +
-                  htab->sgotplt->output_offset + got_offset
-                  - (htab->splt->output_section->vma + h->plt.offset))/2,
-                 htab->splt->contents + h->plt.offset + 2);
+                 (htab->elf.sgotplt->output_section->vma +
+                  htab->elf.sgotplt->output_offset + got_offset
+                  - (htab->elf.splt->output_section->vma + h->plt.offset))/2,
+                 htab->elf.splt->contents + h->plt.offset + 2);
       /* Fixup the relative branch to PLT 0 */
       bfd_put_32 (output_bfd, - (PLT_FIRST_ENTRY_SIZE +
                                 (PLT_ENTRY_SIZE * plt_index) + 22)/2,
-                 htab->splt->contents + h->plt.offset + 24);
-      /* Fixup offset into symbol table */
+                 htab->elf.splt->contents + h->plt.offset + 24);
+      /* Fixup offset into .rela.plt section.  */
       bfd_put_32 (output_bfd, plt_index * sizeof (Elf64_External_Rela),
-                 htab->splt->contents + h->plt.offset + 28);
+                 htab->elf.splt->contents + h->plt.offset + 28);
 
       /* Fill in the entry in the global offset table.
         Points to instruction after GOT offset.  */
       bfd_put_64 (output_bfd,
-                 (htab->splt->output_section->vma
-                  + htab->splt->output_offset
+                 (htab->elf.splt->output_section->vma
+                  + htab->elf.splt->output_offset
                   + h->plt.offset
                   + 14),
-                 htab->sgotplt->contents + got_offset);
+                 htab->elf.sgotplt->contents + got_offset);
 
       /* Fill in the entry in the .rela.plt section.  */
-      rela.r_offset = (htab->sgotplt->output_section->vma
-                      + htab->sgotplt->output_offset
+      rela.r_offset = (htab->elf.sgotplt->output_section->vma
+                      + htab->elf.sgotplt->output_offset
                       + got_offset);
       rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT);
       rela.r_addend = 0;
-      loc = htab->srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
+      loc = htab->elf.srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
 
       if (!h->def_regular)
@@ -3142,11 +3108,11 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
-      if (htab->sgot == NULL || htab->srelgot == NULL)
+      if (htab->elf.sgot == NULL || htab->elf.srelgot == NULL)
        abort ();
 
-      rela.r_offset = (htab->sgot->output_section->vma
-                      + htab->sgot->output_offset
+      rela.r_offset = (htab->elf.sgot->output_section->vma
+                      + htab->elf.sgot->output_offset
                       + (h->got.offset &~ (bfd_vma) 1));
 
       /* If this is a static link, or it is a -Bsymbolic link and the
@@ -3168,13 +3134,13 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
       else
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
-         bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgot->contents + h->got.offset);
+         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;
        }
 
-      loc = htab->srelgot->contents;
-      loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+      loc = htab->elf.srelgot->contents;
+      loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
     }
 
@@ -3233,15 +3199,17 @@ elf_s390_reloc_type_class (rela)
 /* Finish up the dynamic sections.  */
 
 static bfd_boolean
-elf_s390_finish_dynamic_sections (output_bfd, info)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
+elf_s390_finish_dynamic_sections (bfd *output_bfd,
+                                 struct bfd_link_info *info)
 {
   struct elf_s390_link_hash_table *htab;
   bfd *dynobj;
   asection *sdyn;
 
   htab = elf_s390_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
@@ -3249,7 +3217,7 @@ elf_s390_finish_dynamic_sections (output_bfd, info)
     {
       Elf64_External_Dyn *dyncon, *dynconend;
 
-      if (sdyn == NULL || htab->sgot == NULL)
+      if (sdyn == NULL || htab->elf.sgot == NULL)
        abort ();
 
       dyncon = (Elf64_External_Dyn *) sdyn->contents;
@@ -3267,15 +3235,15 @@ elf_s390_finish_dynamic_sections (output_bfd, info)
              continue;
 
            case DT_PLTGOT:
-             dyn.d_un.d_ptr = htab->sgot->output_section->vma;
+             dyn.d_un.d_ptr = htab->elf.sgot->output_section->vma;
              break;
 
            case DT_JMPREL:
-             dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
+             dyn.d_un.d_ptr = htab->elf.srelplt->output_section->vma;
              break;
 
            case DT_PLTRELSZ:
-             s = htab->srelplt->output_section;
+             s = htab->elf.srelplt->output_section;
              dyn.d_un.d_val = s->size;
              break;
 
@@ -3287,7 +3255,7 @@ elf_s390_finish_dynamic_sections (output_bfd, info)
                 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->srelplt->output_section;
+             s = htab->elf.srelplt->output_section;
              dyn.d_un.d_val -= s->size;
              break;
            }
@@ -3296,50 +3264,38 @@ elf_s390_finish_dynamic_sections (output_bfd, info)
        }
 
       /* Fill in the special first entry in the procedure linkage table.  */
-      if (htab->splt && htab->splt->size > 0)
+      if (htab->elf.splt && htab->elf.splt->size > 0)
        {
          /* fill in blueprint for plt 0 entry */
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD0,
-                     htab->splt->contents );
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1,
-                     htab->splt->contents +4 );
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3,
-                     htab->splt->contents +12 );
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4,
-                     htab->splt->contents +16 );
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5,
-                     htab->splt->contents +20 );
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD6,
-                     htab->splt->contents + 24);
-         bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD7,
-                     htab->splt->contents + 28 );
+         memcpy (htab->elf.splt->contents, elf_s390x_first_plt_entry,
+                 PLT_FIRST_ENTRY_SIZE);
          /* Fixup relative address to start of GOT */
          bfd_put_32 (output_bfd,
-                     (htab->sgotplt->output_section->vma +
-                      htab->sgotplt->output_offset
-                      - htab->splt->output_section->vma - 6)/2,
-                     htab->splt->contents + 8);
+                     (htab->elf.sgotplt->output_section->vma +
+                      htab->elf.sgotplt->output_offset
+                      - htab->elf.splt->output_section->vma - 6)/2,
+                     htab->elf.splt->contents + 8);
        }
-      elf_section_data (htab->splt->output_section)
+      elf_section_data (htab->elf.splt->output_section)
        ->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
     }
 
-  if (htab->sgotplt)
+  if (htab->elf.sgotplt)
     {
       /* Fill in the first three entries in the global offset table.  */
-      if (htab->sgotplt->size > 0)
+      if (htab->elf.sgotplt->size > 0)
        {
          bfd_put_64 (output_bfd,
                      (sdyn == NULL ? (bfd_vma) 0
                       : sdyn->output_section->vma + sdyn->output_offset),
-                     htab->sgotplt->contents);
+                     htab->elf.sgotplt->contents);
          /* One entry for shared object struct ptr.  */
-         bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
+         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->sgotplt->contents + 12);
+         bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgotplt->contents + 12);
        }
 
-      elf_section_data (htab->sgot->output_section)
+      elf_section_data (htab->elf.sgot->output_section)
        ->this_hdr.sh_entsize = 8;
     }
   return TRUE;
@@ -3394,6 +3350,7 @@ const struct elf_size_info s390_elf64_size_info =
 #define TARGET_BIG_SYM bfd_elf64_s390_vec
 #define TARGET_BIG_NAME        "elf64-s390"
 #define ELF_ARCH       bfd_arch_s390
+#define ELF_TARGET_ID  S390_ELF_DATA
 #define ELF_MACHINE_CODE EM_S390
 #define ELF_MACHINE_ALT1 EM_S390_OLD
 #define ELF_MAXPAGESIZE 0x1000
This page took 0.042124 seconds and 4 git commands to generate.