* elf32-bfin.c (bfin_howto_table): Set src_mask to 0 for all relocs.
authorJie Zhang <jie.zhang@analog.com>
Mon, 24 Oct 2005 14:25:13 +0000 (14:25 +0000)
committerJie Zhang <jie.zhang@analog.com>
Mon, 24 Oct 2005 14:25:13 +0000 (14:25 +0000)
(bfin_imm16_reloc): Always add in the addend.  Don't fetch existing
contents from section.
(bfin_relocate_section): Rework so as to not call special_functions.
Handle the relocation stack here.  Treat pcrel24 relocs specially.

bfd/ChangeLog
bfd/elf32-bfin.c

index fcb1fbc..2d98ebd 100644 (file)
@@ -1,3 +1,11 @@
+2005-10-24  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+       * elf32-bfin.c (bfin_howto_table): Set src_mask to 0 for all relocs.
+       (bfin_imm16_reloc): Always add in the addend.  Don't fetch existing
+       contents from section.
+       (bfin_relocate_section): Rework so as to not call special_functions.
+       Handle the relocation stack here.  Treat pcrel24 relocs specially.
+
 2005-10-24  Alan Modra  <amodra@bigpond.net.au>
 
        * elflink.c (elf_link_input_bfd): Don't use linker_mark and
index 72f8aee..7cfefd7 100644 (file)
@@ -433,11 +433,8 @@ bfin_imm16_reloc (bfd *abfd,
       if (!relocatable || !strcmp (symbol->name, symbol->section->name))
        relocation += output_base + symbol->section->output_offset;
 
-      if (symbol->flags & BSF_SECTION_SYM)
-       {
-         /* Add in supplied addend.  */
-         relocation += reloc_entry->addend;
-       }
+      /* Add in supplied addend.  */
+      relocation += reloc_entry->addend;
     }
   else
     {
@@ -470,7 +467,6 @@ bfin_imm16_reloc (bfd *abfd,
   /* Here the variable relocation holds the final address of the
      symbol we are relocating against, plus any addend.  */
 
-  x = bfd_get_16 (abfd, (bfd_byte *) data + reloc_addr);
   relocation >>= (bfd_vma) howto->rightshift;
   x = relocation;
   bfd_put_16 (abfd, x, (unsigned char *) data + reloc_addr);
@@ -759,7 +755,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_pcrel5m2",          /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x0000000F,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x0000000F,            /* dst_mask.  */
         FALSE),                /* pcrel_offset.  */
 
@@ -787,7 +783,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_pcrel10",           /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x000003FF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x000003FF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
  
@@ -805,7 +801,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_pcrel12_jump",      /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x0FFF,                /* src_mask.  */
+        0,                     /* src_mask.  */
         0x0FFF,                /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -819,7 +815,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_imm16_reloc,      /* special_function.  */
         "R_rimm16",            /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x0000FFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x0000FFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -833,7 +829,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_imm16_reloc,      /* special_function.  */
         "R_luimm16",           /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x0000FFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x0000FFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
  
@@ -847,7 +843,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_imm16_reloc,      /* special_function.  */
         "R_huimm16",           /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x0000FFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x0000FFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -861,7 +857,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_pcrel12_jump_s",    /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x00000FFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x00000FFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -875,7 +871,7 @@ static reloc_howto_type bfin_howto_table [] =
          bfin_pcrel24_reloc,   /* special_function.  */
          "R_pcrel24_jump_x",   /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x00FFFFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x00FFFFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -889,7 +885,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_pcrel24_reloc,    /* special_function.  */
         "R_pcrel24",           /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x00FFFFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x00FFFFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -931,7 +927,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_pcrel24_reloc,    /* special_function.  */
         "R_pcrel24_jump_l",    /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x00FFFFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x00FFFFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -945,7 +941,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_pcrel24_reloc,    /* special_function.  */
         "R_pcrel24_call_x",    /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x00FFFFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x00FFFFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -973,7 +969,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_byte_data",         /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0xFF,                  /* src_mask.  */
+        0,                     /* src_mask.  */
         0xFF,                  /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -987,7 +983,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_byte2_data",        /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0xFFFF,                /* src_mask.  */
+        0,                     /* src_mask.  */
         0xFFFF,                /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -1001,7 +997,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_byte4_reloc,      /* special_function.  */
         "R_byte4_data",        /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0xFFFFFFFF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0xFFFFFFFF,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
 
@@ -1015,7 +1011,7 @@ static reloc_howto_type bfin_howto_table [] =
         bfin_bfd_reloc,        /* special_function.  */
         "R_pcrel11",           /* name.  */
         FALSE,                 /* partial_inplace.  */
-        0x000003FF,            /* src_mask.  */
+        0,                     /* src_mask.  */
         0x000003FF,            /* dst_mask.  */
         FALSE),                /* pcrel_offset.  */
 };
