This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
index 45b5f5d1d9b697cd2ed881694c362410961cf091..e71353df55f18b65d6609d8c63195bf337bef4c2 100644 (file)
@@ -53,7 +53,7 @@ static boolean v850_elf_check_relocs
 static void remember_hi16s_reloc
   PARAMS ((bfd *, bfd_vma, bfd_byte *));
 static bfd_byte * find_remembered_hi16s_reloc
-  PARAMS ((bfd_vma addend));
+  PARAMS ((bfd_vma, boolean *));
 static bfd_reloc_status_type v850_elf_final_link_relocate
   PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma,
           bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int));
@@ -343,8 +343,6 @@ static reloc_howto_type v850_elf_howto_table[] =
         0xfff,                         /* dst_mask */
         false),                        /* pcrel_offset */
 
-/* start-sanitize-v850e */
-  
   /* 5 bit offset from the tiny data area pointer.  */
   HOWTO (R_V850_TDA_4_5_OFFSET,                /* type */
         1,                             /* rightshift */
@@ -435,7 +433,6 @@ static reloc_howto_type v850_elf_howto_table[] =
         0xffff,                        /* dst_mask */
         false),                        /* pcrel_offset */
 
-/* end-sanitize-v850e */
   /* GNU extension to record C++ vtable hierarchy */
   HOWTO (R_V850_GNU_VTINHERIT, /* type */
          0,                     /* rightshift */
@@ -472,7 +469,9 @@ static reloc_howto_type v850_elf_howto_table[] =
 
 struct v850_elf_reloc_map
 {
-  unsigned char bfd_reloc_val;
+  /* BFD_RELOC_V850_CALLT_16_16_OFFSET is 258, which will not fix in an
+     unsigned char.  */
+  bfd_reloc_code_real_type bfd_reloc_val;
   unsigned char elf_reloc_val;
 };
 
@@ -495,14 +494,12 @@ static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
   { BFD_RELOC_V850_TDA_7_8_OFFSET,   R_V850_TDA_7_8_OFFSET   },
   { BFD_RELOC_V850_TDA_7_7_OFFSET,   R_V850_TDA_7_7_OFFSET   },
   { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
-/* start-sanitize-v850e */
   { BFD_RELOC_V850_TDA_4_5_OFFSET,         R_V850_TDA_4_5_OFFSET         },
   { BFD_RELOC_V850_TDA_4_4_OFFSET,         R_V850_TDA_4_4_OFFSET         },
   { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
   { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
   { BFD_RELOC_V850_CALLT_6_7_OFFSET,       R_V850_CALLT_6_7_OFFSET       },
   { BFD_RELOC_V850_CALLT_16_16_OFFSET,     R_V850_CALLT_16_16_OFFSET     },
-/* end-sanitize-v850e */
   { BFD_RELOC_VTABLE_INHERIT,               R_V850_GNU_VTINHERIT },
   { BFD_RELOC_VTABLE_ENTRY,                 R_V850_GNU_VTENTRY },
 
@@ -623,10 +620,8 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
        case R_V850_32:
        case R_V850_16:
        case R_V850_8:
-/* start-sanitize-v850e */
        case R_V850_CALLT_6_7_OFFSET:
        case R_V850_CALLT_16_16_OFFSET:
-/* end-sanitize-v850e */
          break;
 
         /* This relocation describes the C++ object vtable hierarchy.
@@ -643,28 +638,22 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
             return false;
           break;
 
-/* start-sanitize-v850e */
        case R_V850_SDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
        case R_V850_SDA_16_16_OFFSET:
        case R_V850_SDA_15_16_OFFSET:
          other = V850_OTHER_SDA;
          common = ".scommon";
          goto small_data_common;
          
-/* start-sanitize-v850e */
        case R_V850_ZDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
        case R_V850_ZDA_16_16_OFFSET:
        case R_V850_ZDA_15_16_OFFSET:
          other = V850_OTHER_ZDA;
          common = ".zcommon";
          goto small_data_common;
          
-/* start-sanitize-v850e */
        case R_V850_TDA_4_5_OFFSET:
        case R_V850_TDA_4_4_OFFSET:
-/* end-sanitize-v850e */         
        case R_V850_TDA_6_8_OFFSET:
        case R_V850_TDA_7_8_OFFSET:
        case R_V850_TDA_7_7_OFFSET:
@@ -735,11 +724,27 @@ v850_elf_check_relocs (abfd, info, sec, relocs)
   return ret;
 }
 
+/*
+ * In the old version, when an entry was checked out from the table,
+ * it was deleted.  This produced an error if the entry was needed
+ * more than once, as the second attempted retry failed.
+ *
+ * In the current version, the entry is not deleted, instead we set
+ * the field 'found' to true.  If a second lookup matches the same
+ * entry, then we know that the hi16s reloc has already been updated
+ * and does not need to be updated a second time.
+ *
+ * TODO - TOFIX: If it is possible that we need to restore 2 different
+ * addresses from the same table entry, where the first generates an
+ * overflow, whilst the second do not, then this code will fail.
+ */
+
 typedef struct hi16s_location
 {
   bfd_vma       addend;
   bfd_byte *    address;
   unsigned long counter;
+  boolean       found;
   struct hi16s_location * next;
 }
 hi16s_location;
@@ -760,12 +765,13 @@ remember_hi16s_reloc (abfd, addend, address)
   if (free_hi16s == NULL)
     free_hi16s = (hi16s_location *) bfd_zalloc (abfd, sizeof (* free_hi16s));
 
-  entry = free_hi16s;
+  entry      = free_hi16s;
   free_hi16s = free_hi16s->next;
   
   entry->addend  = addend;
   entry->address = address;
   entry->counter = hi16s_counter ++;
+  entry->found   = false;
   entry->next    = previous_hi16s;
   previous_hi16s = entry;
   
@@ -783,8 +789,9 @@ remember_hi16s_reloc (abfd, addend, address)
 }
 
 static bfd_byte *
-find_remembered_hi16s_reloc (addend)
-     bfd_vma addend;
+find_remembered_hi16s_reloc (addend, already_found)
+     bfd_vma   addend;
+     boolean * already_found;
 {
   hi16s_location * match = NULL;
   hi16s_location * entry;
@@ -796,15 +803,13 @@ find_remembered_hi16s_reloc (addend)
   /* Search the table.  Record the most recent entry that matches.  */
   for (entry = previous_hi16s; entry; entry = entry->next)
     {
-      if (entry->addend == addend)
+      if (entry->addend == addend
+         && (match == NULL || match->counter < entry->counter))
        {
-         if (match == NULL || match->counter < entry->counter)
-           {
-             previous = prev;
-             match    = entry;
-           }
+         previous = prev;
+         match    = entry;
        }
-         
+      
       prev = entry;
     }
 
@@ -813,18 +818,13 @@ find_remembered_hi16s_reloc (addend)
 
   /* Extract the address.  */
   addr = match->address;
-  
-  /* Attach the entry to the free list.  */
-  if (previous)
-    previous->next = match->next;
-  else
-    previous_hi16s = match->next;
-  
-  match->next = free_hi16s->next;
-  free_hi16s  = match;
-  
-  match->addend  = 0;
-  match->address = NULL;
+
+  /* Remeber if this entry has already been used before.  */
+  if (already_found)
+    * already_found = match->found;
+
+  /* Note that this entry has now been used.  */
+  match->found = true;
   
   return addr;
 }     
@@ -1052,14 +1052,19 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
            || (OVERFLOWS (addend, insn)
                && ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
          {
-           bfd_byte * hi16s_address = find_remembered_hi16s_reloc (addend);
+           boolean already_updated;
+           bfd_byte * hi16s_address = find_remembered_hi16s_reloc
+             (addend, & already_updated);
            
            /* Amend the matching HI16_S relocation.  */
            if (hi16s_address != NULL)
              {
-               insn = bfd_get_16 (abfd, hi16s_address);
-               insn += 1;
-               bfd_put_16 (abfd, insn, hi16s_address);
+               if (! already_updated)
+                 {
+                   insn = bfd_get_16 (abfd, hi16s_address);
+                   insn += 1;
+                   bfd_put_16 (abfd, insn, hi16s_address);
+                 }
              }
            else
              {
@@ -1084,7 +1089,6 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
       bfd_put_8 (abfd, addend, address);
       return bfd_reloc_ok;
 
-/* start-sanitize-v850e */
     case R_V850_CALLT_16_16_OFFSET:
       addend += bfd_get_16 (abfd, address);
       
@@ -1095,7 +1099,6 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
 
       insn = addend;
       break;
-/* end-sanitize-v850e */
       
     case R_V850_16:
 
@@ -1174,7 +1177,6 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
       insn |= addend;
       break;
       
-/* start-sanitize-v850e */
     case R_V850_TDA_4_5_OFFSET:
       insn = bfd_get_16 (abfd, address);
       addend += ((insn & 0xf) << 1);
@@ -1236,7 +1238,6 @@ v850_elf_perform_relocation (abfd, r_type, addend, address)
       insn &= 0xff80;
       insn |= (addend >> 1);
       break;
-/* end-sanitize-v850e */
 
     case R_V850_GNU_VTINHERIT:
     case R_V850_GNU_VTENTRY:
@@ -1381,9 +1382,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
 
     case R_V850_ZDA_15_16_OFFSET:      
     case R_V850_ZDA_16_16_OFFSET:
-/* start-sanitize-v850e */
     case R_V850_ZDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
       if (sym_sec == NULL)
        return bfd_reloc_undefined;
          
@@ -1392,9 +1391,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
 
     case R_V850_SDA_15_16_OFFSET:
     case R_V850_SDA_16_16_OFFSET:
-/* start-sanitize-v850e */
     case R_V850_SDA_16_16_SPLIT_OFFSET:
-/* end-sanitize-v850e */
       {
        unsigned long                gp;
        struct bfd_link_hash_entry * h;
@@ -1417,10 +1414,8 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
       }
     break;
 
-/* start-sanitize-v850e */
     case R_V850_TDA_4_4_OFFSET:
     case R_V850_TDA_4_5_OFFSET:
-/* end-sanitize-v850e */
     case R_V850_TDA_16_16_OFFSET:
     case R_V850_TDA_7_7_OFFSET:
     case R_V850_TDA_7_8_OFFSET:
@@ -1443,7 +1438,6 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
       }
     break;
     
-/* start-sanitize-v850e */
     case R_V850_CALLT_6_7_OFFSET:
       {
        unsigned long                ctbp;
@@ -1484,7 +1478,6 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
        value -= (ctbp - sym_sec->output_section->vma);
       }
     break;
-/* end-sanitize-v850e */
       
     case R_V850_NONE:
     case R_V850_GNU_VTINHERIT:
@@ -1521,6 +1514,19 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
 
+  if (sym_hashes == NULL)
+    {
+      info->callbacks->warning
+       (info, "no hash table available", NULL, input_bfd, input_section, 0);
+
+      return false;
+    }
+  
+  /* Reset the list of remembered HI16S relocs to empty.  */
+  free_hi16s     = previous_hi16s;
+  previous_hi16s = NULL;
+  hi16s_counter  = 0;
+  
   rel    = relocs;
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; rel++)
@@ -1541,7 +1547,7 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
           || r_type == R_V850_GNU_VTINHERIT)
         continue;
 
-      howto    = v850_elf_howto_table + r_type;
+      howto = v850_elf_howto_table + r_type;
 
       if (info->relocateable)
        {
@@ -1765,10 +1771,8 @@ v850_elf_object_p (abfd)
     {
     default:
     case E_V850_ARCH:   (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
-/* start-sanitize-v850e */
     case E_V850E_ARCH:  (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
     case E_V850EA_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850ea); break;
-/* end-sanitize-v850e */
     }
   return true;
 }
@@ -1785,10 +1789,8 @@ v850_elf_final_write_processing (abfd, linker)
     {
     default:
     case 0: val = E_V850_ARCH; break;
-/* start-sanitize-v850e */
     case bfd_mach_v850e:  val = E_V850E_ARCH; break;
     case bfd_mach_v850ea: val = E_V850EA_ARCH;  break;
-/* end-sanitize-v850e */
     }
 
   elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
@@ -1900,10 +1902,8 @@ v850_elf_print_private_bfd_data (abfd, ptr)
     {
     default:
     case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
-/* start-sanitize-v850e */
     case E_V850E_ARCH:  fprintf (file, _("v850e architecture")); break;
     case E_V850EA_ARCH: fprintf (file, _("v850ea architecture")); break;
-/* end-sanitize-v850e */
     }
   
   fputc ('\n', file);
This page took 0.032266 seconds and 4 git commands to generate.