This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch, avr] Fix PR ld/20254
- From: Senthil Kumar Selvaraj <senthil_kumar dot selvaraj at atmel dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>, Denis Chertykov <chertykov at gmail dot com>, Nick Clifton <nickc at redhat dot com>
- Date: Tue, 14 Jun 2016 16:05:00 +0530
- Subject: [Patch, avr] Fix PR ld/20254
- Authentication-results: sourceware.org; auth=none
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