@@ -1660,6 +1656,7 @@ elf32_bfin_reloc_type_class (const Elf_Internal_Rela * rela)
       return reloc_class_normal;
     }
 }
+
 static bfd_boolean
 bfin_relocate_section (bfd * output_bfd,
                       struct bfd_link_info *info,
@@ -1678,7 +1675,6 @@ bfin_relocate_section (bfd * output_bfd,
   asection *sreloc;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
-  char *error_msg = NULL;
   int i = 0;
 
   if (info->relocatable)
@@ -1705,6 +1701,7 @@ bfin_relocate_section (bfd * output_bfd,
       bfd_vma relocation = 0;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
+      bfd_vma address;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type < 0 || r_type >= 243)
@@ -1735,10 +1732,6 @@ bfin_relocate_section (bfd * output_bfd,
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-         /* Call to bfd_elf_rela_local_sym would have CHANGED the sec
-             as well as updated relocation. The value returned is
-             w.r.t the original section.  */
-         sec = local_sections[r_symndx];
        }
       else
        {
@@ -1762,6 +1755,45 @@ bfin_relocate_section (bfd * output_bfd,
            }
        }
 
+      address = rel->r_offset;
+      /* First, get stack relocs out of the way.  */
+      switch (r_type)
+       {
+       case R_push:
+         reloc_stack_push (relocation + rel->r_addend);
+         r = bfd_reloc_ok;
+         goto done_reloc;
+       case R_const:
+         reloc_stack_push (rel->r_addend);
+         r = bfd_reloc_ok;
+         goto done_reloc;
+       case R_add:
+       case R_sub:
+       case R_mult:
+       case R_div:
+       case R_mod:
+       case R_lshift:
+       case R_rshift:
+       case R_neg:
+       case R_and:
+       case R_or:
+       case R_xor:
+       case R_land:
+       case R_lor:
+       case R_comp:
+       case R_page:
+       case R_hwpage:
+         reloc_stack_operate (r_type);
+         r = bfd_reloc_ok;
+         goto done_reloc;
+
+       default:
+         if (!is_reloc_stack_empty())
+           relocation = reloc_stack_pop ();
+         break;
+       }
+
+      /* Then, process normally.  */
       switch (r_type)
        {
        case R_BFIN_GNU_VTINHERIT:
@@ -1773,7 +1805,7 @@ bfin_relocate_section (bfd * output_bfd,
             in the global offset table.  */
          if (h != NULL
              && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
-           break;
+           goto do_default;
          /* Fall through.  */
          /* Relocation is the offset of the entry for this symbol in
             the global offset table.  */
@@ -1793,13 +1825,14 @@ bfin_relocate_section (bfd * output_bfd,
 
                off = h->got.offset;
                BFD_ASSERT (off != (bfd_vma) - 1);
-
                dyn = elf_hash_table (info)->dynamic_sections_created;
+
                if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
                    || (info->shared
                        && (info->symbolic
                            || h->dynindx == -1
-                           || h->forced_local) && h->def_regular))
+                           || h->forced_local)
+                       && h->def_regular))
                  {
                    /* This is actually a static link, or it is a
                       -Bsymbolic link and the symbol is defined
@@ -1827,10 +1860,9 @@ bfin_relocate_section (bfd * output_bfd,
              }
            else
              {
-               BFD_ASSERT (local_got_offsets != NULL
-                           && local_got_offsets[r_symndx] != (bfd_vma) - 1);
-
+               BFD_ASSERT (local_got_offsets != NULL);
                off = local_got_offsets[r_symndx];
+               BFD_ASSERT (off != (bfd_vma) - 1);
 
                /* The offset must always be a multiple of 4.  We use
                   the least significant bit to record whether we have
@@ -1839,7 +1871,6 @@ bfin_relocate_section (bfd * output_bfd,
                  off &= ~1;
                else
                  {
-
                    bfd_put_32 (output_bfd, relocation, sgot->contents + off);
 
                    if (info->shared)
@@ -1871,71 +1902,52 @@ bfin_relocate_section (bfd * output_bfd,
             /* bfin : preg = [preg + 17bitdiv4offset] relocation is div by 4.  */
             relocation /= 4;
          }
+         goto do_default;
+
+       case R_pcrel24:
+       case R_pcrel24_jump_l:
+         {
+           bfd_vma x;
+
+           relocation += rel->r_addend;
+
+           /* Perform usual pc-relative correction.  */
+           relocation -= input_section->output_section->vma + input_section->output_offset;
+           relocation -= address;
+
+           /* We are getting reloc_entry->address 2 byte off from
+              the start of instruction. Assuming absolute postion
+              of the reloc data. But, following code had been written assuming 
+              reloc address is starting at begining of instruction.
+              To compensate that I have increased the value of 
+              relocation by 1 (effectively 2) and used the addr -2 instead of addr.  */ 
+
+           relocation += 2;
+           address -= 2;
+
+           relocation >>= 1;
+
+           x = bfd_get_16 (input_bfd, contents + address);
+           x = (x & 0xff00) | ((relocation >> 16) & 0xff);
+           bfd_put_16 (input_bfd, x, contents + address);
+
+           x = bfd_get_16 (input_bfd, contents + address + 2);
+           x = relocation & 0xFFFF;
+           bfd_put_16 (input_bfd, x, contents + address + 2);
+           r = bfd_reloc_ok;
+         }
          break;
 
        default:
-         if (howto->special_function)
-           {
-             bfd_reloc_status_type cont;
-             arelent reloc_ent;
-             asymbol symbol;
-             asymbol *symbol1;
-             symbol.flags = 0;
-             symbol.section = bfd_und_section_ptr;
-             symbol.value = 0;
-
-             if (h != NULL)
-               {
-                 if (unresolved_reloc)
-                   {
-                     break;
-                   }
-                 if (h->root.type != bfd_link_hash_undefweak
-                     && h->root.type != bfd_link_hash_undefined)
-                   {
-                     symbol.the_bfd = input_bfd;
-                     symbol.section = h->root.u.def.section;
-                     symbol.name = h->root.root.string;
-                     symbol.value = h->root.u.def.value;
-                   }
-                 if (h->root.type == bfd_link_hash_defweak
-                      || h->root.type == bfd_link_hash_undefweak)
-                   {
-                     symbol.name = h->root.root.string;
-                     symbol.flags |= BSF_WEAK;
-                   }
-               }
-             else
-               {
-                 symbol = *sec->symbol;
-               }
-             reloc_ent.address = rel->r_offset;
-             reloc_ent.howto = howto;
-             reloc_ent.addend = rel->r_addend;
-             symbol1 = &symbol;
-             reloc_ent.sym_ptr_ptr = &symbol1;
-
-             cont =
-               howto->special_function (input_bfd, &reloc_ent, &symbol,
-                                        contents, input_section,
-                                        info->
-                                        relocatable ? output_bfd : NULL,
-                                        &error_msg);
-             if (cont == bfd_reloc_ok)
-               {
-                 continue;
-               }
-           }
-         else
-           {
-             fprintf (stderr, "%s no special func r_type is %d\n",
-                      input_bfd->filename, r_type);
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
+       do_default:
+         r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                       contents, address,
+                                       relocation, rel->r_addend);
+
          break;
        }
 
+    done_reloc:
       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
          because such sections are not SEC_ALLOC and thus ld.so will
          not process them.  */
@@ -1949,10 +1961,6 @@ bfin_relocate_section (bfd * output_bfd,
          return FALSE;
        }
 
-      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                   contents, rel->r_offset,
-                                   relocation, rel->r_addend);
-
       if (r != bfd_reloc_ok)
        {
          const char *name;