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]

[PATCH]: MN10300 linker relaxation improvements


Hi Guys,

  I am checking in the attached patch to make some improvements to the
  MN10300's linker relaxation code, especially in conjunction with
  DWARF debug information.  The patch also adds a couple of new linker
  tests to cover the changes.

Cheers
  Nick

gas/ChangeLog
2007-11-13  Nick Clifton  <nickc@redhat.com>

	* config/tc-mn10300.c (mn10300_force_relocation): Force a reloc to
	be generated for alignment fixups.
	* config/tc-mn10300.h (TC_FORCE_RELOCATION): Call
	mn10300_force_relocation.

bfd/ChangeLog
2007-11-13  Nick Clifton  <nickc@redhat.com>

	* elf-m10300.c (mn10300_elf_final_link_relocate): Prevent the
	accidental termination of DWARF location list entries.
	(mn10300_elf_relax_delete_bytes): Stop deletion if an align reloc
	is encountered that is larger than or not a multiple of the number
	of bytes being deleted.
	When adjusting symbols, any symbols inside the region being
	deleted must be moved to the end of the region.
	Move align relocs forward if there is room for them after the
	deletion of the region.

ld/testsuite/ChangeLog
2007-11-13  Nick Clifton  <nickc@redhat.com>

	* ld-mn10300/i127740.s: New test: Checks relaxation and alignment.
	* ld-mn10300/i127740.d: New file: Expected disassembly.
	* ld-mn10300/i135409-3.s: New test: Check symbols inside a relaxed region.
	* ld-mn10300/i135409-3.d: New file: Expected disassembly.
	* ld-mn10300/mn10300.exp: Run new tests.
? ld/testsuite/ld-mn10300/i127740.d
? ld/testsuite/ld-mn10300/i127740.s
? ld/testsuite/ld-mn10300/i135409-3.d
? ld/testsuite/ld-mn10300/i135409-3.s
Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.89
diff -c -3 -p -r1.89 elf-m10300.c
*** bfd/elf-m10300.c	31 Oct 2007 11:33:27 -0000	1.89
--- bfd/elf-m10300.c	13 Nov 2007 09:41:51 -0000
*************** mn10300_elf_final_link_relocate (reloc_h
*** 1039,1044 ****
--- 1039,1055 ----
  	case R_MN10300_16:
  	case R_MN10300_8:
  	  value -= sym_diff_value;
+ 	  /* If we are computing a 32-bit value for the location lists
+ 	     and the result is 0 then we add one to the value.  A zero
+ 	     value can result because of linker relaxation deleteing
+ 	     prologue instructions and using a value of 1 (for the begin
+ 	     and end offsets in the location list entry) results in a
+ 	     nul entry which does not prevent the following entries from
+ 	     being parsed.  */
+ 	  if (r_type == R_MN10300_32
+ 	      && value == 0
+ 	      && strcmp (input_section->name, ".debug_loc") == 0)
+ 	    value = 1;
  	  sym_diff_section = NULL;
  	  is_sym_diff_reloc = TRUE;
  	  break;
*************** mn10300_elf_relax_delete_bytes (bfd *abf
*** 1856,1872 ****
  	--irelend;
        
        /* The deletion must stop at the next ALIGN reloc for an aligment
! 	 power larger than the number of bytes we are deleting.  */
        for (; irel < irelend; irel++)
! 	if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN
! 	    && irel->r_offset > addr
! 	    && irel->r_offset < toaddr
! 	    && count < (1 << irel->r_addend))
! 	  {
! 	    irelalign = irel;
! 	    toaddr = irel->r_offset;
! 	    break;
! 	  }
      }
  
    /* Actually delete the bytes.  */
--- 1867,1889 ----
  	--irelend;
        
        /* The deletion must stop at the next ALIGN reloc for an aligment
! 	 power larger than, or not a multiple of, the number of bytes we
! 	 are deleting.  */
        for (; irel < irelend; irel++)
! 	{
! 	  int alignment = 1 << irel->r_addend;
! 
! 	  if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN
! 	      && irel->r_offset > addr
! 	      && irel->r_offset < toaddr
! 	      && (count < alignment
! 		  || alignment % count != 0))
! 	    {
! 	      irelalign = irel;
! 	      toaddr = irel->r_offset;
! 	      break;
! 	    }
! 	}
      }
  
    /* Actually delete the bytes.  */
