[PATCH] Objcopy interleave fails if section address not multiple of interleave.

Jim Wilson jimw@sifive.com
Wed Dec 6 01:54:00 GMT 2017


Here is my objcopy interleave patch again, this time with testcases.

I verified that the testcases fail without my objcopy patch, and work with it.
I ran make check on binutils, gas, and ld on riscv32, riscv64, and x86_64-linux
and there were no regressions.

Comments?

Jim

	PR 22465
	binutils/
	* objcopy.c (copy_section): New local extra.  If isection->lma not
	exactly divisible by interleave, then bias from.  Also adjust
	osection->lma if necessary.

	ld/
	* testsuite/ld-elf/interleave-0.d, testsuite/ld-elf/interleave-4.d,
	* testsuite/ld-elf/interleave.ld, testsuite/ld-elf/interleave.s: New.
---
 binutils/objcopy.c                 | 11 +++++++++++
 ld/testsuite/ld-elf/interleave-0.d |  9 +++++++++
 ld/testsuite/ld-elf/interleave-4.d |  9 +++++++++
 ld/testsuite/ld-elf/interleave.ld  | 10 ++++++++++
 ld/testsuite/ld-elf/interleave.s   | 18 ++++++++++++++++++
 5 files changed, 57 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/interleave-0.d
 create mode 100644 ld/testsuite/ld-elf/interleave-4.d
 create mode 100644 ld/testsuite/ld-elf/interleave.ld
 create mode 100644 ld/testsuite/ld-elf/interleave.s

diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index c45133b41b..f40b355c14 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -3898,6 +3898,15 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 	  char *end = (char *) memhunk + size;
 	  int i;
 
+	  /* If the section address is not exactly divisible by the interleave,
+	     then we must bias the from address.  If the copy_byte is less than
+	     the bias, then we must skip forward one interleave, and increment
+	     the final lma.  */
+	  int extra = isection->lma % interleave;
+	  from -= extra;
+	  if (copy_byte < extra)
+	    from += interleave;
+
 	  for (; from < end; from += interleave)
 	    for (i = 0; i < copy_width; i++)
 	      {
@@ -3908,6 +3917,8 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
 
 	  size = (size + interleave - 1 - copy_byte) / interleave * copy_width;
 	  osection->lma /= interleave;
+	  if (copy_byte < extra)
+	    osection->lma++;
 	}
 
       if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
diff --git a/ld/testsuite/ld-elf/interleave-0.d b/ld/testsuite/ld-elf/interleave-0.d
new file mode 100644
index 0000000000..837223c83a
--- /dev/null
+++ b/ld/testsuite/ld-elf/interleave-0.d
@@ -0,0 +1,9 @@
+#name: --interleave test byte 0
+#source: interleave.s
+#ld: -Tinterleave.ld
+#objcopy: --interleave=8 --interleave-width=1 --byte=0 -O verilog
+
+@0+0
+00 
+@0+2
+14 
diff --git a/ld/testsuite/ld-elf/interleave-4.d b/ld/testsuite/ld-elf/interleave-4.d
new file mode 100644
index 0000000000..a4bb808ab6
--- /dev/null
+++ b/ld/testsuite/ld-elf/interleave-4.d
@@ -0,0 +1,9 @@
+#name: --interleave test byte 4
+#source: interleave.s
+#ld: -Tinterleave.ld
+#objcopy: --interleave=8 --interleave-width=1 --byte=4 -O verilog
+
+@0+0
+04 
+@0+1
+10 
diff --git a/ld/testsuite/ld-elf/interleave.ld b/ld/testsuite/ld-elf/interleave.ld
new file mode 100644
index 0000000000..6406166c88
--- /dev/null
+++ b/ld/testsuite/ld-elf/interleave.ld
@@ -0,0 +1,10 @@
+MEMORY
+{
+  x0(xrw): ORIGIN = 0x0, LENGTH = 8
+  x1(xrw): ORIGIN = 0xC, LENGTH = 8
+}
+SECTIONS
+{
+  .a0 : { *(.text.a0) } > x0
+  .a1 : { *(.text.a1) } > x1
+}
diff --git a/ld/testsuite/ld-elf/interleave.s b/ld/testsuite/ld-elf/interleave.s
new file mode 100644
index 0000000000..490aa59d5b
--- /dev/null
+++ b/ld/testsuite/ld-elf/interleave.s
@@ -0,0 +1,18 @@
+	.section ".text.a0"
+	.byte 0x00
+	.byte 0x01
+	.byte 0x02
+	.byte 0x03
+	.byte 0x04
+	.byte 0x05
+	.byte 0x06
+	.byte 0x07
+	.section ".text.a1"
+	.byte 0x10
+	.byte 0x11
+	.byte 0x12
+	.byte 0x13
+	.byte 0x14
+	.byte 0x15
+	.byte 0x16
+	.byte 0x17
-- 
2.14.1



More information about the Binutils mailing list