This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Blackfin patch: Clean up bfin_relocate_section


This patch cleans up bfin_relocate_section - the BFD documentation suggests that it shouldn't be calling the howto's special_function, and cleaning that up solved some problems I was having with some upcoming assembler modifications.

I'm working on this port at Analog Devices together with Jie Zhang. Can I add myself to the MAINTAINERS file? In the meantime, could someone approve the patch please?


Bernd
	* 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.

Index: elf32-bfin.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-bfin.c,v
retrieving revision 1.1
diff -c -p -r1.1 elf32-bfin.c
*** elf32-bfin.c	30 Sep 2005 15:36:41 -0000	1.1
--- elf32-bfin.c	24 Oct 2005 12:37:42 -0000
*************** bfin_imm16_reloc (bfd *abfd,
*** 433,443 ****
        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;
! 	}
      }
    else
      {
--- 433,440 ----
        if (!relocatable || !strcmp (symbol->name, symbol->section->name))
  	relocation += output_base + symbol->section->output_offset;
  
!       /* Add in supplied addend.  */
!       relocation += reloc_entry->addend;
      }
    else
      {
*************** bfin_imm16_reloc (bfd *abfd,
*** 470,476 ****
    /* 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);
--- 467,472 ----
*************** static reloc_howto_type bfin_howto_table
*** 759,765 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel5m2",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x0000000F,		/* src_mask.  */
  	 0x0000000F,		/* dst_mask.  */
  	 FALSE),		/* pcrel_offset.  */
  
--- 755,761 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel5m2",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x0000000F,		/* dst_mask.  */
  	 FALSE),		/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 787,793 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel10",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x000003FF,		/* src_mask.  */
  	 0x000003FF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
   
--- 783,789 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel10",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x000003FF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
   
*************** static reloc_howto_type bfin_howto_table
*** 805,811 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel12_jump",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x0FFF,		/* src_mask.  */
  	 0x0FFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 801,807 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel12_jump",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x0FFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 819,825 ****
  	 bfin_imm16_reloc,	/* special_function.  */
  	 "R_rimm16",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x0000FFFF,		/* src_mask.  */
  	 0x0000FFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 815,821 ----
  	 bfin_imm16_reloc,	/* special_function.  */
  	 "R_rimm16",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x0000FFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 833,839 ****
  	 bfin_imm16_reloc,	/* special_function.  */
  	 "R_luimm16",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x0000FFFF,		/* src_mask.  */
  	 0x0000FFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
   
--- 829,835 ----
  	 bfin_imm16_reloc,	/* special_function.  */
  	 "R_luimm16",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x0000FFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
   
*************** static reloc_howto_type bfin_howto_table
*** 847,853 ****
  	 bfin_imm16_reloc,	/* special_function.  */
  	 "R_huimm16",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x0000FFFF,		/* src_mask.  */
  	 0x0000FFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 843,849 ----
  	 bfin_imm16_reloc,	/* special_function.  */
  	 "R_huimm16",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x0000FFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 861,867 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel12_jump_s",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x00000FFF,		/* src_mask.  */
  	 0x00000FFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 857,863 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel12_jump_s",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x00000FFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 875,881 ****
           bfin_pcrel24_reloc,	/* special_function.  */
           "R_pcrel24_jump_x",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x00FFFFFF,		/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 871,877 ----
           bfin_pcrel24_reloc,	/* special_function.  */
           "R_pcrel24_jump_x",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 889,895 ****
  	 bfin_pcrel24_reloc,	/* special_function.  */
  	 "R_pcrel24",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x00FFFFFF,		/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 885,891 ----
  	 bfin_pcrel24_reloc,	/* special_function.  */
  	 "R_pcrel24",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 931,937 ****
  	 bfin_pcrel24_reloc,	/* special_function.  */
  	 "R_pcrel24_jump_l",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x00FFFFFF,		/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 927,933 ----
  	 bfin_pcrel24_reloc,	/* special_function.  */
  	 "R_pcrel24_jump_l",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 945,951 ****
  	 bfin_pcrel24_reloc,	/* special_function.  */
  	 "R_pcrel24_call_x",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x00FFFFFF,		/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 941,947 ----
  	 bfin_pcrel24_reloc,	/* special_function.  */
  	 "R_pcrel24_call_x",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x00FFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 973,979 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_byte_data",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0xFF,			/* src_mask.  */
  	 0xFF,			/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 969,975 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_byte_data",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0xFF,			/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 987,993 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_byte2_data",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0xFFFF,		/* src_mask.  */
  	 0xFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 983,989 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_byte2_data",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0xFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 1001,1007 ****
  	 bfin_byte4_reloc,	/* special_function.  */
  	 "R_byte4_data",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0xFFFFFFFF,		/* src_mask.  */
  	 0xFFFFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