*************** mn10300_elf_relax_delete_bytes (bfd *abf
*** 1898,1908 ****
      {
        /* Get the new reloc address.  */
        if ((irel->r_offset > addr
! 	   && irel->r_offset < toaddr))
  	irel->r_offset -= count;
      }
  
!   /* Adjust the local symbols defined in this section.  */
    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    isym = (Elf_Internal_Sym *) symtab_hdr->contents;
    for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
--- 1915,1931 ----
      {
        /* Get the new reloc address.  */
        if ((irel->r_offset > addr
! 	   && irel->r_offset < toaddr)
! 	  || (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN
! 	      && irel->r_offset == toaddr))
  	irel->r_offset -= count;
      }
  
!   /* Adjust the local symbols in the section, reducing their value
!      by the number of bytes deleted.  Note - symbols within the deleted
!      region are moved to the address of the start of the region, which
!      actually means that they will address the byte beyond the end of
!      the region once the deletion has been completed.  */
    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    isym = (Elf_Internal_Sym *) symtab_hdr->contents;
    for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
*************** mn10300_elf_relax_delete_bytes (bfd *abf
*** 1910,1916 ****
        if (isym->st_shndx == sec_shndx
  	  && isym->st_value > addr
  	  && isym->st_value < toaddr)
! 	isym->st_value -= count;
        /* Adjust the function symbol's size as well.  */
        else if (isym->st_shndx == sec_shndx
  	       && ELF_ST_TYPE (isym->st_info) == STT_FUNC
--- 1933,1944 ----
        if (isym->st_shndx == sec_shndx
  	  && isym->st_value > addr
  	  && isym->st_value < toaddr)
! 	{
! 	  if (isym->st_value < addr + count)
! 	    isym->st_value = addr;
! 	  else
! 	    isym->st_value -= count;
! 	}
        /* Adjust the function symbol's size as well.  */
        else if (isym->st_shndx == sec_shndx
  	       && ELF_ST_TYPE (isym->st_info) == STT_FUNC
*************** mn10300_elf_relax_delete_bytes (bfd *abf
*** 1933,1939 ****
  	  && sym_hash->root.u.def.section == sec
  	  && sym_hash->root.u.def.value > addr
  	  && sym_hash->root.u.def.value < toaddr)
! 	sym_hash->root.u.def.value -= count;
        /* Adjust the function symbol's size as well.  */
        else if (sym_hash->root.type == bfd_link_hash_defined
  	       && sym_hash->root.u.def.section == sec
--- 1961,1972 ----
  	  && sym_hash->root.u.def.section == sec
  	  && sym_hash->root.u.def.value > addr
  	  && sym_hash->root.u.def.value < toaddr)
! 	{
! 	  if (sym_hash->root.u.def.value < addr + count)
! 	    sym_hash->root.u.def.value = addr;
! 	  else
! 	    sym_hash->root.u.def.value -= count;
! 	}
        /* Adjust the function symbol's size as well.  */
        else if (sym_hash->root.type == bfd_link_hash_defined
  	       && sym_hash->root.u.def.section == sec
*************** mn10300_elf_relax_delete_bytes (bfd *abf
*** 1943,1948 ****
--- 1976,2001 ----
  	sym_hash->size -= count;
      }
  
+   /* See if we can move the ALIGN reloc forward.
+      We have adjusted r_offset for it already.  */
+   if (irelalign != NULL)
+     {
+       bfd_vma alignto, alignaddr;
+ 
+       if ((int) irelalign->r_addend > 0)
+ 	{
+ 	  /* This is the old address.  */
+ 	  alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_addend);
+ 	  /* This is where the align points to now.  */
+ 	  alignaddr = BFD_ALIGN (irelalign->r_offset,
+ 				 1 << irelalign->r_addend);
+ 	  if (alignaddr < alignto)
+ 	    /* Tail recursion.  */
+ 	    return mn10300_elf_relax_delete_bytes (abfd, sec, alignaddr,
+ 						   (int) (alignto - alignaddr));
+ 	}
+     }
+ 
    return TRUE;
  }
  
Index: gas/config/tc-mn10300.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mn10300.c,v
retrieving revision 1.65
diff -c -3 -p -r1.65 tc-mn10300.c
*** gas/config/tc-mn10300.c	30 Oct 2007 15:18:29 -0000	1.65
--- gas/config/tc-mn10300.c	13 Nov 2007 09:41:51 -0000
*************** mn10300_allow_local_subtract (expression
*** 2571,2581 ****
  void
  mn10300_handle_align (fragS *frag)
  {
!   if (! linkrelax)
!     return;
! 
!   if ((frag->fr_type == rs_align
!        || frag->fr_type == rs_align_code)
        && frag->fr_address + frag->fr_fix > 0
        && frag->fr_offset > 1
        && now_seg != bss_section
--- 2571,2579 ----
  void
  mn10300_handle_align (fragS *frag)
  {
!   if (linkrelax
!       && (frag->fr_type == rs_align
! 	  || frag->fr_type == rs_align_code)
        && frag->fr_address + frag->fr_fix > 0
        && frag->fr_offset > 1
        && now_seg != bss_section
*************** mn10300_handle_align (fragS *frag)
*** 2590,2592 ****
--- 2588,2601 ----
      fix_new (frag, frag->fr_fix, 0, & abs_symbol, frag->fr_offset, FALSE,
  	     BFD_RELOC_MN10300_ALIGN);
  }
+ 
+ bfd_boolean
+ mn10300_force_relocation (struct fix * fixp)
+ {
+   if (linkrelax
+       && (fixp->fx_pcrel
+ 	  || fixp->fx_r_type == BFD_RELOC_MN10300_ALIGN))
+     return TRUE;
+ 
+   return generic_force_reloc (fixp);
+ }
Index: gas/config/tc-mn10300.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mn10300.h,v
retrieving revision 1.24
diff -c -3 -p -r1.24 tc-mn10300.h
*** gas/config/tc-mn10300.h	6 Nov 2007 17:15:10 -0000	1.24
--- gas/config/tc-mn10300.h	13 Nov 2007 09:41:51 -0000
***************
*** 26,33 ****
  #define DIFF_EXPR_OK
  #define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
  
! #define TC_FORCE_RELOCATION(FIX)			\
!   (generic_force_reloc (FIX))
  
  #define TC_FORCE_RELOCATION_LOCAL(FIX)			\
    (!(FIX)->fx_pcrel					\
--- 26,33 ----
  #define DIFF_EXPR_OK
  #define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
  
! #define TC_FORCE_RELOCATION(FIX) mn10300_force_relocation (FIX)
! extern bfd_boolean mn10300_force_relocation (struct fix *);
  
  #define TC_FORCE_RELOCATION_LOCAL(FIX)			\
    (!(FIX)->fx_pcrel					\
***************
*** 36,49 ****
     || (FIX)->fx_r_type == BFD_RELOC_32_GOT_PCREL	\
     || TC_FORCE_RELOCATION (FIX))
  
! #define md_parse_name(name, exprP, mode, nextcharP) \
!     mn10300_parse_name ((name), (exprP), (mode), (nextcharP))
! int mn10300_parse_name PARAMS ((char const *, expressionS *,
! 				enum expr_mode, char *));
  
  #define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \
       mn10300_cons_fix_new ((FRAG), (OFF), (LEN), (EXP))
! void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *));
  
  /* This is used to construct expressions out of @GOTOFF, @PLT and @GOT
     symbols.  The relocation type is stored in X_md.  */
--- 36,48 ----
     || (FIX)->fx_r_type == BFD_RELOC_32_GOT_PCREL	\
     || TC_FORCE_RELOCATION (FIX))
  
! #define md_parse_name(NAME, EXPRP, MODE, NEXTCHARP) \
!     mn10300_parse_name ((NAME), (EXPRP), (MODE), (NEXTCHARP))
! int mn10300_parse_name (char const *, expressionS *, enum expr_mode, char *);
  
  #define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \
       mn10300_cons_fix_new ((FRAG), (OFF), (LEN), (EXP))
! void mn10300_cons_fix_new (fragS *, int, int, expressionS *);
  
  /* This is used to construct expressions out of @GOTOFF, @PLT and @GOT
     symbols.  The relocation type is stored in X_md.  */
Index: ld/testsuite/ld-mn10300/mn10300.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-mn10300/mn10300.exp,v
retrieving revision 1.2
diff -c -3 -p -r1.2 mn10300.exp
*** ld/testsuite/ld-mn10300/mn10300.exp	30 Oct 2007 15:18:29 -0000	1.2
--- ld/testsuite/ld-mn10300/mn10300.exp	13 Nov 2007 09:41:53 -0000
*************** set mn10300_tests {
*** 48,53 ****
--- 48,61 ----
  	"i112045-3.x"
      }
      {
+ 	"relaxation and alignment directives"
+ 	"-relax -Ttext 100"
+ 	""
+ 	{ "i127740.s" }
+ 	{ {objdump -d i127740.d} }
+ 	"i127740.x"
+     }
+     {
  	"adjustment of symbols due to relaxation"
  	"-Tdata 1f -Ttext 0 -relax"
  	""
*************** set mn10300_tests {
*** 63,68 ****
--- 71,84 ----
  	{ {readelf --syms i135409-2.d} }
  	"i135409-2.x"
      }
+     {
+ 	"adjustment of symbols due to relaxation (with a symbol in the deleted region)"
+ 	"-Tdata 1f -Ttext 0 -relax"
+ 	""
+ 	{ "i135409-3.s" }
+ 	{ {objdump -d i135409-3.d} }
+ 	"i135409-3.x"
+     }
  }
  
  run_ld_link_tests $mn10300_tests

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