Fix PR 13402
authorSenthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
Tue, 27 Jun 2017 09:16:08 +0000 (14:46 +0530)
committerSenthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
Tue, 27 Jun 2017 09:17:02 +0000 (14:47 +0530)
Fix incorrect adjustment of diff relocs when relaxing, and thus the
resulting source line to address mismatch.

Fix two issues when adjusting diff relocs to account for
deleted bytes.

1. Don't adjust the difference if the end address is the shrinked
insn's address i.e. use < instead of <=. The relaxation code deletes
count bytes from or after shrinked_insn_address, so the difference
between start_address and end_address should remain unchanged in this
case.

2. Adjust the reloc addend if the difference is to be adjusted and
symval + reloc addend is past the shrinked insn address. This is
because for a typical sym1 - sym2 diff reloc, sym1 is .text +
irel->r_addend, and the addend should be reduced to account for the
shrinked insn.

For example, assume the reloc value is .text + 0x8 with .text = 0, the
diff value in the object file = 0x4, and shrinked_insn_address = 0x4
with count = 0x2. Then the existing code writes 0x2 into the object
file to account for the deleted bytes, as shrinked_insn_address lies
between 0x8 and 0x8 - 0x4 = 0x4, but leaves the addend as is. The next
time the reloc is looked at, the code sees if a shrinked_insn_address
lies between 0x8 and 0x8 - 0x2 = 0x6, instead of 0x6 and 0x4. If there
happens to be one, then the diff value in the object file ends up
getting reduced again.

bfd/

2017-06-27  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>

PR ld/13402
* elf32-avr.c (elf32_avr_adjust_diff_reloc_value): Adjust
reloc addend if necessary. Adjust diff only if
shrinked_insn_address < end_address.

ld/

2017-06-27  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>

PR ld/13402
* testsuite/ld-avr/pr13402.d: New test.
* testsuite/ld-avr/pr13402.s: New test.

bfd/ChangeLog
bfd/elf32-avr.c
ld/ChangeLog
ld/testsuite/ld-avr/pr13402.d [new file with mode: 0644]
ld/testsuite/ld-avr/pr13402.s [new file with mode: 0644]

index 5f840a1ef3eaf4e84d5c0f4c624f8699ffd6d50c..272da0c5c548c37a709281a21b9a7df926d4ba5c 100644 (file)
@@ -1,3 +1,10 @@
+2017-06-27  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
+
+       PR ld/13402
+       * elf32-avr.c (elf32_avr_adjust_diff_reloc_value): Adjust
+       reloc addend if necessary. Adjust diff only if
+       shrinked_insn_address < end_address.
+
 2017-06-27  Alan Modra  <amodra@gmail.com>
 
        PR binutils/21665
index f140aa7ed4829f8188dfdb9b98e241ae0ed4c641..830da288f3cd3e6a070b5ced908ca05d6b11e4b0 100644 (file)
@@ -1785,12 +1785,15 @@ elf32_avr_adjust_diff_reloc_value (bfd *abfd,
 
 
   if (shrinked_insn_address >= start_address
-      && shrinked_insn_address <= end_address)
+      && shrinked_insn_address < end_address)
   {
     /* Reduce the diff value by count bytes and write it back into section
        contents. */
     bfd_signed_vma new_diff = x < 0 ? x + count : x - count;
 
+    if (sym2_address > shrinked_insn_address)
+      irel->r_addend -= count;
+
     switch (ELF32_R_TYPE (irel->r_info))
     {
     case R_AVR_DIFF8:
index 92d0003c305a3c2a318a68d9d7ca4ed5446876e4..fec44c9b027ae88af1dfc671d642c5d3c1038d52 100644 (file)
@@ -1,3 +1,9 @@
+2017-06-27  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
+
+       PR ld/13402
+       * testsuite/ld-avr/pr13402.d: New test.
+       * testsuite/ld-avr/pr13402.s: New test.
+
 2017-06-27  Maciej W. Rozycki  <macro@imgtec.com>
 
        * testsuite/ld-mips-elf/mips-elf-flags.exp (good_combination):
diff --git a/ld/testsuite/ld-avr/pr13402.d b/ld/testsuite/ld-avr/pr13402.d
new file mode 100644 (file)
index 0000000..6663950
--- /dev/null
@@ -0,0 +1,16 @@
+#name: AVR fix broken sync between debug_line and code addresses
+#as: -mmcu=avrxmega2 -mlink-relax -gdwarf-2
+#ld:  -mavrxmega2 --relax
+#source: pr13402.s
+#objdump: -S
+#target: avr-*-*
+
+#...
+main:
+call a
+   0:  02 d0           rcall   .+4             ; 0x6 <_etext>
+call b
+   2:  01 d0           rcall   .+2             ; 0x6 <_etext>
+call c
+   4:  00 d0           rcall   .+0             ; 0x6 <_etext>
+#...
diff --git a/ld/testsuite/ld-avr/pr13402.s b/ld/testsuite/ld-avr/pr13402.s
new file mode 100644 (file)
index 0000000..9539829
--- /dev/null
@@ -0,0 +1,9 @@
+.global main
+main:
+call a
+call b
+call c
+
+a:
+b:
+c: