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, avr] Fix PR ld/20254


Hi,

  This patch fixes another edge case related to alignment property
  records - reloc offsets adjacent to property record offsets were not
  getting adjusted during relaxation.

  The prop record handling code decreases toaddr by the number of bytes
  to be deleted (count) to avoid moving symbols at the prop record
  offset address. The reloc adjustment code only adjusts relocs between
  addr and toaddr though, so when toaddr is decremented by count,
  relocs with offsets between original toaddr to original toaddr+count
  end up getting skipped - their offsets remain unadjusted.

  The typical value for count is 2, so if the last instruction in a
  section is a 16 bit instruction needing a reloc, the instruction moves
  but the reloc offset doesn't, and that results in wrong code.

  The patch fixes this by recording reloc_toaddr separately - its value
  is set to toaddr's value before prop record handling mangles it, and
  by making the reloc offset adjustment range check use reloc_toaddr
  instead of toaddr.

  Is this ok for master and binutils-2_26-branch?

Regards
Senthil

bfd/ChangeLog:

2016-06-14  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>

	PR ld/20254
	* elf32-avr.c (elf32_avr_relax_delete_bytes): Adjust reloc
  offsets until reloc_toaddr.


ld/ChangeLog:

2016-06-14  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>

	PR ld/20254
	* testsuite/ld-avr/avr-prop-6.d: New test.
	* testsuite/ld-avr/avr-prop-6.s: New test.


diff --git bfd/elf32-avr.c bfd/elf32-avr.c
index b95e251..a0a5c69 100644
--- bfd/elf32-avr.c
+++ bfd/elf32-avr.c
@@ -1822,7 +1822,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymbuf = NULL;
-  bfd_vma toaddr;
+  bfd_vma toaddr, reloc_toaddr;
   struct elf_link_hash_entry **sym_hashes;
   struct elf_link_hash_entry **end_hashes;
   unsigned int symcount;
@@ -1859,6 +1859,17 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
         }
     }
 
+  /* We need to look at all relocs with offsets less than toaddr. prop
+     records handling adjusts toaddr downwards to avoid moving syms at the
+     address of the property record, but all relocs with offsets between addr
+     and the current value of toaddr need to have their offsets adjusted.
+     Assume addr = 0, toaddr = 4 and count = 2. After prop records handling,
+     toaddr becomes 2, but relocs with offsets 2 and 3 still need to be
+     adjusted (to 0 and 1 respectively), as the first 2 bytes are now gone.
+     So record the current value of toaddr here, and use it when adjusting
+     reloc offsets. */
+  reloc_toaddr = toaddr;
+
   irel = elf_section_data (sec)->relocs;
   irelend = irel + sec->reloc_count;
 
@@ -1917,7 +1928,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
 
       /* Get the new reloc address.  */
       if ((irel->r_offset > addr
-           && irel->r_offset < toaddr))
+           && irel->r_offset < reloc_toaddr))
         {
           if (debug_relax)
             printf ("Relocation at address 0x%x needs to be moved.\n"
diff --git ld/testsuite/ld-avr/avr-prop-6.d ld/testsuite/ld-avr/avr-prop-6.d
new file mode 100644
index 0000000..1bf8aa1
--- /dev/null
+++ ld/testsuite/ld-avr/avr-prop-6.d
@@ -0,0 +1,14 @@
+#name: AVR .avr.prop, single .align sym at end of section test.
+#as: -mavrxmega2 -mlink-relax
+#ld: -mavrxmega2 --relax
+#source: avr-prop-6.s
+#objdump: -S
+#target: avr-*-*
+
+#...
+   0:	00 c0       	rjmp	.+0      	; 0x2 <dest>
+
+00000002 <dest>:
+   2:	00 00       	nop
+   4:	fe cf       	rjmp	.-4      	; 0x2 <dest>
+#...
diff --git ld/testsuite/ld-avr/avr-prop-6.s ld/testsuite/ld-avr/avr-prop-6.s
new file mode 100644
index 0000000..15f83af
--- /dev/null
+++ ld/testsuite/ld-avr/avr-prop-6.s
@@ -0,0 +1,9 @@
+        .text
+        .global _start, dest
+_start: 
+  jmp dest
+  .align	1
+dest:
+  nop
+  rjmp dest
+
-- 
2.7.4


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