This is the mail archive of the
mailing list for the binutils project.
[Patch, avr] Fix PR 12494 - Make relaxation consider relocations from all sections before deleting ret
- From: Senthil Kumar Selvaraj <senthil_kumar dot selvaraj at atmel dot com>
- To: <binutils at sourceware dot org>
- Cc: <eric dot weddington at atmel dot com>, <joerg dot wunsch at atmel dot com>, <denisc at overta dot ru>
- Date: Thu, 21 Mar 2013 18:57:52 +0530
- Subject: [Patch, avr] Fix PR 12494 - Make relaxation consider relocations from all sections before deleting ret
This patch fixes PR 12494 (relaxation leads to wrong code optimization),
by considering relocations from all sections in the BFD before
determining that it is safe to delete a ret instruction.
The linker relaxation code, as part of relaxing call/ret sequences to
jumps, checks whether the ret instruction involved is referred by
symbols or by relocation values, before deleting the instruction. The
current code only checks relocations in the same (input) section
containing the ret instruction.
This breaks if a relocation entry is emitted in a different section -
which is what happened in the buggy scenario. Computed gotos caused the
compiler to place the array of labels in a different section (.rodata),
and the assembler dutifully emitted relocations in that section (values
resolve to the actual label locations in the .text section). The linker,
however, only considered relocations in the .text section and deleted the
The fix simply iterates over relocations in all input sections in the BFD,
instead of just the input section containing the instruction to delete.
If ok, could someone apply please?
2013-03-21 Senthil Kumar Selvaraj <firstname.lastname@example.org>
* elf32-avr.c (elf32_avr_relax_section) : Loop over all input
diff --git bfd/elf32-avr.c bfd/elf32-avr.c
index a2d4401..a5a9395 100644
@@ -2189,15 +2189,20 @@ elf32_avr_relax_section (bfd *abfd,
/* Now we check for relocations pointing to ret. */
+ struct bfd_section *isec;
+ for (isec = abfd->sections; isec && deleting_ret_is_safe; isec = isec->next)
+ rel = elf_section_data (isec)->relocs;
+ if (rel == NULL)
+ rel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
- relend = elf_section_data (sec)->relocs
- + sec->reloc_count;
+ relend = rel + isec->reloc_count;
- for (rel = elf_section_data (sec)->relocs;
- rel < relend; rel++)
+ for (; rel && rel < relend; rel++)
bfd_vma reloc_target = 0;
@@ -2259,6 +2264,7 @@ elf32_avr_relax_section (bfd *abfd,
" 0x%x could not be deleted. ret"
" is target of a relocation.\n",