[v1,4/5] aarch64: add tests for non-contiguous memory regions

Message ID 20250918150606.1630916-5-matthieu.longo@arm.com
State New
Headers
Series ld: fix segfaults when non-contiguous memory support is enabled |

Commit Message

Matthieu Longo Sept. 18, 2025, 3:06 p.m. UTC
  This patch adds AArch64 test cases for all non-contiguous memory scenarios.
Those tests were copy-pasted from AArch32, and adapted for AArch64.
It also adds a new test case inspired from a real case where several sections
containing interrupt vector tables, declared in different compilation units,
and all aligned on 2KB, are supposed to be merged into one output section
fitting on 2KB memory.
---
 .../aarch64-non-contiguous-mem.exp            | 34 +++++++
 .../non-contiguous-mem/non-contiguous-mem-1.s | 37 ++++++++
 .../non-contiguous-mem/non-contiguous-mem-2.s | 17 ++++
 .../non-contiguous-mem-3-ivt.s                | 15 ++++
 .../non-contiguous-mem/non-contiguous-mem-3.s | 74 ++++++++++++++++
 .../non-contiguous-mem/non-contiguous-nok-1.d |  9 ++
 .../non-contiguous-nok-1.ld                   | 28 ++++++
 .../non-contiguous-mem/non-contiguous-nok-2.d |  8 ++
 .../non-contiguous-nok-2.ld                   | 28 ++++++
 .../non-contiguous-mem/non-contiguous-nok-3.d |  6 ++
 .../non-contiguous-nok-3.err                  |  4 +
 .../non-contiguous-nok-3.ld                   | 26 ++++++
 .../non-contiguous-mem/non-contiguous-nok-4.d | 15 ++++
 .../non-contiguous-nok-4.ld                   | 24 +++++
 .../non-contiguous-mem/non-contiguous-nok-5.d | 10 +++
 .../non-contiguous-nok-5.err                  |  7 ++
 .../non-contiguous-nok-5.ld                   | 30 +++++++
 .../non-contiguous-mem/non-contiguous-ok-1.d  | 80 +++++++++++++++++
 .../non-contiguous-mem/non-contiguous-ok-1.ld | 28 ++++++
 .../non-contiguous-mem/non-contiguous-ok-2.d  | 88 +++++++++++++++++++
 .../non-contiguous-mem/non-contiguous-ok-2.ld | 28 ++++++
 .../non-contiguous-mem/non-contiguous-ok-3.d  | 80 +++++++++++++++++
 .../non-contiguous-mem/non-contiguous-ok-3.ld | 28 ++++++
 .../non-contiguous-mem/non-contiguous-ok-4.d  | 83 +++++++++++++++++
 .../non-contiguous-mem/non-contiguous-ok-4.ld | 28 ++++++
 .../non-contiguous-mem/non-contiguous-ok-5.d  | 87 ++++++++++++++++++
 .../non-contiguous-mem/non-contiguous-ok-5.ld | 31 +++++++
 .../non-contiguous-ok-5.warn                  | 10 +++
 28 files changed, 943 insertions(+)
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/aarch64-non-contiguous-mem.exp
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-1.s
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-2.s
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3-ivt.s
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3.s
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.err
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.err
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-1.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-1.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-3.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-3.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.ld
 create mode 100644 ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.warn
  

Patch

diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/aarch64-non-contiguous-mem.exp b/ld/testsuite/ld-aarch64/non-contiguous-mem/aarch64-non-contiguous-mem.exp
new file mode 100644
index 00000000000..2eaa6b58249
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/aarch64-non-contiguous-mem.exp
@@ -0,0 +1,34 @@ 
+# Expect script for AARCH64 ELF tests related to GNU properties.
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Exclude non-aarch64-ELF targets.
+if { ![is_elf_format] || ![istarget "aarch64*-*-*"] } {
+  return
+}
+
+load_file $srcdir/$subdir/../lib/aarch64-elf-lib.exp
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+
+foreach t $test_list {
+  # We need to strip the ".d", but can leave the dirname.
+  run_dump_test [file rootname $t] \
+    [list [list as "-I\$srcdir/\$subdir"]]
+}
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-1.s b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-1.s
new file mode 100644
index 00000000000..5696cba88ba
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-1.s
@@ -0,0 +1,37 @@ 
+	.section .code.1, "ax", %progbits
+	# Fit in RAML
+	.global code1
+	.type code1, %function
+code1:
+	nop
+	nop
+	bl code2
+	.size code1, . - code1
+
+	.section .code.2, "ax", %progbits
+	# Fit in RAML
+	.global code2
+	.type code2, %function
+code2:
+	nop
+	nop
+	bl code3
+	.size code2, . - code2
+
+	.section .code.3, "ax", %progbits
+	# Fit in RAMU
+	.global code3
+	.type code3, %function
+code3:
+	nop
+	bl code4
+	.size code3, . - code3
+
+	.section .code.4, "ax", %progbits
+	# Fit in RAMZ
+	.global code4
+	.type code4, %function
+code4:
+$a:
+	.fill 20, 4, 0xe1a00000
+	.size code4, . - code4
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-2.s b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-2.s
new file mode 100644
index 00000000000..a52ac366770
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-2.s
@@ -0,0 +1,17 @@ 
+	.section .bss.MY_BUF, "aw", %nobits
+	.global MY_BUF
+	.type MY_BUF, %object
+MY_BUF:
+	.space 102400 /* 100KB */
+	.size MY_BUF, . - MY_BUF
+
+
+	.section .text.foo,"ax",%progbits
+	.global foo
+	.type	foo, %function
+foo:
+	ldr x0, .L3
+	br lr
+.L3:
+	.word	MY_BUF
+	.size	foo, .-foo
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3-ivt.s b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3-ivt.s
new file mode 100644
index 00000000000..dd0efdae55b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3-ivt.s
@@ -0,0 +1,15 @@ 
+	/* Interrupt vector table.  */
+	.section  .vectors,"ax"
+	.p2align 11  /* 2KB alignment (2^11) */
+	.global vector_table2
+vector_table2:
+	b irqhandler2
+	b irqhandler1
+	.size vector_table2, . - vector_table2
+
+	.global irqhandler2
+	.type irqhandler2, %function
+irqhandler2:
+	b foo
+	eret
+	.size irqhandler2, . - irqhandler2
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3.s b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3.s
new file mode 100644
index 00000000000..31cd9ee0ce3
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-mem-3.s
@@ -0,0 +1,74 @@ 
+	.section .boot, "ax", %progbits
+	.p2align 11  /* 2KB alignment (2^11) */
+	# Fit in RAML
+	.global bootloader
+	.type bootloader, %function
+bootloader:
+	nop
+	nop
+	bl code2
+	.size bootloader, . - bootloader
+
+
+	/* Interrupt vector table.  */
+	.section  .vectors,"ax"
+	.p2align 11  /* 2KB alignment (2^11) */
+	.global vector_table1
+vector_table1:
+	b irqhandler1
+	.size vector_table1, . - vector_table1
+
+	.global irqhandler1
+	.type irqhandler1, %function
+irqhandler1:
+	eret
+	.size irqhandler1, . - irqhandler1
+
+
+	.section .code.2, "ax", %progbits
+	# Fit in RAMU
+	.global code2
+	.type code2, %function
+code2:
+	nop
+	nop
+	bl code3
+	.size code2, . - code2
+
+
+	/* Interrupt vector table.  */
+	.section  .vectors
+	.global vector_table3
+vector_table3:
+	b irqhandler3
+	.size vector_table3, . - vector_table3
+
+	.global irqhandler3
+	.type irqhandler3, %function
+irqhandler3:
+	eret
+	.size irqhandler3, . - irqhandler3
+
+	.section .code.3, "ax", %progbits
+	# Fit in RAMU
+	.global code3
+	.type code3, %function
+code3:
+	nop
+	bl code4
+	.size code3, . - code3
+
+	.section .code.4, "ax", %progbits
+	# Fit in RAMU
+	.global code4
+	.type code4, %function
+code4:
+$a:
+	.fill 20, 4, 0xe1a00000
+	.size code4, . - code4
+
+	.global foo
+	.type foo, %function
+foo:
+	ret
+	.size foo, . - foo
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.d
new file mode 100644
index 00000000000..1b540743cb6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.d
@@ -0,0 +1,9 @@ 
+#name: last section .code.4 is too big to fit in any of the available memories.
+## Use case description:
+## - sections .code.1 and .code.2 fit in .raml
+## - section .code.3 fits in .ramu
+## - section .code.4 is too large to fit in .ramz, we should expect an error
+##   message about unability to assign the input section to an output one.
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-nok-1.ld
+# error: .*Could not assign .?\.code\.4.? to an output section. Retry without --enable-non-contiguous-regions\.
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.ld
new file mode 100644
index 00000000000..ff1b6619448
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-1.ld
@@ -0,0 +1,28 @@ 
+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-aarch64/non-contiguous-mem/non-contiguous-nok-2.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.d
new file mode 100644
index 00000000000..9cbab256ccb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.d
@@ -0,0 +1,8 @@ 
+#name: all code sections fit in the available memories BUT farcall stub to jump to code4 DOES NOT not fits in .ramu
+## Use case description:
+## - 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
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-nok-2.ld
+# error: Memory region `RAMU' not large enough for the linker-created stubs section `\.code\.3\.stub' associated to output section `\.ramu'
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.ld
new file mode 100644
index 00000000000..6c23900de16
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-2.ld
@@ -0,0 +1,28 @@ 
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c
+  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-aarch64/non-contiguous-mem/non-contiguous-nok-3.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.d
new file mode 100644
index 00000000000..34198eef8d0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.d
@@ -0,0 +1,6 @@ 
+#name: .bss section bigger than all the available RAMs.
+## Use case description:
+## The section .bss.MY_BUF (100KB) won't fit in RAM1 (64KB) or RAM2 (96KB)
+#source: non-contiguous-mem-2.s
+#ld: -T non-contiguous-nok-3.ld --enable-non-contiguous-regions --enable-non-contiguous-regions-warnings
+#error_output: non-contiguous-nok-3.err
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.err b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.err
new file mode 100644
index 00000000000..ca23fc6b0b5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.err
@@ -0,0 +1,4 @@ 
+.*: warning: --enable-non-contiguous-regions may change behaviour for section .?\.bss.? from .*
+.*: warning: --enable-non-contiguous-regions may change behaviour for section .?\.bss\.MY_BUF.? from .*
+.*: error: --enable-non-contiguous-regions was not able to allocate the input section `.bss.MY_BUF' \(.*non-contiguous-mem-2\.o\) to an output section
+.*: final link failed
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.ld
new file mode 100644
index 00000000000..5d8100676cf
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-3.ld
@@ -0,0 +1,26 @@ 
+MEMORY
+{
+  ROM  (rx)    : ORIGIN = 0x8000000,    LENGTH = 10K
+  RAM1 (xrw)   : ORIGIN = 0x10000000,   LENGTH = 64K
+  RAM2 (xrw)   : ORIGIN = 0x20000000,   LENGTH = 96K
+}
+
+SECTIONS
+{
+  .text :
+  {
+    KEEP(*(.text.foo)) ;
+  } >ROM
+
+  .bss_ram1 :
+  { _sbss_ram1 = .;
+    *(.bss) *(.bss*) ;
+    _ebss_ram1 = .;
+  } >RAM1
+
+  .bss_ram2 :
+  { _sbss_ram2 = .;
+    *(.bss) *(.bss*) ;
+    _ebss_ram2 = .;
+  } >RAM2
+}
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.d
new file mode 100644
index 00000000000..260eb76dece
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.d
@@ -0,0 +1,15 @@ 
+#name: Discard 2nd interrupt vector table because of alignment requirements
+## Use case description:
+## 3 IVTs are defined in section .vectors (2KB):
+## - vector_table1 and vector_table3 in the first file, and vector_table3 does
+##   not redefine the section, so is directly appended after vector_table1.
+## - vector_table2 is defined in a second file, and redefines the section
+##   .vectors with an alignment of 2KB.
+## Since all .vectors sections should be moved to the VECTORS memory (2KB),
+## vector_table2 will be discarded as the space was taken by the padding of
+## the section defined in the first file.
+#source: non-contiguous-mem-3.s
+#source: non-contiguous-mem-3-ivt.s
+#ld: -T non-contiguous-nok-4.ld --enable-non-contiguous-regions
+#error: --enable-non-contiguous-regions was not able to allocate the input section `\.vectors' \(.*non-contiguous-mem-3-ivt\.o\) to an output section
+#error: .*: final link failed$
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.ld
new file mode 100644
index 00000000000..43fa2c19b71
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-4.ld
@@ -0,0 +1,24 @@ 
+MEMORY
+{
+  RAML    (rwx) : ORIGIN = 0x8000000,          LENGTH = 2K
+  VECTORS (xrw) : ORIGIN = (0x8000000 + 2048), LENGTH = 2K
+  RAMU    (xrw) : ORIGIN = 0x40000000,         LENGTH = 64K
+}
+
+SECTIONS
+{
+  RAM_REGION_START = ORIGIN(RAML);
+  .boot : {
+    *(.bootloader) *(.bootloader.*);
+  } >RAML
+
+  .vectors : AT ( ADDR (.boot) + SIZEOF (.boot) ) {
+    *(.vectors)
+  } >VECTORS
+
+  .text : AT ( ADDR (.vectors) + SIZEOF (.vectors) )
+  { _text_start = . ;
+    *(.code) *(.code.*) ;
+    _text_end = . ;
+  } > RAMU
+}
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.d
new file mode 100644
index 00000000000..2e42375c59c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.d
@@ -0,0 +1,10 @@ 
+#name: input section is discarded because the output section match clauses succeed the matching DISCARD clause.
+## Use case description:
+## - sections .code.1, .code.2 and .code.3 (+ farcall stub) fit in .raml
+## - section .code.4 fits in .ramz
+## - nothing fits in .ramu
+## The linker script contains a DISCARD clause for ".code.4" that precedes all
+## the output clauses.
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions --enable-non-contiguous-regions-warnings -T non-contiguous-nok-5.ld
+#error_output: non-contiguous-nok-5.err
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.err b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.err
new file mode 100644
index 00000000000..4b14de9f429
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.err
@@ -0,0 +1,7 @@ 
+.*: warning: .* may change behaviour for section `\.code\.1' from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* may change behaviour for section `\.code\.2' from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* may change behaviour for section `\.code\.3' from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* may change behaviour for section `\.code\.1' from .* \(assigned to \.ramu, but additional match: \.ramz\)
+.*: warning: .* may change behaviour for section `\.code\.2' from .* \(assigned to \.ramu, but additional match: \.ramz\)
+.*: warning: .* may change behaviour for section `\.code\.3' from .* \(assigned to \.ramu, but additional match: \.ramz\)
+`code4' referenced in section `\.code\.3' of .*: defined in discarded section `\.code\.4' of .*\Z
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.ld
new file mode 100644
index 00000000000..9aea032face
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-nok-5.ld
@@ -0,0 +1,30 @@ 
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00040
+  RAMU (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00010
+  RAMZ (rwx) : ORIGIN = 0x40040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+  /DISCARD/ : { *(.code.4) }
+
+  .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-aarch64/non-contiguous-mem/non-contiguous-ok-1.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-1.d
new file mode 100644
index 00000000000..25e437dddd6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-1.d
@@ -0,0 +1,80 @@ 
+# name: all sections fit in the available memories + no farcall stub.
+## Use case description:
+## - 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
+# source: non-contiguous-mem-1.s
+# ld: --enable-non-contiguous-regions -T non-contiguous-ok-1.ld
+# objdump: -rdth
+
+.*:     file format elf64-(little|big)aarch64
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.raml         00000018  000000001fff0000  000000001fff0000  00010000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramu         00000008  0000000020000000  000000001fff0018  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \.ramz         00000050  0000000020040000  0000000020000008  00030000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+SYMBOL TABLE:
+000000001fff0000 l    d  \.raml	0000000000000000 \.raml
+0000000020000000 l    d  \.ramu	0000000000000000 \.ramu
+0000000020040000 l    d  \.ramz	0000000000000000 \.ramz
+0000000000000000 l    df \*ABS\*	0000000000000000 non-contiguous-mem-.*\.o
+0000000020040000 l       \.ramz	0000000000000000 \$a
+000000001fff0018 g       \.raml	0000000000000000 _raml_end
+0000000020000000 g       \.ramu	0000000000000000 _ramu_start
+000000001fff000c g     F \.raml	000000000000000c code2
+0000000020040000 g       \.ramz	0000000000000000 _ramz_start
+000000001fff0000 g       \.raml	0000000000000000 _raml_start
+0000000020000000 g     F \.ramu	0000000000000008 code3
+000000001fff0000 g     F \.raml	000000000000000c code1
+0000000020040050 g       \.ramz	0000000000000000 _ramz_end
+0000000020040000 g     F \.ramz	0000000000000050 code4
+0000000020000008 g       \.ramu	0000000000000000 _ramu_end
+
+
+
+Disassembly of section \.raml:
+
+000000001fff0000 \<code1\>:
+    1fff0000:	d503201f 	nop
+    1fff0004:	d503201f 	nop
+    1fff0008:	94000001 	bl	1fff000c \<code2\>
+
+000000001fff000c \<code2\>:
+    1fff000c:	d503201f 	nop
+    1fff0010:	d503201f 	nop
+    1fff0014:	94003ffb 	bl	20000000 \<code3\>
+
+Disassembly of section \.ramu:
+
+0000000020000000 \<code3\>:
+    20000000:	d503201f 	nop
+    20000004:	9400ffff 	bl	20040000 \<code4\>
+
+Disassembly of section \.ramz:
+
+0000000020040000 \<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-aarch64/non-contiguous-mem/non-contiguous-ok-1.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-1.ld
new file mode 100644
index 00000000000..257a4ca905c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-1.ld
@@ -0,0 +1,28 @@ 
+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-aarch64/non-contiguous-mem/non-contiguous-ok-2.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d
new file mode 100644
index 00000000000..4ab720b133e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d
@@ -0,0 +1,88 @@ 
+#name: all code sections fit in the available memories AND farcall stub to jump to code4 ALSO fits in .ramu
+## Use case description:
+## - sections .code.1 and .code.2 fit in .raml
+## - both section .code.3 and farcall stub to jump to code4 fits in .ramu
+## - section .code.4 fits in .ramz
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-ok-2.ld
+#objdump: -rdth
+
+.*:     file format elf64-(little|big)aarch64
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.raml         00000018  000000001fff0000  000000001fff0000  00010000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramu         00000028  0000000020000000  000000001fff0018  00020000  2\*\*3
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \.ramz         00000050  0000000030040000  0000000020000028  00030000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+SYMBOL TABLE:
+000000001fff0000 l    d  \.raml	0000000000000000 \.raml
+0000000020000000 l    d  \.ramu	0000000000000000 \.ramu
+0000000030040000 l    d  \.ramz	0000000000000000 \.ramz
+0000000000000000 l    df \*ABS\*	0000000000000000 non-contiguous-mem-.*\.o
+0000000030040000 l       \.ramz	0000000000000000 \$a
+0000000020000010 l     F \.ramu	000000000000000c __code4_veneer
+000000001fff0018 g       \.raml	0000000000000000 _raml_end
+0000000020000000 g       \.ramu	0000000000000000 _ramu_start
+000000001fff000c g     F \.raml	000000000000000c code2
+0000000030040000 g       \.ramz	0000000000000000 _ramz_start
+000000001fff0000 g       \.raml	0000000000000000 _raml_start
+0000000020000000 g     F \.ramu	0000000000000008 code3
+000000001fff0000 g     F \.raml	000000000000000c code1
+0000000030040050 g       \.ramz	0000000000000000 _ramz_end
+0000000030040000 g     F \.ramz	0000000000000050 code4
+0000000020000028 g       \.ramu	0000000000000000 _ramu_end
+
+
+
+Disassembly of section \.raml:
+
+000000001fff0000 \<code1\>:
+    1fff0000:	d503201f 	nop
+    1fff0004:	d503201f 	nop
+    1fff0008:	94000001 	bl	1fff000c \<code2\>
+
+000000001fff000c \<code2\>:
+    1fff000c:	d503201f 	nop
+    1fff0010:	d503201f 	nop
+    1fff0014:	94003ffb 	bl	20000000 \<code3\>
+
+Disassembly of section \.ramu:
+
+0000000020000000 \<code3\>:
+    20000000:	d503201f 	nop
+    20000004:	94000003 	bl	20000010 \<__code4_veneer\>
+    20000008:	14000008 	b	20000028 \<_ramu_end\>
+    2000000c:	d503201f 	nop
+
+0000000020000010 \<__code4_veneer\>:
+    20000010:	90080210 	adrp	x16, 30040000 \<code4\>
+    20000014:	91000210 	add	x16, x16, #0x0
+    20000018:	d61f0200 	br	x16
+	\.\.\.
+
+Disassembly of section \.ramz:
+
+0000000030040000 \<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-aarch64/non-contiguous-mem/non-contiguous-ok-2.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.ld
new file mode 100644
index 00000000000..56b75c5856f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.ld
@@ -0,0 +1,28 @@ 
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00028
+  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-aarch64/non-contiguous-mem/non-contiguous-ok-3.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-3.d
new file mode 100644
index 00000000000..fa257e72521
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-3.d
@@ -0,0 +1,80 @@ 
+#name: subsequent sections should not be swapped, even if they fit in a previous hole.
+## Use case description:
+## - 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
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-ok-3.ld
+#objdump: -rdth
+
+.*:     file format elf64-(little|big)aarch64
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.raml         0000000c  000000001fff0000  000000001fff0000  00010000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramu         00000014  0000000020000000  000000001fff000c  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \.ramz         00000050  0000000020040000  0000000020000014  00030000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+SYMBOL TABLE:
+000000001fff0000 l    d  \.raml	0000000000000000 \.raml
+0000000020000000 l    d  \.ramu	0000000000000000 \.ramu
+0000000020040000 l    d  \.ramz	0000000000000000 \.ramz
+0000000000000000 l    df \*ABS\*	0000000000000000 non-contiguous-mem-.*\.o
+0000000020040000 l       \.ramz	0000000000000000 \$a
+000000001fff000c g       \.raml	0000000000000000 _raml_end
+0000000020000000 g       \.ramu	0000000000000000 _ramu_start
+0000000020000000 g     F \.ramu	000000000000000c code2
+0000000020040000 g       \.ramz	0000000000000000 _ramz_start
+000000001fff0000 g       \.raml	0000000000000000 _raml_start
+000000002000000c g     F \.ramu	0000000000000008 code3
+000000001fff0000 g     F \.raml	000000000000000c code1
+0000000020040050 g       \.ramz	0000000000000000 _ramz_end
+0000000020040000 g     F \.ramz	0000000000000050 code4
+0000000020000014 g       \.ramu	0000000000000000 _ramu_end
+
+
+
+Disassembly of section \.raml:
+
+000000001fff0000 \<code1\>:
+    1fff0000:	d503201f 	nop
+    1fff0004:	d503201f 	nop
+    1fff0008:	94003ffe 	bl	20000000 \<code2\>
+
+Disassembly of section \.ramu:
+
+0000000020000000 \<code2\>:
+    20000000:	d503201f 	nop
+    20000004:	d503201f 	nop
+    20000008:	94000001 	bl	2000000c \<code3\>
+
+000000002000000c \<code3\>:
+    2000000c:	d503201f 	nop
+    20000010:	9400fffc 	bl	20040000 \<code4\>
+
+Disassembly of section \.ramz:
+
+0000000020040000 \<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-aarch64/non-contiguous-mem/non-contiguous-ok-3.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-3.ld
new file mode 100644
index 00000000000..e6b3cd3b0f7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-3.ld
@@ -0,0 +1,28 @@ 
+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-aarch64/non-contiguous-mem/non-contiguous-ok-4.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d
new file mode 100644
index 00000000000..6fbe17ea385
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d
@@ -0,0 +1,83 @@ 
+#name: a "middle" memory is too small to fit anything, the sections are moved to the next available memory.
+## Use case description:
+## - sections .code.1, .code.2 and .code.3 (+ farcall stub) fit in .raml
+## - section .code.4 fits in .ramz
+## - nothing fits in .ramu
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-ok-4.ld
+#objdump: -rdth
+
+.*:     file format elf64-(little|big)aarch64
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.raml         00000040  000000001fff0000  000000001fff0000  00010000  2\*\*3
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramz         00000050  0000000040040000  0000000030000000  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+SYMBOL TABLE:
+000000001fff0000 l    d  \.raml	0000000000000000 \.raml
+0000000040040000 l    d  \.ramz	0000000000000000 \.ramz
+0000000000000000 l    df \*ABS\*	0000000000000000 non-contiguous-mem-.*\.o
+0000000040040000 l       \.ramz	0000000000000000 \$a
+000000001fff0028 l     F \.raml	000000000000000c __code4_veneer
+000000001fff0040 g       \.raml	0000000000000000 _raml_end
+0000000030000000 g       \.raml	0000000000000000 _ramu_start
+000000001fff000c g     F \.raml	000000000000000c code2
+0000000040040000 g       \.ramz	0000000000000000 _ramz_start
+000000001fff0000 g       \.raml	0000000000000000 _raml_start
+000000001fff0018 g     F \.raml	0000000000000008 code3
+000000001fff0000 g     F \.raml	000000000000000c code1
+0000000040040050 g       \.ramz	0000000000000000 _ramz_end
+0000000040040000 g     F \.ramz	0000000000000050 code4
+0000000030000000 g       \.raml	0000000000000000 _ramu_end
+
+
+
+Disassembly of section \.raml:
+
+000000001fff0000 \<code1\>:
+    1fff0000:	d503201f 	nop
+    1fff0004:	d503201f 	nop
+    1fff0008:	94000001 	bl	1fff000c \<code2\>
+
+000000001fff000c \<code2\>:
+    1fff000c:	d503201f 	nop
+    1fff0010:	d503201f 	nop
+    1fff0014:	94000001 	bl	1fff0018 \<code3\>
+
+000000001fff0018 \<code3\>:
+    1fff0018:	d503201f 	nop
+    1fff001c:	94000003 	bl	1fff0028 \<__code4_veneer\>
+    1fff0020:	14000008 	b	1fff0040 \<_raml_end\>
+    1fff0024:	d503201f 	nop
+
+000000001fff0028 \<__code4_veneer\>:
+    1fff0028:	90100290 	adrp	x16, 40040000 \<code4\>
+    1fff002c:	91000210 	add	x16, x16, #0x0
+    1fff0030:	d61f0200 	br	x16
+	...
+
+Disassembly of section \.ramz:
+
+0000000040040000 \<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-aarch64/non-contiguous-mem/non-contiguous-ok-4.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.ld
new file mode 100644
index 00000000000..bdafce7587d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.ld
@@ -0,0 +1,28 @@ 
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00040
+  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
+}
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d
new file mode 100644
index 00000000000..e160d8b9540
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d
@@ -0,0 +1,87 @@ 
+#name: input section is kept because a match clause precedes the matching DISCARD clause.
+## Use case description:
+## - sections .code.1, .code.2 and .code.3 (+ farcall stub) fit in .raml
+## - section .code.4 fits in .ramz
+## - nothing fits in .ramu
+## The linker script contains a ".code.4" match clause for .raml, before
+## the DISCARD clause.
+#source: non-contiguous-mem-1.s
+#ld: --enable-non-contiguous-regions --enable-non-contiguous-regions-warnings -T non-contiguous-ok-5.ld
+#warning_output: non-contiguous-ok-5.warn
+
+#objdump: -rdth
+
+.*:     file format elf64-(little|big)aarch64
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.raml         00000040  000000001fff0000  000000001fff0000  00010000  2\*\*3
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.ramz         00000050  0000000040040000  0000000030000000  00020000  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+SYMBOL TABLE:
+000000001fff0000 l    d  \.raml	0000000000000000 \.raml
+0000000040040000 l    d  \.ramz	0000000000000000 \.ramz
+0000000000000000 l    df \*ABS\*	0000000000000000 non-contiguous-mem-.*\.o
+0000000040040000 l       \.ramz	0000000000000000 \$a
+000000001fff0028 l     F \.raml	000000000000000c __code4_veneer
+000000001fff0040 g       \.raml	0000000000000000 _raml_end
+0000000030000000 g       \.raml	0000000000000000 _ramu_start
+000000001fff000c g     F \.raml	000000000000000c code2
+0000000040040000 g       \.ramz	0000000000000000 _ramz_start
+000000001fff0000 g       \.raml	0000000000000000 _raml_start
+000000001fff0018 g     F \.raml	0000000000000008 code3
+000000001fff0000 g     F \.raml	000000000000000c code1
+0000000040040050 g       \.ramz	0000000000000000 _ramz_end
+0000000040040000 g     F \.ramz	0000000000000050 code4
+0000000030000000 g       \.raml	0000000000000000 _ramu_end
+
+
+
+Disassembly of section \.raml:
+
+000000001fff0000 \<code1\>:
+    1fff0000:	d503201f 	nop
+    1fff0004:	d503201f 	nop
+    1fff0008:	94000001 	bl	1fff000c \<code2\>
+
+000000001fff000c \<code2\>:
+    1fff000c:	d503201f 	nop
+    1fff0010:	d503201f 	nop
+    1fff0014:	94000001 	bl	1fff0018 \<code3\>
+
+000000001fff0018 \<code3\>:
+    1fff0018:	d503201f 	nop
+    1fff001c:	94000003 	bl	1fff0028 \<__code4_veneer\>
+    1fff0020:	14000008 	b	1fff0040 \<_raml_end\>
+    1fff0024:	d503201f 	nop
+
+000000001fff0028 \<__code4_veneer\>:
+    1fff0028:	90100290 	adrp	x16, 40040000 \<code4\>
+    1fff002c:	91000210 	add	x16, x16, #0x0
+    1fff0030:	d61f0200 	br	x16
+	...
+
+Disassembly of section \.ramz:
+
+0000000040040000 \<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-aarch64/non-contiguous-mem/non-contiguous-ok-5.ld b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.ld
new file mode 100644
index 00000000000..127e179b93e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.ld
@@ -0,0 +1,31 @@ 
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00040
+  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
+
+  /DISCARD/ :
+  { *(.code.2) *(.code.4) }
+
+  .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+  { _ramz_start = . ;
+    *(.code) *(.code.*) ;
+    _ramz_end = . ;
+  } > RAMZ
+}
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.warn b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.warn
new file mode 100644
index 00000000000..730599ef289
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.warn
@@ -0,0 +1,10 @@ 
+.*: warning: .* may change behaviour for section .\.code\.1. from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* may change behaviour for section .\.code\.2. from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* may change behaviour for section .\.code\.3. from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* may change behaviour for section .\.code\.4. from .* \(assigned to \.raml, but additional match: \.ramu\)
+.*: warning: .* makes section .\.code\.2. from .* match /DISCARD/ clause\.
+.*: warning: .* makes section .\.code\.4. from .* match /DISCARD/ clause\.
+.*: warning: .* may change behaviour for section .\.code\.1. from .* \(assigned to \.ramu, but additional match: \.ramz\)
+.*: warning: .* may change behaviour for section .\.code\.2. from .* \(assigned to \.ramu, but additional match: \.ramz\)
+.*: warning: .* may change behaviour for section .\.code\.3. from .* \(assigned to \.ramu, but additional match: \.ramz\)
+.*: warning: .* may change behaviour for section .\.code\.4. from .* \(assigned to \.ramu, but additional match: \.ramz\)