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]

Commit: RX: Fix relaxation problems when linking with --no-keep-memory


Hi Guys,

  I am checking in the patch below to fix a problem with the RX linker
  when running with --no-keep-memory specified.  Under these
  circumstances the relaxation pass can fail because the relocs are
  continually loaded and unloaded without be saved in between.  Since
  there is no safe place to actually store the relocs between relaxation
  passes I have elected to keep them in memory despite the setting of
  link_info->keep_memory.

Cheers
  Nick

bfd/ChangeLog
2015-12-07  Nick Clifton  <nickc@redhat.com>

	* elf32-rx.c (elf32_rx_relax_delete_bytes): Add extra parameter -
	the start of the relocs for the section.  Delete code to load in
	the relocs.
	(elf32_rx_relax_section): Do not free the loaded relocs.

diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index c58c184..004d7c2 100644
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -1531,7 +1531,8 @@ next_smaller_reloc (int r)
 
 static bfd_boolean
 elf32_rx_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count,
-			     Elf_Internal_Rela *alignment_rel, int force_snip)
+			     Elf_Internal_Rela *alignment_rel, int force_snip,
+			     Elf_Internal_Rela *irelstart)
 {
   Elf_Internal_Shdr * symtab_hdr;
   unsigned int        sec_shndx;
@@ -1558,20 +1559,7 @@ elf32_rx_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count,
   if (alignment_rel)
     toaddr = alignment_rel->r_offset;
 
-  irel = elf_section_data (sec)->relocs;
-  irelend = irel + sec->reloc_count;
-
-  if (irel == NULL && sec->reloc_count > 0)
-    {
-      /* If the relocs have not been kept in the section data
-	 structure (because -no-keep-memory was used) then
-	 reread them now.  */
-      irel = (_bfd_elf_link_read_relocs
-	      (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, FALSE));
-      if (irel == NULL)
-	/* FIXME: Return FALSE instead ?  */
-	irelend = irel;
-    }
+  BFD_ASSERT (toaddr > addr);  
 
   /* Actually delete the bytes.  */
   memmove (contents + addr, contents + addr + count,
@@ -1585,6 +1573,10 @@ elf32_rx_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count,
   else
     memset (contents + toaddr - count, 0x03, count);
 
+  irel = irelstart;
+  BFD_ASSERT (irel != NULL || sec->reloc_count == 0);
+  irelend = irel + sec->reloc_count;
+
   /* Adjust all the relocs.  */
   for (; irel < irelend; irel++)
     {
@@ -1977,7 +1969,6 @@ elf32_rx_relax_section (bfd *                  abfd,
   Elf_Internal_Shdr * symtab_hdr;
   Elf_Internal_Shdr * shndx_hdr;
   Elf_Internal_Rela * internal_relocs;
-  Elf_Internal_Rela * free_relocs = NULL;
   Elf_Internal_Rela * irel;
   Elf_Internal_Rela * srel;
   Elf_Internal_Rela * irelend;
@@ -2054,13 +2045,15 @@ elf32_rx_relax_section (bfd *                  abfd,
     }
 
   /* Get a copy of the native relocations.  */
-  internal_relocs = (_bfd_elf_link_read_relocs
-		     (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
-		      link_info->keep_memory));
+  /* Note - we ignore the setting of link_info->keep_memory when reading
+     in these relocs.  We have to maintain a permanent copy of the relocs
+     because we are going to walk over them multiple times, adjusting them
+     as bytes are deleted from the section, and with this relaxation
+     function itself being called multiple times on the same section...  */
+  internal_relocs = _bfd_elf_link_read_relocs
+    (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, TRUE);
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   /* The RL_ relocs must be just before the operand relocs they go
      with, so we must sort them to guarantee this.  We use bubblesort
@@ -2150,7 +2143,7 @@ elf32_rx_relax_section (bfd *                  abfd,
 	  nbytes *= alignment;
 
 	  elf32_rx_relax_delete_bytes (abfd, sec, erel->r_offset-nbytes, nbytes, next_alignment,
-				       erel->r_offset == sec->size);
+				       erel->r_offset == sec->size, internal_relocs);
 	  *again = TRUE;
 
 	  continue;
@@ -2189,7 +2182,7 @@ elf32_rx_relax_section (bfd *                  abfd,
       nrelocs --;
 
 #define SNIPNR(offset, nbytes) \
-	elf32_rx_relax_delete_bytes (abfd, sec, (insn - contents) + offset, nbytes, next_alignment, 0);
+      elf32_rx_relax_delete_bytes (abfd, sec, (insn - contents) + offset, nbytes, next_alignment, 0, internal_relocs);
 #define SNIP(offset, nbytes, newtype) \
         SNIPNR (offset, nbytes);						\
 	srel->r_info = ELF32_R_INFO (ELF32_R_SYM (srel->r_info), newtype)
@@ -3009,9 +3002,6 @@ elf32_rx_relax_section (bfd *                  abfd,
   return TRUE;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-
   if (free_contents != NULL)
     free (free_contents);
 


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