Add --no-dynamic-linker option to ld, for static PIE use
[deliverable/binutils-gdb.git] / bfd / elf32-s390.c
index bee532d2d473a4955c0f538b7bc4a2fd90344d37..2143ee1773d9683e6d8dd9bb4b139a6a1dbe30e7 100644 (file)
@@ -1,6 +1,5 @@
 /* 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-2015 Free Software Foundation, Inc.
    Contributed by Carl B. Pedersen and Martin Schwidefsky.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -40,7 +39,7 @@ static reloc_howto_type elf_howto_table[] =
 {
   HOWTO (R_390_NONE,           /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
+        3,                     /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -857,11 +856,11 @@ elf_s390_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   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)
+  if (!bfd_link_pic (info))
     htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
 
   if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
-      || (!info->shared && !htab->srelbss))
+      || (!bfd_link_pic (info) && !htab->srelbss))
     abort ();
 
   return TRUE;
@@ -938,7 +937,7 @@ elf_s390_tls_transition (struct bfd_link_info *info,
                         int r_type,
                         int is_local)
 {
-  if (info->shared)
+  if (bfd_link_pic (info))
     return r_type;
 
   switch (r_type)
@@ -979,7 +978,7 @@ elf_s390_check_relocs (bfd *abfd,
   int tls_type, old_tls_type;
   Elf_Internal_Sym *isym;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   BFD_ASSERT (is_s390_elf (abfd));
@@ -1178,7 +1177,7 @@ elf_s390_check_relocs (bfd *abfd,
        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.  */
 
