Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elf32-s390.c
index 8d654d5486705c5372021493543ae0c416ecc232..b79e283ce3864f448c1ac4962794b1051712f09a 100644 (file)
@@ -1,6 +1,5 @@
 /* IBM S/390-specific support for 32-bit ELF
 /* IBM S/390-specific support for 32-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2000-2021 Free Software Foundation, Inc.
    Contributed by Carl B. Pedersen and Martin Schwidefsky.
 
    This file is part of BFD, the Binary File Descriptor library.
    Contributed by Carl B. Pedersen and Martin Schwidefsky.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -26,6 +25,7 @@
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/s390.h"
 #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 *,
 
 static bfd_reloc_status_type
 s390_tls_reloc (bfd *, arelent *, asymbol *, void *,
@@ -40,134 +40,142 @@ static reloc_howto_type elf_howto_table[] =
 {
   HOWTO (R_390_NONE,           /* type */
         0,                     /* rightshift */
 {
   HOWTO (R_390_NONE,           /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
         0,                     /* bitsize */
         0,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_390_NONE",          /* name */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_390_NONE",          /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
-
-  HOWTO(R_390_8,         0, 0,  8, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_8",        FALSE, 0,0x000000ff, FALSE),
-  HOWTO(R_390_12,        0, 1, 12, FALSE, 0, complain_overflow_dont,
-       bfd_elf_generic_reloc, "R_390_12",       FALSE, 0,0x00000fff, FALSE),
-  HOWTO(R_390_16,        0, 1, 16, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_16",       FALSE, 0,0x0000ffff, FALSE),
-  HOWTO(R_390_32,        0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_32",       FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_PC32,     0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PC32",     FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_GOT12,    0, 1, 12, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOT12",    FALSE, 0,0x00000fff, FALSE),
-  HOWTO(R_390_GOT32,    0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOT32",    FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_PLT32,    0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PLT32",    FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_COPY,      0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_COPY",     FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_GLOB_DAT,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GLOB_DAT", FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_JMP_SLOT,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_JMP_SLOT", FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_RELATIVE,  0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_RELATIVE", FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_GOTOFF32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTOFF32", FALSE, 0,0xffffffff, FALSE),
-  HOWTO(R_390_GOTPC,     0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTPC",    FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_GOT16,     0, 1, 16, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOT16",    FALSE, 0,0x0000ffff, FALSE),
-  HOWTO(R_390_PC16,      0, 1, 16,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PC16",     FALSE, 0,0x0000ffff, TRUE),
-  HOWTO(R_390_PC16DBL,   1, 1, 16,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PC16DBL",  FALSE, 0,0x0000ffff, TRUE),
-  HOWTO(R_390_PLT16DBL,  1, 1, 16,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PLT16DBL", FALSE, 0,0x0000ffff, TRUE),
-  HOWTO(R_390_PC32DBL,  1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PC32DBL",  FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_PLT32DBL,         1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PLT32DBL", FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_GOTPCDBL,  1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTPCDBL", FALSE, 0,0xffffffff, TRUE),
+        false),                /* pcrel_offset */
+
+  HOWTO(R_390_8,        0, 0,  8, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_8",        false, 0,0x000000ff, false),
+  HOWTO(R_390_12,       0, 1, 12, false, 0, complain_overflow_dont,
+       bfd_elf_generic_reloc, "R_390_12",       false, 0,0x00000fff, false),
+  HOWTO(R_390_16,       0, 1, 16, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_16",       false, 0,0x0000ffff, false),
+  HOWTO(R_390_32,       0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_32",       false, 0,0xffffffff, false),
+  HOWTO(R_390_PC32,     0, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PC32",     false, 0,0xffffffff, true),
+  HOWTO(R_390_GOT12,    0, 1, 12, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOT12",    false, 0,0x00000fff, false),
+  HOWTO(R_390_GOT32,    0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOT32",    false, 0,0xffffffff, false),
+  HOWTO(R_390_PLT32,    0, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLT32",    false, 0,0xffffffff, true),
+  HOWTO(R_390_COPY,     0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_COPY",     false, 0,0xffffffff, false),
+  HOWTO(R_390_GLOB_DAT,         0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GLOB_DAT", false, 0,0xffffffff, false),
+  HOWTO(R_390_JMP_SLOT,         0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_JMP_SLOT", false, 0,0xffffffff, false),
+  HOWTO(R_390_RELATIVE,         0, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_RELATIVE", false, 0,0xffffffff, false),
+  HOWTO(R_390_GOTOFF32,         0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTOFF32", false, 0,0xffffffff, false),
+  HOWTO(R_390_GOTPC,    0, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTPC",    false, 0,0xffffffff, true),
+  HOWTO(R_390_GOT16,    0, 1, 16, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOT16",    false, 0,0x0000ffff, false),
+  HOWTO(R_390_PC16,     0, 1, 16,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PC16",     false, 0,0x0000ffff, true),
+  HOWTO(R_390_PC16DBL,  1, 1, 16,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PC16DBL",  false, 0,0x0000ffff, true),
+  HOWTO(R_390_PLT16DBL,         1, 1, 16,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLT16DBL", false, 0,0x0000ffff, true),
+  HOWTO(R_390_PC32DBL,  1, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PC32DBL",  false, 0,0xffffffff, true),
+  HOWTO(R_390_PLT32DBL,         1, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLT32DBL", false, 0,0xffffffff, true),
+  HOWTO(R_390_GOTPCDBL,         1, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTPCDBL", false, 0,0xffffffff, true),
   EMPTY_HOWTO (R_390_64),      /* Empty entry for R_390_64.  */
   EMPTY_HOWTO (R_390_PC64),    /* Empty entry for R_390_PC64.  */
   EMPTY_HOWTO (R_390_GOT64),   /* Empty entry for R_390_GOT64.  */
   EMPTY_HOWTO (R_390_PLT64),   /* Empty entry for R_390_PLT64.  */
   EMPTY_HOWTO (R_390_64),      /* Empty entry for R_390_64.  */
   EMPTY_HOWTO (R_390_PC64),    /* Empty entry for R_390_PC64.  */
   EMPTY_HOWTO (R_390_GOT64),   /* Empty entry for R_390_GOT64.  */
   EMPTY_HOWTO (R_390_PLT64),   /* Empty entry for R_390_PLT64.  */
-  HOWTO(R_390_GOTENT,   1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTENT",   FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_GOTOFF16,  0, 1, 16, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTOFF16", FALSE, 0,0x0000ffff, FALSE),
+  HOWTO(R_390_GOTENT,   1, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTENT",   false, 0,0xffffffff, true),
+  HOWTO(R_390_GOTOFF16,         0, 1, 16, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTOFF16", false, 0,0x0000ffff, false),
   EMPTY_HOWTO (R_390_GOTOFF64),        /* Empty entry for R_390_GOTOFF64.  */
   EMPTY_HOWTO (R_390_GOTOFF64),        /* Empty entry for R_390_GOTOFF64.  */
-  HOWTO(R_390_GOTPLT12,  0, 1, 12, FALSE, 0, complain_overflow_dont,
-       bfd_elf_generic_reloc, "R_390_GOTPLT12", FALSE, 0,0x00000fff, FALSE),
-  HOWTO(R_390_GOTPLT16,  0, 1, 16, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTPLT16", FALSE, 0,0x0000ffff, FALSE),
-  HOWTO(R_390_GOTPLT32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTPLT32", FALSE, 0,0xffffffff, FALSE),
+  HOWTO(R_390_GOTPLT12,         0, 1, 12, false, 0, complain_overflow_dont,
+       bfd_elf_generic_reloc, "R_390_GOTPLT12", false, 0,0x00000fff, false),
+  HOWTO(R_390_GOTPLT16,         0, 1, 16, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTPLT16", false, 0,0x0000ffff, false),
+  HOWTO(R_390_GOTPLT32,         0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTPLT32", false, 0,0xffffffff, false),
   EMPTY_HOWTO (R_390_GOTPLT64),        /* Empty entry for R_390_GOTPLT64.  */
   EMPTY_HOWTO (R_390_GOTPLT64),        /* Empty entry for R_390_GOTPLT64.  */
-  HOWTO(R_390_GOTPLTENT, 1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_GOTPLTENT",FALSE, 0,0xffffffff, TRUE),
-  HOWTO(R_390_PLTOFF16,  0, 1, 16, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PLTOFF16", FALSE, 0,0x0000ffff, FALSE),
-  HOWTO(R_390_PLTOFF32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_PLTOFF32", FALSE, 0,0xffffffff, FALSE),
+  HOWTO(R_390_GOTPLTENT, 1, 2, 32,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_GOTPLTENT",false, 0,0xffffffff, true),
+  HOWTO(R_390_PLTOFF16,         0, 1, 16, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLTOFF16", false, 0,0x0000ffff, false),
+  HOWTO(R_390_PLTOFF32,         0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLTOFF32", false, 0,0xffffffff, false),
   EMPTY_HOWTO (R_390_PLTOFF64),        /* Empty entry for R_390_PLTOFF64.  */
   EMPTY_HOWTO (R_390_PLTOFF64),        /* Empty entry for R_390_PLTOFF64.  */
-  HOWTO(R_390_TLS_LOAD, 0, 0, 0, FALSE, 0, complain_overflow_dont,
-       s390_tls_reloc, "R_390_TLS_LOAD", FALSE, 0, 0, FALSE),
-  HOWTO(R_390_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
-       s390_tls_reloc, "R_390_TLS_GDCALL", FALSE, 0, 0, FALSE),
-  HOWTO(R_390_TLS_LDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
-       s390_tls_reloc, "R_390_TLS_LDCALL", FALSE, 0, 0, FALSE),
-  HOWTO(R_390_TLS_GD32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_GD32", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_LOAD, 0, 0, 0, false, 0, complain_overflow_dont,
+       s390_tls_reloc, "R_390_TLS_LOAD", false, 0, 0, false),
+  HOWTO(R_390_TLS_GDCALL, 0, 0, 0, false, 0, complain_overflow_dont,
+       s390_tls_reloc, "R_390_TLS_GDCALL", false, 0, 0, false),
+  HOWTO(R_390_TLS_LDCALL, 0, 0, 0, false, 0, complain_overflow_dont,
+       s390_tls_reloc, "R_390_TLS_LDCALL", false, 0, 0, false),
+  HOWTO(R_390_TLS_GD32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_GD32", false, 0, 0xffffffff, false),
   EMPTY_HOWTO (R_390_TLS_GD64),        /* Empty entry for R_390_TLS_GD64.  */
   EMPTY_HOWTO (R_390_TLS_GD64),        /* Empty entry for R_390_TLS_GD64.  */
-  HOWTO(R_390_TLS_GOTIE12, 0, 1, 12, FALSE, 0, complain_overflow_dont,
-       bfd_elf_generic_reloc, "R_390_TLS_GOTIE12", FALSE, 0, 0x00000fff, FALSE),
-  HOWTO(R_390_TLS_GOTIE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_GOTIE32", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_GOTIE12, 0, 1, 12, false, 0, complain_overflow_dont,
+       bfd_elf_generic_reloc, "R_390_TLS_GOTIE12", false, 0, 0x00000fff, false),
+  HOWTO(R_390_TLS_GOTIE32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_GOTIE32", false, 0, 0xffffffff, false),
   EMPTY_HOWTO (R_390_TLS_GOTIE64),     /* Empty entry for R_390_TLS_GOTIE64.  */
   EMPTY_HOWTO (R_390_TLS_GOTIE64),     /* Empty entry for R_390_TLS_GOTIE64.  */
-  HOWTO(R_390_TLS_LDM32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_LDM32", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_LDM32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_LDM32", false, 0, 0xffffffff, false),
   EMPTY_HOWTO (R_390_TLS_LDM64),       /* Empty entry for R_390_TLS_LDM64.  */
   EMPTY_HOWTO (R_390_TLS_LDM64),       /* Empty entry for R_390_TLS_LDM64.  */
-  HOWTO(R_390_TLS_IE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_IE32", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_IE32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_IE32", false, 0, 0xffffffff, false),
   EMPTY_HOWTO (R_390_TLS_IE64),        /* Empty entry for R_390_TLS_IE64.  */
   EMPTY_HOWTO (R_390_TLS_IE64),        /* Empty entry for R_390_TLS_IE64.  */
-  HOWTO(R_390_TLS_IEENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_IEENT", FALSE, 0, 0xffffffff, TRUE),
-  HOWTO(R_390_TLS_LE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_LE32", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_IEENT, 1, 2, 32, true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_IEENT", false, 0, 0xffffffff, true),
+  HOWTO(R_390_TLS_LE32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_LE32", false, 0, 0xffffffff, false),
   EMPTY_HOWTO (R_390_TLS_LE64),        /* Empty entry for R_390_TLS_LE64.  */
   EMPTY_HOWTO (R_390_TLS_LE64),        /* Empty entry for R_390_TLS_LE64.  */
-  HOWTO(R_390_TLS_LDO32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_LDO32", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_LDO32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_LDO32", false, 0, 0xffffffff, false),
   EMPTY_HOWTO (R_390_TLS_LDO64),       /* Empty entry for R_390_TLS_LDO64.  */
   EMPTY_HOWTO (R_390_TLS_LDO64),       /* Empty entry for R_390_TLS_LDO64.  */
-  HOWTO(R_390_TLS_DTPMOD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_DTPMOD", FALSE, 0, 0xffffffff, FALSE),
-  HOWTO(R_390_TLS_DTPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_DTPOFF", FALSE, 0, 0xffffffff, FALSE),
-  HOWTO(R_390_TLS_TPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_TLS_TPOFF", FALSE, 0, 0xffffffff, FALSE),
-  HOWTO(R_390_20,        0, 2, 20, FALSE, 8, complain_overflow_dont,
-       s390_elf_ldisp_reloc, "R_390_20",      FALSE, 0,0x0fffff00, FALSE),
-  HOWTO(R_390_GOT20,    0, 2, 20, FALSE, 8, complain_overflow_dont,
-       s390_elf_ldisp_reloc, "R_390_GOT20",   FALSE, 0,0x0fffff00, FALSE),
-  HOWTO(R_390_GOTPLT20,  0, 2, 20, FALSE, 8, complain_overflow_dont,
-       s390_elf_ldisp_reloc, "R_390_GOTPLT20", FALSE, 0,0x0fffff00, FALSE),
-  HOWTO(R_390_TLS_GOTIE20, 0, 2, 20, FALSE, 8, complain_overflow_dont,
-       s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE),
-  HOWTO(R_390_IRELATIVE, 0, 2, 32, TRUE, 0, complain_overflow_bitfield,
-       bfd_elf_generic_reloc, "R_390_IRELATIVE", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_DTPMOD, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_DTPMOD", false, 0, 0xffffffff, false),
+  HOWTO(R_390_TLS_DTPOFF, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_DTPOFF", false, 0, 0xffffffff, false),
+  HOWTO(R_390_TLS_TPOFF, 0, 2, 32, false, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_TLS_TPOFF", false, 0, 0xffffffff, false),
+  HOWTO(R_390_20,       0, 2, 20, false, 8, complain_overflow_dont,
+       s390_elf_ldisp_reloc, "R_390_20",      false, 0,0x0fffff00, false),
+  HOWTO(R_390_GOT20,    0, 2, 20, false, 8, complain_overflow_dont,
+       s390_elf_ldisp_reloc, "R_390_GOT20",   false, 0,0x0fffff00, false),
+  HOWTO(R_390_GOTPLT20,         0, 2, 20, false, 8, complain_overflow_dont,
+       s390_elf_ldisp_reloc, "R_390_GOTPLT20", false, 0,0x0fffff00, false),
+  HOWTO(R_390_TLS_GOTIE20, 0, 2, 20, false, 8, complain_overflow_dont,
+       s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", false, 0,0x0fffff00, false),
+  HOWTO(R_390_IRELATIVE, 0, 2, 32, true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_IRELATIVE", false, 0, 0xffffffff, false),
+  HOWTO(R_390_PC12DBL,  1, 1, 12,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PC12DBL",  false, 0,0x00000fff, true),
+  HOWTO(R_390_PLT12DBL,         1, 1, 12,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLT12DBL", false, 0,0x00000fff, true),
+  HOWTO(R_390_PC24DBL,  1, 2, 24,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PC24DBL",  false, 0,0x00ffffff, true),
+  HOWTO(R_390_PLT24DBL,         1, 2, 24,  true, 0, complain_overflow_bitfield,
+       bfd_elf_generic_reloc, "R_390_PLT24DBL", false, 0,0x00ffffff, true),
 };
 
 /* GNU extension to record C++ vtable hierarchy.  */
 static reloc_howto_type elf32_s390_vtinherit_howto =
 };
 
 /* GNU extension to record C++ vtable hierarchy.  */
 static reloc_howto_type elf32_s390_vtinherit_howto =
-  HOWTO (R_390_GNU_VTINHERIT, 0,2,0,FALSE,0,complain_overflow_dont, NULL, "R_390_GNU_VTINHERIT", FALSE,0, 0, FALSE);
+  HOWTO (R_390_GNU_VTINHERIT, 0,2,0,false,0,complain_overflow_dont, NULL, "R_390_GNU_VTINHERIT", false,0, 0, false);
 static reloc_howto_type elf32_s390_vtentry_howto =
 static reloc_howto_type elf32_s390_vtentry_howto =
-  HOWTO (R_390_GNU_VTENTRY, 0,2,0,FALSE,0,complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_390_GNU_VTENTRY", FALSE,0,0, FALSE);
+  HOWTO (R_390_GNU_VTENTRY, 0,2,0,false,0,complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_390_GNU_VTENTRY", false,0,0, false);
 
 static reloc_howto_type *
 elf_s390_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
 static reloc_howto_type *
 elf_s390_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
@@ -211,10 +219,18 @@ elf_s390_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       return &elf_howto_table[(int) R_390_GOT16];
     case BFD_RELOC_16_PCREL:
       return &elf_howto_table[(int) R_390_PC16];
       return &elf_howto_table[(int) R_390_GOT16];
     case BFD_RELOC_16_PCREL:
       return &elf_howto_table[(int) R_390_PC16];
+    case BFD_RELOC_390_PC12DBL:
+      return &elf_howto_table[(int) R_390_PC12DBL];
+    case BFD_RELOC_390_PLT12DBL:
+      return &elf_howto_table[(int) R_390_PLT12DBL];
     case BFD_RELOC_390_PC16DBL:
       return &elf_howto_table[(int) R_390_PC16DBL];
     case BFD_RELOC_390_PLT16DBL:
       return &elf_howto_table[(int) R_390_PLT16DBL];
     case BFD_RELOC_390_PC16DBL:
       return &elf_howto_table[(int) R_390_PC16DBL];
     case BFD_RELOC_390_PLT16DBL:
       return &elf_howto_table[(int) R_390_PLT16DBL];
+    case BFD_RELOC_390_PC24DBL:
+      return &elf_howto_table[(int) R_390_PC24DBL];
+    case BFD_RELOC_390_PLT24DBL:
+      return &elf_howto_table[(int) R_390_PLT24DBL];
     case BFD_RELOC_390_PC32DBL:
       return &elf_howto_table[(int) R_390_PC32DBL];
     case BFD_RELOC_390_PLT32DBL:
     case BFD_RELOC_390_PC32DBL:
       return &elf_howto_table[(int) R_390_PC32DBL];
     case BFD_RELOC_390_PLT32DBL:
@@ -307,12 +323,13 @@ elf_s390_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 /* We need to use ELF32_R_TYPE so we have our own copy of this function,
    and elf32-s390.c has its own copy.  */
 
 /* We need to use ELF32_R_TYPE so we have our own copy of this function,
    and elf32-s390.c has its own copy.  */
 
-static void
-elf_s390_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+static bool
+elf_s390_info_to_howto (bfd *abfd,
                        arelent *cache_ptr,
                        Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE(dst->r_info);
                        arelent *cache_ptr,
                        Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE(dst->r_info);
+
   switch (r_type)
     {
     case R_390_GNU_VTINHERIT:
   switch (r_type)
     {
     case R_390_GNU_VTINHERIT:
@@ -326,12 +343,16 @@ elf_s390_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
     default:
       if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
        {
     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);
-         r_type = R_390_NONE;
+         /* xgettext:c-format */
+         _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                             abfd, r_type);
+         bfd_set_error (bfd_error_bad_value);
+         return false;
        }
       cache_ptr->howto = &elf_howto_table[r_type];
     }
        }
       cache_ptr->howto = &elf_howto_table[r_type];
     }
+
+  return true;
 }
 
 /* A relocation function which doesn't do anything.  */
 }
 
 /* A relocation function which doesn't do anything.  */
@@ -362,7 +383,7 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   reloc_howto_type *howto = reloc_entry->howto;
   bfd_vma relocation;
   bfd_vma insn;
   reloc_howto_type *howto = reloc_entry->howto;
   bfd_vma relocation;
   bfd_vma insn;
-  
+
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && (! howto->partial_inplace
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && (! howto->partial_inplace
@@ -371,13 +392,13 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
-  
+
   if (output_bfd != NULL)
     return bfd_reloc_continue;
   if (output_bfd != NULL)
     return bfd_reloc_continue;
-  
+
   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
-  
+
   relocation = (symbol->value
                + symbol->section->output_section->vma
                + symbol->section->output_offset);
   relocation = (symbol->value
                + symbol->section->output_section->vma
                + symbol->section->output_offset);
@@ -388,11 +409,11 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                     + input_section->output_offset);
       relocation -= reloc_entry->address;
     }
                     + input_section->output_offset);
       relocation -= reloc_entry->address;
     }
-  
+
   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
   insn |= (relocation & 0xfff) << 16 | (relocation & 0xff000) >> 4;
   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
   insn |= (relocation & 0xfff) << 16 | (relocation & 0xff000) >> 4;
   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
-  
+
   if ((bfd_signed_vma) relocation < - 0x80000
       || (bfd_signed_vma) relocation > 0x7ffff)
     return bfd_reloc_overflow;
   if ((bfd_signed_vma) relocation < - 0x80000
       || (bfd_signed_vma) relocation > 0x7ffff)
     return bfd_reloc_overflow;
@@ -400,11 +421,11 @@ s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
     return bfd_reloc_ok;
 }
 
     return bfd_reloc_ok;
 }
 
-static bfd_boolean
+static bool
 elf_s390_is_local_label_name (bfd *abfd, const char *name)
 {
   if (name[0] == '.' && (name[1] == 'X' || name[1] == 'L'))
 elf_s390_is_local_label_name (bfd *abfd, const char *name)
 {
   if (name[0] == '.' && (name[1] == 'X' || name[1] == 'L'))
-    return TRUE;
+    return true;
 
   return _bfd_elf_is_local_label_name (abfd, name);
 }
 
   return _bfd_elf_is_local_label_name (abfd, name);
 }
@@ -461,100 +482,100 @@ elf_s390_is_local_label_name (bfd *abfd, const char *name)
    and insert the address in the GOT.
 
   Note: 390 can only address +- 64 K relative.
    and insert the address in the GOT.
 
   Note: 390 can only address +- 64 K relative.
-        We check if offset > 65536, then make a relative branch -64xxx
-        back to a previous defined branch
-
-PLT1: BASR 1,0         # 2 bytes
-      L    1,22(1)     # 4 bytes  Load offset in GOT in r 1
-      L    1,(1,12)    # 4 bytes  Load address from GOT in r1
-      BCR  15,1        # 2 bytes  Jump to address
-RET1: BASR 1,0         # 2 bytes  Return from GOT 1st time
-      L    1,14(1)     # 4 bytes  Load offset in symol table in r1
+       We check if offset > 65536, then make a relative branch -64xxx
+       back to a previous defined branch
+
+PLT1: BASR 1,0        # 2 bytes
+      L           1,22(1)     # 4 bytes  Load offset in GOT in r 1
+      L           1,(1,12)    # 4 bytes  Load address from GOT in r1
+      BCR  15,1               # 2 bytes  Jump to address
+RET1: BASR 1,0        # 2 bytes  Return from GOT 1st time
+      L           1,14(1)     # 4 bytes  Load offset in symol table in r1
       BRC  15,-x       # 4 bytes  Jump to start of PLT
       BRC  15,-x       # 4 bytes  Jump to start of PLT
-      .word 0          # 2 bytes filler
-      .long ?          # 4 bytes  offset in GOT
-      .long ?          # 4 bytes  offset into rela.plt
+      .word 0         # 2 bytes filler
+      .long ?         # 4 bytes  offset in GOT
+      .long ?         # 4 bytes  offset into rela.plt
 
   This was the general case. There are two additional, optimizes PLT
   definitions. One for GOT offsets < 4096 and one for GOT offsets < 32768.
   First the one for GOT offsets < 4096:
 
 
   This was the general case. There are two additional, optimizes PLT
   definitions. One for GOT offsets < 4096 and one for GOT offsets < 32768.
   First the one for GOT offsets < 4096:
 
-PLT1: L    1,<offset>(12) # 4 bytes  Load address from GOT in R1
-      BCR  15,1           # 2 bytes  Jump to address
-      .word 0,0,0         # 6 bytes  filler
-RET1: BASR 1,0            # 2 bytes  Return from GOT 1st time
-      L    1,14(1)        # 4 bytes  Load offset in rela.plt in r1
-      BRC  15,-x          # 4 bytes  Jump to start of PLT
-      .word 0,0,0         # 6 bytes  filler
-      .long ?             # 4 bytes  offset into rela.plt
+PLT1: L           1,<offset>(12) # 4 bytes  Load address from GOT in R1
+      BCR  15,1                  # 2 bytes  Jump to address
+      .word 0,0,0        # 6 bytes  filler
+RET1: BASR 1,0           # 2 bytes  Return from GOT 1st time
+      L           1,14(1)        # 4 bytes  Load offset in rela.plt in r1
+      BRC  15,-x         # 4 bytes  Jump to start of PLT
+      .word 0,0,0        # 6 bytes  filler
+      .long ?            # 4 bytes  offset into rela.plt
 
   Second the one for GOT offsets < 32768:
 
 
   Second the one for GOT offsets < 32768:
 
-PLT1: LHI  1,<offset>     # 4 bytes  Load offset in GOT to r1
-      L    1,(1,12)       # 4 bytes  Load address from GOT to r1
-      BCR  15,1           # 2 bytes  Jump to address
-      .word 0             # 2 bytes  filler
-RET1: BASR 1,0            # 2 bytes  Return from GOT 1st time
-      L    1,14(1)        # 4 bytes  Load offset in rela.plt in r1
-      BRC  15,-x          # 4 bytes  Jump to start of PLT
-      .word 0,0,0         # 6 bytes  filler
-      .long ?             # 4 bytes  offset into rela.plt
+PLT1: LHI  1,<offset>    # 4 bytes  Load offset in GOT to r1
+      L           1,(1,12)       # 4 bytes  Load address from GOT to r1
+      BCR  15,1                  # 2 bytes  Jump to address
+      .word 0            # 2 bytes  filler
+RET1: BASR 1,0           # 2 bytes  Return from GOT 1st time
+      L           1,14(1)        # 4 bytes  Load offset in rela.plt in r1
+      BRC  15,-x         # 4 bytes  Jump to start of PLT
+      .word 0,0,0        # 6 bytes  filler
+      .long ?            # 4 bytes  offset into rela.plt
 
 Total = 32 bytes per PLT entry
 
    The code for static build PLT entries looks like this:
 
 
 Total = 32 bytes per PLT entry
 
    The code for static build PLT entries looks like this:
 
-PLT1: BASR 1,0         # 2 bytes
-      L    1,22(1)     # 4 bytes  Load address of GOT entry
-      L    1,0(0,1)    # 4 bytes  Load address from GOT in r1
-      BCR  15,1        # 2 bytes  Jump to address
-RET1: BASR 1,0         # 2 bytes  Return from GOT 1st time
-      L    1,14(1)     # 4 bytes  Load offset in symbol table in r1
+PLT1: BASR 1,0        # 2 bytes
+      L           1,22(1)     # 4 bytes  Load address of GOT entry
+      L           1,0(0,1)    # 4 bytes  Load address from GOT in r1
+      BCR  15,1               # 2 bytes  Jump to address
+RET1: BASR 1,0        # 2 bytes  Return from GOT 1st time
+      L           1,14(1)     # 4 bytes  Load offset in symbol table in r1
       BRC  15,-x       # 4 bytes  Jump to start of PLT
       BRC  15,-x       # 4 bytes  Jump to start of PLT
-      .word 0          # 2 bytes  filler
-      .long ?          # 4 bytes  address of GOT entry
-      .long ?          # 4 bytes  offset into rela.plt  */
+      .word 0         # 2 bytes  filler
+      .long ?         # 4 bytes  address of GOT entry
+      .long ?         # 4 bytes  offset into rela.plt  */
 
 static const bfd_byte elf_s390_plt_entry[PLT_ENTRY_SIZE] =
   {
 
 static const bfd_byte elf_s390_plt_entry[PLT_ENTRY_SIZE] =
   {
-    0x0d, 0x10,                             /* basr    %r1,%r0     */
-    0x58, 0x10, 0x10, 0x16,                 /* l       %r1,22(%r1) */
-    0x58, 0x10, 0x10, 0x00,                 /* l       %r1,0(%r1)  */
-    0x07, 0xf1,                             /* br      %r1         */
-    0x0d, 0x10,                             /* basr    %r1,%r0     */
-    0x58, 0x10, 0x10, 0x0e,                 /* l       %r1,14(%r1) */
-    0xa7, 0xf4, 0x00, 0x00,                 /* j       first plt   */
-    0x00, 0x00,                             /* padding             */
-    0x00, 0x00, 0x00, 0x00,                 /* GOT offset          */
-    0x00, 0x00, 0x00, 0x00                  /* rela.plt offset     */
+    0x0d, 0x10,                                    /* basr    %r1,%r0     */
+    0x58, 0x10, 0x10, 0x16,                /* l       %r1,22(%r1) */
+    0x58, 0x10, 0x10, 0x00,                /* l       %r1,0(%r1)  */
+    0x07, 0xf1,                                    /* br      %r1         */
+    0x0d, 0x10,                                    /* basr    %r1,%r0     */
+    0x58, 0x10, 0x10, 0x0e,                /* l       %r1,14(%r1) */
+    0xa7, 0xf4, 0x00, 0x00,                /* j       first plt   */
+    0x00, 0x00,                                    /* padding             */
+    0x00, 0x00, 0x00, 0x00,                /* GOT offset          */
+    0x00, 0x00, 0x00, 0x00                 /* rela.plt offset     */
   };
 
 /* Generic PLT pic entry.  */
 static const bfd_byte elf_s390_plt_pic_entry[PLT_ENTRY_SIZE] =
   {
   };
 
 /* Generic PLT pic entry.  */
 static const bfd_byte elf_s390_plt_pic_entry[PLT_ENTRY_SIZE] =
   {
-    0x0d, 0x10,                             /* basr    %r1,%r0         */
-    0x58, 0x10, 0x10, 0x16,                 /* l       %r1,22(%r1)     */
-    0x58, 0x11, 0xc0, 0x00,                 /* l       %r1,0(%r1,%r12) */
-    0x07, 0xf1,                             /* br      %r1             */
-    0x0d, 0x10,                             /* basr    %r1,%r0         */
-    0x58, 0x10, 0x10, 0x0e,                 /* l       %r1,14(%r1)     */
-    0xa7, 0xf4, 0x00, 0x00,                 /* j       first plt       */
-    0x00, 0x00,                             /* padding                 */
-    0x00, 0x00, 0x00, 0x00,                 /* GOT offset              */
-    0x00, 0x00, 0x00, 0x00                  /* rela.plt offset         */
+    0x0d, 0x10,                                    /* basr    %r1,%r0         */
+    0x58, 0x10, 0x10, 0x16,                /* l       %r1,22(%r1)     */
+    0x58, 0x11, 0xc0, 0x00,                /* l       %r1,0(%r1,%r12) */
+    0x07, 0xf1,                                    /* br      %r1             */
+    0x0d, 0x10,                                    /* basr    %r1,%r0         */
+    0x58, 0x10, 0x10, 0x0e,                /* l       %r1,14(%r1)     */
+    0xa7, 0xf4, 0x00, 0x00,                /* j       first plt       */
+    0x00, 0x00,                                    /* padding                 */
+    0x00, 0x00, 0x00, 0x00,                /* GOT offset              */
+    0x00, 0x00, 0x00, 0x00                 /* rela.plt offset         */
   };
 
 /* Optimized PLT pic entry for GOT offset < 4k.  xx will be replaced
    when generating the PLT slot with the GOT offset.  */
 static const bfd_byte elf_s390_plt_pic12_entry[PLT_ENTRY_SIZE] =
   {
   };
 
 /* Optimized PLT pic entry for GOT offset < 4k.  xx will be replaced
    when generating the PLT slot with the GOT offset.  */
 static const bfd_byte elf_s390_plt_pic12_entry[PLT_ENTRY_SIZE] =
   {
-    0x58, 0x10, 0xc0, 0x00,                 /* l       %r1,xx(%r12) */
-    0x07, 0xf1,                             /* br      %r1          */
-    0x00, 0x00, 0x00, 0x00,                 /* padding              */
+    0x58, 0x10, 0xc0, 0x00,                /* l       %r1,xx(%r12) */
+    0x07, 0xf1,                                    /* br      %r1          */
+    0x00, 0x00, 0x00, 0x00,                /* padding              */
     0x00, 0x00,
     0x00, 0x00,
-    0x0d, 0x10,                             /* basr    %r1,%r0      */
-    0x58, 0x10, 0x10, 0x0e,                 /* l       %r1,14(%r1)  */
-    0xa7, 0xf4, 0x00, 0x00,                 /* j       first plt    */
+    0x0d, 0x10,                                    /* basr    %r1,%r0      */
+    0x58, 0x10, 0x10, 0x0e,                /* l       %r1,14(%r1)  */
+    0xa7, 0xf4, 0x00, 0x00,                /* j       first plt    */
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00
   };
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00
   };
@@ -563,13 +584,13 @@ static const bfd_byte elf_s390_plt_pic12_entry[PLT_ENTRY_SIZE] =
    when generating the PLT slot with the GOT offset.  */
 static const bfd_byte elf_s390_plt_pic16_entry[PLT_ENTRY_SIZE] =
   {
    when generating the PLT slot with the GOT offset.  */
 static const bfd_byte elf_s390_plt_pic16_entry[PLT_ENTRY_SIZE] =
   {
-    0xa7, 0x18, 0x00, 0x00,                 /* lhi     %r1,xx          */
-    0x58, 0x11, 0xc0, 0x00,                 /* l       %r1,0(%r1,%r12) */
-    0x07, 0xf1,                             /* br      %r1             */
+    0xa7, 0x18, 0x00, 0x00,                /* lhi     %r1,xx          */
+    0x58, 0x11, 0xc0, 0x00,                /* l       %r1,0(%r1,%r12) */
+    0x07, 0xf1,                                    /* br      %r1             */
     0x00, 0x00,
     0x00, 0x00,
-    0x0d, 0x10,                             /* basr    %r1,%r0         */
-    0x58, 0x10, 0x10, 0x0e,                 /* l       %r1,14(%r1)     */
-    0xa7, 0xf4, 0x00, 0x00,                 /* j       first plt       */
+    0x0d, 0x10,                                    /* basr    %r1,%r0         */
+    0x58, 0x10, 0x10, 0x0e,                /* l       %r1,14(%r1)     */
+    0xa7, 0xf4, 0x00, 0x00,                /* j       first plt       */
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00
@@ -582,32 +603,32 @@ static const bfd_byte elf_s390_plt_pic16_entry[PLT_ENTRY_SIZE] =
 /* The first entry in the PLT for PIC code:
 
 PLT0:
 /* The first entry in the PLT for PIC code:
 
 PLT0:
-   ST   1,28(15)  # R1 has offset into rela.plt
-   L    1,4(12)   # Get loader ino(object struct address)
-   ST   1,24(15)  # Store address
-   L    1,8(12)   # Entry address of loader in R1
-   BR   1         # Jump to loader
+   ST  1,28(15)  # R1 has offset into rela.plt
+   L   1,4(12)   # Get loader ino(object struct address)
+   ST  1,24(15)  # Store address
+   L   1,8(12)   # Entry address of loader in R1
+   BR  1         # Jump to loader
 
    The first entry in the PLT for static code:
 
 PLT0:
 
    The first entry in the PLT for static code:
 
 PLT0:
-   ST   1,28(15)      # R1 has offset into rela.plt
+   ST  1,28(15)      # R1 has offset into rela.plt
    BASR 1,0
    BASR 1,0
-   L    1,18(0,1)     # Get address of GOT
-   MVC  24(4,15),4(1) # Move loader ino to stack
-   L    1,8(1)        # Get address of loader
-   BR   1             # Jump to loader
-   .word 0            # filler
-   .long got          # address of GOT  */
+   L   1,18(0,1)     # Get address of GOT
+   MVC 24(4,15),4(1) # Move loader ino to stack
+   L   1,8(1)        # Get address of loader
+   BR  1             # Jump to loader
+   .word 0           # filler
+   .long got         # address of GOT  */
 
 static const bfd_byte elf_s390_plt_first_entry[PLT_FIRST_ENTRY_SIZE] =
   {
 
 static const bfd_byte elf_s390_plt_first_entry[PLT_FIRST_ENTRY_SIZE] =
   {
-    0x50, 0x10, 0xf0, 0x1c,                   /* st      %r1,28(%r15)      */
-    0x0d, 0x10,                               /* basr    %r1,%r0           */
-    0x58, 0x10, 0x10, 0x12,                   /* l       %r1,18(%r1)       */
-    0xd2, 0x03, 0xf0, 0x18, 0x10, 0x04,       /* mvc     24(4,%r15),4(%r1) */
-    0x58, 0x10, 0x10, 0x08,                   /* l       %r1,8(%r1)        */
-    0x07, 0xf1,                               /* br      %r1               */
+    0x50, 0x10, 0xf0, 0x1c,                  /* st      %r1,28(%r15)      */
+    0x0d, 0x10,                                      /* basr    %r1,%r0           */
+    0x58, 0x10, 0x10, 0x12,                  /* l       %r1,18(%r1)       */
+    0xd2, 0x03, 0xf0, 0x18, 0x10, 0x04,              /* mvc     24(4,%r15),4(%r1) */
+    0x58, 0x10, 0x10, 0x08,                  /* l       %r1,8(%r1)        */
+    0x07, 0xf1,                                      /* br      %r1               */
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00
@@ -615,11 +636,11 @@ static const bfd_byte elf_s390_plt_first_entry[PLT_FIRST_ENTRY_SIZE] =
 
 static const bfd_byte elf_s390_plt_pic_first_entry[PLT_FIRST_ENTRY_SIZE] =
   {
 
 static const bfd_byte elf_s390_plt_pic_first_entry[PLT_FIRST_ENTRY_SIZE] =
   {
-    0x50, 0x10, 0xf0, 0x1c,                     /* st      %r1,28(%r15)  */
-    0x58, 0x10, 0xc0, 0x04,                     /* l       %r1,4(%r12)   */
-    0x50, 0x10, 0xf0, 0x18,                     /* st      %r1,24(%r15)  */
-    0x58, 0x10, 0xc0, 0x08,                     /* l       %r1,8(%r12)   */
-    0x07, 0xf1,                                 /* br      %r1           */
+    0x50, 0x10, 0xf0, 0x1c,                    /* st      %r1,28(%r15)  */
+    0x58, 0x10, 0xc0, 0x04,                    /* l       %r1,4(%r12)   */
+    0x50, 0x10, 0xf0, 0x18,                    /* st      %r1,24(%r15)  */
+    0x58, 0x10, 0xc0, 0x08,                    /* l       %r1,8(%r12)   */
+    0x07, 0xf1,                                        /* br      %r1           */
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00,
@@ -633,9 +654,6 @@ struct elf_s390_link_hash_entry
 {
   struct elf_link_hash_entry elf;
 
 {
   struct elf_link_hash_entry elf;
 
-  /* Track dynamic relocs copied for this symbol.  */
-  struct elf_dyn_relocs *dyn_relocs;
-
   /* Number of GOTPLT references for a function.  */
   bfd_signed_vma gotplt_refcount;
 
   /* Number of GOTPLT references for a function.  */
   bfd_signed_vma gotplt_refcount;
 
@@ -700,14 +718,14 @@ struct elf_s390_obj_tdata
    && elf_tdata (bfd) != NULL \
    && elf_object_id (bfd) == S390_ELF_DATA)
 
    && elf_tdata (bfd) != NULL \
    && elf_object_id (bfd) == S390_ELF_DATA)
 
-static bfd_boolean
+static bool
 elf_s390_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd, sizeof (struct elf_s390_obj_tdata),
                                  S390_ELF_DATA);
 }
 
 elf_s390_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd, sizeof (struct elf_s390_obj_tdata),
                                  S390_ELF_DATA);
 }
 
-static bfd_boolean
+static bool
 elf_s390_object_p (bfd *abfd)
 {
   /* Set the right machine number for an s390 elf32 file.  */
 elf_s390_object_p (bfd *abfd)
 {
   /* Set the right machine number for an s390 elf32 file.  */
@@ -721,8 +739,6 @@ struct elf_s390_link_hash_table
   struct elf_link_hash_table elf;
 
   /* Short-cuts to get to dynamic linker sections.  */
   struct elf_link_hash_table elf;
 
   /* Short-cuts to get to dynamic linker sections.  */
-  asection *sdynbss;
-  asection *srelbss;
   asection *irelifunc;
 
   union
   asection *irelifunc;
 
   union
@@ -730,16 +746,14 @@ struct elf_s390_link_hash_table
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ldm_got;
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ldm_got;
-
-  /* Small local sym cache.  */
-  struct sym_cache sym_cache;
 };
 
 /* Get the s390 ELF linker hash table from a link_info structure.  */
 
 #define elf_s390_hash_table(p) \
 };
 
 /* 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)
+  ((is_elf_hash_table ((p)->hash)                                      \
+    && elf_hash_table_id (elf_hash_table (p)) == S390_ELF_DATA)                \
+   ? (struct elf_s390_link_hash_table *) (p)->hash : NULL)
 
 #undef ELF64
 #include "elf-s390-common.c"
 
 #undef ELF64
 #include "elf-s390-common.c"
@@ -768,7 +782,6 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
       struct elf_s390_link_hash_entry *eh;
 
       eh = (struct elf_s390_link_hash_entry *) entry;
       struct elf_s390_link_hash_entry *eh;
 
       eh = (struct elf_s390_link_hash_entry *) entry;
-      eh->dyn_relocs = NULL;
       eh->gotplt_refcount = 0;
       eh->tls_type = GOT_UNKNOWN;
       eh->ifunc_resolver_address = 0;
       eh->gotplt_refcount = 0;
       eh->tls_type = GOT_UNKNOWN;
       eh->ifunc_resolver_address = 0;
@@ -784,9 +797,9 @@ static struct bfd_link_hash_table *
 elf_s390_link_hash_table_create (bfd *abfd)
 {
   struct elf_s390_link_hash_table *ret;
 elf_s390_link_hash_table_create (bfd *abfd)
 {
   struct elf_s390_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf_s390_link_hash_table);
+  size_t amt = sizeof (struct elf_s390_link_hash_table);
 
 
-  ret = (struct elf_s390_link_hash_table *) bfd_malloc (amt);
+  ret = (struct elf_s390_link_hash_table *) bfd_zmalloc (amt);
   if (ret == NULL)
     return NULL;
 
   if (ret == NULL)
     return NULL;
 
@@ -798,69 +811,9 @@ elf_s390_link_hash_table_create (bfd *abfd)
       return NULL;
     }
 
       return 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;
-  ret->sym_cache.abfd = NULL;
-
   return &ret->elf.root;
 }
 
   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 (!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
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
@@ -873,37 +826,6 @@ elf_s390_copy_indirect_symbol (struct bfd_link_info *info,
   edir = (struct elf_s390_link_hash_entry *) dir;
   eind = (struct elf_s390_link_hash_entry *) ind;
 
   edir = (struct elf_s390_link_hash_entry *) dir;
   eind = (struct elf_s390_link_hash_entry *) ind;
 
-  if (eind->dyn_relocs != NULL)
-    {
-      if (edir->dyn_relocs != NULL)
-       {
-         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_dyn_relocs *q;
-
-             for (q = edir->dyn_relocs; q != NULL; q = q->next)
-               if (q->sec == p->sec)
-                 {
-                   q->pc_count += p->pc_count;
-                   q->count += p->count;
-                   *pp = p->next;
-                   break;
-                 }
-             if (q == NULL)
-               pp = &p->next;
-           }
-         *pp = edir->dyn_relocs;
-       }
-
-      edir->dyn_relocs = eind->dyn_relocs;
-      eind->dyn_relocs = NULL;
-    }
-
   if (ind->root.type == bfd_link_hash_indirect
       && dir->got.refcount <= 0)
     {
   if (ind->root.type == bfd_link_hash_indirect
       && dir->got.refcount <= 0)
     {
@@ -918,7 +840,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.  */
       /* 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;
       dir->ref_regular |= ind->ref_regular;
       dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
       dir->needs_plt |= ind->needs_plt;
@@ -932,7 +855,7 @@ elf_s390_tls_transition (struct bfd_link_info *info,
                         int r_type,
                         int is_local)
 {
                         int r_type,
                         int is_local)
 {
-  if (info->shared)
+  if (bfd_link_pic (info))
     return r_type;
 
   switch (r_type)
     return r_type;
 
   switch (r_type)
@@ -957,7 +880,7 @@ elf_s390_tls_transition (struct bfd_link_info *info,
    allocate space in the global offset table or procedure linkage
    table.  */
 
    allocate space in the global offset table or procedure linkage
    table.  */
 
-static bfd_boolean
+static bool
 elf_s390_check_relocs (bfd *abfd,
                       struct bfd_link_info *info,
                       asection *sec,
 elf_s390_check_relocs (bfd *abfd,
                       struct bfd_link_info *info,
                       asection *sec,
@@ -973,8 +896,8 @@ elf_s390_check_relocs (bfd *abfd,
   int tls_type, old_tls_type;
   Elf_Internal_Sym *isym;
 
   int tls_type, old_tls_type;
   Elf_Internal_Sym *isym;
 
-  if (info->relocatable)
-    return TRUE;
+  if (bfd_link_relocatable (info))
+    return true;
 
   BFD_ASSERT (is_s390_elf (abfd));
 
 
   BFD_ASSERT (is_s390_elf (abfd));
 
@@ -989,37 +912,41 @@ elf_s390_check_relocs (bfd *abfd,
   for (rel = relocs; rel < rel_end; rel++)
     {
       unsigned int r_type;
   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))
        {
       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);
-         return FALSE;
+         /* xgettext:c-format */
+         _bfd_error_handler (_("%pB: bad symbol index: %d"),
+                             abfd, r_symndx);
+         return false;
        }
 
       if (r_symndx < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
        }
 
       if (r_symndx < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
-         isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+         isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                        abfd, r_symndx);
          if (isym == NULL)
                                        abfd, r_symndx);
          if (isym == NULL)
-           return FALSE;
+           return false;
 
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              struct plt_entry *plt;
 
 
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              struct plt_entry *plt;
 
+             if (htab->elf.dynobj == NULL)
+               htab->elf.dynobj = abfd;
+
              if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
              if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
-               return FALSE;
+               return false;
 
              if (local_got_refcounts == NULL)
                {
                  if (!elf_s390_allocate_local_syminfo (abfd, symtab_hdr))
 
              if (local_got_refcounts == NULL)
                {
                  if (!elf_s390_allocate_local_syminfo (abfd, symtab_hdr))
-                   return FALSE;
+                   return false;
                  local_got_refcounts = elf_local_got_refcounts (abfd);
                }
              plt = elf_s390_local_plt (abfd);
                  local_got_refcounts = elf_local_got_refcounts (abfd);
                }
              plt = elf_s390_local_plt (abfd);
@@ -1063,7 +990,7 @@ elf_s390_check_relocs (bfd *abfd,
              && local_got_refcounts == NULL)
            {
              if (!elf_s390_allocate_local_syminfo (abfd, symtab_hdr))
              && local_got_refcounts == NULL)
            {
              if (!elf_s390_allocate_local_syminfo (abfd, symtab_hdr))
-               return FALSE;
+               return false;
              local_got_refcounts = elf_local_got_refcounts (abfd);
            }
          /* Fall through.  */
              local_got_refcounts = elf_local_got_refcounts (abfd);
            }
          /* Fall through.  */
@@ -1075,8 +1002,8 @@ elf_s390_check_relocs (bfd *abfd,
            {
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
            {
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
-             if (!create_got_section (htab->elf.dynobj, info))
-               return FALSE;
+             if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
+               return false;
            }
        }
 
            }
        }
 
@@ -1085,7 +1012,7 @@ elf_s390_check_relocs (bfd *abfd,
          if (htab->elf.dynobj == NULL)
            htab->elf.dynobj = abfd;
          if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
          if (htab->elf.dynobj == NULL)
            htab->elf.dynobj = abfd;
          if (!s390_elf_create_ifunc_sections (htab->elf.dynobj, info))
-           return FALSE;
+           return false;
 
          /* Make sure an IFUNC symbol defined in a non-shared object
             always gets a PLT slot.  */
 
          /* Make sure an IFUNC symbol defined in a non-shared object
             always gets a PLT slot.  */
@@ -1100,8 +1027,6 @@ elf_s390_check_relocs (bfd *abfd,
        }
       switch (r_type)
        {
        }
       switch (r_type)
        {
-       case R_390_GOTOFF16:
-       case R_390_GOTOFF32:
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
          /* These relocs do not need a GOT slot.  They just load the
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
          /* These relocs do not need a GOT slot.  They just load the
@@ -1109,8 +1034,15 @@ elf_s390_check_relocs (bfd *abfd,
             the GOT.  Since the GOT pointer has been set up above we
             are done.  */
          break;
             the GOT.  Since the GOT pointer has been set up above we
             are done.  */
          break;
+       case R_390_GOTOFF16:
+       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:
        case R_390_PLT16DBL:
+       case R_390_PLT24DBL:
        case R_390_PLT32DBL:
        case R_390_PLT32:
        case R_390_PLTOFF16:
        case R_390_PLT32DBL:
        case R_390_PLT32:
        case R_390_PLTOFF16:
@@ -1163,7 +1095,7 @@ elf_s390_check_relocs (bfd *abfd,
        case R_390_TLS_GOTIE20:
        case R_390_TLS_GOTIE32:
        case R_390_TLS_IEENT:
        case R_390_TLS_GOTIE20:
        case R_390_TLS_GOTIE32:
        case R_390_TLS_IEENT:
-         if (info->shared)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
          /* Fall through.  */
 
            info->flags |= DF_STATIC_TLS;
          /* Fall through.  */
 
@@ -1214,10 +1146,11 @@ elf_s390_check_relocs (bfd *abfd,
            {
              if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL)
                {
            {
              if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL)
                {
-                 (*_bfd_error_handler)
-                   (_("%B: `%s' accessed both as normal and thread local symbol"),
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("%pB: `%s' accessed both as normal and thread local symbol"),
                     abfd, h->root.root.string);
                     abfd, h->root.root.string);
-                 return FALSE;
+                 return false;
                }
              if (old_tls_type > tls_type)
                tls_type = old_tls_type;
                }
              if (old_tls_type > tls_type)
                tls_type = old_tls_type;
@@ -1236,7 +1169,13 @@ elf_s390_check_relocs (bfd *abfd,
          /* Fall through.  */
 
        case R_390_TLS_LE32:
          /* Fall through.  */
 
        case R_390_TLS_LE32:
-         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_LE32 && bfd_link_pie (info))
+           break;
+
+         if (!bfd_link_pic (info))
            break;
          info->flags |= DF_STATIC_TLS;
          /* Fall through.  */
            break;
          info->flags |= DF_STATIC_TLS;
          /* Fall through.  */
@@ -1245,10 +1184,12 @@ elf_s390_check_relocs (bfd *abfd,
        case R_390_16:
        case R_390_32:
        case R_390_PC16:
        case R_390_16:
        case R_390_32:
        case R_390_PC16:
+       case R_390_PC12DBL:
        case R_390_PC16DBL:
        case R_390_PC16DBL:
+       case R_390_PC24DBL:
        case R_390_PC32DBL:
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC32:
-         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
            {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
@@ -1258,7 +1199,7 @@ elf_s390_check_relocs (bfd *abfd,
                 adjust_dynamic_symbol.  */
              h->non_got_ref = 1;
 
                 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.  */
                {
                  /* We may need a .plt entry if the function this reloc
                     refers to is in a shared lib.  */
@@ -1287,10 +1228,12 @@ 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.  */
             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
               && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
               && (sec->flags & SEC_ALLOC) != 0
               && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
+                   && ELF32_R_TYPE (rel->r_info) != R_390_PC12DBL
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL
+                   && ELF32_R_TYPE (rel->r_info) != R_390_PC24DBL
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC32)
                   || (h != NULL
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC32)
                   || (h != NULL
@@ -1298,7 +1241,7 @@ elf_s390_check_relocs (bfd *abfd,
                           || h->root.type == bfd_link_hash_defweak
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
                           || 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
                  && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
@@ -1316,17 +1259,17 @@ elf_s390_check_relocs (bfd *abfd,
                    htab->elf.dynobj = abfd;
 
                  sreloc = _bfd_elf_make_dynamic_reloc_section
                    htab->elf.dynobj = abfd;
 
                  sreloc = _bfd_elf_make_dynamic_reloc_section
-                   (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ TRUE);
+                   (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ true);
 
                  if (sreloc == NULL)
 
                  if (sreloc == NULL)
-                   return FALSE;
+                   return false;
                }
 
              /* If this is a global symbol, we count the number of
                 relocations we need for this symbol.  */
              if (h != NULL)
                {
                }
 
              /* If this is a global symbol, we count the number of
                 relocations we need for this symbol.  */
              if (h != NULL)
                {
-                 head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs;
+                 head = &h->dyn_relocs;
                }
              else
                {
                }
              else
                {
@@ -1336,10 +1279,10 @@ elf_s390_check_relocs (bfd *abfd,
                  asection *s;
                  void *vpp;
 
                  asection *s;
                  void *vpp;
 
-                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                                abfd, r_symndx);
                  if (isym == NULL)
                                                abfd, r_symndx);
                  if (isym == NULL)
-                   return FALSE;
+                   return false;
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s == NULL)
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s == NULL)
@@ -1352,12 +1295,12 @@ elf_s390_check_relocs (bfd *abfd,
              p = *head;
              if (p == NULL || p->sec != sec)
                {
              p = *head;
              if (p == NULL || p->sec != sec)
                {
-                 bfd_size_type amt = sizeof *p;
+                 size_t amt = sizeof *p;
 
                  p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
                  if (p == NULL)
 
                  p = ((struct elf_dyn_relocs *)
                       bfd_alloc (htab->elf.dynobj, amt));
                  if (p == NULL)
-                   return FALSE;
+                   return false;
                  p->next = *head;
                  *head = p;
                  p->sec = sec;
                  p->next = *head;
                  *head = p;
                  p->sec = sec;
@@ -1367,7 +1310,9 @@ elf_s390_check_relocs (bfd *abfd,
 
              p->count += 1;
              if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
 
              p->count += 1;
              if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
+                 || ELF32_R_TYPE (rel->r_info) == R_390_PC12DBL
                  || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
                  || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
+                 || ELF32_R_TYPE (rel->r_info) == R_390_PC24DBL
                  || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL
                  || ELF32_R_TYPE (rel->r_info) == R_390_PC32)
                p->pc_count += 1;
                  || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL
                  || ELF32_R_TYPE (rel->r_info) == R_390_PC32)
                p->pc_count += 1;
@@ -1378,16 +1323,14 @@ elf_s390_check_relocs (bfd *abfd,
             Reconstruct it for later use during GC.  */
        case R_390_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
             Reconstruct it for later use during GC.  */
        case R_390_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-           return FALSE;
+           return false;
          break;
 
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_390_GNU_VTENTRY:
          break;
 
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_390_GNU_VTENTRY:
-         BFD_ASSERT (h != NULL);
-         if (h != NULL
-             && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-           return FALSE;
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+           return false;
          break;
 
        default:
          break;
 
        default:
@@ -1395,7 +1338,7 @@ elf_s390_check_relocs (bfd *abfd,
        }
     }
 
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Return the section that should be marked against GC for a given
 }
 
 /* Return the section that should be marked against GC for a given
@@ -1419,168 +1362,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 (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);
-  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_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_GOTOFF16:
-       case R_390_GOTOFF32:
-       case R_390_GOTPC:
-       case R_390_GOTPCDBL:
-       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_PC16DBL:
-       case R_390_PC32DBL:
-       case R_390_PC32:
-         if (info->shared)
-           break;
-         /* Fall through.  */
-
-       case R_390_PLT16DBL:
-       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
 /* 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
@@ -1609,16 +1390,54 @@ elf_s390_adjust_gotplt (struct elf_s390_link_hash_entry *h)
    change the definition to something the rest of the link can
    understand.  */
 
    change the definition to something the rest of the link can
    understand.  */
 
-static bfd_boolean
+static bool
 elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h)
 {
   struct elf_s390_link_hash_table *htab;
 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))
 
   /* 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_dyn_relocs *p;
+
+         for (pp = &h->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
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later
@@ -1641,7 +1460,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
          elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
        }
 
          elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
        }
 
-      return TRUE;
+      return true;
     }
   else
     /* It's possible that we incorrectly decided a .plt reloc was
     }
   else
     /* It's possible that we incorrectly decided a .plt reloc was
@@ -1654,15 +1473,15 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->u.weakdef != NULL)
+  if (h->is_weakalias)
     {
     {
-      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
-                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->u.weakdef->root.u.def.section;
-      h->root.u.def.value = h->u.weakdef->root.u.def.value;
+      struct elf_link_hash_entry *def = weakdef (h);
+      BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+      h->root.u.def.section = def->root.u.def.section;
+      h->root.u.def.value = def->root.u.def.value;
       if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
       if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
-       h->non_got_ref = h->u.weakdef->non_got_ref;
-      return TRUE;
+       h->non_got_ref = def->non_got_ref;
+      return true;
     }
 
   /* This is a reference to a symbol defined by a dynamic object which
     }
 
   /* This is a reference to a symbol defined by a dynamic object which
@@ -1672,41 +1491,27 @@ 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.  */
      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)
-    return TRUE;
+  if (bfd_link_pic (info))
+    return true;
 
   /* If there are no references to this symbol that do not use the
      GOT, we don't need to generate a copy reloc.  */
   if (!h->non_got_ref)
 
   /* If there are no references to this symbol that do not use the
      GOT, we don't need to generate a copy reloc.  */
   if (!h->non_got_ref)
-    return TRUE;
+    return true;
 
   /* If -z nocopyreloc was given, we won't generate them either.  */
   if (info->nocopyreloc)
     {
       h->non_got_ref = 0;
 
   /* If -z nocopyreloc was given, we won't generate them either.  */
   if (info->nocopyreloc)
     {
       h->non_got_ref = 0;
-      return TRUE;
+      return true;
     }
 
     }
 
-  if (ELIMINATE_COPY_RELOCS)
+  /* If we don't find any dynamic relocs in read-only sections, then
+     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
+  if (ELIMINATE_COPY_RELOCS && !_bfd_elf_readonly_dynrelocs (h))
     {
     {
-      struct elf_s390_link_hash_entry * eh;
-      struct elf_dyn_relocs *p;
-
-      eh = (struct elf_s390_link_hash_entry *) h;
-      for (p = eh->dyn_relocs; p != NULL; p = p->next)
-       {
-         s = p->sec->output_section;
-         if (s != NULL && (s->flags & SEC_READONLY) != 0)
-           break;
-       }
-
-      /* If we didn't find any dynamic relocs in read-only sections, then
-        we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-      if (p == NULL)
-       {
-         h->non_got_ref = 0;
-         return TRUE;
-       }
+      h->non_got_ref = 0;
+      return true;
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -1724,30 +1529,37 @@ 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.  */
   /* 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)
     {
   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;
     }
 
       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
    dynamic relocs.  */
 
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
    dynamic relocs.  */
 
-static bfd_boolean
+static bool
 allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 {
   struct bfd_link_info *info;
   struct elf_s390_link_hash_table *htab;
 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_link_hash_entry *)h;
   struct elf_dyn_relocs *p;
 
   if (h->root.type == bfd_link_hash_indirect)
   struct elf_dyn_relocs *p;
 
   if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
+    return true;
 
   info = (struct bfd_link_info *) inf;
   htab = elf_s390_hash_table (info);
 
   info = (struct bfd_link_info *) inf;
   htab = elf_s390_hash_table (info);
@@ -1755,8 +1567,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   /* 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)
   /* 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)
     {
   else if (htab->elf.dynamic_sections_created
           && h->plt.refcount > 0)
     {
@@ -1766,10 +1577,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
+           return false;
        }
 
        }
 
-      if (info->shared
+      if (bfd_link_pic (info)
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
          asection *s = htab->elf.splt;
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
          asection *s = htab->elf.splt;
@@ -1786,7 +1597,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
             location in the .plt.  This is required to make function
             pointers compare as equal between the normal executable and
             the shared library.  */
             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;
              && !h->def_regular)
            {
              h->root.u.def.section = s;
@@ -1805,7 +1616,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
        }
       else
        {
        }
       else
        {
-         h->plt.offset = (bfd_vma) -1;
+         h->plt.offset = (bfd_vma) -1;
          h->needs_plt = 0;
          elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
        }
          h->needs_plt = 0;
          elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
        }
@@ -1822,7 +1633,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
      to R_390_TLS_LE32 requiring no TLS entry. For GOTIE12 and IEENT
      we can save the dynamic TLS relocation.  */
   if (h->got.refcount > 0
      to R_390_TLS_LE32 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)
     {
       && h->dynindx == -1
       && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE)
     {
@@ -1838,9 +1649,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
        h->got.offset = (bfd_vma) -1;
     }
   else if (h->got.refcount > 0)
        h->got.offset = (bfd_vma) -1;
     }
   else if (h->got.refcount > 0)
-   {
+    {
       asection *s;
       asection *s;
-      bfd_boolean dyn;
+      bool dyn;
       int tls_type = elf_s390_hash_entry(h)->tls_type;
 
       /* Make sure this symbol is output as a dynamic symbol.
       int tls_type = elf_s390_hash_entry(h)->tls_type;
 
       /* Make sure this symbol is output as a dynamic symbol.
@@ -1849,7 +1660,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
+           return false;
        }
 
       s = htab->elf.sgot;
        }
 
       s = htab->elf.sgot;
@@ -1868,15 +1679,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
        htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rela);
       else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                || h->root.type != bfd_link_hash_undefweak)
        htab->elf.srelgot->size += 2 * sizeof (Elf32_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 (Elf32_External_Rela);
     }
   else
     h->got.offset = (bfd_vma) -1;
 
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
        htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  if (eh->dyn_relocs == NULL)
-    return TRUE;
+  if (h->dyn_relocs == NULL)
+    return true;
 
   /* In the shared -Bsymbolic case, discard space allocated for
      dynamic pc-relative relocs against symbols which turn out to be
 
   /* In the shared -Bsymbolic case, discard space allocated for
      dynamic pc-relative relocs against symbols which turn out to be
@@ -1884,13 +1695,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
      space for pc-relative relocs that have become local due to symbol
      visibility changes.  */
 
      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))
        {
          struct elf_dyn_relocs **pp;
 
     {
       if (SYMBOL_CALLS_LOCAL (info, h))
        {
          struct elf_dyn_relocs **pp;
 
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+         for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
            {
              p->count -= p->pc_count;
              p->pc_count = 0;
            {
              p->count -= p->pc_count;
              p->pc_count = 0;
@@ -1903,11 +1714,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (eh->dyn_relocs != NULL
+      if (h->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
        {
          && h->root.type == bfd_link_hash_undefweak)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-           eh->dyn_relocs = NULL;
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+             || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+           h->dyn_relocs = NULL;
 
          /* Make sure undefined weak symbols are output as a dynamic
             symbol in PIEs.  */
 
          /* Make sure undefined weak symbols are output as a dynamic
             symbol in PIEs.  */
@@ -1915,7 +1727,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
                   && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
                   && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
            }
        }
     }
            }
        }
     }
@@ -1938,7 +1750,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
              && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
              && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
            }
 
          /* If that succeeded, we know we'll be keeping all the
            }
 
          /* If that succeeded, we know we'll be keeping all the
@@ -1947,58 +1759,32 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
            goto keep;
        }
 
            goto keep;
        }
 
-      eh->dyn_relocs = NULL;
+      h->dyn_relocs = NULL;
 
     keep: ;
     }
 
   /* Finally, allocate space.  */
 
     keep: ;
     }
 
   /* Finally, allocate space.  */
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
     {
       asection *sreloc = elf_section_data (p->sec)->sreloc;
 
       sreloc->size += p->count * sizeof (Elf32_External_Rela);
     }
 
     {
       asection *sreloc = elf_section_data (p->sec)->sreloc;
 
       sreloc->size += p->count * sizeof (Elf32_External_Rela);
     }
 
-  return TRUE;
-}
-
-/* Find any dynamic relocs that apply to read-only sections.  */
-
-static bfd_boolean
-readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf)
-{
-  struct elf_s390_link_hash_entry *eh;
-  struct elf_dyn_relocs *p;
-
-  eh = (struct elf_s390_link_hash_entry *) h;
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
-    {
-      asection *s = p->sec->output_section;
-
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       {
-         struct bfd_link_info *info = (struct bfd_link_info *) inf;
-
-         info->flags |= DF_TEXTREL;
-
-         /* Not an error, just cut short the traversal.  */
-         return FALSE;
-       }
-    }
-  return TRUE;
+  return true;
 }
 
 /* Set the sizes of the dynamic sections.  */
 
 }
 
 /* Set the sizes of the dynamic sections.  */
 
-static bfd_boolean
+static bool
 elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                                struct bfd_link_info *info)
 {
   struct elf_s390_link_hash_table *htab;
   bfd *dynobj;
   asection *s;
 elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                                struct bfd_link_info *info)
 {
   struct elf_s390_link_hash_table *htab;
   bfd *dynobj;
   asection *s;
-  bfd_boolean relocs;
+  bool relocs;
   bfd *ibfd;
 
   htab = elf_s390_hash_table (info);
   bfd *ibfd;
 
   htab = elf_s390_hash_table (info);
@@ -2009,7 +1795,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 (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)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
@@ -2021,7 +1807,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
 
   /* 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;
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
@@ -2077,7 +1863,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;
              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 (Elf32_External_Rela);
            }
          else
                srela->size += sizeof (Elf32_External_Rela);
            }
          else
@@ -2094,7 +1880,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              htab->elf.irelplt->size += RELA_ENTRY_SIZE;
            }
          else
              htab->elf.irelplt->size += RELA_ENTRY_SIZE;
            }
          else
-            local_plt[i].plt.offset = (bfd_vma) -1;
+           local_plt[i].plt.offset = (bfd_vma) -1;
        }
     }
 
        }
     }
 
@@ -2115,7 +1901,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
 
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
-  relocs = FALSE;
+  relocs = false;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LINKER_CREATED) == 0)
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LINKER_CREATED) == 0)
@@ -2124,7 +1910,8 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (s == htab->elf.splt
          || s == htab->elf.sgot
          || s == htab->elf.sgotplt
       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)
          || s == htab->elf.iplt
          || s == htab->elf.igotplt
          || s == htab->irelifunc)
@@ -2132,10 +1919,10 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
+      else if (startswith (bfd_section_name (s), ".rela"))
        {
          if (s->size != 0)
        {
          if (s->size != 0)
-           relocs = TRUE;
+           relocs = true;
 
          /* We use the reloc_count field as a counter if we need
             to copy relocs into the output file.  */
 
          /* We use the reloc_count field as a counter if we need
             to copy relocs into the output file.  */
@@ -2173,56 +1960,10 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         of garbage.  */
       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
         of garbage.  */
       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
-       return FALSE;
+       return false;
     }
 
     }
 
-  if (htab->elf.dynamic_sections_created)
-    {
-      /* Add some entries to the .dynamic section.  We fill in the
-        values later, in elf_s390_finish_dynamic_sections, but we
-        must add the entries now so that we get the correct size for
-        the .dynamic section.  The DT_DEBUG entry is filled in by the
-        dynamic linker and used by the debugger.  */
-#define add_dynamic_entry(TAG, VAL) \
-  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
-
-      if (info->executable)
-       {
-         if (!add_dynamic_entry (DT_DEBUG, 0))
-           return FALSE;
-       }
-
-      if (htab->elf.splt->size != 0)
-       {
-         if (!add_dynamic_entry (DT_PLTGOT, 0)
-             || !add_dynamic_entry (DT_PLTRELSZ, 0)
-             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
-             || !add_dynamic_entry (DT_JMPREL, 0))
-           return FALSE;
-       }
-
-      if (relocs)
-       {
-         if (!add_dynamic_entry (DT_RELA, 0)
-             || !add_dynamic_entry (DT_RELASZ, 0)
-             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
-           return FALSE;
-
-         /* If any dynamic relocs apply to a read-only section,
-            then we need a DT_TEXTREL entry.  */
-         if ((info->flags & DF_TEXTREL) == 0)
-           elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
-
-         if ((info->flags & DF_TEXTREL) != 0)
-           {
-             if (!add_dynamic_entry (DT_TEXTREL, 0))
-               return FALSE;
-           }
-       }
-    }
-#undef add_dynamic_entry
-
-  return TRUE;
+  return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
 }
 
 /* Return the base VMA address which should be subtracted from real addresses
 }
 
 /* Return the base VMA address which should be subtracted from real addresses
@@ -2263,18 +2004,19 @@ invalid_tls_insn (bfd *input_bfd,
   reloc_howto_type *howto;
 
   howto = elf_howto_table + ELF32_R_TYPE (rel->r_info);
   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 */
+    (_("%pB(%pA+%#" PRIx64 "): invalid instruction for TLS relocation %s"),
      input_bfd,
      input_section,
      input_bfd,
      input_section,
-     (long) rel->r_offset,
+     (uint64_t) rel->r_offset,
      howto->name);
   bfd_set_error (bfd_error_bad_value);
 }
 
 /* Relocate a 390 ELF section.  */
 
      howto->name);
   bfd_set_error (bfd_error_bad_value);
 }
 
 /* Relocate a 390 ELF section.  */
 
-static bfd_boolean
+static int
 elf_s390_relocate_section (bfd *output_bfd,
                           struct bfd_link_info *info,
                           bfd *input_bfd,
 elf_s390_relocate_section (bfd *output_bfd,
                           struct bfd_link_info *info,
                           bfd *input_bfd,
@@ -2291,7 +2033,11 @@ elf_s390_relocate_section (bfd *output_bfd,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
-  BFD_ASSERT (is_s390_elf (input_bfd));
+  if (!is_s390_elf (input_bfd))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
 
   htab = elf_s390_hash_table (info);
   symtab_hdr = &elf_symtab_hdr (input_bfd);
 
   htab = elf_s390_hash_table (info);
   symtab_hdr = &elf_symtab_hdr (input_bfd);
@@ -2310,10 +2056,11 @@ elf_s390_relocate_section (bfd *output_bfd,
       asection *sec;
       bfd_vma off;
       bfd_vma relocation;
       asection *sec;
       bfd_vma off;
       bfd_vma relocation;
-      bfd_boolean unresolved_reloc;
+      bool unresolved_reloc;
       bfd_reloc_status_type r;
       int tls_type;
       asection *base_got = htab->elf.sgot;
       bfd_reloc_status_type r;
       int tls_type;
       asection *base_got = htab->elf.sgot;
+      bool resolved_to_zero;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_390_GNU_VTINHERIT
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_390_GNU_VTINHERIT
@@ -2322,7 +2069,7 @@ elf_s390_relocate_section (bfd *output_bfd,
       if (r_type >= (int) R_390_max)
        {
          bfd_set_error (bfd_error_bad_value);
       if (r_type >= (int) R_390_max)
        {
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
 
       howto = elf_howto_table + r_type;
        }
 
       howto = elf_howto_table + r_type;
@@ -2331,7 +2078,7 @@ elf_s390_relocate_section (bfd *output_bfd,
       h = NULL;
       sym = NULL;
       sec = NULL;
       h = NULL;
       sym = NULL;
       sec = NULL;
-      unresolved_reloc = FALSE;
+      unresolved_reloc = false;
       if (r_symndx < symtab_hdr->sh_info)
        {
          sym = local_syms + r_symndx;
       if (r_symndx < symtab_hdr->sh_info)
        {
          sym = local_syms + r_symndx;
@@ -2340,7 +2087,7 @@ elf_s390_relocate_section (bfd *output_bfd,
            {
              struct plt_entry *local_plt = elf_s390_local_plt (input_bfd);
              if (local_plt == NULL)
            {
              struct plt_entry *local_plt = elf_s390_local_plt (input_bfd);
              if (local_plt == NULL)
-               return FALSE;
+               return false;
 
              /* Address of the PLT slot.  */
              relocation = (htab->elf.iplt->output_section->vma
 
              /* Address of the PLT slot.  */
              relocation = (htab->elf.iplt->output_section->vma
@@ -2349,6 +2096,10 @@ elf_s390_relocate_section (bfd *output_bfd,
 
              switch (r_type)
                {
 
              switch (r_type)
                {
+               case R_390_PLTOFF16:
+               case R_390_PLTOFF32:
+                 relocation -= htab->elf.sgot->output_section->vma;
+                 break;
                case R_390_GOTPLT12:
                case R_390_GOTPLT16:
                case R_390_GOTPLT20:
                case R_390_GOTPLT12:
                case R_390_GOTPLT16:
                case R_390_GOTPLT20:
@@ -2385,21 +2136,25 @@ elf_s390_relocate_section (bfd *output_bfd,
        }
       else
        {
        }
       else
        {
-         bfd_boolean warned ATTRIBUTE_UNUSED;
+         bool warned ATTRIBUTE_UNUSED;
+         bool ignored ATTRIBUTE_UNUSED;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h, sec, relocation,
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h, sec, relocation,
-                                  unresolved_reloc, warned);
+                                  unresolved_reloc, warned, ignored);
        }
 
       if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
                                         rel, 1, relend, howto, 0, contents);
 
        }
 
       if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
                                         rel, 1, relend, howto, 0, contents);
 
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        continue;
 
        continue;
 
+      resolved_to_zero = (h != NULL
+                         && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+
       switch (r_type)
        {
        case R_390_GOTPLT12:
       switch (r_type)
        {
        case R_390_GOTPLT12:
@@ -2441,7 +2196,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                  if (r_type == R_390_GOTPLTENT)
                    relocation += htab->elf.sgot->output_section->vma;
                }
                  if (r_type == R_390_GOTPLTENT)
                    relocation += htab->elf.sgot->output_section->vma;
                }
-             unresolved_reloc = FALSE;
+             unresolved_reloc = false;
 
            }
          /* Fall through.  */
 
            }
          /* Fall through.  */
@@ -2458,7 +2213,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          if (h != NULL)
            {
 
          if (h != NULL)
            {
-             bfd_boolean dyn;
+             bool dyn;
 
              off = h->got.offset;
              dyn = htab->elf.dynamic_sections_created;
 
              off = h->got.offset;
              dyn = htab->elf.dynamic_sections_created;
@@ -2480,8 +2235,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                         finish_dynamic_symbol.  */
                    }
                }
                         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))
                           && SYMBOL_REFERENCES_LOCAL (info, h))
                       || (ELF_ST_VISIBILITY (h->other)
                           && h->root.type == bfd_link_hash_undefweak))
@@ -2507,9 +2264,39 @@ elf_s390_relocate_section (bfd *output_bfd,
                                  base_got->contents + off);
                      h->got.offset |= 1;
                    }
                                  base_got->contents + off);
                      h->got.offset |= 1;
                    }
+
+                 if ((h->def_regular
+                      && bfd_link_pic (info)
+                      && SYMBOL_REFERENCES_LOCAL (info, h))
+                     /* lrl rx,sym@GOTENT -> larl rx, sym */
+                     && ((r_type == R_390_GOTENT
+                          && (bfd_get_16 (input_bfd,
+                                          contents + rel->r_offset - 2)
+                              & 0xff0f) == 0xc40d)
+                         /* ly rx, sym@GOT(r12) -> larl rx, sym */
+                         || (r_type == R_390_GOT20
+                             && (bfd_get_32 (input_bfd,
+                                             contents + rel->r_offset - 2)
+                                 & 0xff00f000) == 0xe300c000
+                             && bfd_get_8 (input_bfd,
+                                           contents + rel->r_offset + 3) == 0x58)))
+                   {
+                     unsigned short new_insn =
+                       (0xc000 | (bfd_get_8 (input_bfd,
+                                             contents + rel->r_offset - 1) & 0xf0));
+                     bfd_put_16 (output_bfd, new_insn,
+                                 contents + rel->r_offset - 2);
+                     r_type = R_390_PC32DBL;
+                     rel->r_addend = 2;
+                     howto = elf_howto_table + r_type;
+                     relocation = h->root.u.def.value
+                       + h->root.u.def.section->output_section->vma
+                       + h->root.u.def.section->output_offset;
+                     goto do_relocation;
+                   }
                }
              else
                }
              else
-               unresolved_reloc = FALSE;
+               unresolved_reloc = false;
            }
          else
            {
            }
          else
            {
@@ -2528,7 +2315,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                  bfd_put_32 (output_bfd, relocation,
                              htab->elf.sgot->contents + off);
 
                  bfd_put_32 (output_bfd, relocation,
                              htab->elf.sgot->contents + off);
 
-                 if (info->shared)
+                 if (bfd_link_pic (info))
                    {
                      asection *srelgot;
                      Elf_Internal_Rela outrel;
                    {
                      asection *srelgot;
                      Elf_Internal_Rela outrel;
@@ -2572,6 +2359,18 @@ elf_s390_relocate_section (bfd *output_bfd,
          /* Relocation is relative to the start of the global offset
             table.  */
 
          /* 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
          /* 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
@@ -2584,10 +2383,12 @@ elf_s390_relocate_section (bfd *output_bfd,
        case R_390_GOTPCDBL:
          /* Use global offset table as symbol value.  */
          relocation = htab->elf.sgot->output_section->vma;
        case R_390_GOTPCDBL:
          /* Use global offset table as symbol value.  */
          relocation = htab->elf.sgot->output_section->vma;
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
          break;
 
+       case R_390_PLT12DBL:
        case R_390_PLT16DBL:
        case R_390_PLT16DBL:
+       case R_390_PLT24DBL:
        case R_390_PLT32DBL:
        case R_390_PLT32:
          /* Relocation is to the entry for this symbol in the
        case R_390_PLT32DBL:
        case R_390_PLT32:
          /* Relocation is to the entry for this symbol in the
@@ -2609,13 +2410,13 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          if (s390_is_ifunc_symbol_p (h))
            relocation = (htab->elf.iplt->output_section->vma
 
          if (s390_is_ifunc_symbol_p (h))
            relocation = (htab->elf.iplt->output_section->vma
-                          + htab->elf.iplt->output_offset
+                         + htab->elf.iplt->output_offset
                          + h->plt.offset);
          else
            relocation = (htab->elf.splt->output_section->vma
                          + htab->elf.splt->output_offset
                          + h->plt.offset);
                          + h->plt.offset);
          else
            relocation = (htab->elf.splt->output_section->vma
                          + htab->elf.splt->output_offset
                          + h->plt.offset);
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        case R_390_PLTOFF16:
          break;
 
        case R_390_PLTOFF16:
@@ -2625,9 +2426,9 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          /* For local symbols or if we didn't make a PLT entry for
             this symbol resolve the symbol directly.  */
 
          /* For local symbols or if we didn't make a PLT entry for
             this symbol resolve the symbol directly.  */
-         if (   h == NULL
+         if (h == NULL
              || h->plt.offset == (bfd_vma) -1
              || h->plt.offset == (bfd_vma) -1
-             || htab->elf.splt == NULL)
+             || (htab->elf.splt == NULL && !s390_is_ifunc_symbol_p (h)))
            {
              relocation -= htab->elf.sgot->output_section->vma;
              break;
            {
              relocation -= htab->elf.sgot->output_section->vma;
              break;
@@ -2643,21 +2444,47 @@ elf_s390_relocate_section (bfd *output_bfd,
                          + htab->elf.splt->output_offset
                          + h->plt.offset
                          - htab->elf.sgot->output_section->vma);
                          + htab->elf.splt->output_offset
                          + h->plt.offset
                          - htab->elf.sgot->output_section->vma);
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
          break;
 
-       case R_390_8:
-       case R_390_16:
-       case R_390_32:
        case R_390_PC16:
        case R_390_PC16:
+       case R_390_PC12DBL:
        case R_390_PC16DBL:
        case R_390_PC16DBL:
+       case R_390_PC24DBL:
        case R_390_PC32DBL:
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC32:
+         if (h != NULL
+             && s390_is_ifunc_symbol_p (h)
+             && h->def_regular
+             && !bfd_link_executable (info))
+           {
+             /* This will not work our if the function does not
+                happen to set up the GOT pointer for some other
+                reason.  31 bit PLT entries require r12 to hold the
+                GOT pointer.
+                FIXME: Implement an errorcheck.
+                NOTE: It will work when brasl is not available
+                (e.g. with -m31 -march=g5) since a local function
+                call then does use GOTOFF which implies r12 being set
+                up.  */
+             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:
+         if ((input_section->flags & SEC_ALLOC) == 0)
+           break;
+
          if (h != NULL
              && s390_is_ifunc_symbol_p (h)
              && h->def_regular)
            {
          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 STT_GNU_IFUNC symbol must
                     go through PLT.  */
@@ -2688,7 +2515,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
                  if (h->dynindx == -1
                      || h->forced_local
 
                  if (h->dynindx == -1
                      || h->forced_local
-                     || info->executable)
+                     || bfd_link_executable (info))
                    {
                      /* This symbol is resolved locally.  */
                      outrel.r_info = ELF32_R_INFO (0, R_390_IRELATIVE);
                    {
                      /* This symbol is resolved locally.  */
                      outrel.r_info = ELF32_R_INFO (0, R_390_IRELATIVE);
@@ -2714,20 +2541,20 @@ 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
               && (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
                   || h->root.type != bfd_link_hash_undefweak)
               && ((r_type != R_390_PC16
+                   && r_type != R_390_PC12DBL
                    && r_type != R_390_PC16DBL
                    && r_type != R_390_PC16DBL
+                   && r_type != R_390_PC24DBL
                    && r_type != R_390_PC32DBL
                    && r_type != R_390_PC32)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
                    && r_type != R_390_PC32DBL
                    && r_type != R_390_PC32)
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
+                 && !bfd_link_pic (info)
                  && h != NULL
                  && h->dynindx != -1
                  && !h->non_got_ref
                  && h != NULL
                  && h->dynindx != -1
                  && !h->non_got_ref
@@ -2737,7 +2564,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                      || h->root.type == bfd_link_hash_undefined)))
            {
              Elf_Internal_Rela outrel;
                      || h->root.type == bfd_link_hash_undefined)))
            {
              Elf_Internal_Rela outrel;
-             bfd_boolean skip, relocate;
+             bool skip, relocate;
              asection *sreloc;
              bfd_byte *loc;
 
              asection *sreloc;
              bfd_byte *loc;
 
@@ -2745,16 +2572,16 @@ elf_s390_relocate_section (bfd *output_bfd,
                 are copied into the output file to be resolved at run
                 time.  */
 
                 are copied into the output file to be resolved at run
                 time.  */
 
-             skip = FALSE;
-             relocate = FALSE;
+             skip = false;
+             relocate = false;
 
              outrel.r_offset =
                _bfd_elf_section_offset (output_bfd, info, input_section,
                                         rel->r_offset);
              if (outrel.r_offset == (bfd_vma) -1)
 
              outrel.r_offset =
                _bfd_elf_section_offset (output_bfd, info, input_section,
                                         rel->r_offset);
              if (outrel.r_offset == (bfd_vma) -1)
-               skip = TRUE;
+               skip = true;
              else if (outrel.r_offset == (bfd_vma) -2)
              else if (outrel.r_offset == (bfd_vma) -2)
-               skip = TRUE, relocate = TRUE;
+               skip = true, relocate = true;
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
 
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
 
@@ -2763,10 +2590,12 @@ elf_s390_relocate_section (bfd *output_bfd,
              else if (h != NULL
                       && h->dynindx != -1
                       && (r_type == R_390_PC16
              else if (h != NULL
                       && h->dynindx != -1
                       && (r_type == R_390_PC16
+                          || r_type == R_390_PC12DBL
                           || r_type == R_390_PC16DBL
                           || r_type == R_390_PC16DBL
+                          || r_type == R_390_PC24DBL
                           || r_type == R_390_PC32DBL
                           || r_type == R_390_PC32
                           || r_type == R_390_PC32DBL
                           || r_type == R_390_PC32
-                          || !info->shared
+                          || !bfd_link_pic (info)
                           || !SYMBOLIC_BIND (info, h)
                           || !h->def_regular))
                {
                           || !SYMBOLIC_BIND (info, h)
                           || !h->def_regular))
                {
@@ -2779,7 +2608,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                  outrel.r_addend = relocation + rel->r_addend;
                  if (r_type == R_390_32)
                    {
                  outrel.r_addend = relocation + rel->r_addend;
                  if (r_type == R_390_32)
                    {
-                     relocate = TRUE;
+                     relocate = true;
                      outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
                    }
                  else
                      outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
                    }
                  else
@@ -2791,7 +2620,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                      else if (sec == NULL || sec->owner == NULL)
                        {
                          bfd_set_error(bfd_error_bad_value);
                      else if (sec == NULL || sec->owner == NULL)
                        {
                          bfd_set_error(bfd_error_bad_value);
-                         return FALSE;
+                         return false;
                        }
                      else
                        {
                        }
                      else
                        {
@@ -2836,7 +2665,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          /* Relocations for tls literal pool entries.  */
        case R_390_TLS_IE32:
 
          /* Relocations for tls literal pool entries.  */
        case R_390_TLS_IE32:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              Elf_Internal_Rela outrel;
              asection *sreloc;
            {
              Elf_Internal_Rela outrel;
              asection *sreloc;
@@ -2864,7 +2693,9 @@ elf_s390_relocate_section (bfd *output_bfd,
          else if (h != NULL)
            {
              tls_type = elf_s390_hash_entry(h)->tls_type;
          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_LE32;
            }
          if (r_type == R_390_TLS_GD32 && tls_type >= GOT_TLS_IE)
                r_type = R_390_TLS_LE32;
            }
          if (r_type == R_390_TLS_GD32 && tls_type >= GOT_TLS_IE)
@@ -2957,7 +2788,7 @@ elf_s390_relocate_section (bfd *output_bfd,
              relocation = htab->elf.sgot->output_offset + off;
              if (r_type == R_390_TLS_IE32 || r_type == R_390_TLS_IEENT)
                relocation += htab->elf.sgot->output_section->vma;
              relocation = htab->elf.sgot->output_offset + off;
              if (r_type == R_390_TLS_IE32 || r_type == R_390_TLS_IEENT)
                relocation += htab->elf.sgot->output_section->vma;
-             unresolved_reloc = FALSE;
+             unresolved_reloc = false;
            }
          else
            {
            }
          else
            {
@@ -2975,14 +2806,16 @@ elf_s390_relocate_section (bfd *output_bfd,
              if (local_got_offsets == NULL)
                abort();
              off = local_got_offsets[r_symndx];
              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;
                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;
            }
 
                goto emit_tls_relocs;
            }
 
@@ -2995,11 +2828,11 @@ elf_s390_relocate_section (bfd *output_bfd,
          relocation = htab->elf.sgot->output_offset + off;
          if (r_type == R_390_TLS_IEENT)
            relocation += htab->elf.sgot->output_section->vma;
          relocation = htab->elf.sgot->output_offset + off;
          if (r_type == R_390_TLS_IEENT)
            relocation += htab->elf.sgot->output_section->vma;
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        case R_390_TLS_LDM32:
          break;
 
        case R_390_TLS_LDM32:
-         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.  */
            /* 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.  */
@@ -3033,11 +2866,11 @@ elf_s390_relocate_section (bfd *output_bfd,
              htab->tls_ldm_got.offset |= 1;
            }
          relocation = htab->elf.sgot->output_offset + off;
              htab->tls_ldm_got.offset |= 1;
            }
          relocation = htab->elf.sgot->output_offset + off;
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        case R_390_TLS_LE32:
          break;
 
        case R_390_TLS_LE32:
-         if (info->shared)
+         if (bfd_link_dll (info))
            {
              /* Linking a shared library with non-fpic code requires
                 a R_390_TLS_TPOFF relocation.  */
            {
              /* Linking a shared library with non-fpic code requires
                 a R_390_TLS_TPOFF relocation.  */
@@ -3074,7 +2907,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          continue;
 
        case R_390_TLS_LDO32:
          continue;
 
        case R_390_TLS_LDO32:
-         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.  */
            relocation -= dtpoff_base (info);
          else
            /* When converting LDO to LE, we must negate.  */
@@ -3096,7 +2929,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          if (r_type == R_390_TLS_LOAD)
            {
 
          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:
                     l %rx,0(0,%ry)    -> lr %rx,%ry + bcr 0,0
                {
                  /* IE->LE transition. Four valid cases:
                     l %rx,0(0,%ry)    -> lr %rx,%ry + bcr 0,0
@@ -3106,7 +2939,6 @@ elf_s390_relocate_section (bfd *output_bfd,
                  unsigned int insn, ry;
 
                  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  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);
                  if ((insn & 0xff00f000) == 0x58000000)
                    /* l %rx,0(%ry,0) -> lr %rx,%ry + bcr 0,0  */
                    ry = (insn & 0x000f0000);
@@ -3120,7 +2952,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                    /* l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0  */
                    ry = (insn & 0x0000f000) << 4;
                  else
                    /* 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);
                }
                  insn = 0x18000700 | (insn & 0x00f00000) | ry;
                  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
                }
@@ -3133,8 +2968,11 @@ elf_s390_relocate_section (bfd *output_bfd,
              if ((insn & 0xff000fff) != 0x4d000000 &&
                  (insn & 0xffff0000) != 0xc0e50000 &&
                  (insn & 0xff000000) != 0x0d000000)
              if ((insn & 0xff000fff) != 0x4d000000 &&
                  (insn & 0xffff0000) != 0xc0e50000 &&
                  (insn & 0xff000000) != 0x0d000000)
-               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))
                {
                  if ((insn & 0xff000000) == 0x0d000000)
                    {
                {
                  if ((insn & 0xff000000) == 0x0d000000)
                    {
@@ -3162,7 +3000,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)
                  /* 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)
                    {
 
                  if ((insn & 0xff000000) == 0x4d000000)
                    {
@@ -3174,7 +3015,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                    {
                      /* GD->IE transition.
                         brasl %r14,__tls_get_addr@plt ->
                    {
                      /* GD->IE transition.
                         brasl %r14,__tls_get_addr@plt ->
-                               l %r2,0(%r2,%r12) ; bcr 0,0 */
+                               l %r2,0(%r2,%r12) ; bcr 0,0 */
                      insn = 0x5822c000;
                      bfd_put_16 (output_bfd, 0x0700,
                                  contents + rel->r_offset + 4);
                      insn = 0x5822c000;
                      bfd_put_16 (output_bfd, 0x0700,
                                  contents + rel->r_offset + 4);
@@ -3184,7 +3025,7 @@ elf_s390_relocate_section (bfd *output_bfd,
            }
          else if (r_type == R_390_TLS_LDCALL)
            {
            }
          else if (r_type == R_390_TLS_LDCALL)
            {
-             if (!info->shared)
+             if (!bfd_link_pic (info))
                {
                  unsigned int insn;
 
                {
                  unsigned int insn;
 
@@ -3192,7 +3033,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                  if ((insn & 0xff000fff) != 0x4d000000 &&
                      (insn & 0xffff0000) != 0xc0e50000 &&
                      (insn & 0xff000000) != 0x0d000000)
                  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)
                    {
 
                  if ((insn & 0xff000000) == 0x0d000000)
                    {
@@ -3231,16 +3075,25 @@ 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)
               && 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 */
+         (_("%pB(%pA+%#" PRIx64 "): "
+            "unresolvable %s relocation against symbol `%s'"),
           input_bfd,
           input_section,
           input_bfd,
           input_section,
-          (long) rel->r_offset,
+          (uint64_t) rel->r_offset,
           howto->name,
           h->root.root.string);
 
     do_relocation:
 
           howto->name,
           h->root.root.string);
 
     do_relocation:
 
+      /* When applying a 24 bit reloc we need to start one byte
+        earlier.  Otherwise the 32 bit get/put bfd operations might
+        access a byte after the actual section.  */
+      if (r_type == R_390_PC24DBL
+         || r_type == R_390_PLT24DBL)
+       rel->r_offset--;
+
       if (r_type == R_390_20
          || r_type == R_390_GOT20
          || r_type == R_390_GOTPLT20
       if (r_type == R_390_20
          || r_type == R_390_GOT20
          || r_type == R_390_GOTPLT20
@@ -3269,32 +3122,28 @@ elf_s390_relocate_section (bfd *output_bfd,
                                                      symtab_hdr->sh_link,
                                                      sym->st_name);
              if (name == NULL)
                                                      symtab_hdr->sh_link,
                                                      sym->st_name);
              if (name == NULL)
-               return FALSE;
+               return false;
              if (*name == '\0')
              if (*name == '\0')
-               name = bfd_section_name (input_bfd, sec);
+               name = bfd_section_name (sec);
            }
 
          if (r == bfd_reloc_overflow)
            }
 
          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
            {
          else
            {
-             (*_bfd_error_handler)
-               (_("%B(%A+0x%lx): reloc against `%s': error %d"),
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB(%pA+%#" PRIx64 "): reloc against `%s': error %d"),
                 input_bfd, input_section,
                 input_bfd, input_section,
-                (long) rel->r_offset, name, (int) r);
-             return FALSE;
+                (uint64_t) rel->r_offset, name, (int) r);
+             return false;
            }
        }
     }
 
            }
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Generate the PLT slots together with the dynamic relocations needed
 }
 
 /* Generate the PLT slots together with the dynamic relocations needed
@@ -3335,14 +3184,14 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
   /* S390 uses halfwords for relative branch calc!  */
   relative_offset = - (plt->output_offset +
                       (PLT_ENTRY_SIZE * iplt_index) + 18) / 2;
   /* S390 uses halfwords for relative branch calc!  */
   relative_offset = - (plt->output_offset +
                       (PLT_ENTRY_SIZE * iplt_index) + 18) / 2;
-/* If offset is > 32768, branch to a previous branch
-   390 can only handle +-64 K jumps.  */
+  /* If offset is > 32768, branch to a previous branch
+     390 can only handle +-64 K jumps.  */
   if ( -32768 > (int) relative_offset )
     relative_offset
       = -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2);
 
   /* Fill in the entry in the procedure linkage table.  */
   if ( -32768 > (int) relative_offset )
     relative_offset
       = -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2);
 
   /* Fill in the entry in the procedure linkage table.  */
-  if (!info->shared)
+  if (!bfd_link_pic (info))
     {
       memcpy (plt->contents + iplt_offset, elf_s390_plt_entry,
              PLT_ENTRY_SIZE);
     {
       memcpy (plt->contents + iplt_offset, elf_s390_plt_entry,
              PLT_ENTRY_SIZE);
@@ -3425,7 +3274,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
 
   if (!h
       || h->dynindx == -1
 
   if (!h
       || h->dynindx == -1
-      || ((info->executable
+      || ((bfd_link_executable (info)
           || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
          && h->def_regular))
     {
           || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
          && h->def_regular))
     {
@@ -3446,7 +3295,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static bfd_boolean
+static bool
 elf_s390_finish_dynamic_symbol (bfd *output_bfd,
                                struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
 elf_s390_finish_dynamic_symbol (bfd *output_bfd,
                                struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
@@ -3467,16 +3316,15 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
 
       /* This symbol has an entry in the procedure linkage table.  Set
         it up.  */
 
       /* 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
        {
        }
       else
        {
@@ -3504,7 +3352,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
              = -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2);
 
          /* Fill in the entry in the procedure linkage table.  */
              = -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2);
 
          /* Fill in the entry in the procedure linkage table.  */
-         if (!info->shared)
+         if (!bfd_link_pic (info))
            {
              memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390_plt_entry,
                      PLT_ENTRY_SIZE);
            {
              memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390_plt_entry,
                      PLT_ENTRY_SIZE);
@@ -3530,7 +3378,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
 
              /* Put in the GOT offset as displacement value.  The 0xc000
                 value comes from the first word of the plt entry.  Look
 
              /* Put in the GOT offset as displacement value.  The 0xc000
                 value comes from the first word of the plt entry.  Look
-                at the elf_s390_plt_pic16_entry content.  */
+                at the elf_s390_plt_pic12_entry content.  */
              bfd_put_16 (output_bfd, (bfd_vma)0xc000 | got_offset,
                          htab->elf.splt->contents + h->plt.offset + 2);
 
              bfd_put_16 (output_bfd, (bfd_vma)0xc000 | got_offset,
                          htab->elf.splt->contents + h->plt.offset + 2);
 
@@ -3628,7 +3476,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
         initialized in the relocate_section function.  */
       if (h->def_regular && s390_is_ifunc_symbol_p (h))
        {
         initialized in the relocate_section function.  */
       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
            {
              /* An explicit GOT slot usage needs GLOB_DAT.  If the
                 symbol references local the implicit got.iplt slot
@@ -3645,11 +3493,11 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
                                       + htab->elf.iplt->output_offset
                                       + h->plt.offset),
                          htab->elf.sgot->contents + h->got.offset);
                                       + htab->elf.iplt->output_offset
                                       + h->plt.offset),
                          htab->elf.sgot->contents + h->got.offset);
-             return TRUE;
+             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
        {
          /* If this is a static link, or it is a -Bsymbolic link and
             the symbol is defined locally or was forced to be local
@@ -3657,8 +3505,8 @@ 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.  */
             RELATIVE reloc.  The entry in the global offset table
             will already have been initialized in the
             relocate_section function.  */
-         if (!h->def_regular)
-           return FALSE;
+         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);
          rela.r_addend = (h->root.u.def.value
          BFD_ASSERT((h->got.offset & 1) != 0);
          rela.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
          rela.r_addend = (h->root.u.def.value
@@ -3682,6 +3530,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
   if (h->needs_copy)
     {
       Elf_Internal_Rela rela;
+      asection *s;
       bfd_byte *loc;
 
       /* This symbols needs a copy reloc.  Set it up.  */
       bfd_byte *loc;
 
       /* This symbols needs a copy reloc.  Set it up.  */
@@ -3689,7 +3538,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)
       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
        abort ();
 
       rela.r_offset = (h->root.u.def.value
@@ -3697,26 +3547,48 @@ 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;
                       + 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);
     }
 
   /* Mark some specially defined symbols as absolute.  */
       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
     }
 
   /* Mark some specially defined symbols as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+  if (h == htab->elf.hdynamic
       || h == htab->elf.hgot
       || h == htab->elf.hplt)
     sym->st_shndx = SHN_ABS;
 
       || h == htab->elf.hgot
       || h == htab->elf.hplt)
     sym->st_shndx = SHN_ABS;
 
-  return TRUE;
+  return true;
 }
 
 /* Used to decide how to sort relocs in an optimal manner for the
    dynamic linker, before writing them out.  */
 
 static enum elf_reloc_type_class
 }
 
 /* Used to decide how to sort relocs in an optimal manner for the
    dynamic linker, before writing them out.  */
 
 static enum elf_reloc_type_class
-elf_s390_reloc_type_class (const Elf_Internal_Rela *rela)
+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 = ELF32_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) ELF32_R_TYPE (rela->r_info))
     {
     case R_390_RELATIVE:
   switch ((int) ELF32_R_TYPE (rela->r_info))
     {
     case R_390_RELATIVE:
@@ -3732,7 +3604,7 @@ elf_s390_reloc_type_class (const Elf_Internal_Rela *rela)
 
 /* Finish up the dynamic sections.  */
 
 
 /* Finish up the dynamic sections.  */
 
-static bfd_boolean
+static bool
 elf_s390_finish_dynamic_sections (bfd *output_bfd,
                                  struct bfd_link_info *info)
 {
 elf_s390_finish_dynamic_sections (bfd *output_bfd,
                                  struct bfd_link_info *info)
 {
@@ -3768,16 +3640,19 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
              continue;
 
            case DT_PLTGOT:
              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:
              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:
              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;
+             if (htab->elf.irelplt)
+               dyn.d_un.d_val += htab->elf.irelplt->size;
              break;
            }
 
              break;
            }
 
@@ -3788,7 +3663,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
       if (htab->elf.splt && htab->elf.splt->size > 0)
        {
          memset (htab->elf.splt->contents, 0, PLT_FIRST_ENTRY_SIZE);
       if (htab->elf.splt && htab->elf.splt->size > 0)
        {
          memset (htab->elf.splt->contents, 0, PLT_FIRST_ENTRY_SIZE);
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              memcpy (htab->elf.splt->contents, elf_s390_plt_pic_first_entry,
                      PLT_FIRST_ENTRY_SIZE);
            {
              memcpy (htab->elf.splt->contents, elf_s390_plt_pic_first_entry,
                      PLT_FIRST_ENTRY_SIZE);
@@ -3801,7 +3676,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
                          htab->elf.sgotplt->output_section->vma
                          + htab->elf.sgotplt->output_offset,
                          htab->elf.splt->contents + 24);
                          htab->elf.sgotplt->output_section->vma
                          + htab->elf.sgotplt->output_offset,
                          htab->elf.splt->contents + 24);
-          }
+           }
          elf_section_data (htab->elf.splt->output_section)
            ->this_hdr.sh_entsize = 4;
        }
          elf_section_data (htab->elf.splt->output_section)
            ->this_hdr.sh_entsize = 4;
        }
@@ -3827,7 +3702,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
        ->this_hdr.sh_entsize = 4;
     }
   /* Finish dynamic symbol for local IFUNC symbols.  */
        ->this_hdr.sh_entsize = 4;
     }
   /* 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;
     {
       struct plt_entry *local_plt;
       Elf_Internal_Sym *isym;
@@ -3835,6 +3710,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
 
       symtab_hdr = &elf_symtab_hdr (ibfd);
 
 
       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++)
       local_plt = elf_s390_local_plt (ibfd);
       if (local_plt != NULL)
        for (i = 0; i < symtab_hdr->sh_info; i++)
@@ -3842,9 +3720,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
            if (local_plt[i].plt.offset != (bfd_vma) -1)
              {
                asection *sec = local_plt[i].sec;
            if (local_plt[i].plt.offset != (bfd_vma) -1)
              {
                asection *sec = local_plt[i].sec;
-               isym = bfd_sym_from_r_symndx (&htab->sym_cache, ibfd, i);
+               isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, ibfd, i);
                if (isym == NULL)
                if (isym == NULL)
-                 return FALSE;
+                 return false;
 
                if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
                  elf_s390_finish_ifunc_symbol (output_bfd, info, NULL, htab,
 
                if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
                  elf_s390_finish_ifunc_symbol (output_bfd, info, NULL, htab,
@@ -3856,10 +3734,12 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
              }
          }
     }
              }
          }
     }
-  return TRUE;
+  return true;
 }
 }
+\f
+/* Support for core dump NOTE sections.  */
 
 
-static bfd_boolean
+static bool
 elf_s390_grok_prstatus (bfd * abfd, Elf_Internal_Note * note)
 {
   int offset;
 elf_s390_grok_prstatus (bfd * abfd, Elf_Internal_Note * note)
 {
   int offset;
@@ -3867,20 +3747,20 @@ elf_s390_grok_prstatus (bfd * abfd, Elf_Internal_Note * note)
 
   switch (note->descsz)
     {
 
   switch (note->descsz)
     {
-      default:
-       return FALSE;
+    default:
+      return false;
 
 
-      case 224:                /* S/390 Linux.  */
-       /* pr_cursig */
-       elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+    case 224:                  /* S/390 Linux.  */
+      /* 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 + 24);
+      /* pr_pid */
+      elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
 
 
-       /* pr_reg */
-       offset = 72;
-       size = 144;
-       break;
+      /* pr_reg */
+      offset = 72;
+      size = 144;
+      break;
     }
 
   /* Make a ".reg/999" section.  */
     }
 
   /* Make a ".reg/999" section.  */
@@ -3888,6 +3768,100 @@ elf_s390_grok_prstatus (bfd * abfd, Elf_Internal_Note * note)
                                          size, note->descpos + offset);
 }
 
                                          size, note->descpos + offset);
 }
 
+static bool
+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] ATTRIBUTE_NONSTRING = { 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);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+       DIAGNOSTIC_PUSH;
+       /* GCC 8.0 and 8.1 warn about 80 equals destination size with
+          -Wstringop-truncation:
+          https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
+        */
+       DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
+#endif
+       strncpy (data + 44, psargs, 80);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+       DIAGNOSTIC_POP;
+#endif
+       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.  */
 
 /* Return address for Ith PLT stub in section PLT, for relocation REL
    or (bfd_vma) -1 if it should not be included.  */
 
@@ -3898,15 +3872,26 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt,
   return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
 }
 
   return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
 }
 
-static bfd_boolean
-elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bool
+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, info))
+    return false;
+
   elf_elfheader (obfd)->e_flags |= elf_elfheader (ibfd)->e_flags;
   elf_elfheader (obfd)->e_flags |= elf_elfheader (ibfd)->e_flags;
-  return TRUE;
+  return true;
 }
 
 
 }
 
 
-#define TARGET_BIG_SYM bfd_elf32_s390_vec
+#define TARGET_BIG_SYM s390_elf32_vec
 #define TARGET_BIG_NAME        "elf32-s390"
 #define ELF_ARCH       bfd_arch_s390
 #define ELF_TARGET_ID  S390_ELF_DATA
 #define TARGET_BIG_NAME        "elf32-s390"
 #define ELF_ARCH       bfd_arch_s390
 #define ELF_TARGET_ID  S390_ELF_DATA
@@ -3920,6 +3905,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_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
 #define elf_backend_rela_normal                1
 
 #define elf_info_to_howto                    elf_s390_info_to_howto
@@ -3934,21 +3920,23 @@ 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_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_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_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_reloc_type_class         elf_s390_reloc_type_class
 #define elf_backend_grok_prstatus            elf_s390_grok_prstatus
 #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_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 bfd_elf32_mkobject             elf_s390_mkobject
 #define elf_backend_object_p           elf_s390_object_p
 
 
 #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"
 #include "elf32-target.h"
This page took 0.089607 seconds and 4 git commands to generate.