* elf32-score.c (score_elf_got_lo16_reloc): Change some variables type from
authorMei Ligang <ligang@sunnorth.com.cn>
Mon, 25 Dec 2006 09:22:06 +0000 (09:22 +0000)
committerMei Ligang <ligang@sunnorth.com.cn>
Mon, 25 Dec 2006 09:22:06 +0000 (09:22 +0000)
unsigned to signed.
(score_elf_final_link_relocate): Fix bugs of handling relocation type R_SCORE_GOT15,
R_SCORE_GOT_LO16, and R_SCORE_REL32.
(_bfd_score_elf_relocate_section): Handle R_SCORE_GOT_LO16 specially.

bfd/ChangeLog
bfd/elf32-score.c

index 8913eaab3b4a3fb76b2e2f9df6929b3d91e9447a..0b86d0d7b6c10e1b791e7c617e3819da996dd3e6 100644 (file)
@@ -1,3 +1,11 @@
+2006-12-25  Mei Ligang  <ligang@sunnorth.com.cn>
+       
+       * elf32-score.c (score_elf_got_lo16_reloc): Change some variables type from
+       unsigned to signed.
+       (score_elf_final_link_relocate): Fix bugs of handling relocation type R_SCORE_GOT15,
+       R_SCORE_GOT_LO16, and R_SCORE_REL32.
+       (_bfd_score_elf_relocate_section): Handle R_SCORE_GOT_LO16 specially.
+
 2006-12-23  Jakub Jelinek  <jakub@redhat.com>
 
        * elf-bfd.h (struct elf_backend_data): Add as_needed_cleanup hook.
index 17c4aa974f9bb84db43f23dfa89d58125180502b..1246e26156d619dcbddb97d6c3cb59a58fb6d1eb 100644 (file)
@@ -532,8 +532,8 @@ score_elf_got_lo16_reloc (bfd *abfd,
                          char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma addend = 0, offset = 0;
-  unsigned long val;
-  unsigned long hi16_offset, hi16_value, uvalue;
+  signed long val;
+  signed long hi16_offset, hi16_value, uvalue;
 
   hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
   hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
@@ -543,7 +543,10 @@ score_elf_got_lo16_reloc (bfd *abfd,
   if (reloc_entry->address > input_section->size)
     return bfd_reloc_outofrange;
   uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
-  hi16_offset = (uvalue >> 16) & 0x7fff;
+  if ((uvalue > -0x8000) && (uvalue < 0x7fff))
+    hi16_offset = 0;
+  else
+    hi16_offset = (uvalue >> 16) & 0x7fff;
   hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
   bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
   offset = (uvalue & 0xffff) << 1;
@@ -1897,6 +1900,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
   r_symndx = ELF32_R_SYM (rel->r_info);
   r_type = ELF32_R_TYPE (rel->r_info);
   rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
+  local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE);
 
   if (r_type == R_SCORE_GOT15)
     {
@@ -1905,25 +1909,22 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
       const struct elf_backend_data *bed;
       bfd_vma lo_value = 0;
 
-      addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
-
       bed = get_elf_backend_data (output_bfd);
       relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
       lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
-      if (lo16_rel != NULL)
+      if ((local_p) && (lo16_rel != NULL))
        {
-          lo_value = (bfd_get_32 (input_bfd, contents + lo16_rel->r_offset) >> howto->bitpos)
-                      & howto->src_mask;
+         bfd_vma tmp = 0;
+         tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
+         lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1);
        }
-      addend = (addend << 16) + lo_value;
+      addend = lo_value;
     }
   else
     {
       addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
     }
 
-  local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE);
-
   /* If we haven't already determined the GOT offset, or the GP value,
      and we're going to need it, get it now.  */
   switch (r_type)
@@ -1932,9 +1933,21 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
     case R_SCORE_GOT15:
       if (!local_p)
         {
-         g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
-                                         (struct elf_link_hash_entry *) h);
-       }
+          g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
+                                          (struct elf_link_hash_entry *) h);
+          if ((! elf_hash_table(info)->dynamic_sections_created
+               || (info->shared
+                   && (info->symbolic || h->root.dynindx == -1)
+                   && h->root.def_regular)))
+            {
+              /* This is a static link or a -Bsymbolic link.  The
+                 symbol is defined locally, or was forced to be local.
+                 We must initialize this entry in the GOT.  */
+              bfd *tmpbfd = elf_hash_table (info)->dynobj;
+              asection *sgot = score_elf_got_section (tmpbfd, FALSE);
+              bfd_put_32 (tmpbfd, value, sgot->contents + g);
+            }
+        }
       else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
         {
          /* There's no need to create a local GOT entry here; the
@@ -1993,6 +2006,11 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
                                                    input_section))
            return bfd_reloc_undefined;
        }
+      else if (r_symndx == 0)
+        /* r_symndx will be zero only for relocs against symbols
+           from removed linkonce sections, or sections discarded by
+           a linker script.  */
+        value = 0;
       else
        {
          if (r_type != R_SCORE_REL32)
@@ -2122,7 +2140,10 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
 
       if ((long) value > 0x3fff || (long) value < -0x4000)
         return bfd_reloc_overflow;
-      bfd_put_16 (input_bfd, value, hit_data + 2);
+
+      addend = bfd_get_32 (input_bfd, hit_data);
+      value = (addend & ~howto->dst_mask) | (value & howto->dst_mask);
+      bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_GPREL32:
@@ -2133,10 +2154,10 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
 
     case R_SCORE_GOT_LO16:
       addend = bfd_get_32 (input_bfd, hit_data);
-      value = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
+      value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1);
       value += symbol;
-      offset = (value & 0xffff) << 1;
-      value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
+      value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)  
+               | (((value >> 14) & 0x3) << 16);
 
       bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
@@ -2303,6 +2324,17 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
                     | (offset & 0x7fff) | ((offset << 1) & 0x30000);
                   bfd_put_32 (input_bfd, value, contents + rel->r_offset);
                   break;
+                case R_SCORE_GOT_LO16:
+                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
+                  addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
+                  msec = sec;
+                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+                  addend += msec->output_section->vma + msec->output_offset;
+                  value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
+                           | (((addend >> 14) & 0x3) << 16);
+
+                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                  break;
                 default:
                   value = bfd_get_32 (input_bfd, contents + rel->r_offset);
                   /* Get the (signed) value from the instruction.  */