resize_section_table cleanup
[deliverable/binutils-gdb.git] / bfd / elf64-s390.c
index d939a3d68b45687863e424fca65de49fb482c0cd..831c4a2dc05a0b2419eb800988a2ad180794c769 100644 (file)
@@ -1,6 +1,5 @@
 /* IBM S/390-specific support for 64-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2000-2014 Free Software Foundation, Inc.
    Contributed Martin Schwidefsky (schwidefsky@de.ibm.com).
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -43,7 +42,7 @@ static reloc_howto_type elf_howto_table[] =
 {
   HOWTO (R_390_NONE,           /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* size (0 = byte, 1 = 2 byte, 2 = 4 byte) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -171,7 +170,14 @@ static reloc_howto_type elf_howto_table[] =
        s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE),
   HOWTO(R_390_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_390_IRELATIVE", FALSE, 0, MINUS_ONE, 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.  */
@@ -222,10 +228,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];
+    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_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:
@@ -950,6 +964,10 @@ elf_s390_check_relocs (bfd *abfd,
          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;
+
+         /* PR15323, ref flags aren't set for references in the same
+            object.  */
+         h->root.non_ir_ref = 1;
        }
 
       /* Create got section and local_got_refcounts array if they
@@ -1033,7 +1051,9 @@ elf_s390_check_relocs (bfd *abfd,
             are done.  */
          break;
 
+       case R_390_PLT12DBL:
        case R_390_PLT16DBL:
+       case R_390_PLT24DBL:
        case R_390_PLT32:
        case R_390_PLT32DBL:
        case R_390_PLT64:
@@ -1172,8 +1192,10 @@ elf_s390_check_relocs (bfd *abfd,
        case R_390_16:
        case R_390_32:
        case R_390_64:
+       case R_390_PC12DBL:
        case R_390_PC16:
        case R_390_PC16DBL:
+       case R_390_PC24DBL:
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC64:
@@ -1219,7 +1241,9 @@ elf_s390_check_relocs (bfd *abfd,
          if ((info->shared
               && (sec->flags & SEC_ALLOC) != 0
               && ((ELF64_R_TYPE (rel->r_info) != R_390_PC16
+                   && ELF64_R_TYPE (rel->r_info) != R_390_PC12DBL
                    && ELF64_R_TYPE (rel->r_info) != R_390_PC16DBL
+                   && ELF64_R_TYPE (rel->r_info) != R_390_PC24DBL
                    && ELF64_R_TYPE (rel->r_info) != R_390_PC32
                    && ELF64_R_TYPE (rel->r_info) != R_390_PC32DBL
                    && ELF64_R_TYPE (rel->r_info) != R_390_PC64)
@@ -1296,6 +1320,8 @@ elf_s390_check_relocs (bfd *abfd,
 
              p->count += 1;
              if (ELF64_R_TYPE (rel->r_info) == R_390_PC16
+                 || ELF64_R_TYPE (rel->r_info) == R_390_PC12DBL
+                 || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL
                  || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL
                  || ELF64_R_TYPE (rel->r_info) == R_390_PC32
                  || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL
@@ -1467,7 +1493,9 @@ elf_s390_gc_sweep_hook (bfd *abfd,
        case R_390_32:
        case R_390_64:
        case R_390_PC16:
+       case R_390_PC12DBL:
        case R_390_PC16DBL:
+       case R_390_PC24DBL:
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC64:
@@ -1475,7 +1503,9 @@ elf_s390_gc_sweep_hook (bfd *abfd,
            break;
          /* Fall through */
 
+       case R_390_PLT12DBL:
        case R_390_PLT16DBL:
+       case R_390_PLT24DBL:
        case R_390_PLT32:
        case R_390_PLT32DBL:
        case R_390_PLT64:
@@ -2343,11 +2373,12 @@ 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))
@@ -2465,6 +2496,37 @@ elf_s390_relocate_section (bfd *output_bfd,
                                  base_got->contents + off);
                      h->got.offset |= 1;
                    }
+
+                 if ((h->def_regular
+                      && info->shared
+                      && SYMBOL_REFERENCES_LOCAL (info, h))
+                     /* lgrl rx,sym@GOTENT -> larl rx, sym */
+                     && ((r_type == R_390_GOTENT
+                          && (bfd_get_16 (input_bfd,
+                                          contents + rel->r_offset - 2)
+                              & 0xff0f) == 0xc408)
+                         /* lg 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) == 0x04)))
+
+                   {
+                     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;
@@ -2546,7 +2608,9 @@ elf_s390_relocate_section (bfd *output_bfd,
          unresolved_reloc = FALSE;
          break;
 
+       case R_390_PLT12DBL:
        case R_390_PLT16DBL:
+       case R_390_PLT24DBL:
        case R_390_PLT32:
        case R_390_PLT32DBL:
        case R_390_PLT64:
@@ -2611,7 +2675,9 @@ elf_s390_relocate_section (bfd *output_bfd,
        case R_390_32:
        case R_390_64:
        case R_390_PC16:
+       case R_390_PC12DBL:
        case R_390_PC16DBL:
+       case R_390_PC24DBL:
        case R_390_PC32:
        case R_390_PC32DBL:
        case R_390_PC64:
@@ -2685,7 +2751,9 @@ elf_s390_relocate_section (bfd *output_bfd,
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                   || 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_PC24DBL
                    && r_type != R_390_PC32
                    && r_type != R_390_PC32DBL
                    && r_type != R_390_PC64)
@@ -2727,7 +2795,9 @@ elf_s390_relocate_section (bfd *output_bfd,
              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_PC24DBL
                           || r_type == R_390_PC32
                           || r_type == R_390_PC32DBL
                           || r_type == R_390_PC64
@@ -3164,6 +3234,13 @@ elf_s390_relocate_section (bfd *output_bfd,
 
     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
@@ -3615,8 +3692,9 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
                       - htab->elf.splt->output_section->vma - 6)/2,
                      htab->elf.splt->contents + 8);
        }
-      elf_section_data (htab->elf.splt->output_section)
-       ->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
+      if (elf_section_data (htab->elf.splt->output_section) != NULL)
+       elf_section_data (htab->elf.splt->output_section)->this_hdr.sh_entsize
+         = PLT_ENTRY_SIZE;
     }
 
   if (htab->elf.sgotplt)
@@ -3717,7 +3795,7 @@ const struct elf_size_info s390_elf64_size_info =
   bfd_elf64_swap_reloca_out
 };
 
-#define TARGET_BIG_SYM bfd_elf64_s390_vec
+#define TARGET_BIG_SYM s390_elf64_vec
 #define TARGET_BIG_NAME        "elf64-s390"
 #define ELF_ARCH       bfd_arch_s390
 #define ELF_TARGET_ID  S390_ELF_DATA
This page took 0.027637 seconds and 4 git commands to generate.