This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, avr] Fix PR 13402 - sync loss between .debug_line and code


  The below patch fixes incorrect adjustment of diff relocs when
  relaxing, and thus the resulting source line to address mismatch.

  The patch fixes 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

  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.

  Ok for master and backport to 2.28?



2017-06-22  Senthil Kumar Selvaraj  <>

	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-22  Senthil Kumar Selvaraj  <>

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

diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index f140aa7ed48..830da288f3c 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -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:
diff --git a/ld/testsuite/ld-avr/pr13402.d b/ld/testsuite/ld-avr/pr13402.d
new file mode 100644
index 00000000000..6663950559e
--- /dev/null
+++ b/ld/testsuite/ld-avr/pr13402.d
@@ -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-*-*
+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
index 00000000000..95398295f62
--- /dev/null
+++ b/ld/testsuite/ld-avr/pr13402.s
@@ -0,0 +1,9 @@ main
+call a
+call b
+call c

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]