This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch, avr] Fix PR 20221 - adjust syms and relocs only if relax shrunk section
- From: Senthil Kumar Selvaraj <senthil_kumar dot selvaraj at atmel dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: Andrew Burgess <andrew dot burgess at embecosm dot com>, Denis Chertykov <chertykov at gmail dot com>, Nick Clifton <nickc at redhat dot com>
- Date: Wed, 8 Jun 2016 14:23:40 +0530
- Subject: [Patch, avr] Fix PR 20221 - adjust syms and relocs only if relax shrunk section
- Authentication-results: sourceware.org; auth=none
Hi,
This patch fixes an edge case in linker relaxation that causes symbol
values to be computed incorrectly in the presence of align directives
in input source code.
As the below testcase demonstrates, for code like
_start:
CALL dest
.align 1
dest:
NOP
where the bytes to be deleted (CALL to RCALL, 2 bytes) are adjacent to an
alignment boundary, no deletion happens - the prop record handling
merely overwrites the to-be-deleted-bytes with NOPs. AFAICT, this is
ok - eventually, relaxation sees that the padding is unnecessary and
strips the NOPs away.
However, the rest of elf32_avr_relax_delete_bytes runs with the assumption
that the bytes have been deleted, and this causes symbol values and/or
reloc offsets to be decremented even if nothing has moved. dest, in the
above testcase, gets decremented by 2 even when the gap got alignment
padded, and then again when the padding was removed - it ends up
getting adjusted down twice.
The patch fixes this by recording whether shrinking actually occurred,
and then skipping the reloc offset/sym value adjutment if it did
not. There's also a testcase that fails with master (and 2.26) that
passes with this patch.
Ok for master? Can I backport to 2.26 branch if ok?
Regards
Senthil
bfd/ChangeLog
2016-06-08 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
PR ld/20221
* elf32-avr.c (elf32_avr_relax_delete_bytes): Adjust syms
and relocs only if shrinking occurred.
ld/ChangeLog
2016-06-08 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
PR ld/20221
* testsuite/ld-avr/avr-prop-5.d: New.
* testsuite/ld-avr/avr-prop-5.s: New.
diff --git bfd/elf32-avr.c bfd/elf32-avr.c
index d463d78..b95e251 100644
--- bfd/elf32-avr.c
+++ bfd/elf32-avr.c
@@ -1828,6 +1828,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
unsigned int symcount;
struct avr_relax_info *relax_info;
struct avr_property_record *prop_record = NULL;
+ bfd_boolean did_shrink = FALSE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
@@ -1863,10 +1864,16 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
/* Actually delete the bytes. */
if (toaddr - addr - count > 0)
- memmove (contents + addr, contents + addr + count,
- (size_t) (toaddr - addr - count));
+ {
+ memmove (contents + addr, contents + addr + count,
+ (size_t) (toaddr - addr - count));
+ did_shrink = TRUE;
+ }
if (prop_record == NULL)
- sec->size -= count;
+ {
+ sec->size -= count;
+ did_shrink = TRUE;
+ }
else
{
/* Use the property record to fill in the bytes we've opened up. */
@@ -1885,6 +1892,11 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
prop_record->data.align.preceding_deleted += count;
break;
};
+ /* If toaddr == (addr + count), then we didn't delete anything, yet
+ we fill count bytes backwards from toaddr. This is still ok - we
+ end up overwriting the bytes we would have deleted. We just need
+ to remember we didn't delete anything i.e. don't set did_shrink,
+ so that we don't corrupt reloc offsets or symbol values.*/
memset (contents + toaddr - count, fill, count);
/* Adjust the TOADDR to avoid moving symbols located at the address
@@ -1892,6 +1904,9 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
toaddr -= count;
}
+ if (!did_shrink)
+ return TRUE;
+
/* Adjust all the reloc addresses. */
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
{
diff --git ld/testsuite/ld-avr/avr-prop-5.d ld/testsuite/ld-avr/avr-prop-5.d
new file mode 100644
index 0000000..5f62ba3
--- /dev/null
+++ ld/testsuite/ld-avr/avr-prop-5.d
@@ -0,0 +1,10 @@
+#name: AVR .avr.prop, single .align proper sym val test.
+#as: -mmcu=avrxmega2 -mlink-relax
+#ld: -mavrxmega2 --relax
+#source: avr-prop-5.s
+#objdump: -S
+#target: avr-*-*
+
+#...
+ 0: 00 d0\s+rcall\s+\.\+0\s+; 0x2 <dest>
+#...
\ No newline at end of file
diff --git ld/testsuite/ld-avr/avr-prop-5.s ld/testsuite/ld-avr/avr-prop-5.s
new file mode 100644
index 0000000..6a3359a
--- /dev/null
+++ ld/testsuite/ld-avr/avr-prop-5.s
@@ -0,0 +1,7 @@
+ .text
+ .global _start, dest
+_start:
+ CALL dest
+ .align 1
+dest:
+ NOP
--
2.7.4