--- 997,1003 ----
  	 bfin_byte4_reloc,	/* special_function.  */
  	 "R_byte4_data",	/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0xFFFFFFFF,		/* dst_mask.  */
  	 TRUE),			/* pcrel_offset.  */
  
*************** static reloc_howto_type bfin_howto_table
*** 1015,1021 ****
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel11",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0x000003FF,		/* src_mask.  */
  	 0x000003FF,		/* dst_mask.  */
  	 FALSE),		/* pcrel_offset.  */
  };
--- 1011,1017 ----
  	 bfin_bfd_reloc,	/* special_function.  */
  	 "R_pcrel11",		/* name.  */
  	 FALSE,			/* partial_inplace.  */
! 	 0,			/* src_mask.  */
  	 0x000003FF,		/* dst_mask.  */
  	 FALSE),		/* pcrel_offset.  */
  };
*************** elf32_bfin_reloc_type_class (const Elf_I
*** 1660,1665 ****
--- 1656,1662 ----
        return reloc_class_normal;
      }
  }
+ 
  static bfd_boolean
  bfin_relocate_section (bfd * output_bfd,
  		       struct bfd_link_info *info,
*************** bfin_relocate_section (bfd * output_bfd,
*** 1678,1684 ****
    asection *sreloc;
    Elf_Internal_Rela *rel;
    Elf_Internal_Rela *relend;
-   char *error_msg = NULL;
    int i = 0;
  
    if (info->relocatable)
--- 1675,1680 ----
*************** bfin_relocate_section (bfd * output_bfd,
*** 1705,1710 ****
--- 1701,1707 ----
        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)
*************** bfin_relocate_section (bfd * output_bfd,
*** 1735,1744 ****
  	  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
  	{
--- 1732,1737 ----
*************** bfin_relocate_section (bfd * output_bfd,
*** 1762,1767 ****
--- 1755,1799 ----
  	    }
  	}
  
+       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:
*************** bfin_relocate_section (bfd * output_bfd,
*** 1773,1779 ****
  	     in the global offset table.  */
  	  if (h != NULL
  	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
! 	    break;
  	  /* Fall through.  */
  	  /* Relocation is the offset of the entry for this symbol in
  	     the global offset table.  */
--- 1805,1811 ----
  	     in the global offset table.  */
  	  if (h != NULL
  	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
! 	    goto do_default;
  	  /* Fall through.  */
  	  /* Relocation is the offset of the entry for this symbol in
  	     the global offset table.  */
*************** bfin_relocate_section (bfd * output_bfd,
*** 1793,1805 ****
  
  		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))
  		  {
  		    /* This is actually a static link, or it is a
  		       -Bsymbolic link and the symbol is defined
--- 1825,1838 ----
  
  		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))
  		  {
  		    /* This is actually a static link, or it is a
  		       -Bsymbolic link and the symbol is defined
*************** bfin_relocate_section (bfd * output_bfd,
*** 1827,1836 ****
  	      }
  	    else
  	      {
! 		BFD_ASSERT (local_got_offsets != NULL
! 			    && local_got_offsets[r_symndx] != (bfd_vma) - 1);
! 
  		off = local_got_offsets[r_symndx];
  
  		/* The offset must always be a multiple of 4.  We use
  		   the least significant bit to record whether we have
--- 1860,1868 ----
  	      }
  	    else
  	      {
! 		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
*************** bfin_relocate_section (bfd * output_bfd,
*** 1839,1845 ****
  		  off &= ~1;
  		else
  		  {
- 
  		    bfd_put_32 (output_bfd, relocation, sgot->contents + off);
  
  		    if (info->shared)
--- 1871,1876 ----
*************** bfin_relocate_section (bfd * output_bfd,
*** 1871,1941 ****
              /* bfin : preg = [preg + 17bitdiv4offset] relocation is div by 4.  */
              relocation /= 4;
  	  }
  	  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;
- 	    }
  	  break;
  	}
  
        /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
           because such sections are not SEC_ALLOC and thus ld.so will
           not process them.  */
--- 1902,1953 ----
              /* 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:
! 	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.  */
*************** bfin_relocate_section (bfd * output_bfd,
*** 1949,1958 ****
  	  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;
--- 1961,1966 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]