[RFC,v3] Add support for non-contiguous memory regions

Message ID CAKdteOaNaGXdemOzT7EmHdS++48SwuVG9h6sTkza0frbFxB0ZQ@mail.gmail.com
State New
Headers show
Series
  • [RFC,v3] Add support for non-contiguous memory regions
Related show

Commit Message

Christophe Lyon Feb. 3, 2020, 10:08 a.m.
Hi,

This is a follow-up to
https://sourceware.org/ml/binutils/2019-11/msg00402.html
and
https://sourceware.org/ml/binutils/2020-01/msg00064.html

The changes between v2 and v3:
* added some doc/NEWS
* fixed bugs detected when running the testsuite with the option
activated by default. In particular, I've noticed and documented the
incompatibility with INSERT (or rather, it's likely to cause problems,
but depends on the actual linker scripts contents), because my new
option breaks the assumption of the parsing & processing order assumed
by INSERT.
* added new option --enable-non-contiguous-regions-warnings which
activates some warnings to help understand why the behaviour changes
in some cases

We'd still have to do modify target that has XXX_build_one_stub(), in
a way similar to what I did in elf32-arm.c.

What is the recommended way of early-exiting the linker when a problem
is detected? I'm using abort(), but that's not very nice and implies
that there's a bug in the linker code. I'm more willing to report
unsupported cases in a friendly way.

There are 4 patches, to hopefully make review/comments easier; I can
squash them at commit time if this is preferable.
* patch1: is the main (code) patch
* patch2: generic test
* patch3: arm tests
* patch4: powerpc test

Thoughts?

Thanks,

Christophe

Patch

From ad381e5cb59f17da928af23d420ce33d466348f1 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 6 Jan 2020 14:58:24 +0000
Subject: [PATCH 3/4] Add arm tests for non-contiguous memory regions

2020-01-06  Christophe Lyon  <christophe.lyon@linaro.org>

	ld/
	* testsuite/ld-arm/arm-elf.exp: Run the new tests.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm.s: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm.d: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm.ld: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm2.d: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm3.ld: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm3.d: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm3.ld: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm4.d: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm4.ld: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm5.d: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm5.ld: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm6.d: New.
	* testsuite/ld-arm/arm-elf/non-contiguous-arm6.ld: New.

Change-Id: Ib9e82b1eedd84aee936e01f9aeee7fdd4aa331bb
---
 ld/testsuite/ld-arm/arm-elf.exp            |  7 +++
 ld/testsuite/ld-arm/non-contiguous-arm.d   |  4 ++
 ld/testsuite/ld-arm/non-contiguous-arm.ld  | 34 +++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm.s   | 35 +++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm2.d  | 77 ++++++++++++++++++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm2.ld | 33 ++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm3.d  | 82 ++++++++++++++++++++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm3.ld | 33 ++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm4.d  |  4 ++
 ld/testsuite/ld-arm/non-contiguous-arm4.ld | 34 +++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm5.d  | 77 ++++++++++++++++++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm5.ld | 34 +++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm6.d  | 76 +++++++++++++++++++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm6.ld | 33 ++++++++++++
 14 files changed, 563 insertions(+)
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm.d
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm.ld
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm.s
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm2.d
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm2.ld
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm3.d
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm3.ld
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm4.d
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm4.ld
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm5.d
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm5.ld
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm6.d
 create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm6.ld

diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 44e599f..18177d1 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -1261,3 +1261,10 @@  set arm_unwind_tests {
      "unwind-mix"}
 }
 run_ld_link_tests $arm_unwind_tests
