summaryrefslogtreecommitdiff
path: root/bfd/elf32-avr.c
diff options
context:
space:
mode:
authorEric B. Weddington <eric.weddington@atmel.com>2012-02-02 18:02:09 +0000
committerEric B. Weddington <eric.weddington@atmel.com>2012-02-02 18:02:09 +0000
commitbd642a00565fe286e8249364a5e557a5e2719900 (patch)
tree1cbd0a29103de01b34f4207f28163223e45298c1 /bfd/elf32-avr.c
parent620d3ab97a06b39b47a73a3574806ad200138be9 (diff)
downloadbinutils-redhat-bd642a00565fe286e8249364a5e557a5e2719900.tar.gz
2012-02-02 Vidya Praveen (vidya.praveen@atmel.com)
PR bfd/13410 * bfd/elf32-avr.c (elf32_avr_relax_section): Correct the condition that qualifies the candidates for relaxation.
Diffstat (limited to 'bfd/elf32-avr.c')
-rw-r--r--bfd/elf32-avr.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index a7f9217413..2a10162465 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -1659,6 +1659,16 @@ elf32_avr_relax_section (bfd *abfd,
Elf_Internal_Sym *isymbuf = NULL;
struct elf32_avr_link_hash_table *htab;
+ /* If 'shrinkable' is FALSE, do not shrink by deleting bytes while
+ relaxing. Such shrinking can cause issues for the sections such
+ as .vectors and .jumptables. Instead the unused bytes should be
+ filled with nop instructions. */
+ bfd_boolean shrinkable = TRUE;
+
+ if (!strcmp (sec->name,".vectors")
+ || !strcmp (sec->name,".jumptables"))
+ shrinkable = FALSE;
+
if (link_info->relocatable)
(*link_info->callbacks->einfo)
(_("%P%F: --relax and -r may not be used together\n"));
@@ -1815,10 +1825,16 @@ elf32_avr_relax_section (bfd *abfd,
/* Compute the distance from this insn to the branch target. */
gap = value - dot;
- /* If the distance is within -4094..+4098 inclusive, then we can
- relax this jump/call. +4098 because the call/jump target
- will be closer after the relaxation. */
- if ((int) gap >= -4094 && (int) gap <= 4098)
+ /* Check if the gap falls in the range that can be accommodated
+ in 13bits signed (It is 12bits when encoded, as we deal with
+ word addressing). */
+ if (!shrinkable && ((int) gap >= -4096 && (int) gap <= 4095))
+ distance_short_enough = 1;
+ /* If shrinkable, then we can check for a range of distance which
+ is two bytes farther on both the directions because the call
+ or jump target will be closer by two bytes after the
+ relaxation. */
+ else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4097))
distance_short_enough = 1;
/* Here we handle the wrap-around case. E.g. for a 16k device
@@ -1892,11 +1908,9 @@ elf32_avr_relax_section (bfd *abfd,
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_AVR_13_PCREL);
- /* Check for the vector section. There we don't want to
- modify the ordering! */
-
- if (!strcmp (sec->name,".vectors")
- || !strcmp (sec->name,".jumptables"))
+ /* We should not modify the ordering if 'shrinkable' is
+ FALSE. */
+ if (!shrinkable)
{
/* Let's insert a nop. */
bfd_put_8 (abfd, 0x00, contents + irel->r_offset + 2);