2012-02-24 Luis Machado <lgustavo@codesourcery>
[deliverable/binutils-gdb.git] / bfd / elf32-s390.c
index bc8e054a841836169b8d5e220bc3c5dc935fa1e2..85a20bdc46bf9365eff367fd4505facb87a48a1e 100644 (file)
@@ -1,6 +1,6 @@
 /* IBM S/390-specific support for 32-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2011 Free Software Foundation, Inc.
    Contributed by Carl B. Pedersen and Martin Schwidefsky.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -1696,12 +1696,6 @@ allocate_dynrelocs (h, inf)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   info = (struct bfd_link_info *) inf;
   htab = elf_s390_hash_table (info);
 
@@ -1922,9 +1916,6 @@ readonly_dynrelocs (h, inf)
   struct elf_s390_link_hash_entry *eh;
   struct elf_s390_dyn_relocs *p;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   eh = (struct elf_s390_link_hash_entry *) h;
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
     {
@@ -2292,15 +2283,8 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
        }
 
       if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, relend, howto, contents);
 
       if (info->relocatable)
        continue;
@@ -2878,7 +2862,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
 
        case R_390_TLS_LDO32:
-         if (info->shared)
+         if (info->shared || (input_section->flags & SEC_DEBUGGING))
            relocation -= dtpoff_base (info);
          else
            /* When converting LDO to LE, we must negate.  */
@@ -2935,11 +2919,18 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
 
              insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
              if ((insn & 0xff000fff) != 0x4d000000 &&
-                 (insn & 0xffff0000) != 0xc0e50000)
+                 (insn & 0xffff0000) != 0xc0e50000 &&
+                 (insn & 0xff000000) != 0x0d000000)
                invalid_tls_insn (input_bfd, input_section, rel);
              if (!info->shared && (h == NULL || h->dynindx == -1))
                {
-                 if ((insn & 0xff000000) == 0x4d000000)
+                 if ((insn & 0xff000000) == 0x0d000000)
+                   {
+                     /* GD->LE transition.
+                        basr rx, ry -> nopr r7 */
+                     insn = 0x07070000 | (insn & 0xffff);
+                   }
+                 else if ((insn & 0xff000000) == 0x4d000000)
                    {
                      /* GD->LE transition.
                         bas %r14,0(%rx,%r13) -> bc 0,0  */
@@ -2948,7 +2939,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                  else
                    {
                      /* GD->LE transition.
-                        brasl %r14,_tls_get_addr@plt -> brcl 0,.  */
+                        brasl %r14,_tls_get_offset@plt -> brcl 0,.  */
                      insn = 0xc0040000;
                      bfd_put_16 (output_bfd, 0x0000,
                                  contents + rel->r_offset + 4);
@@ -2956,6 +2947,11 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                }
              else
                {
+                 /* 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);
+
                  if ((insn & 0xff000000) == 0x4d000000)
                    {
                      /* GD->IE transition.
@@ -2982,9 +2978,17 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
 
                  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
                  if ((insn & 0xff000fff) != 0x4d000000 &&
-                     (insn & 0xffff0000) != 0xc0e50000)
+                     (insn & 0xffff0000) != 0xc0e50000 &&
+                     (insn & 0xff000000) != 0x0d000000)
                    invalid_tls_insn (input_bfd, input_section, rel);
-                 if ((insn & 0xff000000) == 0x4d000000)
+
+                 if ((insn & 0xff000000) == 0x0d000000)
+                   {
+                     /* LD->LE transition.
+                        basr rx, ry -> nopr r7 */
+                     insn = 0x07070000 | (insn & 0xffff);
+                   }
+                 else if ((insn & 0xff000000) == 0x4d000000)
                    {
                      /* LD->LE transition.
                         bas %r14,0(%rx,%r13) -> bc 0,0  */
@@ -2993,7 +2997,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
                  else
                    {
                      /* LD->LE transition.
-                        brasl %r14,__tls_get_addr@plt -> brcl 0,. */
+                        brasl %r14,__tls_get_offset@plt -> brcl 0,. */
                      insn = 0xc0040000;
                      bfd_put_16 (output_bfd, 0x0000,
                                  contents + rel->r_offset + 4);
@@ -3012,7 +3016,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
         not process them.  */
       if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
-              && h->def_dynamic))
+              && h->def_dynamic)
+         && _bfd_elf_section_offset (output_bfd, info, input_section,
+                                     rel->r_offset) != (bfd_vma) -1)
        (*_bfd_error_handler)
          (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
This page took 0.025269 seconds and 4 git commands to generate.