+
+run_dump_test "non-contiguous-arm"
+run_dump_test "non-contiguous-arm2"
+run_dump_test "non-contiguous-arm3"
+run_dump_test "non-contiguous-arm4"
+run_dump_test "non-contiguous-arm5"
+run_dump_test "non-contiguous-arm6"
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm.d b/ld/testsuite/ld-arm/non-contiguous-arm.d
new file mode 100644
index 0000000..c62a453
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm.d
@@ -0,0 +1,4 @@ 
+#name: non-contiguous-arm
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm.ld
+# error: \A.*Could not assign .code.4 to an output section. Retry without --enable-non-contiguous-regions.*\Z
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm.ld b/ld/testsuite/ld-arm/non-contiguous-arm.ld
new file mode 100644
index 0000000..a50621b
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm.ld
@@ -0,0 +1,34 @@ 
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu
+ section .code.4 too large to fit
+ expect an error about .code.4
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040
+  RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00040
+}
+
+SECTIONS
+{
+   .raml :
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.code) *(.code.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.code) *(.code.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.code) *(.code.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm.s b/ld/testsuite/ld-arm/non-contiguous-arm.s
new file mode 100644
index 0000000..cdc8b00
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm.s
@@ -0,0 +1,35 @@ 
+	.syntax unified
+	.section .code.1, "ax", %progbits
+	.arm
+	# Fit in RAML
+	.global code1
+	.type code1, %function
+code1:
+	nop
+	nop
+	bl code2
+
+	.section .code.2, "ax", %progbits
+	# Fit in RAML
+	.global code2
+	.type code2, %function
+code2:
+	nop
+	nop
+	bl code3
+
+	.section .code.3, "ax", %progbits
+	# Fit in RAMU
+	.global code3
+	.type code3, %function
+code3:
+	nop
+	bl code4
+
+	.section .code.4, "ax", %progbits
+	# Fit in RAMZ
+	.global code4
+	.type code4, %function
+code4:
+$a:
+	.fill 20, 4, 0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm2.d b/ld/testsuite/ld-arm/non-contiguous-arm2.d
new file mode 100644
index 0000000..ed2ba69
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm2.d
@@ -0,0 +1,77 @@ 
+#name: non-contiguous-arm2
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm2.ld
+#objdump: -rdth
+#xfail: [is_generic]
+
+.*:     file format elf32-(little|big)arm
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 \.raml         00000018  1fff0000  1fff0000  00010000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramu         00000008  20000000  1fff0018  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \.ramz         00000050  20040000  20000008  00030000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  3 .ARM.attributes 00000012  00000000  00000000  00030050  2\*\*0
+                  CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l    d  .raml	00000000 .raml
+20000000 l    d  .ramu	00000000 .ramu
+20040000 l    d  .ramz	00000000 .ramz
+00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
+00000000 l    df \*ABS\*	00000000 .*/non-contiguous-arm.o
+1fff0018 g       .raml	00000000 _raml_end
+20000000 g       .ramu	00000000 _ramu_start
+1fff000c g     F .raml	00000000 code2
+20040000 g       .ramz	00000000 _ramz_start
+1fff0000 g       .raml	00000000 _raml_start
+20000000 g     F .ramu	00000000 code3
+1fff0000 g     F .raml	00000000 code1
+20040050 g       .ramz	00000000 _ramz_end
+20040000 g     F .ramz	00000000 code4
+20000008 g       .ramu	00000000 _ramu_end
+
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0004:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0008:	ebffffff 	bl	1fff000c \<code2\>
+
+1fff000c \<code2\>:
+1fff000c:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0010:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0014:	eb003ff9 	bl	20000000 \<code3\>
+
+Disassembly of section .ramu:
+
+20000000 \<code3\>:
+20000000:	e1a00000 	nop			; \(mov r0, r0\)
+20000004:	eb00fffd 	bl	20040000 \<code4\>
+
+Disassembly of section .ramz:
+
+20040000 \<code4\>:
+20040000:	e1a00000 	.word	0xe1a00000
+20040004:	e1a00000 	.word	0xe1a00000
+20040008:	e1a00000 	.word	0xe1a00000
+2004000c:	e1a00000 	.word	0xe1a00000
+20040010:	e1a00000 	.word	0xe1a00000
+20040014:	e1a00000 	.word	0xe1a00000
+20040018:	e1a00000 	.word	0xe1a00000
+2004001c:	e1a00000 	.word	0xe1a00000
+20040020:	e1a00000 	.word	0xe1a00000
+20040024:	e1a00000 	.word	0xe1a00000
+20040028:	e1a00000 	.word	0xe1a00000
+2004002c:	e1a00000 	.word	0xe1a00000
+20040030:	e1a00000 	.word	0xe1a00000
+20040034:	e1a00000 	.word	0xe1a00000
+20040038:	e1a00000 	.word	0xe1a00000
+2004003c:	e1a00000 	.word	0xe1a00000
+20040040:	e1a00000 	.word	0xe1a00000
+20040044:	e1a00000 	.word	0xe1a00000
+20040048:	e1a00000 	.word	0xe1a00000
+2004004c:	e1a00000 	.word	0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm2.ld b/ld/testsuite/ld-arm/non-contiguous-arm2.ld
new file mode 100644
index 0000000..f13567e
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm2.ld
@@ -0,0 +1,33 @@ 
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu and does not need a farcall stub to jump to code4
+ section .code.4 fits in .ramz
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008
+  RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+   .raml :
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.code) *(.code.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.code) *(.code.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.code) *(.code.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm3.d b/ld/testsuite/ld-arm/non-contiguous-arm3.d
new file mode 100644
index 0000000..f8bbf98
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm3.d
@@ -0,0 +1,82 @@ 
+#name: non-contiguous-arm3
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm3.ld
+#objdump: -rdth
+#xfail: [is_generic]
+
+.*:     file format elf32-(little|big)arm
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 \.raml         00000018  1fff0000  1fff0000  00010000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramu         00000010  20000000  1fff0018  00020000  2\*\*3
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \.ramz         00000050  30040000  20000010  00030000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  3 .ARM.attributes 00000012  00000000  00000000  00030050  2\*\*0
+                  CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l    d  .raml	00000000 .raml
+20000000 l    d  .ramu	00000000 .ramu
+30040000 l    d  .ramz	00000000 .ramz
+00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
+00000000 l    df \*ABS\*	00000000 .*/non-contiguous-arm.o
+20000008 l     F .ramu	00000008 __code4_veneer
+1fff0018 g       .raml	00000000 _raml_end
+20000000 g       .ramu	00000000 _ramu_start
+1fff000c g     F .raml	00000000 code2
+30040000 g       .ramz	00000000 _ramz_start
+1fff0000 g       .raml	00000000 _raml_start
+20000000 g     F .ramu	00000000 code3
+1fff0000 g     F .raml	00000000 code1
+30040050 g       .ramz	00000000 _ramz_end
+30040000 g     F .ramz	00000000 code4
+20000010 g       .ramu	00000000 _ramu_end
+
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0004:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0008:	ebffffff 	bl	1fff000c \<code2\>
+
+1fff000c \<code2\>:
+1fff000c:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0010:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0014:	eb003ff9 	bl	20000000 \<code3\>
+
+Disassembly of section .ramu:
+
+20000000 \<code3\>:
+20000000:	e1a00000 	nop			; \(mov r0, r0\)
+20000004:	ebffffff 	bl	20000008 \<__code4_veneer\>
+
+20000008 \<__code4_veneer\>:
+20000008:	e51ff004 	ldr	pc, \[pc, #-4\]	; 2000000c \<__code4_veneer\+0x4\>
+2000000c:	30040000 	.word	0x30040000
+
+Disassembly of section .ramz:
+
+30040000 \<code4\>:
+30040000:	e1a00000 	.word	0xe1a00000
+30040004:	e1a00000 	.word	0xe1a00000
+30040008:	e1a00000 	.word	0xe1a00000
+3004000c:	e1a00000 	.word	0xe1a00000
+30040010:	e1a00000 	.word	0xe1a00000
+30040014:	e1a00000 	.word	0xe1a00000
+30040018:	e1a00000 	.word	0xe1a00000
+3004001c:	e1a00000 	.word	0xe1a00000
+30040020:	e1a00000 	.word	0xe1a00000
+30040024:	e1a00000 	.word	0xe1a00000
+30040028:	e1a00000 	.word	0xe1a00000
+3004002c:	e1a00000 	.word	0xe1a00000
+30040030:	e1a00000 	.word	0xe1a00000
+30040034:	e1a00000 	.word	0xe1a00000
+30040038:	e1a00000 	.word	0xe1a00000
+3004003c:	e1a00000 	.word	0xe1a00000
+30040040:	e1a00000 	.word	0xe1a00000
+30040044:	e1a00000 	.word	0xe1a00000
+30040048:	e1a00000 	.word	0xe1a00000
+3004004c:	e1a00000 	.word	0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm3.ld b/ld/testsuite/ld-arm/non-contiguous-arm3.ld
new file mode 100644
index 0000000..81bb695
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm3.ld
@@ -0,0 +1,33 @@ 
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu even with a farcall stub to jump to code4
+ section .code.4 fits in .ramz
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010
+  RAMZ (rwx) : ORIGIN = 0x30040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+   .raml :
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.code) *(.code.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.code) *(.code.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.code) *(.code.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm4.d b/ld/testsuite/ld-arm/non-contiguous-arm4.d
new file mode 100644
index 0000000..6b99544
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm4.d
@@ -0,0 +1,4 @@ 
+#name: non-contiguous-arm4
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm4.ld
+# error: \AOutput section .ramu not large enough for the linker-created stubs section .code.3.__stub.*\Z
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm4.ld b/ld/testsuite/ld-arm/non-contiguous-arm4.ld
new file mode 100644
index 0000000..1e0c376
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm4.ld
@@ -0,0 +1,34 @@ 
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu but not its farcall stub to jump to code4
+ section .code.4 fits in .ramz
+ expect an error about .code.3
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008
+  RAMZ (rwx) : ORIGIN = 0x30040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+   .raml :
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.code) *(.code.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.code) *(.code.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.code) *(.code.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm5.d b/ld/testsuite/ld-arm/non-contiguous-arm5.d
new file mode 100644
index 0000000..30f6118
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm5.d
@@ -0,0 +1,77 @@ 
+#name: non-contiguous-arm5
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm5.ld
+#objdump: -rdth
+#xfail: [is_generic]
+
+.*:     file format elf32-(little|big)arm
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 \.raml         0000000c  1fff0000  1fff0000  00010000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramu         00000014  20000000  1fff000c  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \.ramz         00000050  20040000  20000014  00030000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  3 .ARM.attributes 00000012  00000000  00000000  00030050  2\*\*0
+                  CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l    d  .raml	00000000 .raml
+20000000 l    d  .ramu	00000000 .ramu
+20040000 l    d  .ramz	00000000 .ramz
+00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
+00000000 l    df \*ABS\*	00000000 .*/non-contiguous-arm.o
+1fff000c g       .raml	00000000 _raml_end
+20000000 g       .ramu	00000000 _ramu_start
+20000000 g     F .ramu	00000000 code2
+20040000 g       .ramz	00000000 _ramz_start
+1fff0000 g       .raml	00000000 _raml_start
+2000000c g     F .ramu	00000000 code3
+1fff0000 g     F .raml	00000000 code1
+20040050 g       .ramz	00000000 _ramz_end
+20040000 g     F .ramz	00000000 code4
+20000014 g       .ramu	00000000 _ramu_end
+
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0004:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0008:	eb003ffc 	bl	20000000 \<code2\>
+
+Disassembly of section .ramu:
+
+20000000 \<code2\>:
+20000000:	e1a00000 	nop			; \(mov r0, r0\)
+20000004:	e1a00000 	nop			; \(mov r0, r0\)
+20000008:	ebffffff 	bl	2000000c \<code3\>
+
+2000000c \<code3\>:
+2000000c:	e1a00000 	nop			; \(mov r0, r0\)
+20000010:	eb00fffa 	bl	20040000 \<code4\>
+
+Disassembly of section .ramz:
+
+20040000 \<code4\>:
+20040000:	e1a00000 	.word	0xe1a00000
+20040004:	e1a00000 	.word	0xe1a00000
+20040008:	e1a00000 	.word	0xe1a00000
+2004000c:	e1a00000 	.word	0xe1a00000
+20040010:	e1a00000 	.word	0xe1a00000
+20040014:	e1a00000 	.word	0xe1a00000
+20040018:	e1a00000 	.word	0xe1a00000
+2004001c:	e1a00000 	.word	0xe1a00000
+20040020:	e1a00000 	.word	0xe1a00000
+20040024:	e1a00000 	.word	0xe1a00000
+20040028:	e1a00000 	.word	0xe1a00000
+2004002c:	e1a00000 	.word	0xe1a00000
+20040030:	e1a00000 	.word	0xe1a00000
+20040034:	e1a00000 	.word	0xe1a00000
+20040038:	e1a00000 	.word	0xe1a00000
+2004003c:	e1a00000 	.word	0xe1a00000
+20040040:	e1a00000 	.word	0xe1a00000
+20040044:	e1a00000 	.word	0xe1a00000
+20040048:	e1a00000 	.word	0xe1a00000
+2004004c:	e1a00000 	.word	0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm5.ld b/ld/testsuite/ld-arm/non-contiguous-arm5.ld
new file mode 100644
index 0000000..99c0234
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm5.ld
@@ -0,0 +1,34 @@ 
+/*
+ section .code.1 fits in .raml
+ section .code.2 does not fit in .raml and goes to .ramu
+ section .code.3 would fit in .raml, but goes to .ramu:  Check that .code.2 and .code.3 are not swapped
+ section .code.4 fits in .ramz
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00014
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020
+  RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+   .raml :
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.code) *(.code.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.code) *(.code.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.code) *(.code.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm6.d b/ld/testsuite/ld-arm/non-contiguous-arm6.d
new file mode 100644
index 0000000..5c1c938
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm6.d
@@ -0,0 +1,76 @@ 
+#name: non-contiguous-arm6
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm6.ld
+#objdump: -rdth
+#xfail: [is_generic]
+
+.*:     file format elf32-(little|big)arm
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 \.raml         00000028  1fff0000  1fff0000  00010000  2\*\*3
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramz         00000050  40040000  30000000  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 .ARM.attributes 00000012  00000000  00000000  00020050  2\*\*0
+                  CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l    d  .raml	00000000 .raml
+40040000 l    d  .ramz	00000000 .ramz
+00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
+00000000 l    df \*ABS\*	00000000 .*/non-contiguous-arm.o
+1fff0020 l     F .raml	00000008 __code4_veneer
+1fff0028 g       .raml	00000000 _raml_end
+30000000 g       .raml	00000000 _ramu_start
+1fff000c g     F .raml	00000000 code2
+40040000 g       .ramz	00000000 _ramz_start
+1fff0000 g       .raml	00000000 _raml_start
+1fff0018 g     F .raml	00000000 code3
+1fff0000 g     F .raml	00000000 code1
+40040050 g       .ramz	00000000 _ramz_end
+40040000 g     F .ramz	00000000 code4
+30000000 g       .raml	00000000 _ramu_end
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0004:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0008:	ebffffff 	bl	1fff000c \<code2\>
+
+1fff000c \<code2\>:
+1fff000c:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0010:	e1a00000 	nop			; \(mov r0, r0\)
+1fff0014:	ebffffff 	bl	1fff0018 \<code3\>
+
+1fff0018 \<code3\>:
+1fff0018:	e1a00000 	nop			; \(mov r0, r0\)
+1fff001c:	ebffffff 	bl	1fff0020 \<__code4_veneer\>
+
+1fff0020 \<__code4_veneer\>:
+1fff0020:	e51ff004 	ldr	pc, \[pc, #-4\]	; 1fff0024 \<__code4_veneer\+0x4\>
+1fff0024:	40040000 	.word	0x40040000
+
+Disassembly of section .ramz:
+
+40040000 \<code4\>:
+40040000:	e1a00000 	.word	0xe1a00000
+40040004:	e1a00000 	.word	0xe1a00000
+40040008:	e1a00000 	.word	0xe1a00000
+4004000c:	e1a00000 	.word	0xe1a00000
+40040010:	e1a00000 	.word	0xe1a00000
+40040014:	e1a00000 	.word	0xe1a00000
+40040018:	e1a00000 	.word	0xe1a00000
+4004001c:	e1a00000 	.word	0xe1a00000
+40040020:	e1a00000 	.word	0xe1a00000
+40040024:	e1a00000 	.word	0xe1a00000
+40040028:	e1a00000 	.word	0xe1a00000
+4004002c:	e1a00000 	.word	0xe1a00000
+40040030:	e1a00000 	.word	0xe1a00000
+40040034:	e1a00000 	.word	0xe1a00000
+40040038:	e1a00000 	.word	0xe1a00000
+4004003c:	e1a00000 	.word	0xe1a00000
+40040040:	e1a00000 	.word	0xe1a00000
+40040044:	e1a00000 	.word	0xe1a00000
+40040048:	e1a00000 	.word	0xe1a00000
+4004004c:	e1a00000 	.word	0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm6.ld b/ld/testsuite/ld-arm/non-contiguous-arm6.ld
new file mode 100644
index 0000000..6d6d6fe
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm6.ld
@@ -0,0 +1,33 @@ 
+/*
+ sections .code.1, .code.2 and .code.3 (+ farcall stub) fit in .raml
+ section .code.4 fits in .ramz
+ nothing fits in .ramu
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00030
+  RAMU (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00010
+  RAMZ (rwx) : ORIGIN = 0x40040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+   .raml :
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.code) *(.code.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.code) *(.code.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.code) *(.code.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
-- 
2.7.4