@@ -1251,7 +1250,13 @@ elf_s390_check_relocs (bfd *abfd,
          /* 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.  */
@@ -1275,7 +1280,7 @@ elf_s390_check_relocs (bfd *abfd,
                 adjust_dynamic_symbol.  */
              h->non_got_ref = 1;
 
-             if (!info->shared)
+             if (!bfd_link_pic (info))
                {
                  /* We may need a .plt entry if the function this reloc
                     refers to is in a shared lib.  */
@@ -1304,7 +1309,7 @@ elf_s390_check_relocs (bfd *abfd,
             may need to keep relocations for symbols satisfied by a
             dynamic library if we manage to avoid copy relocs for the
             symbol.  */
-         if ((info->shared
+         if ((bfd_link_pic (info)
               && (sec->flags & SEC_ALLOC) != 0
               && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
                    && ELF32_R_TYPE (rel->r_info) != R_390_PC12DBL
@@ -1317,7 +1322,7 @@ elf_s390_check_relocs (bfd *abfd,
                           || h->root.type == bfd_link_hash_defweak
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
+                 && !bfd_link_pic (info)
                  && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
@@ -1454,7 +1459,7 @@ elf_s390_gc_sweep_hook (bfd *abfd,
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   htab = elf_s390_hash_table (info);
@@ -1560,7 +1565,7 @@ elf_s390_gc_sweep_hook (bfd *abfd,
        case R_390_PC24DBL:
        case R_390_PC32DBL:
        case R_390_PC32:
-         if (info->shared)
+         if (bfd_link_pic (info))
            break;
          /* Fall through.  */
 
@@ -1697,7 +1702,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
-  if (info->shared)
+  if (bfd_link_pic (info))
     return TRUE;
 
   /* If there are no references to this symbol that do not use the
@@ -1757,7 +1762,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   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
@@ -1794,7 +1799,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
            return FALSE;
        }
 
-      if (info->shared
+      if (bfd_link_pic (info)
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
          asection *s = htab->elf.splt;
@@ -1811,7 +1816,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.  */
-         if (! info->shared
+         if (! bfd_link_pic (info)
              && !h->def_regular)
            {
              h->root.u.def.section = s;
@@ -1847,7 +1852,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
-      && !info->shared
+      && !bfd_link_pic (info)
       && h->dynindx == -1
       && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE)
     {
@@ -1893,7 +1898,7 @@ 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)
-              && (info->shared
+              && (bfd_link_pic (info)
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
        htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
     }
@@ -1909,7 +1914,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
      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))
        {
@@ -2034,7 +2039,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
@@ -2046,7 +2051,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
@@ -2102,7 +2107,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              s->size += GOT_ENTRY_SIZE;
              if (*local_tls_type == GOT_TLS_GD)
                s->size += GOT_ENTRY_SIZE;
-             if (info->shared)
+             if (bfd_link_pic (info))
                srela->size += sizeof (Elf32_External_Rela);
            }
          else
@@ -2211,7 +2216,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (info->executable)
+      if (bfd_link_executable (info))
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -2415,18 +2420,19 @@ elf_s390_relocate_section (bfd *output_bfd,
       else
        {
          bfd_boolean warned ATTRIBUTE_UNUSED;
+         bfd_boolean ignored ATTRIBUTE_UNUSED;
 
          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 (info->relocatable)
+      if (bfd_link_relocatable (info))
        continue;
 
       switch (r_type)
@@ -2509,8 +2515,10 @@ elf_s390_relocate_section (bfd *output_bfd,
                         finish_dynamic_symbol.  */
                    }
                }
-             else if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-                      || (info->shared
+             else if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+                                                         bfd_link_pic (info),
+                                                         h)
+                      || (bfd_link_pic (info)
                           && SYMBOL_REFERENCES_LOCAL (info, h))
                       || (ELF_ST_VISIBILITY (h->other)
                           && h->root.type == bfd_link_hash_undefweak))
@@ -2536,6 +2544,36 @@ elf_s390_relocate_section (bfd *output_bfd,
                                  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
                unresolved_reloc = FALSE;
@@ -2557,7 +2595,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                  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;
@@ -2690,7 +2728,7 @@ elf_s390_relocate_section (bfd *output_bfd,
              && s390_is_ifunc_symbol_p (h)
              && h->def_regular)
            {
-             if (!info->shared || !h->non_got_ref)
+             if (!bfd_link_pic (info) || !h->non_got_ref)
                {
                  /* For a non-shared object STT_GNU_IFUNC symbol must
                     go through PLT.  */
@@ -2721,7 +2759,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
                  if (h->dynindx == -1
                      || h->forced_local
-                     || info->executable)
+                     || bfd_link_executable (info))
                    {
                      /* This symbol is resolved locally.  */
                      outrel.r_info = ELF32_R_INFO (0, R_390_IRELATIVE);
@@ -2750,7 +2788,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          if ((input_section->flags & SEC_ALLOC) == 0)
            break;
 
-         if ((info->shared
+         if ((bfd_link_pic (info)
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                   || h->root.type != bfd_link_hash_undefweak)
@@ -2762,7 +2800,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                    && 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
@@ -2803,7 +2841,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                           || r_type == R_390_PC24DBL
                           || r_type == R_390_PC32DBL
                           || r_type == R_390_PC32
-                          || !info->shared
+                          || !bfd_link_pic (info)
                           || !SYMBOLIC_BIND (info, h)
                           || !h->def_regular))
                {
@@ -2873,7 +2911,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          /* 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;
@@ -2901,7 +2939,9 @@ elf_s390_relocate_section (bfd *output_bfd,
          else if (h != NULL)
            {
              tls_type = elf_s390_hash_entry(h)->tls_type;
-             if (!info->shared && h->dynindx == -1 && tls_type >= GOT_TLS_IE)
+             if (!bfd_link_pic (info)
+                 && h->dynindx == -1
+                 && tls_type >= GOT_TLS_IE)
                r_type = R_390_TLS_LE32;
            }
          if (r_type == R_390_TLS_GD32 && tls_type >= GOT_TLS_IE)
@@ -3012,14 +3052,16 @@ elf_s390_relocate_section (bfd *output_bfd,
              if (local_got_offsets == NULL)
                abort();
              off = local_got_offsets[r_symndx];
-             if (info->shared)
+             if (bfd_link_pic (info))
                goto emit_tls_relocs;
            }
          else
            {
              off = h->got.offset;
              tls_type = elf_s390_hash_entry(h)->tls_type;
-             if (info->shared || h->dynindx != -1 || tls_type < GOT_TLS_IE)
+             if (bfd_link_pic (info)
+                 || h->dynindx != -1
+                 || tls_type < GOT_TLS_IE)
                goto emit_tls_relocs;
            }
 
@@ -3036,7 +3078,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          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.  */
@@ -3074,7 +3116,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          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.  */
@@ -3111,7 +3153,7 @@ elf_s390_relocate_section (bfd *output_bfd,
          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.  */
@@ -3133,7 +3175,7 @@ elf_s390_relocate_section (bfd *output_bfd,
 
          if (r_type == R_390_TLS_LOAD)
            {
-             if (!info->shared && (h == NULL || h->dynindx == -1))
+             if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1))
                {
                  /* IE->LE transition. Four valid cases:
                     l %rx,0(0,%ry)    -> lr %rx,%ry + bcr 0,0
@@ -3171,7 +3213,7 @@ elf_s390_relocate_section (bfd *output_bfd,
                  (insn & 0xffff0000) != 0xc0e50000 &&
                  (insn & 0xff000000) != 0x0d000000)
                invalid_tls_insn (input_bfd, input_section, rel);
-             if (!info->shared && (h == NULL || h->dynindx == -1))
+             if (!bfd_link_pic (info) && (h == NULL || h->dynindx == -1))
                {
                  if ((insn & 0xff000000) == 0x0d000000)
                    {
@@ -3221,7 +3263,7 @@ elf_s390_relocate_section (bfd *output_bfd,
            }
          else if (r_type == R_390_TLS_LDCALL)
            {
-             if (!info->shared)
+             if (!bfd_link_pic (info))
                {
                  unsigned int insn;
 
@@ -3386,7 +3428,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
       = -(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);
@@ -3469,7 +3511,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
 
   if (!h
       || h->dynindx == -1
-      || ((info->executable
+      || ((bfd_link_executable (info)
           || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
          && h->def_regular))
     {
@@ -3548,7 +3590,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.  */
-         if (!info->shared)
+         if (!bfd_link_pic (info))
            {
              memcpy (htab->elf.splt->contents + h->plt.offset, elf_s390_plt_entry,
                      PLT_ENTRY_SIZE);
@@ -3672,7 +3714,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))
        {
-         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
@@ -3692,7 +3734,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
              return TRUE;
            }
        }
-      else if (info->shared
+      else if (bfd_link_pic (info)
          && SYMBOL_REFERENCES_LOCAL (info, h))
        {
          /* If this is a static link, or it is a -Bsymbolic link and
@@ -3834,7 +3876,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 (info->shared)
+         if (bfd_link_pic (info))
            {
              memcpy (htab->elf.splt->contents, elf_s390_plt_pic_first_entry,
                      PLT_FIRST_ENTRY_SIZE);
@@ -3873,7 +3915,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
        ->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;
@@ -3944,15 +3986,24 @@ elf_s390_plt_sym_val (bfd_vma i, const asection *plt,
   return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
 }
 
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
 static bfd_boolean
 elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
+  if (!is_s390_elf (ibfd) || !is_s390_elf (obfd))
+    return TRUE;
+
+  if (!elf_s390_merge_obj_attributes (ibfd, obfd))
+    return FALSE;
+
   elf_elfheader (obfd)->e_flags |= elf_elfheader (ibfd)->e_flags;
   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
@@ -3992,6 +4043,7 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 #define elf_backend_grok_prstatus            elf_s390_grok_prstatus
 #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
This page took 0.049259 seconds and 4 git commands to generate.