public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add support for non-contiguous memory regions
@ 2020-02-14 12:34 Christophe Lyon
  2020-02-14 13:02 ` Tamar Christina
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-02-14 12:34 UTC (permalink / raw)
  To: binutils

Hi,

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

Changes between v3 and v4:
* I ran the tests on more targets (those that have xxx_build_one_stub:
avr csky hppa mc68ch11 metag nios2 ppc aarch64 m68hc11 m68hc12)
* this made me update the generic test (match addresses more lazily to
cope with 64 bits outputs, ignore symbol table whose order depends on
the target), and skip it for the targets that don't support
-mlittle-endian. Is there a more generic way of doing this? (for sure,
there are other targets that don't support that option but that I
haven't tested)
* I updated xxx_build_one_stub similarly to what I needed for arm,
although I didn't write specific tests

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

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

OK?

Thanks,

Christophe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH] Add support for non-contiguous memory regions
  2020-02-14 12:34 [PATCH] Add support for non-contiguous memory regions Christophe Lyon
@ 2020-02-14 13:02 ` Tamar Christina
  2020-02-14 13:54   ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Tamar Christina @ 2020-02-14 13:02 UTC (permalink / raw)
  To: Christophe Lyon, binutils; +Cc: nd

Hi Christophe,

Did you forget to attach the patches perhaps? I don't see any attachments.

Cheers,
Tamar

> -----Original Message-----
> From: binutils-owner@sourceware.org <binutils-owner@sourceware.org>
> On Behalf Of Christophe Lyon
> Sent: Friday, February 14, 2020 12:34 PM
> To: binutils <binutils@sourceware.org>
> Subject: [PATCH] Add support for non-contiguous memory regions
> 
> Hi,
> 
> This is a follow-up to
> https://sourceware.org/ml/binutils/2019-11/msg00402.html
> https://sourceware.org/ml/binutils/2020-01/msg00064.html
> and
> https://sourceware.org/ml/binutils/2020-02/msg00037.html
> 
> Changes between v3 and v4:
> * I ran the tests on more targets (those that have xxx_build_one_stub:
> avr csky hppa mc68ch11 metag nios2 ppc aarch64 m68hc11 m68hc12)
> * this made me update the generic test (match addresses more lazily to cope
> with 64 bits outputs, ignore symbol table whose order depends on the
> target), and skip it for the targets that don't support -mlittle-endian. Is there
> a more generic way of doing this? (for sure, there are other targets that don't
> support that option but that I haven't tested)
> * I updated xxx_build_one_stub similarly to what I needed for arm, although
> I didn't write specific tests
> 
> 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
> 
> 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
> 
> OK?
> 
> Thanks,
> 
> Christophe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-14 13:02 ` Tamar Christina
@ 2020-02-14 13:54   ` Christophe Lyon
  2020-02-19  7:19     ` Alan Modra
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-02-14 13:54 UTC (permalink / raw)
  To: Tamar Christina; +Cc: binutils, nd

[-- Attachment #1: Type: text/plain, Size: 2332 bytes --]

Oops!

Here are the updated patches.

Thanks!

On Fri, 14 Feb 2020 at 14:01, Tamar Christina <Tamar.Christina@arm.com> wrote:
>
> Hi Christophe,
>
> Did you forget to attach the patches perhaps? I don't see any attachments.
>
> Cheers,
> Tamar
>
> > -----Original Message-----
> > From: binutils-owner@sourceware.org <binutils-owner@sourceware.org>
> > On Behalf Of Christophe Lyon
> > Sent: Friday, February 14, 2020 12:34 PM
> > To: binutils <binutils@sourceware.org>
> > Subject: [PATCH] Add support for non-contiguous memory regions
> >
> > Hi,
> >
> > This is a follow-up to
> > https://sourceware.org/ml/binutils/2019-11/msg00402.html
> > https://sourceware.org/ml/binutils/2020-01/msg00064.html
> > and
> > https://sourceware.org/ml/binutils/2020-02/msg00037.html
> >
> > Changes between v3 and v4:
> > * I ran the tests on more targets (those that have xxx_build_one_stub:
> > avr csky hppa mc68ch11 metag nios2 ppc aarch64 m68hc11 m68hc12)
> > * this made me update the generic test (match addresses more lazily to cope
> > with 64 bits outputs, ignore symbol table whose order depends on the
> > target), and skip it for the targets that don't support -mlittle-endian. Is there
> > a more generic way of doing this? (for sure, there are other targets that don't
> > support that option but that I haven't tested)
> > * I updated xxx_build_one_stub similarly to what I needed for arm, although
> > I didn't write specific tests
> >
> > 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
> >
> > 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
> >
> > OK?
> >
> > Thanks,
> >
> > Christophe

[-- Attachment #2: 0002-Add-generic-test-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 3900 bytes --]

From 1faf99eb496fe2f39a8fe7f1f4d24c1534feb123 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 25 Nov 2019 08:56:22 +0000
Subject: [PATCH 2/4] Add generic test for non-contiguous memory regions

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

	ld/
	* testsuite/ld-elf/non-contiguous.d: New.
	* testsuite/ld-elf/non-contiguous.ld: New.
	* testsuite/ld-elf/non-contiguous.s: New.

Change-Id: Ia81d08450956f0fee7eff365ab23060f4882703b
---
 ld/testsuite/ld-elf/non-contiguous.d  | 31 +++++++++++++++++++++++++++++++
 ld/testsuite/ld-elf/non-contiguous.ld | 35 +++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-elf/non-contiguous.s  | 21 +++++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.d
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.ld
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.s

diff --git a/ld/testsuite/ld-elf/non-contiguous.d b/ld/testsuite/ld-elf/non-contiguous.d
new file mode 100644
index 0000000..078b733
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.d
@@ -0,0 +1,31 @@
+#name: non-contiguous
+#source: non-contiguous.s
+#as: -mlittle-endian
+#ld: --enable-non-contiguous-regions -T non-contiguous.ld -EL
+#objdump: -rdsh
+#xfail: [is_generic]
+# These targets do not support -mlittle-endian
+#skip: avr* hppa* m68hc* metag* nios2*
+
+.*:     file format .*
+
+Sections:
+Idx Name          Size      VMA  *     LMA  *     File off  Algn
+  0 \.raml         0000000c  0*1fff0000  0*1fff0000  .*  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+  1 \.ramu         00000014  0*20000000  0*1fff000c  .*  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+  2 \.ramz         0000003c  0*20040000  0*20000014  .*  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+
+
+Contents of section .raml:
+ 1fff0000 01000000 02000000 03000000           ............    
+Contents of section .ramu:
+ 20000000 04000000 05000000 06000000 07000000  ................
+ 20000010 08000000                             ....            
+Contents of section .ramz:
+ 20040000 09090909 09090909 09090909 09090909  ................
+ 20040010 09090909 09090909 09090909 09090909  ................
+ 20040020 09090909 09090909 09090909 09090909  ................
+ 20040030 09090909 09090909 09090909           ............    
diff --git a/ld/testsuite/ld-elf/non-contiguous.ld b/ld/testsuite/ld-elf/non-contiguous.ld
new file mode 100644
index 0000000..3e23087
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.ld
@@ -0,0 +1,35 @@
+/*
+ section .data.1 fits in .raml
+ sections .data.2 .data.3 fit in .ramu
+ section .data.4 fits in .ramz
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00014
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040
+  RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00040
+}
+
+SECTIONS
+{
+   /* Ignore this target specific info in output comparison.  */
+   /DISCARD/ : { *(.ARM.attributes) }
+   .raml : AT ( ADDR (.text) + SIZEOF (.text) )
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.data) *(.data.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.data) *(.data.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.data) *(.data.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-elf/non-contiguous.s b/ld/testsuite/ld-elf/non-contiguous.s
new file mode 100644
index 0000000..8e2d581
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.s
@@ -0,0 +1,21 @@
+	.section .data.1
+	# Fit in RAML
+	.4byte 1
+	.4byte 2
+	.4byte 3
+
+	.section .data.2
+	# Fit in RAMU
+	.4byte 4
+	.4byte 5
+	.4byte 6
+
+	.section .data.3
+	# Fit in RAMU
+	.4byte 7
+	.4byte 8
+
+	.section .data.4
+	# Fit in RAMZ
+	.fill 0x3c, 1, 9
+
-- 
2.7.4


[-- Attachment #3: 0001-Add-support-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 27995 bytes --]

From f97d789e0dd5961578173666b76e93c18b65ac27 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 25 Nov 2019 08:55:37 +0000
Subject: [PATCH 1/4] Add support for non-contiguous memory regions

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

	bfd/
	* bfd-in2.h: Regenerate.
	* section.c (asection): Add already_assigned field.
	(BFD_FAKE_SECTION): Add default initializer for it.
	* ecoff.c (bfd_debug_section): Initialize already_assigned field.
	* elf32-arm.c (arm_build_one_stub): Add support for
	non_contiguous_regions.
	* elf32-csky.c (csky_build_one_stub): Likewise.
	* elf32-hppa.c (hppa_build_one_stub): Likewise.
	* elf32-m68hc11.c (m68hc11_elf_build_one_stub): Likewise.
	* elf32-m68hc12.c (m68hc12_elf_build_one_stub): Likewise.
	* elf32-metag.c (metag_build_one_stub): Likewise.
	* elf32-nios2.c (nios2_build_one_stub): Likewise.
	* elf64-ppc.c (ppc_build_one_stub): Likewise.
	* elfnn-aarch64.c (aarch64_build_one_stub): Likewise.
	* elflink.c (elf_link_input_bfd): Likewise.

	include/
	* bfdlink.h (bfd_link_info): Add non_contiguous_regions and
	non_contiguous_regions_warnings fields.

	ld/
	* ldlang.c (lang_add_section): Add support for
	non_contiguous_regions.
	(size_input_section): Likewise.
	(lang_size_sections_1): Likewise.
	(process_insert_statements): Likewise.
	* ldlex.h (option_values): Add OPTION_NON_CONTIGUOUS_REGIONS and
	OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS.
	* lexsup.c (ld_options): Add entries for
	--enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings.
	(parse_args): Handle it.
	* NEWS: Add --enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings.
	* ld.texi: Add --enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings documentation.
	* emultempl/armelf.em (elf32_arm_add_stub_section): Add
	SEC_LINKER_CREATED flag.

Change-Id: Iac2f395b3a1fbea4b3a732ba5a9b847e10b4b2f0
---
 bfd/bfd-in2.h          |   9 ++-
 bfd/ecoff.c            |   6 +-
 bfd/elf32-arm.c        |  11 ++++
 bfd/elf32-csky.c       |  11 ++++
 bfd/elf32-hppa.c       |  31 +++++++++++
 bfd/elf32-m68hc11.c    |  11 ++++
 bfd/elf32-m68hc12.c    |  11 ++++
 bfd/elf32-metag.c      |  14 ++++-
 bfd/elf32-nios2.c      |  12 ++++
 bfd/elf64-ppc.c        |  11 ++++
 bfd/elflink.c          |  12 ++++
 bfd/elfnn-aarch64.c    |  15 ++++-
 bfd/section.c          |   9 ++-
 include/bfdlink.h      |   8 +++
 ld/NEWS                |   3 +
 ld/emultempl/armelf.em |   3 +-
 ld/ld.texi             |  42 ++++++++++++++
 ld/ldlang.c            | 146 +++++++++++++++++++++++++++++++++++++++++++++++--
 ld/ldlex.h             |   2 +
 ld/lexsup.c            |  10 ++++
 20 files changed, 366 insertions(+), 11 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 09a5a39..35d1abb 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1190,6 +1190,10 @@ typedef struct bfd_section
     struct bfd_link_order *link_order;
     struct bfd_section *s;
   } map_head, map_tail;
+ /* Points to the output section this section is already assigned to, if any.
+    This is used when support for non-contiguous memory regions is enabled.  */
+ struct bfd_section *already_assigned;
+
 } asection;
 
 /* Relax table contains information about instructions which can
@@ -1371,7 +1375,10 @@ discarded_section (const asection *sec)
      (struct bfd_symbol *) SYM, &SEC.symbol,                           \
                                                                        \
   /* map_head, map_tail                                            */  \
-     { NULL }, { NULL }                                                \
+     { NULL }, { NULL },                                               \
+                                                                       \
+  /* already_assigned                                              */  \
+     NULL                                                              \
     }
 
 /* We use a macro to initialize the static asymbol structures because
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 050fd7b..58620e5 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -78,8 +78,10 @@ static asection bfd_debug_section =
      NULL,
   /* symbol_ptr_ptr,						   */
      NULL,
-  /* map_head, map_tail						   */
-     { NULL }, { NULL }
+  /* map_head, map_tail,					   */
+     { NULL }, { NULL },
+  /* already_assigned 						   */
+     NULL,
 };
 
 /* Create an ECOFF object.  */
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index faf8376..a10d32b 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5064,6 +5064,17 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   globals = elf32_arm_hash_table (info);
   if (globals == NULL)
     return FALSE;
diff --git a/bfd/elf32-csky.c b/bfd/elf32-csky.c
index 04214f2..d12a898 100644
--- a/bfd/elf32-csky.c
+++ b/bfd/elf32-csky.c
@@ -3621,6 +3621,17 @@ csky_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_csky_stub_hash_entry *)gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   globals = csky_elf_hash_table (info);
   if (globals == NULL)
     return FALSE;
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 2e65308..7ac4b23 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -731,6 +731,17 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
   switch (hsh->stub_type)
     {
     case hppa_stub_long_branch:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
+
       /* Create the long branch.  A long branch is formed with "ldil"
 	 loading the upper bits of the target address into a register,
 	 then branching with "be" which adds in the lower bits.
@@ -751,6 +762,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
       break;
 
     case hppa_stub_long_branch_shared:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
       /* Branches are relative.  This is where we are going to.  */
       sym_value = (hsh->target_value
 		   + hsh->target_section->output_offset
@@ -823,6 +844,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
       break;
 
     case hppa_stub_export:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
       /* Branches are relative.  This is where we are going to.  */
       sym_value = (hsh->target_value
 		   + hsh->target_section->output_offset
diff --git a/bfd/elf32-m68hc11.c b/bfd/elf32-m68hc11.c
index 8d4d227..177feb6 100644
--- a/bfd/elf32-m68hc11.c
+++ b/bfd/elf32-m68hc11.c
@@ -415,6 +415,17 @@ m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = m68hc11_elf_hash_table (info);
   if (htab == NULL)
     return FALSE;
diff --git a/bfd/elf32-m68hc12.c b/bfd/elf32-m68hc12.c
index e41b4c7..9ff8270 100644
--- a/bfd/elf32-m68hc12.c
+++ b/bfd/elf32-m68hc12.c
@@ -535,6 +535,17 @@ m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = m68hc11_elf_hash_table (info);
 
   stub_sec = stub_entry->stub_sec;
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 08eb70b..477baae 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -3459,7 +3459,7 @@ metag_type_of_stub (asection *input_sec,
 #define MOV_PC_A0_3	0xa3180ca0
 
 static bfd_boolean
-metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_UNUSED)
+metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 {
   struct elf_metag_stub_hash_entry *hsh;
   asection *stub_sec;
@@ -3470,6 +3470,18 @@ metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
 
   /* Massage our args to the form they really have.  */
   hsh = (struct elf_metag_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (hsh->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  hsh->target_section);
+      abort();
+    }
 
   stub_sec = hsh->stub_sec;
 
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index 947eaeb..517bdc4 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -2491,6 +2491,18 @@ nios2_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
   asection *stub_sec = hsh->stub_sec;
   bfd_vma sym_value;
 
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (hsh->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  hsh->target_section);
+      abort();
+    }
   /* Make a note of the offset within the stubs for this entry.  */
   hsh->stub_offset = stub_sec->size;
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index b3f8f6b..8fca552 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11349,6 +11349,17 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
   info = in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section != NULL
+      && stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 5217528..deef7f5 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10569,6 +10569,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 	 discarding, we don't need to keep it.  */
       if (isym->st_shndx != SHN_UNDEF
 	  && isym->st_shndx < SHN_LORESERVE
+	  && isec->output_section == NULL
+	  && flinfo->info->non_contiguous_regions
+	  && flinfo->info->non_contiguous_regions_warnings)
+	{
+	  _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+				"discards section `%s' from '%s'\n"),
+			      isec->name, isec->owner->filename);
+	  continue;
+	}
+
+      if (isym->st_shndx != SHN_UNDEF
+	  && isym->st_shndx < SHN_LORESERVE
 	  && bfd_section_removed_from_list (output_bfd,
 					    isec->output_section))
 	continue;
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 5fabcd8..75edd45 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -3278,7 +3278,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name,
 
 static bfd_boolean
 aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
-			void *in_arg ATTRIBUTE_UNUSED)
+			void *in_arg)
 {
   struct elf_aarch64_stub_hash_entry *stub_entry;
   asection *stub_sec;
@@ -3295,6 +3295,19 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
 
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   stub_sec = stub_entry->stub_sec;
 
   /* Make a note of the offset within the stubs for this entry.  */
diff --git a/bfd/section.c b/bfd/section.c
index 0c15a0d..c1a1a4b 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -549,6 +549,10 @@ CODE_FRAGMENT
 .    struct bfd_link_order *link_order;
 .    struct bfd_section *s;
 .  } map_head, map_tail;
+. {* Points to the output section this section is already assigned to, if any.
+.    This is used when support for non-contiguous memory regions is enabled.  *}
+. struct bfd_section *already_assigned;
+.
 .} asection;
 .
 .{* Relax table contains information about instructions which can
@@ -730,7 +734,10 @@ CODE_FRAGMENT
 .     (struct bfd_symbol *) SYM, &SEC.symbol,				\
 .									\
 .  {* map_head, map_tail                                            *}	\
-.     { NULL }, { NULL }						\
+.     { NULL }, { NULL },						\
+.									\
+.  {* already_assigned                                             *}	\
+.     NULL								\
 .    }
 .
 .{* We use a macro to initialize the static asymbol structures because
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 8d85530..529ea6e 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -501,6 +501,14 @@ struct bfd_link_info
   /* TRUE if "-Map map" is passed to linker.  */
   unsigned int has_map_file : 1;
 
+  /* TRUE if "--enable-non-contiguous-regions" is passed to the
+     linker.  */
+  unsigned int non_contiguous_regions : 1;
+
+  /* TRUE if "--enable-non-contiguous-regions-warnings" is passed to
+     the linker.  */
+  unsigned int non_contiguous_regions_warnings : 1;
+
   /* Char that may appear as the first char of a symbol, but should be
      skipped (like symbol_leading_char) when looking up symbols in
      wrap_hash.  Used by PowerPC Linux for 'dot' symbols.  */
diff --git a/ld/NEWS b/ld/NEWS
index f659ccf..2611a3e 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add command-line options --enable-non-contiguous-regions and
+  --enable-non-contiguous-regions-warnings.
+
 Changes in 2.34:
 
 * cr16c support removed.
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index efdcf5a..fb5bbf8 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -227,7 +227,8 @@ elf32_arm_add_stub_section (const char * stub_sec_name,
   struct hook_stub_info info;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
-	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP
+	   | SEC_LINKER_CREATED);
   stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
 						 stub_sec_name, flags);
   if (stub_sec == NULL)
diff --git a/ld/ld.texi b/ld/ld.texi
index 9bb3d55..07933b2 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -459,6 +459,48 @@ will contain a colon separated list of audit interfaces to use.  This
 option is only meaningful on ELF platforms supporting the rtld-audit interface.
 The -P option is provided for Solaris compatibility.
 
+@kindex --enable-non-contiguous-regions
+@item --enable-non-contiguous-regions
+This option avoids generating an error if an input section does not
+fit a matching output section. The linker tries to allocate the input
+section to subseque nt matching output sections, and generates an
+error only if no output section is large enough.  This is useful when
+several non-contiguous memory regions are available and the input
+section does not require a particular one.  The order in which input
+sections are evaluated does not change, for instance:
+
+@smallexample
+  MEMORY @{
+    MEM1 (rwx) : ORIGIN : 0x1000, LENGTH = 0x14
+    MEM2 (rwx) : ORIGIN : 0x1000, LENGTH = 0x40
+    MEM3 (rwx) : ORIGIN : 0x2000, LENGTH = 0x40
+  @}
+  SECTIONS @{
+    mem1 : @{ *(.data.*); @} > MEM1
+    mem2 : @{ *(.data.*); @} > MEM2
+    mem3 : @{ *(.data.*); @} > MEM2
+  @}
+
+  with input sections:
+  .data.1: size 8
+  .data.2: size 0x10
+  .data.3: size 4
+
+  results in .data.1 affected to mem1, and .data.2 and .data.3
+  affected to mem2, even though .data.3 would fit in mem3.
+@end smallexample
+
+This option is incompatible with INSERT statements because it changes
+the way input sections are mapped to output sections.
+
+@kindex --enable-non-contiguous-regions-warnings
+@item --enable-non-contiguous-regions-warnings
+This option enables warnings when
+@code{--enable-non-contiguous-regions} allows possibly unexpected
+matches in sections mapping, potentially leading to silently
+discarding a section instead of failing because it does not fit any
+output region.
+
 @cindex entry point, from command line
 @kindex -e @var{entry}
 @kindex --entry=@var{entry}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 91c160b..d34919e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2537,6 +2537,11 @@ lang_add_section (lang_statement_list_type *ptr,
 	  /* This prevents future calls from assigning this section.  */
 	  section->output_section = bfd_abs_section_ptr;
 	}
+      else if (link_info.non_contiguous_regions_warnings)
+	einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
+		 "section `%pA' from '%pB' match /DISCARD/ clause.\n"),
+	       NULL, section, section->owner);
+
       return;
     }
 
@@ -2550,7 +2555,33 @@ lang_add_section (lang_statement_list_type *ptr,
     }
 
   if (section->output_section != NULL)
-    return;
+    {
+      if (!link_info.non_contiguous_regions)
+	return;
+
+      /* SECTION has already been handled in a special way
+	 (eg. LINK_ONCE): skip it.  */
+      if (bfd_is_abs_section (section->output_section))
+	return;
+
+      /* Already assigned to the same output section, do not process
+	 it again, to avoid creating loops between duplicate sections
+	 later.  */
+      if (section->output_section == output->bfd_section)
+	return;
+
+      if (link_info.non_contiguous_regions_warnings && output->bfd_section)
+	einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
+		 "change behaviour for section `%pA' from '%pB' (assigned to "
+		 "%pA, but additional match: %pA)\n"),
+	       NULL, section, section->owner, section->output_section,
+	       output->bfd_section);
+
+      /* SECTION has already been assigned to an output section, but
+	 the user allows it to be mapped to another one in case it
+	 overflows. We'll later update the actual output section in
+	 size_input_section as appropriate.  */
+    }
 
   /* We don't copy the SEC_NEVER_LOAD flag from an input section
      to an output section, because we want to be able to include a
@@ -4194,6 +4225,12 @@ process_insert_statements (lang_statement_union_type **start)
 	  lang_statement_union_type **ptr;
 	  lang_statement_union_type *first;
 
+	  if (link_info.non_contiguous_regions)
+	    {
+	      einfo (_("warning: INSERT statement in linker script is "
+		       "incompatible with --enable-non-contiguous-regions.\n"));
+	    }
+
 	  where = lang_output_section_find (i->where);
 	  if (where != NULL && i->is_before)
 	    {
@@ -5116,11 +5153,27 @@ size_input_section
   (lang_statement_union_type **this_ptr,
    lang_output_section_statement_type *output_section_statement,
    fill_type *fill,
+   bfd_boolean *removed,
    bfd_vma dot)
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
   asection *o = output_section_statement->bfd_section;
+  *removed = 0;
+
+  if (link_info.non_contiguous_regions)
+    {
+      /* If the input section I has already been successfully assigned
+	 to an output section other than O, don't bother with it and
+	 let the caller remove it from the list.  Keep processing in
+	 case we have already handled O, because the repeated passes
+	 have reinitialized its size.  */
+      if (i->already_assigned && i->already_assigned != o)
+	{
+	  *removed = 1;
+	  return dot;
+	}
+    }
 
   if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
     i->output_offset = i->vma - o->vma;
@@ -5152,6 +5205,43 @@ size_input_section
 	  dot += alignment_needed;
 	}
 
+      if (link_info.non_contiguous_regions)
+	{
+	  /* If I would overflow O, let the caller remove I from the
+	     list.  */
+	  if (output_section_statement->region)
+	    {
+	      bfd_vma end = output_section_statement->region->origin
+		+ output_section_statement->region->length;
+
+	      if (dot + TO_ADDR (i->size) > end)
+		{
+		  if (i->flags & SEC_LINKER_CREATED)
+		    {
+		      einfo (_("Output section %s not large enough for the "
+			       "linker-created stubs section %s.\n"),
+			     i->output_section->name, i->name);
+		      abort();
+		    }
+
+		  if (i->rawsize && i->rawsize != i->size)
+		    {
+		      einfo (_("Relaxation not supported with "
+			       "--enable-non-contiguous-regions (section %s "
+			       "would overflow %s after it changed size).\n"),
+			     i->name, i->output_section->name);
+		      abort();
+		    }
+
+		  *removed = 1;
+		  dot = end;
+		  ASSERT (i->already_assigned == NULL);
+		  i->output_section = NULL;
+		  return dot;
+		}
+	    }
+	}
+
       /* Remember where in the output section this input section goes.  */
       i->output_offset = dot - o->vma;
 
@@ -5159,6 +5249,14 @@ size_input_section
       dot += TO_ADDR (i->size);
       if (!(o->flags & SEC_FIXED_SIZE))
 	o->size = TO_SIZE (dot - o->vma);
+
+      if (link_info.non_contiguous_regions)
+	{
+	  /* Record that I was successfully assigned to O, and update
+	     its actual output section too.  */
+	  i->already_assigned = o;
+	  i->output_section = o;
+	}
     }
 
   return dot;
@@ -5445,10 +5543,14 @@ lang_size_sections_1
    bfd_boolean check_regions)
 {
   lang_statement_union_type *s;
+  lang_statement_union_type *prev_s = NULL;
+  bfd_boolean removed_prev_s = FALSE;
 
   /* Size up the sections from their constituent parts.  */
-  for (s = *prev; s != NULL; s = s->header.next)
+  for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
     {
+      bfd_boolean removed=FALSE;
+
       switch (s->header.type)
 	{
 	case lang_output_section_statement_enum:
@@ -5874,7 +5976,7 @@ lang_size_sections_1
 		  *relax = TRUE;
 	      }
 	    dot = size_input_section (prev, output_section_statement,
-				      fill, dot);
+				      fill, &removed, dot);
 	  }
 	  break;
 
@@ -5979,7 +6081,43 @@ lang_size_sections_1
 	  FAIL ();
 	  break;
 	}
-      prev = &s->header.next;
+
+      /* If an input section doesn't fit in the current output
+	 section, remove it from the list.  Handle the case where we
+	 have to remove an input_section statement here: there is a
+	 special case to remove the first element of the list.  */
+      if (link_info.non_contiguous_regions && removed)
+	{
+	  /* If we removed the first element during the previous
+	     iteration, override the loop assignment of prev_s.  */
+	  if (removed_prev_s)
+	      prev_s = NULL;
+
+	  if (prev_s)
+	    {
+	      /* If there was a real previous input section, just skip
+		 the current one.  */
+	      prev_s->header.next=s->header.next;
+	      s = prev_s;
+	      removed_prev_s = FALSE;
+	    }
+	  else
+	    {
+	      /* Remove the first input section of the list.  */
+	      *prev = s->header.next;
+	      removed_prev_s = TRUE;
+	    }
+
+	  /* Move to next element, unless we removed the head of the
+	     list.  */
+	  if (!removed_prev_s)
+	    prev = &s->header.next;
+	}
+      else
+	{
+	  prev = &s->header.next;
+	  removed_prev_s = FALSE;
+	}
     }
   return dot;
 }
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 5287f19..22b928d 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -150,6 +150,8 @@ enum option_values
   OPTION_FORCE_GROUP_ALLOCATION,
   OPTION_PRINT_MAP_DISCARDED,
   OPTION_NO_PRINT_MAP_DISCARDED,
+  OPTION_NON_CONTIGUOUS_REGIONS,
+  OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS,
 };
 
 /* The initial parser states.  */
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 3d15cc4..2597e2d 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -122,6 +122,10 @@ static const struct ld_option ld_options[] =
     'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
   { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
     '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
+  { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS},
+    '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES },
+  { {"enable-non-contiguous-regions-warnings", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS},
+    '\0', NULL, N_("Enable warnings when --enable-non-contiguous-regions may cause unexpected behaviour"), TWO_DASHES },
   { {"EB", no_argument, NULL, OPTION_EB},
     '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
   { {"EL", no_argument, NULL, OPTION_EL},
@@ -845,6 +849,12 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_NO_EXPORT_DYNAMIC:
 	  link_info.export_dynamic = FALSE;
 	  break;
+	case OPTION_NON_CONTIGUOUS_REGIONS:
+	  link_info.non_contiguous_regions = TRUE;
+	  break;
+	case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
+	  link_info.non_contiguous_regions_warnings = TRUE;
+	  break;
 	case 'e':
 	  lang_add_entry (optarg, TRUE);
 	  break;
-- 
2.7.4


[-- Attachment #4: 0003-Add-arm-tests-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 23045 bytes --]

From 8b1542e4c2256f1cf0c5d26368896f87a8b807ec 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


[-- Attachment #5: 0004-Add-powerpc-test-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 3115 bytes --]

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

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

	ld/
	* testsuite/ld-powerpc/powerpc.exp: Run new test.
	* testsuite/ld-powerpc/non-contiguous-powerpc.d: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc.ld: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc.sd: New.

Change-Id: Iad0b160ad1b382a158dc06fa4e4656eb06691a8a
---
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d  |  4 ++++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld | 22 ++++++++++++++++++++++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s  |  8 ++++++++
 ld/testsuite/ld-powerpc/powerpc.exp               |  2 ++
 4 files changed, 36 insertions(+)
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s

diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
new file mode 100644
index 0000000..2dd7d21
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
@@ -0,0 +1,4 @@
+#name: non-contiguous-powerpc
+#source: non-contiguous-powerpc.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-powerpc.ld
+#error: \ARelaxation not supported with --enable-non-contiguous-regions.*
\ No newline at end of file
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
new file mode 100644
index 0000000..744d246
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
@@ -0,0 +1,22 @@
+/* Distance between 'one' and 'two' means that relaxation implies that
+   .text.one's size increases. Even though the result would fit in
+   'oneandhalf', this is not supported by
+   --enable-non-contiguous-regions.  */
+
+MEMORY {
+       one (RXAI) : ORIGIN = 0x00000000, LENGTH = 0x00000010
+       oneandhalf (RXAI) : ORIGIN = 0x00001000, LENGTH = 0x00001010
+       two (RXAI) : ORIGIN = 0x20000000, LENGTH = 0x10000000
+}
+
+SECTIONS {
+      one : {
+         *(.text.one)
+      } > one
+      oneandhalf : {
+         *(.text.one)
+      } > oneandhalf
+      two : {
+      *(.text.two)
+      } > two
+}
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
new file mode 100644
index 0000000..e02b322
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
@@ -0,0 +1,8 @@
+	.machine "ppc"
+
+	.section .text.one
+	b	2f
+
+	.section .text.two
+2:
+	nop
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 94b2fac..796635f 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -443,3 +443,5 @@ run_dump_test "vle-multiseg-6"
 
 run_dump_test "ppc476-shared"
 run_dump_test "ppc476-shared2"
+
+run_dump_test "non-contiguous-powerpc"
-- 
2.7.4


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-14 13:54   ` Christophe Lyon
@ 2020-02-19  7:19     ` Alan Modra
  2020-02-19 12:28       ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2020-02-19  7:19 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Tamar Christina, binutils, nd

On Fri, Feb 14, 2020 at 02:53:55PM +0100, Christophe Lyon wrote:
> Here are the updated patches.

Wrong set of patches?  elfnn-aarch64.c, elf32-metag.c, and
elf32-nios2.c won't compile with these patches applied.  All due to
missing "struct bfd_link_info *info;" in build_one_stub.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-19  7:19     ` Alan Modra
@ 2020-02-19 12:28       ` Christophe Lyon
  2020-02-19 22:23         ` Alan Modra
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-02-19 12:28 UTC (permalink / raw)
  To: Alan Modra; +Cc: Tamar Christina, binutils, nd

[-- Attachment #1: Type: text/plain, Size: 613 bytes --]

On Wed, 19 Feb 2020 at 08:19, Alan Modra <amodra@gmail.com> wrote:
>
> On Fri, Feb 14, 2020 at 02:53:55PM +0100, Christophe Lyon wrote:
> > Here are the updated patches.
>
> Wrong set of patches?  elfnn-aarch64.c, elf32-metag.c, and
> elf32-nios2.c won't compile with these patches applied.  All due to
> missing "struct bfd_link_info *info;" in build_one_stub.
>

Oops, thanks for noticing.
I don't understand what happened. Here's the right version (the only
difference is the declaration of struct bfd_link_info *info; in
build_one_stub.

Thanks

Christophe

> --
> Alan Modra
> Australia Development Lab, IBM

[-- Attachment #2: 0002-Add-generic-test-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 3900 bytes --]

From 4fcd6a8bacdb7a33d2bfb25f364d163e5ea58934 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 25 Nov 2019 08:56:22 +0000
Subject: [PATCH 2/4] Add generic test for non-contiguous memory regions

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

	ld/
	* testsuite/ld-elf/non-contiguous.d: New.
	* testsuite/ld-elf/non-contiguous.ld: New.
	* testsuite/ld-elf/non-contiguous.s: New.

Change-Id: Ia81d08450956f0fee7eff365ab23060f4882703b
---
 ld/testsuite/ld-elf/non-contiguous.d  | 31 +++++++++++++++++++++++++++++++
 ld/testsuite/ld-elf/non-contiguous.ld | 35 +++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-elf/non-contiguous.s  | 21 +++++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.d
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.ld
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.s

diff --git a/ld/testsuite/ld-elf/non-contiguous.d b/ld/testsuite/ld-elf/non-contiguous.d
new file mode 100644
index 0000000..078b733
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.d
@@ -0,0 +1,31 @@
+#name: non-contiguous
+#source: non-contiguous.s
+#as: -mlittle-endian
+#ld: --enable-non-contiguous-regions -T non-contiguous.ld -EL
+#objdump: -rdsh
+#xfail: [is_generic]
+# These targets do not support -mlittle-endian
+#skip: avr* hppa* m68hc* metag* nios2*
+
+.*:     file format .*
+
+Sections:
+Idx Name          Size      VMA  *     LMA  *     File off  Algn
+  0 \.raml         0000000c  0*1fff0000  0*1fff0000  .*  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+  1 \.ramu         00000014  0*20000000  0*1fff000c  .*  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+  2 \.ramz         0000003c  0*20040000  0*20000014  .*  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+
+
+Contents of section .raml:
+ 1fff0000 01000000 02000000 03000000           ............    
+Contents of section .ramu:
+ 20000000 04000000 05000000 06000000 07000000  ................
+ 20000010 08000000                             ....            
+Contents of section .ramz:
+ 20040000 09090909 09090909 09090909 09090909  ................
+ 20040010 09090909 09090909 09090909 09090909  ................
+ 20040020 09090909 09090909 09090909 09090909  ................
+ 20040030 09090909 09090909 09090909           ............    
diff --git a/ld/testsuite/ld-elf/non-contiguous.ld b/ld/testsuite/ld-elf/non-contiguous.ld
new file mode 100644
index 0000000..3e23087
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.ld
@@ -0,0 +1,35 @@
+/*
+ section .data.1 fits in .raml
+ sections .data.2 .data.3 fit in .ramu
+ section .data.4 fits in .ramz
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00014
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040
+  RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00040
+}
+
+SECTIONS
+{
+   /* Ignore this target specific info in output comparison.  */
+   /DISCARD/ : { *(.ARM.attributes) }
+   .raml : AT ( ADDR (.text) + SIZEOF (.text) )
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.data) *(.data.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.data) *(.data.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.data) *(.data.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-elf/non-contiguous.s b/ld/testsuite/ld-elf/non-contiguous.s
new file mode 100644
index 0000000..8e2d581
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.s
@@ -0,0 +1,21 @@
+	.section .data.1
+	# Fit in RAML
+	.4byte 1
+	.4byte 2
+	.4byte 3
+
+	.section .data.2
+	# Fit in RAMU
+	.4byte 4
+	.4byte 5
+	.4byte 6
+
+	.section .data.3
+	# Fit in RAMU
+	.4byte 7
+	.4byte 8
+
+	.section .data.4
+	# Fit in RAMZ
+	.fill 0x3c, 1, 9
+
-- 
2.7.4


[-- Attachment #3: 0003-Add-arm-tests-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 23045 bytes --]

From 8e7650efc69cce07c1f6c95bfd026a095538e5f3 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


[-- Attachment #4: 0004-Add-powerpc-test-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 3115 bytes --]

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

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

	ld/
	* testsuite/ld-powerpc/powerpc.exp: Run new test.
	* testsuite/ld-powerpc/non-contiguous-powerpc.d: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc.ld: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc.sd: New.

Change-Id: Iad0b160ad1b382a158dc06fa4e4656eb06691a8a
---
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d  |  4 ++++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld | 22 ++++++++++++++++++++++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s  |  8 ++++++++
 ld/testsuite/ld-powerpc/powerpc.exp               |  2 ++
 4 files changed, 36 insertions(+)
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s

diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
new file mode 100644
index 0000000..2dd7d21
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
@@ -0,0 +1,4 @@
+#name: non-contiguous-powerpc
+#source: non-contiguous-powerpc.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-powerpc.ld
+#error: \ARelaxation not supported with --enable-non-contiguous-regions.*
\ No newline at end of file
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
new file mode 100644
index 0000000..744d246
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
@@ -0,0 +1,22 @@
+/* Distance between 'one' and 'two' means that relaxation implies that
+   .text.one's size increases. Even though the result would fit in
+   'oneandhalf', this is not supported by
+   --enable-non-contiguous-regions.  */
+
+MEMORY {
+       one (RXAI) : ORIGIN = 0x00000000, LENGTH = 0x00000010
+       oneandhalf (RXAI) : ORIGIN = 0x00001000, LENGTH = 0x00001010
+       two (RXAI) : ORIGIN = 0x20000000, LENGTH = 0x10000000
+}
+
+SECTIONS {
+      one : {
+         *(.text.one)
+      } > one
+      oneandhalf : {
+         *(.text.one)
+      } > oneandhalf
+      two : {
+      *(.text.two)
+      } > two
+}
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
new file mode 100644
index 0000000..e02b322
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
@@ -0,0 +1,8 @@
+	.machine "ppc"
+
+	.section .text.one
+	b	2f
+
+	.section .text.two
+2:
+	nop
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 94b2fac..796635f 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -443,3 +443,5 @@ run_dump_test "vle-multiseg-6"
 
 run_dump_test "ppc476-shared"
 run_dump_test "ppc476-shared2"
+
+run_dump_test "non-contiguous-powerpc"
-- 
2.7.4


[-- Attachment #5: 0001-Add-support-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 28282 bytes --]

From e780801dcb2c5ae7fa9d2c53c410e715d7d521f8 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 25 Nov 2019 08:55:37 +0000
Subject: [PATCH 1/4] Add support for non-contiguous memory regions

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

	bfd/
	* bfd-in2.h: Regenerate.
	* section.c (asection): Add already_assigned field.
	(BFD_FAKE_SECTION): Add default initializer for it.
	* ecoff.c (bfd_debug_section): Initialize already_assigned field.
	* elf32-arm.c (arm_build_one_stub): Add support for
	non_contiguous_regions.
	* elf32-csky.c (csky_build_one_stub): Likewise.
	* elf32-hppa.c (hppa_build_one_stub): Likewise.
	* elf32-m68hc11.c (m68hc11_elf_build_one_stub): Likewise.
	* elf32-m68hc12.c (m68hc12_elf_build_one_stub): Likewise.
	* elf32-metag.c (metag_build_one_stub): Likewise.
	* elf32-nios2.c (nios2_build_one_stub): Likewise.
	* elf64-ppc.c (ppc_build_one_stub): Likewise.
	* elfnn-aarch64.c (aarch64_build_one_stub): Likewise.
	* elflink.c (elf_link_input_bfd): Likewise.

	include/
	* bfdlink.h (bfd_link_info): Add non_contiguous_regions and
	non_contiguous_regions_warnings fields.

	ld/
	* ldlang.c (lang_add_section): Add support for
	non_contiguous_regions.
	(size_input_section): Likewise.
	(lang_size_sections_1): Likewise.
	(process_insert_statements): Likewise.
	* ldlex.h (option_values): Add OPTION_NON_CONTIGUOUS_REGIONS and
	OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS.
	* lexsup.c (ld_options): Add entries for
	--enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings.
	(parse_args): Handle it.
	* NEWS: Add --enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings.
	* ld.texi: Add --enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings documentation.
	* emultempl/armelf.em (elf32_arm_add_stub_section): Add
	SEC_LINKER_CREATED flag.

Change-Id: Iac2f395b3a1fbea4b3a732ba5a9b847e10b4b2f0
---
 bfd/bfd-in2.h          |   9 ++-
 bfd/ecoff.c            |   6 +-
 bfd/elf32-arm.c        |  11 ++++
 bfd/elf32-csky.c       |  11 ++++
 bfd/elf32-hppa.c       |  31 +++++++++++
 bfd/elf32-m68hc11.c    |  11 ++++
 bfd/elf32-m68hc12.c    |  11 ++++
 bfd/elf32-metag.c      |  15 ++++-
 bfd/elf32-nios2.c      |  13 +++++
 bfd/elf64-ppc.c        |  11 ++++
 bfd/elflink.c          |  12 ++++
 bfd/elfnn-aarch64.c    |  16 +++++-
 bfd/section.c          |   9 ++-
 include/bfdlink.h      |   8 +++
 ld/NEWS                |   3 +
 ld/emultempl/armelf.em |   3 +-
 ld/ld.texi             |  42 ++++++++++++++
 ld/ldlang.c            | 146 +++++++++++++++++++++++++++++++++++++++++++++++--
 ld/ldlex.h             |   2 +
 ld/lexsup.c            |  10 ++++
 20 files changed, 369 insertions(+), 11 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 09a5a39..35d1abb 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1190,6 +1190,10 @@ typedef struct bfd_section
     struct bfd_link_order *link_order;
     struct bfd_section *s;
   } map_head, map_tail;
+ /* Points to the output section this section is already assigned to, if any.
+    This is used when support for non-contiguous memory regions is enabled.  */
+ struct bfd_section *already_assigned;
+
 } asection;
 
 /* Relax table contains information about instructions which can
@@ -1371,7 +1375,10 @@ discarded_section (const asection *sec)
      (struct bfd_symbol *) SYM, &SEC.symbol,                           \
                                                                        \
   /* map_head, map_tail                                            */  \
-     { NULL }, { NULL }                                                \
+     { NULL }, { NULL },                                               \
+                                                                       \
+  /* already_assigned                                              */  \
+     NULL                                                              \
     }
 
 /* We use a macro to initialize the static asymbol structures because
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 050fd7b..58620e5 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -78,8 +78,10 @@ static asection bfd_debug_section =
      NULL,
   /* symbol_ptr_ptr,						   */
      NULL,
-  /* map_head, map_tail						   */
-     { NULL }, { NULL }
+  /* map_head, map_tail,					   */
+     { NULL }, { NULL },
+  /* already_assigned 						   */
+     NULL,
 };
 
 /* Create an ECOFF object.  */
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index faf8376..a10d32b 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5064,6 +5064,17 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   globals = elf32_arm_hash_table (info);
   if (globals == NULL)
     return FALSE;
diff --git a/bfd/elf32-csky.c b/bfd/elf32-csky.c
index 04214f2..d12a898 100644
--- a/bfd/elf32-csky.c
+++ b/bfd/elf32-csky.c
@@ -3621,6 +3621,17 @@ csky_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_csky_stub_hash_entry *)gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   globals = csky_elf_hash_table (info);
   if (globals == NULL)
     return FALSE;
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 2e65308..7ac4b23 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -731,6 +731,17 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
   switch (hsh->stub_type)
     {
     case hppa_stub_long_branch:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
+
       /* Create the long branch.  A long branch is formed with "ldil"
 	 loading the upper bits of the target address into a register,
 	 then branching with "be" which adds in the lower bits.
@@ -751,6 +762,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
       break;
 
     case hppa_stub_long_branch_shared:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
       /* Branches are relative.  This is where we are going to.  */
       sym_value = (hsh->target_value
 		   + hsh->target_section->output_offset
@@ -823,6 +844,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
       break;
 
     case hppa_stub_export:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
       /* Branches are relative.  This is where we are going to.  */
       sym_value = (hsh->target_value
 		   + hsh->target_section->output_offset
diff --git a/bfd/elf32-m68hc11.c b/bfd/elf32-m68hc11.c
index 8d4d227..177feb6 100644
--- a/bfd/elf32-m68hc11.c
+++ b/bfd/elf32-m68hc11.c
@@ -415,6 +415,17 @@ m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = m68hc11_elf_hash_table (info);
   if (htab == NULL)
     return FALSE;
diff --git a/bfd/elf32-m68hc12.c b/bfd/elf32-m68hc12.c
index e41b4c7..9ff8270 100644
--- a/bfd/elf32-m68hc12.c
+++ b/bfd/elf32-m68hc12.c
@@ -535,6 +535,17 @@ m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = m68hc11_elf_hash_table (info);
 
   stub_sec = stub_entry->stub_sec;
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 08eb70b..8e4dde1 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -3459,7 +3459,7 @@ metag_type_of_stub (asection *input_sec,
 #define MOV_PC_A0_3	0xa3180ca0
 
 static bfd_boolean
-metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_UNUSED)
+metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 {
   struct elf_metag_stub_hash_entry *hsh;
   asection *stub_sec;
@@ -3467,9 +3467,22 @@ metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
   bfd_byte *loc;
   bfd_vma sym_value;
   int size;
+  struct bfd_link_info *info;
 
   /* Massage our args to the form they really have.  */
   hsh = (struct elf_metag_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (hsh->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  hsh->target_section);
+      abort();
+    }
 
   stub_sec = hsh->stub_sec;
 
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index 947eaeb..8126b0d 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -2490,7 +2490,20 @@ nios2_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
     = (struct elf32_nios2_stub_hash_entry *) gen_entry;
   asection *stub_sec = hsh->stub_sec;
   bfd_vma sym_value;
+  struct bfd_link_info *info;
+
+  info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (hsh->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  hsh->target_section);
+      abort();
+    }
   /* Make a note of the offset within the stubs for this entry.  */
   hsh->stub_offset = stub_sec->size;
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index b3f8f6b..8fca552 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11349,6 +11349,17 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
   info = in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section != NULL
+      && stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 5217528..deef7f5 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10569,6 +10569,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 	 discarding, we don't need to keep it.  */
       if (isym->st_shndx != SHN_UNDEF
 	  && isym->st_shndx < SHN_LORESERVE
+	  && isec->output_section == NULL
+	  && flinfo->info->non_contiguous_regions
+	  && flinfo->info->non_contiguous_regions_warnings)
+	{
+	  _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+				"discards section `%s' from '%s'\n"),
+			      isec->name, isec->owner->filename);
+	  continue;
+	}
+
+      if (isym->st_shndx != SHN_UNDEF
+	  && isym->st_shndx < SHN_LORESERVE
 	  && bfd_section_removed_from_list (output_bfd,
 					    isec->output_section))
 	continue;
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 5fabcd8..724693c 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -3278,7 +3278,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name,
 
 static bfd_boolean
 aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
-			void *in_arg ATTRIBUTE_UNUSED)
+			void *in_arg)
 {
   struct elf_aarch64_stub_hash_entry *stub_entry;
   asection *stub_sec;
@@ -3291,10 +3291,24 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
   unsigned int template_size;
   const uint32_t *template;
   unsigned int i;
+  struct bfd_link_info *info;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
 
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   stub_sec = stub_entry->stub_sec;
 
   /* Make a note of the offset within the stubs for this entry.  */
diff --git a/bfd/section.c b/bfd/section.c
index 0c15a0d..c1a1a4b 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -549,6 +549,10 @@ CODE_FRAGMENT
 .    struct bfd_link_order *link_order;
 .    struct bfd_section *s;
 .  } map_head, map_tail;
+. {* Points to the output section this section is already assigned to, if any.
+.    This is used when support for non-contiguous memory regions is enabled.  *}
+. struct bfd_section *already_assigned;
+.
 .} asection;
 .
 .{* Relax table contains information about instructions which can
@@ -730,7 +734,10 @@ CODE_FRAGMENT
 .     (struct bfd_symbol *) SYM, &SEC.symbol,				\
 .									\
 .  {* map_head, map_tail                                            *}	\
-.     { NULL }, { NULL }						\
+.     { NULL }, { NULL },						\
+.									\
+.  {* already_assigned                                             *}	\
+.     NULL								\
 .    }
 .
 .{* We use a macro to initialize the static asymbol structures because
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 8d85530..529ea6e 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -501,6 +501,14 @@ struct bfd_link_info
   /* TRUE if "-Map map" is passed to linker.  */
   unsigned int has_map_file : 1;
 
+  /* TRUE if "--enable-non-contiguous-regions" is passed to the
+     linker.  */
+  unsigned int non_contiguous_regions : 1;
+
+  /* TRUE if "--enable-non-contiguous-regions-warnings" is passed to
+     the linker.  */
+  unsigned int non_contiguous_regions_warnings : 1;
+
   /* Char that may appear as the first char of a symbol, but should be
      skipped (like symbol_leading_char) when looking up symbols in
      wrap_hash.  Used by PowerPC Linux for 'dot' symbols.  */
diff --git a/ld/NEWS b/ld/NEWS
index f659ccf..2611a3e 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add command-line options --enable-non-contiguous-regions and
+  --enable-non-contiguous-regions-warnings.
+
 Changes in 2.34:
 
 * cr16c support removed.
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index efdcf5a..fb5bbf8 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -227,7 +227,8 @@ elf32_arm_add_stub_section (const char * stub_sec_name,
   struct hook_stub_info info;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
-	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP
+	   | SEC_LINKER_CREATED);
   stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
 						 stub_sec_name, flags);
   if (stub_sec == NULL)
diff --git a/ld/ld.texi b/ld/ld.texi
index 9bb3d55..07933b2 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -459,6 +459,48 @@ will contain a colon separated list of audit interfaces to use.  This
 option is only meaningful on ELF platforms supporting the rtld-audit interface.
 The -P option is provided for Solaris compatibility.
 
+@kindex --enable-non-contiguous-regions
+@item --enable-non-contiguous-regions
+This option avoids generating an error if an input section does not
+fit a matching output section. The linker tries to allocate the input
+section to subseque nt matching output sections, and generates an
+error only if no output section is large enough.  This is useful when
+several non-contiguous memory regions are available and the input
+section does not require a particular one.  The order in which input
+sections are evaluated does not change, for instance:
+
+@smallexample
+  MEMORY @{
+    MEM1 (rwx) : ORIGIN : 0x1000, LENGTH = 0x14
+    MEM2 (rwx) : ORIGIN : 0x1000, LENGTH = 0x40
+    MEM3 (rwx) : ORIGIN : 0x2000, LENGTH = 0x40
+  @}
+  SECTIONS @{
+    mem1 : @{ *(.data.*); @} > MEM1
+    mem2 : @{ *(.data.*); @} > MEM2
+    mem3 : @{ *(.data.*); @} > MEM2
+  @}
+
+  with input sections:
+  .data.1: size 8
+  .data.2: size 0x10
+  .data.3: size 4
+
+  results in .data.1 affected to mem1, and .data.2 and .data.3
+  affected to mem2, even though .data.3 would fit in mem3.
+@end smallexample
+
+This option is incompatible with INSERT statements because it changes
+the way input sections are mapped to output sections.
+
+@kindex --enable-non-contiguous-regions-warnings
+@item --enable-non-contiguous-regions-warnings
+This option enables warnings when
+@code{--enable-non-contiguous-regions} allows possibly unexpected
+matches in sections mapping, potentially leading to silently
+discarding a section instead of failing because it does not fit any
+output region.
+
 @cindex entry point, from command line
 @kindex -e @var{entry}
 @kindex --entry=@var{entry}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 91c160b..d34919e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2537,6 +2537,11 @@ lang_add_section (lang_statement_list_type *ptr,
 	  /* This prevents future calls from assigning this section.  */
 	  section->output_section = bfd_abs_section_ptr;
 	}
+      else if (link_info.non_contiguous_regions_warnings)
+	einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
+		 "section `%pA' from '%pB' match /DISCARD/ clause.\n"),
+	       NULL, section, section->owner);
+
       return;
     }
 
@@ -2550,7 +2555,33 @@ lang_add_section (lang_statement_list_type *ptr,
     }
 
   if (section->output_section != NULL)
-    return;
+    {
+      if (!link_info.non_contiguous_regions)
+	return;
+
+      /* SECTION has already been handled in a special way
+	 (eg. LINK_ONCE): skip it.  */
+      if (bfd_is_abs_section (section->output_section))
+	return;
+
+      /* Already assigned to the same output section, do not process
+	 it again, to avoid creating loops between duplicate sections
+	 later.  */
+      if (section->output_section == output->bfd_section)
+	return;
+
+      if (link_info.non_contiguous_regions_warnings && output->bfd_section)
+	einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
+		 "change behaviour for section `%pA' from '%pB' (assigned to "
+		 "%pA, but additional match: %pA)\n"),
+	       NULL, section, section->owner, section->output_section,
+	       output->bfd_section);
+
+      /* SECTION has already been assigned to an output section, but
+	 the user allows it to be mapped to another one in case it
+	 overflows. We'll later update the actual output section in
+	 size_input_section as appropriate.  */
+    }
 
   /* We don't copy the SEC_NEVER_LOAD flag from an input section
      to an output section, because we want to be able to include a
@@ -4194,6 +4225,12 @@ process_insert_statements (lang_statement_union_type **start)
 	  lang_statement_union_type **ptr;
 	  lang_statement_union_type *first;
 
+	  if (link_info.non_contiguous_regions)
+	    {
+	      einfo (_("warning: INSERT statement in linker script is "
+		       "incompatible with --enable-non-contiguous-regions.\n"));
+	    }
+
 	  where = lang_output_section_find (i->where);
 	  if (where != NULL && i->is_before)
 	    {
@@ -5116,11 +5153,27 @@ size_input_section
   (lang_statement_union_type **this_ptr,
    lang_output_section_statement_type *output_section_statement,
    fill_type *fill,
+   bfd_boolean *removed,
    bfd_vma dot)
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
   asection *o = output_section_statement->bfd_section;
+  *removed = 0;
+
+  if (link_info.non_contiguous_regions)
+    {
+      /* If the input section I has already been successfully assigned
+	 to an output section other than O, don't bother with it and
+	 let the caller remove it from the list.  Keep processing in
+	 case we have already handled O, because the repeated passes
+	 have reinitialized its size.  */
+      if (i->already_assigned && i->already_assigned != o)
+	{
+	  *removed = 1;
+	  return dot;
+	}
+    }
 
   if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
     i->output_offset = i->vma - o->vma;
@@ -5152,6 +5205,43 @@ size_input_section
 	  dot += alignment_needed;
 	}
 
+      if (link_info.non_contiguous_regions)
+	{
+	  /* If I would overflow O, let the caller remove I from the
+	     list.  */
+	  if (output_section_statement->region)
+	    {
+	      bfd_vma end = output_section_statement->region->origin
+		+ output_section_statement->region->length;
+
+	      if (dot + TO_ADDR (i->size) > end)
+		{
+		  if (i->flags & SEC_LINKER_CREATED)
+		    {
+		      einfo (_("Output section %s not large enough for the "
+			       "linker-created stubs section %s.\n"),
+			     i->output_section->name, i->name);
+		      abort();
+		    }
+
+		  if (i->rawsize && i->rawsize != i->size)
+		    {
+		      einfo (_("Relaxation not supported with "
+			       "--enable-non-contiguous-regions (section %s "
+			       "would overflow %s after it changed size).\n"),
+			     i->name, i->output_section->name);
+		      abort();
+		    }
+
+		  *removed = 1;
+		  dot = end;
+		  ASSERT (i->already_assigned == NULL);
+		  i->output_section = NULL;
+		  return dot;
+		}
+	    }
+	}
+
       /* Remember where in the output section this input section goes.  */
       i->output_offset = dot - o->vma;
 
@@ -5159,6 +5249,14 @@ size_input_section
       dot += TO_ADDR (i->size);
       if (!(o->flags & SEC_FIXED_SIZE))
 	o->size = TO_SIZE (dot - o->vma);
+
+      if (link_info.non_contiguous_regions)
+	{
+	  /* Record that I was successfully assigned to O, and update
+	     its actual output section too.  */
+	  i->already_assigned = o;
+	  i->output_section = o;
+	}
     }
 
   return dot;
@@ -5445,10 +5543,14 @@ lang_size_sections_1
    bfd_boolean check_regions)
 {
   lang_statement_union_type *s;
+  lang_statement_union_type *prev_s = NULL;
+  bfd_boolean removed_prev_s = FALSE;
 
   /* Size up the sections from their constituent parts.  */
-  for (s = *prev; s != NULL; s = s->header.next)
+  for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
     {
+      bfd_boolean removed=FALSE;
+
       switch (s->header.type)
 	{
 	case lang_output_section_statement_enum:
@@ -5874,7 +5976,7 @@ lang_size_sections_1
 		  *relax = TRUE;
 	      }
 	    dot = size_input_section (prev, output_section_statement,
-				      fill, dot);
+				      fill, &removed, dot);
 	  }
 	  break;
 
@@ -5979,7 +6081,43 @@ lang_size_sections_1
 	  FAIL ();
 	  break;
 	}
-      prev = &s->header.next;
+
+      /* If an input section doesn't fit in the current output
+	 section, remove it from the list.  Handle the case where we
+	 have to remove an input_section statement here: there is a
+	 special case to remove the first element of the list.  */
+      if (link_info.non_contiguous_regions && removed)
+	{
+	  /* If we removed the first element during the previous
+	     iteration, override the loop assignment of prev_s.  */
+	  if (removed_prev_s)
+	      prev_s = NULL;
+
+	  if (prev_s)
+	    {
+	      /* If there was a real previous input section, just skip
+		 the current one.  */
+	      prev_s->header.next=s->header.next;
+	      s = prev_s;
+	      removed_prev_s = FALSE;
+	    }
+	  else
+	    {
+	      /* Remove the first input section of the list.  */
+	      *prev = s->header.next;
+	      removed_prev_s = TRUE;
+	    }
+
+	  /* Move to next element, unless we removed the head of the
+	     list.  */
+	  if (!removed_prev_s)
+	    prev = &s->header.next;
+	}
+      else
+	{
+	  prev = &s->header.next;
+	  removed_prev_s = FALSE;
+	}
     }
   return dot;
 }
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 5287f19..22b928d 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -150,6 +150,8 @@ enum option_values
   OPTION_FORCE_GROUP_ALLOCATION,
   OPTION_PRINT_MAP_DISCARDED,
   OPTION_NO_PRINT_MAP_DISCARDED,
+  OPTION_NON_CONTIGUOUS_REGIONS,
+  OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS,
 };
 
 /* The initial parser states.  */
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 3d15cc4..2597e2d 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -122,6 +122,10 @@ static const struct ld_option ld_options[] =
     'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
   { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
     '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
+  { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS},
+    '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES },
+  { {"enable-non-contiguous-regions-warnings", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS},
+    '\0', NULL, N_("Enable warnings when --enable-non-contiguous-regions may cause unexpected behaviour"), TWO_DASHES },
   { {"EB", no_argument, NULL, OPTION_EB},
     '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
   { {"EL", no_argument, NULL, OPTION_EL},
@@ -845,6 +849,12 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_NO_EXPORT_DYNAMIC:
 	  link_info.export_dynamic = FALSE;
 	  break;
+	case OPTION_NON_CONTIGUOUS_REGIONS:
+	  link_info.non_contiguous_regions = TRUE;
+	  break;
+	case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
+	  link_info.non_contiguous_regions_warnings = TRUE;
+	  break;
 	case 'e':
 	  lang_add_entry (optarg, TRUE);
 	  break;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-19 12:28       ` Christophe Lyon
@ 2020-02-19 22:23         ` Alan Modra
  2020-02-20  4:37           ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2020-02-19 22:23 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Tamar Christina, binutils, nd

On Wed, Feb 19, 2020 at 01:28:23PM +0100, Christophe Lyon wrote:
> On Wed, 19 Feb 2020 at 08:19, Alan Modra <amodra@gmail.com> wrote:
> >
> > On Fri, Feb 14, 2020 at 02:53:55PM +0100, Christophe Lyon wrote:
> > > Here are the updated patches.
> >
> > Wrong set of patches?  elfnn-aarch64.c, elf32-metag.c, and
> > elf32-nios2.c won't compile with these patches applied.  All due to
> > missing "struct bfd_link_info *info;" in build_one_stub.
> >
> 
> Oops, thanks for noticing.
> I don't understand what happened. Here's the right version (the only
> difference is the declaration of struct bfd_link_info *info; in
> build_one_stub.

The test results don't inspire me with confidence.  A lot of the fails
are due to targets not supporting -mlittle-endian, but there are other
fails that show the patch series needs more work before it is ready
for review.  Also, please don't write tests that require one
particular endianness.  Write the objdump match patterns to suit both
endians instead.  Something like this:

Contents of section \.raml:
 1fff0000 (010+ 020+ 030+|0+01 0+02 0+03)  .*


alpha-linux  FAIL: non-contiguous
alpha-netbsd  FAIL: non-contiguous
alpha-unknown-freebsd4.7  FAIL: non-contiguous
am33_2.0-linux  FAIL: non-contiguous
arc-elf  FAIL: non-contiguous
arc-linux-uclibc  FAIL: non-contiguous
arm-nacl  FAIL: non-contiguous-arm2
arm-nacl  FAIL: non-contiguous-arm3
arm-nacl  FAIL: non-contiguous-arm5
arm-nacl  FAIL: non-contiguous-arm6
bfin-elf  FAIL: non-contiguous
bfin-linux-uclibc  FAIL: non-contiguous
cr16-elf  FAIL: non-contiguous
cris-elf  FAIL: non-contiguous
cris-linux  FAIL: non-contiguous
crisv32-linux  FAIL: non-contiguous
crx-elf  FAIL: non-contiguous
d10v-elf  FAIL: non-contiguous
epiphany-elf  FAIL: non-contiguous
fr30-elf  FAIL: non-contiguous
frv-elf  FAIL: non-contiguous
frv-linux  FAIL: non-contiguous
ft32-elf  FAIL: non-contiguous
h8300-elf  FAIL: non-contiguous
h8300-linux  FAIL: non-contiguous
i386-lynxos  FAIL: non-contiguous
i586-linux  FAIL: non-contiguous
i686-nacl  FAIL: non-contiguous
i686-nto  FAIL: non-contiguous
i686-pc-elf  FAIL: non-contiguous
ia64-elf  FAIL: non-contiguous
ia64-freebsd5  FAIL: non-contiguous
ia64-linux  FAIL: non-contiguous
ia64-netbsd  FAIL: non-contiguous
ip2k-elf  FAIL: non-contiguous
iq2000-elf  FAIL: non-contiguous
lm32-elf  FAIL: non-contiguous
lm32-linux  FAIL: non-contiguous
m32c-elf  FAIL: non-contiguous
m32r-elf  FAIL: non-contiguous
m32r-linux  FAIL: non-contiguous
m68k-elf  FAIL: non-contiguous
m68k-linux  FAIL: non-contiguous
mcore-elf  FAIL: non-contiguous
mep-elf  FAIL: non-contiguous
microblaze-elf  FAIL: non-contiguous
microblaze-linux  FAIL: non-contiguous
mips64el-openbsd  FAIL: non-contiguous
mips64-linux  FAIL: non-contiguous
mips64-openbsd  FAIL: non-contiguous
mipsel-linux-gnu  FAIL: non-contiguous
mipsisa32el-linux  FAIL: non-contiguous
mips-linux  FAIL: non-contiguous
mips-sgi-irix6  FAIL: non-contiguous
mipstx39-elf  FAIL: non-contiguous
mn10200-elf  FAIL: non-contiguous
mn10300-elf  FAIL: non-contiguous
moxie-elf  FAIL: non-contiguous
msp430-elf  FAIL: non-contiguous
mt-elf  FAIL: non-contiguous
nds32be-elf  FAIL: non-contiguous
nds32le-linux  FAIL: non-contiguous
or1k-elf  FAIL: non-contiguous
or1k-linux  FAIL: non-contiguous
powerpc64-freebsd  FAIL: non-contiguous-powerpc
powerpc64le-linux  FAIL: non-contiguous-powerpc
powerpc64-linux  FAIL: non-contiguous-powerpc
powerpc-freebsd  FAIL: non-contiguous
pru-elf  FAIL: non-contiguous
riscv32-elf  FAIL: non-contiguous
riscv64-linux  FAIL: non-contiguous
rl78-elf  FAIL: non-contiguous
s390-linux  FAIL: non-contiguous
s390x-linux  FAIL: non-contiguous
score-elf  FAIL: non-contiguous
shle-unknown-netbsdelf  FAIL: non-contiguous
sh-linux  FAIL: non-contiguous
sh-nto  FAIL: non-contiguous
sh-rtems  FAIL: non-contiguous
sparc64-linux  FAIL: non-contiguous
sparc-elf  FAIL: non-contiguous
sparc-linux  FAIL: non-contiguous
sparc-sun-solaris2  FAIL: non-contiguous
spu-elf  FAIL: non-contiguous
tic6x-elf  FAIL: non-contiguous
tilegx-linux  FAIL: non-contiguous
tilepro-linux  FAIL: non-contiguous
v850-elf  FAIL: non-contiguous
vax-netbsdelf  FAIL: non-contiguous
visium-elf  FAIL: non-contiguous
x86_64-cloudabi  FAIL: non-contiguous
x86_64-linux  FAIL: non-contiguous
x86_64-nacl  FAIL: non-contiguous
x86_64-pc-linux-gnux32  FAIL: non-contiguous
xc16x-elf  FAIL: non-contiguous
xstormy16-elf  FAIL: non-contiguous
xtensa-elf  FAIL: non-contiguous
z80-elf  FAIL: non-contiguous

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-19 22:23         ` Alan Modra
@ 2020-02-20  4:37           ` Christophe Lyon
  2020-02-20  8:15             ` Alan Modra
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-02-20  4:37 UTC (permalink / raw)
  To: Alan Modra; +Cc: Tamar Christina, binutils, nd

On Wed, 19 Feb 2020 at 23:23, Alan Modra <amodra@gmail.com> wrote:
>
> On Wed, Feb 19, 2020 at 01:28:23PM +0100, Christophe Lyon wrote:
> > On Wed, 19 Feb 2020 at 08:19, Alan Modra <amodra@gmail.com> wrote:
> > >
> > > On Fri, Feb 14, 2020 at 02:53:55PM +0100, Christophe Lyon wrote:
> > > > Here are the updated patches.
> > >
> > > Wrong set of patches?  elfnn-aarch64.c, elf32-metag.c, and
> > > elf32-nios2.c won't compile with these patches applied.  All due to
> > > missing "struct bfd_link_info *info;" in build_one_stub.
> > >
> >
> > Oops, thanks for noticing.
> > I don't understand what happened. Here's the right version (the only
> > difference is the declaration of struct bfd_link_info *info; in
> > build_one_stub.
>

Hi Alan,

Thanks for the feedback.

> The test results don't inspire me with confidence.  A lot of the fails
> are due to targets not supporting -mlittle-endian, but there are other
> fails that show the patch series needs more work before it is ready
> for review.  Also, please don't write tests that require one
> particular endianness.  Write the objdump match patterns to suit both
> endians instead.  Something like this:
>
> Contents of section \.raml:
>  1fff0000 (010+ 020+ 030+|0+01 0+02 0+03)  .*
>
OK, I was wondering/hoping there's a nicer way of achieving this. I'll
update my patch to use this pattern.

>
> alpha-linux  FAIL: non-contiguous
> alpha-netbsd  FAIL: non-contiguous
> alpha-unknown-freebsd4.7  FAIL: non-contiguous
> am33_2.0-linux  FAIL: non-contiguous
> arc-elf  FAIL: non-contiguous
> arc-linux-uclibc  FAIL: non-contiguous
> arm-nacl  FAIL: non-contiguous-arm2
> arm-nacl  FAIL: non-contiguous-arm3
> arm-nacl  FAIL: non-contiguous-arm5
> arm-nacl  FAIL: non-contiguous-arm6
> bfin-elf  FAIL: non-contiguous
> bfin-linux-uclibc  FAIL: non-contiguous
> cr16-elf  FAIL: non-contiguous
> cris-elf  FAIL: non-contiguous
> cris-linux  FAIL: non-contiguous
> crisv32-linux  FAIL: non-contiguous
> crx-elf  FAIL: non-contiguous
> d10v-elf  FAIL: non-contiguous
> epiphany-elf  FAIL: non-contiguous
> fr30-elf  FAIL: non-contiguous
> frv-elf  FAIL: non-contiguous
> frv-linux  FAIL: non-contiguous
> ft32-elf  FAIL: non-contiguous
> h8300-elf  FAIL: non-contiguous
> h8300-linux  FAIL: non-contiguous
> i386-lynxos  FAIL: non-contiguous
> i586-linux  FAIL: non-contiguous
> i686-nacl  FAIL: non-contiguous
> i686-nto  FAIL: non-contiguous
> i686-pc-elf  FAIL: non-contiguous
> ia64-elf  FAIL: non-contiguous
> ia64-freebsd5  FAIL: non-contiguous
> ia64-linux  FAIL: non-contiguous
> ia64-netbsd  FAIL: non-contiguous
> ip2k-elf  FAIL: non-contiguous
> iq2000-elf  FAIL: non-contiguous
> lm32-elf  FAIL: non-contiguous
> lm32-linux  FAIL: non-contiguous
> m32c-elf  FAIL: non-contiguous
> m32r-elf  FAIL: non-contiguous
> m32r-linux  FAIL: non-contiguous
> m68k-elf  FAIL: non-contiguous
> m68k-linux  FAIL: non-contiguous
> mcore-elf  FAIL: non-contiguous
> mep-elf  FAIL: non-contiguous
> microblaze-elf  FAIL: non-contiguous
> microblaze-linux  FAIL: non-contiguous
> mips64el-openbsd  FAIL: non-contiguous
> mips64-linux  FAIL: non-contiguous
> mips64-openbsd  FAIL: non-contiguous
> mipsel-linux-gnu  FAIL: non-contiguous
> mipsisa32el-linux  FAIL: non-contiguous
> mips-linux  FAIL: non-contiguous
> mips-sgi-irix6  FAIL: non-contiguous
> mipstx39-elf  FAIL: non-contiguous
> mn10200-elf  FAIL: non-contiguous
> mn10300-elf  FAIL: non-contiguous
> moxie-elf  FAIL: non-contiguous
> msp430-elf  FAIL: non-contiguous
> mt-elf  FAIL: non-contiguous
> nds32be-elf  FAIL: non-contiguous
> nds32le-linux  FAIL: non-contiguous
> or1k-elf  FAIL: non-contiguous
> or1k-linux  FAIL: non-contiguous
> powerpc64-freebsd  FAIL: non-contiguous-powerpc
> powerpc64le-linux  FAIL: non-contiguous-powerpc
> powerpc64-linux  FAIL: non-contiguous-powerpc
> powerpc-freebsd  FAIL: non-contiguous
> pru-elf  FAIL: non-contiguous
> riscv32-elf  FAIL: non-contiguous
> riscv64-linux  FAIL: non-contiguous
> rl78-elf  FAIL: non-contiguous
> s390-linux  FAIL: non-contiguous
> s390x-linux  FAIL: non-contiguous
> score-elf  FAIL: non-contiguous
> shle-unknown-netbsdelf  FAIL: non-contiguous
> sh-linux  FAIL: non-contiguous
> sh-nto  FAIL: non-contiguous
> sh-rtems  FAIL: non-contiguous
> sparc64-linux  FAIL: non-contiguous
> sparc-elf  FAIL: non-contiguous
> sparc-linux  FAIL: non-contiguous
> sparc-sun-solaris2  FAIL: non-contiguous
> spu-elf  FAIL: non-contiguous
> tic6x-elf  FAIL: non-contiguous
> tilegx-linux  FAIL: non-contiguous
> tilepro-linux  FAIL: non-contiguous
> v850-elf  FAIL: non-contiguous
> vax-netbsdelf  FAIL: non-contiguous
> visium-elf  FAIL: non-contiguous
> x86_64-cloudabi  FAIL: non-contiguous
> x86_64-linux  FAIL: non-contiguous
> x86_64-nacl  FAIL: non-contiguous
> x86_64-pc-linux-gnux32  FAIL: non-contiguous
> xc16x-elf  FAIL: non-contiguous
> xstormy16-elf  FAIL: non-contiguous
> xtensa-elf  FAIL: non-contiguous
> z80-elf  FAIL: non-contiguous
>

So... I did run the tests on a few targets, but obviously not this long list.
How do you manage this? Is that list maintained somewhere?
Are there scripts to exercise all these targets? (--enable-targets=all
is not enough AFAICT)

Or should I just copy & paste that list from your email and
for i in <that-list>
do
  configure --target=$i
  make all check
done

Thanks,

Christophe


> --
> Alan Modra
> Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-20  4:37           ` Christophe Lyon
@ 2020-02-20  8:15             ` Alan Modra
  2020-02-20  9:00               ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2020-02-20  8:15 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Tamar Christina, binutils, nd

On Thu, Feb 20, 2020 at 05:37:03AM +0100, Christophe Lyon wrote:
> Or should I just copy & paste that list from your email and
> for i in <that-list>
> do
>   configure --target=$i
>   make all check
> done

Yes, more or less.  No need to build gdb though for binutils changes,
unless you're messing with libbfd or libopcodes API.  I build with
--disable-nls --enable-plugins \
--disable-gdb --disable-gdbserver --disable-sim --disable-readline \
--disable-libdecnumber --enable-obsolete --target=$i
Parallel builds work too, except for m68hc11 and m68hc12 which write
to source directories.

I also build --enable-targets=all --enable-nls with a recent 64-bit
gcc, an older gcc, and with gcc -m32 to pick up any 32 bit problems.
My current target list is:

aarch64-elf
aarch64-linux
aarch64_be-linux-gnu_ilp32
alpha-dec-vms
alpha-linux
alpha-linuxecoff
alpha-netbsd
alpha-unknown-freebsd4.7
am33_2.0-linux
arc-elf
arc-linux-uclibc
arm-elf
arm-linuxeabi
arm-nacl
arm-netbsdelf
arm-nto
arm-pe
arm-symbianelf
arm-vxworks
arm-wince-pe
armeb-linuxeabi
avr-elf
bfin-elf
bfin-linux-uclibc
bpf-none
cr16-elf
cris-elf
cris-linux
crisv32-linux
crx-elf
csky-elf
csky-linux
d10v-elf
d30v-elf
dlx-elf
epiphany-elf
fr30-elf
frv-elf
frv-linux
ft32-elf
h8300-elf
h8300-linux
hppa-hp-hpux10
hppa-linux
hppa64-hp-hpux11.23
hppa64-linux
i386-bsd
i386-darwin
i386-lynxos
i586-linux
i686-nacl
i686-nto
i686-pc-beos
i686-pc-elf
i686-pe
i686-vxworks
ia64-elf
ia64-freebsd5
ia64-hpux
ia64-linux
ia64-netbsd
ia64-vms
ip2k-elf
iq2000-elf
lm32-elf
lm32-linux
m32c-elf
m32r-elf
m32r-linux
m68hc11-elf
m68hc12-elf
m68k-elf
m68k-linux
mcore-elf
mcore-pe
mep-elf
metag-linux
microblaze-elf
microblaze-linux
mips-linux
mips-sgi-irix6
mips-vxworks
mips64-linux
mips64-openbsd
mips64el-openbsd
mipsel-linux-gnu
mipsisa32el-linux
mipstx39-elf
mmix
mn10200-elf
mn10300-elf
moxie-elf
msp430-elf
mt-elf
nds32be-elf
nds32le-linux
nios2-linux
ns32k-netbsd
ns32k-pc532-mach
or1k-elf
or1k-linux
pdp11-dec-aout
pj-elf
powerpc-aix5.1
powerpc-aix5.2
powerpc-eabisim
powerpc-eabivle
powerpc-freebsd
powerpc-linux
powerpc-nto
powerpc-wrs-vxworks
powerpc64-freebsd
powerpc64-linux
powerpc64le-linux
powerpcle-cygwin
powerpcle-elf
pru-elf
riscv32-elf
riscv64-linux
rl78-elf
rs6000-aix4.3.3
rs6000-aix5.1
rs6000-aix5.2
rx-elf
s12z-elf
s390-linux
s390x-linux
score-elf
sh-linux
sh-nto
sh-pe
sh-rtems
sh-vxworks
shle-unknown-netbsdelf
sparc-elf
sparc-linux
sparc-sun-solaris2
sparc-vxworks
sparc64-linux
spu-elf
tic30-unknown-coff
tic4x-coff
tic54x-coff
tic6x-elf
tilegx-linux
tilepro-linux
v850-elf
vax-netbsdelf
visium-elf
wasm32
x86_64-cloudabi
x86_64-linux
x86_64-nacl
x86_64-pc-linux-gnux32
x86_64-rdos
x86_64-w64-mingw32
xc16x-elf
xgate-elf
xstormy16-elf
xtensa-elf
z80-coff
z80-elf
z8k-coff

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-20  8:15             ` Alan Modra
@ 2020-02-20  9:00               ` Christophe Lyon
  2020-02-28 17:31                 ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-02-20  9:00 UTC (permalink / raw)
  To: Alan Modra; +Cc: Tamar Christina, binutils, nd

On Thu, 20 Feb 2020 at 09:15, Alan Modra <amodra@gmail.com> wrote:
>
> On Thu, Feb 20, 2020 at 05:37:03AM +0100, Christophe Lyon wrote:
> > Or should I just copy & paste that list from your email and
> > for i in <that-list>
> > do
> >   configure --target=$i
> >   make all check
> > done
>
> Yes, more or less.  No need to build gdb though for binutils changes,
> unless you're messing with libbfd or libopcodes API.  I build with
> --disable-nls --enable-plugins \
> --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> --disable-libdecnumber --enable-obsolete --target=$i
> Parallel builds work too, except for m68hc11 and m68hc12 which write
> to source directories.
>
> I also build --enable-targets=all --enable-nls with a recent 64-bit
> gcc, an older gcc, and with gcc -m32 to pick up any 32 bit problems.
> My current target list is:
>
Thanks, I'm looking at all these targets, then. I'll update my patches
as needed.


> aarch64-elf
> aarch64-linux
> aarch64_be-linux-gnu_ilp32
> alpha-dec-vms
> alpha-linux
> alpha-linuxecoff
> alpha-netbsd
> alpha-unknown-freebsd4.7
> am33_2.0-linux
> arc-elf
> arc-linux-uclibc
> arm-elf
> arm-linuxeabi
> arm-nacl
> arm-netbsdelf
> arm-nto
> arm-pe
> arm-symbianelf
> arm-vxworks
> arm-wince-pe
> armeb-linuxeabi
> avr-elf
> bfin-elf
> bfin-linux-uclibc
> bpf-none
> cr16-elf
> cris-elf
> cris-linux
> crisv32-linux
> crx-elf
> csky-elf
> csky-linux
> d10v-elf
> d30v-elf
> dlx-elf
> epiphany-elf
> fr30-elf
> frv-elf
> frv-linux
> ft32-elf
> h8300-elf
> h8300-linux
> hppa-hp-hpux10
> hppa-linux
> hppa64-hp-hpux11.23
> hppa64-linux
> i386-bsd
> i386-darwin
> i386-lynxos
> i586-linux
> i686-nacl
> i686-nto
> i686-pc-beos
> i686-pc-elf
> i686-pe
> i686-vxworks
> ia64-elf
> ia64-freebsd5
> ia64-hpux
> ia64-linux
> ia64-netbsd
> ia64-vms
> ip2k-elf
> iq2000-elf
> lm32-elf
> lm32-linux
> m32c-elf
> m32r-elf
> m32r-linux
> m68hc11-elf
> m68hc12-elf
> m68k-elf
> m68k-linux
> mcore-elf
> mcore-pe
> mep-elf
> metag-linux
> microblaze-elf
> microblaze-linux
> mips-linux
> mips-sgi-irix6
> mips-vxworks
> mips64-linux
> mips64-openbsd
> mips64el-openbsd
> mipsel-linux-gnu
> mipsisa32el-linux
> mipstx39-elf
> mmix
> mn10200-elf
> mn10300-elf
> moxie-elf
> msp430-elf
> mt-elf
> nds32be-elf
> nds32le-linux
> nios2-linux
> ns32k-netbsd
> ns32k-pc532-mach
> or1k-elf
> or1k-linux
> pdp11-dec-aout
> pj-elf
> powerpc-aix5.1
> powerpc-aix5.2
> powerpc-eabisim
> powerpc-eabivle
> powerpc-freebsd
> powerpc-linux
> powerpc-nto
> powerpc-wrs-vxworks
> powerpc64-freebsd
> powerpc64-linux
> powerpc64le-linux
> powerpcle-cygwin
> powerpcle-elf
> pru-elf
> riscv32-elf
> riscv64-linux
> rl78-elf
> rs6000-aix4.3.3
> rs6000-aix5.1
> rs6000-aix5.2
> rx-elf
> s12z-elf
> s390-linux
> s390x-linux
> score-elf
> sh-linux
> sh-nto
> sh-pe
> sh-rtems
> sh-vxworks
> shle-unknown-netbsdelf
> sparc-elf
> sparc-linux
> sparc-sun-solaris2
> sparc-vxworks
> sparc64-linux
> spu-elf
> tic30-unknown-coff
> tic4x-coff
> tic54x-coff
> tic6x-elf
> tilegx-linux
> tilepro-linux
> v850-elf
> vax-netbsdelf
> visium-elf
> wasm32
> x86_64-cloudabi
> x86_64-linux
> x86_64-nacl
> x86_64-pc-linux-gnux32
> x86_64-rdos
> x86_64-w64-mingw32
> xc16x-elf
> xgate-elf
> xstormy16-elf
> xtensa-elf
> z80-coff
> z80-elf
> z8k-coff
>
> --
> Alan Modra
> Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-20  9:00               ` Christophe Lyon
@ 2020-02-28 17:31                 ` Christophe Lyon
  2020-03-09 13:10                   ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-02-28 17:31 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 5097 bytes --]

Hi,

Here is an updated patch.

Changes between v4 and v5:
* Added sanity checks for powerpc64 and xtensa
(--enable-non-contiguous-regions does not work with relaxation), to
emit an error message rather than crash
* Removed a bogus assert in size_input_section
* Added quotes around section names in error messages
* Updated tests:
- ld-arm/non-contiguous-arm[25] now pass on arm-nacl
- ld-arm/non-contiguous-arm[36] are now skipped on arm-nacl because
the stub code is different from the expected one and a dedicated test
didn't seem mandatory
- ld-arm/non-contiguous-arm4 updated expected error message
- ld-elf/non-contiguous: do not require little-endian, accept both
endiannesses, discard target-specific sections to make expected output
matching possible. Skip on xtensa where relaxation is enabled by
default and conflicts with the new option
- ld-powerpc/non-contiguous-powerpc: skip on powerpc64 (because the
error message is different)
- ld/powerpc/non-contiguous-powerpc64: new test, with the error
message expected on powerpc64
* Squashed all patches into one

Tested for non-regression on the list of 163 targets provided by Alan.
I left the error on mep-elf, because many other tests fails on that
target with the same error message (selected target format
'elf32-mep-little' unknown)

Christophe


On Thu, 20 Feb 2020 at 09:59, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
>
> On Thu, 20 Feb 2020 at 09:15, Alan Modra <amodra@gmail.com> wrote:
> >
> > On Thu, Feb 20, 2020 at 05:37:03AM +0100, Christophe Lyon wrote:
> > > Or should I just copy & paste that list from your email and
> > > for i in <that-list>
> > > do
> > >   configure --target=$i
> > >   make all check
> > > done
> >
> > Yes, more or less.  No need to build gdb though for binutils changes,
> > unless you're messing with libbfd or libopcodes API.  I build with
> > --disable-nls --enable-plugins \
> > --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> > --disable-libdecnumber --enable-obsolete --target=$i
> > Parallel builds work too, except for m68hc11 and m68hc12 which write
> > to source directories.
> >
> > I also build --enable-targets=all --enable-nls with a recent 64-bit
> > gcc, an older gcc, and with gcc -m32 to pick up any 32 bit problems.
> > My current target list is:
> >
> Thanks, I'm looking at all these targets, then. I'll update my patches
> as needed.
>
>
> > aarch64-elf
> > aarch64-linux
> > aarch64_be-linux-gnu_ilp32
> > alpha-dec-vms
> > alpha-linux
> > alpha-linuxecoff
> > alpha-netbsd
> > alpha-unknown-freebsd4.7
> > am33_2.0-linux
> > arc-elf
> > arc-linux-uclibc
> > arm-elf
> > arm-linuxeabi
> > arm-nacl
> > arm-netbsdelf
> > arm-nto
> > arm-pe
> > arm-symbianelf
> > arm-vxworks
> > arm-wince-pe
> > armeb-linuxeabi
> > avr-elf
> > bfin-elf
> > bfin-linux-uclibc
> > bpf-none
> > cr16-elf
> > cris-elf
> > cris-linux
> > crisv32-linux
> > crx-elf
> > csky-elf
> > csky-linux
> > d10v-elf
> > d30v-elf
> > dlx-elf
> > epiphany-elf
> > fr30-elf
> > frv-elf
> > frv-linux
> > ft32-elf
> > h8300-elf
> > h8300-linux
> > hppa-hp-hpux10
> > hppa-linux
> > hppa64-hp-hpux11.23
> > hppa64-linux
> > i386-bsd
> > i386-darwin
> > i386-lynxos
> > i586-linux
> > i686-nacl
> > i686-nto
> > i686-pc-beos
> > i686-pc-elf
> > i686-pe
> > i686-vxworks
> > ia64-elf
> > ia64-freebsd5
> > ia64-hpux
> > ia64-linux
> > ia64-netbsd
> > ia64-vms
> > ip2k-elf
> > iq2000-elf
> > lm32-elf
> > lm32-linux
> > m32c-elf
> > m32r-elf
> > m32r-linux
> > m68hc11-elf
> > m68hc12-elf
> > m68k-elf
> > m68k-linux
> > mcore-elf
> > mcore-pe
> > mep-elf
> > metag-linux
> > microblaze-elf
> > microblaze-linux
> > mips-linux
> > mips-sgi-irix6
> > mips-vxworks
> > mips64-linux
> > mips64-openbsd
> > mips64el-openbsd
> > mipsel-linux-gnu
> > mipsisa32el-linux
> > mipstx39-elf
> > mmix
> > mn10200-elf
> > mn10300-elf
> > moxie-elf
> > msp430-elf
> > mt-elf
> > nds32be-elf
> > nds32le-linux
> > nios2-linux
> > ns32k-netbsd
> > ns32k-pc532-mach
> > or1k-elf
> > or1k-linux
> > pdp11-dec-aout
> > pj-elf
> > powerpc-aix5.1
> > powerpc-aix5.2
> > powerpc-eabisim
> > powerpc-eabivle
> > powerpc-freebsd
> > powerpc-linux
> > powerpc-nto
> > powerpc-wrs-vxworks
> > powerpc64-freebsd
> > powerpc64-linux
> > powerpc64le-linux
> > powerpcle-cygwin
> > powerpcle-elf
> > pru-elf
> > riscv32-elf
> > riscv64-linux
> > rl78-elf
> > rs6000-aix4.3.3
> > rs6000-aix5.1
> > rs6000-aix5.2
> > rx-elf
> > s12z-elf
> > s390-linux
> > s390x-linux
> > score-elf
> > sh-linux
> > sh-nto
> > sh-pe
> > sh-rtems
> > sh-vxworks
> > shle-unknown-netbsdelf
> > sparc-elf
> > sparc-linux
> > sparc-sun-solaris2
> > sparc-vxworks
> > sparc64-linux
> > spu-elf
> > tic30-unknown-coff
> > tic4x-coff
> > tic54x-coff
> > tic6x-elf
> > tilegx-linux
> > tilepro-linux
> > v850-elf
> > vax-netbsdelf
> > visium-elf
> > wasm32
> > x86_64-cloudabi
> > x86_64-linux
> > x86_64-nacl
> > x86_64-pc-linux-gnux32
> > x86_64-rdos
> > x86_64-w64-mingw32
> > xc16x-elf
> > xgate-elf
> > xstormy16-elf
> > xtensa-elf
> > z80-coff
> > z80-elf
> > z8k-coff
> >
> > --
> > Alan Modra
> > Australia Development Lab, IBM

[-- Attachment #2: 0001-Add-support-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 61044 bytes --]

From c76ce7778b90c533ca172731f99e2c2e80755e12 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 25 Nov 2019 08:55:37 +0000
Subject: [PATCH 1/1] Add support for non-contiguous memory regions

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

	bfd/
	* bfd-in2.h: Regenerate.
	* section.c (asection): Add already_assigned field.
	(BFD_FAKE_SECTION): Add default initializer for it.
	* ecoff.c (bfd_debug_section): Initialize already_assigned field.
	* elf32-arm.c (arm_build_one_stub): Add support for
	non_contiguous_regions.
	* elf32-csky.c (csky_build_one_stub): Likewise.
	* elf32-hppa.c (hppa_build_one_stub): Likewise.
	* elf32-m68hc11.c (m68hc11_elf_build_one_stub): Likewise.
	* elf32-m68hc12.c (m68hc12_elf_build_one_stub): Likewise.
	* elf32-metag.c (metag_build_one_stub): Likewise.
	* elf32-nios2.c (nios2_build_one_stub): Likewise.
	* elf64-ppc.c (ppc_build_one_stub): Likewise.
	(ppc_size_one_stub): Likewise.
	* elfnn-aarch64.c (aarch64_build_one_stub): Likewise.
	* elflink.c (elf_link_input_bfd): Likewise.

	include/
	* bfdlink.h (bfd_link_info): Add non_contiguous_regions and
	non_contiguous_regions_warnings fields.

	ld/
	* ldlang.c (lang_add_section): Add support for
	non_contiguous_regions.
	(size_input_section): Likewise.
	(lang_size_sections_1): Likewise.
	(process_insert_statements): Likewise.
	* ldlex.h (option_values): Add OPTION_NON_CONTIGUOUS_REGIONS and
	OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS.
	* lexsup.c (ld_options): Add entries for
	--enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings.
	(parse_args): Handle it.
	* NEWS: Add --enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings.
	* ld.texi: Add --enable-non-contiguous-regions and
	--enable-non-contiguous-regions-warnings documentation.
	* emultempl/armelf.em (elf32_arm_add_stub_section): Add
	SEC_LINKER_CREATED flag.
	* emultempl/xtensaelf.em (ld_build_required_section_dependence):
	Emit an error when --enable-non-contiguous-regions is used.
	* testsuite/ld-elf/non-contiguous.d: New.
	* testsuite/ld-elf/non-contiguous.ld: New.
	* testsuite/ld-elf/non-contiguous.s: New.
	* 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.
	* testsuite/ld-powerpc/powerpc.exp: Run new tests.
	* testsuite/ld-powerpc/non-contiguous-powerpc.d: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc.ld: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc.sd: New.
	* testsuite/ld-powerpc/non-contiguous-powerpc64.d: New.
---
 bfd/bfd-in2.h                                      |   9 +-
 bfd/ecoff.c                                        |   6 +-
 bfd/elf32-arm.c                                    |  11 ++
 bfd/elf32-csky.c                                   |  11 ++
 bfd/elf32-hppa.c                                   |  31 +++++
 bfd/elf32-m68hc11.c                                |  11 ++
 bfd/elf32-m68hc12.c                                |  11 ++
 bfd/elf32-metag.c                                  |  15 ++-
 bfd/elf32-nios2.c                                  |  13 ++
 bfd/elf64-ppc.c                                    |  50 +++++++
 bfd/elflink.c                                      |  12 ++
 bfd/elfnn-aarch64.c                                |  16 ++-
 bfd/section.c                                      |   9 +-
 include/bfdlink.h                                  |   8 ++
 ld/NEWS                                            |   3 +
 ld/emultempl/armelf.em                             |   3 +-
 ld/emultempl/xtensaelf.em                          |   6 +
 ld/ld.texi                                         |  42 ++++++
 ld/ldlang.c                                        | 145 ++++++++++++++++++++-
 ld/ldlex.h                                         |   2 +
 ld/lexsup.c                                        |  10 ++
 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          |  83 ++++++++++++
 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          |  77 +++++++++++
 ld/testsuite/ld-arm/non-contiguous-arm6.ld         |  33 +++++
 ld/testsuite/ld-elf/non-contiguous.d               |  29 +++++
 ld/testsuite/ld-elf/non-contiguous.ld              |  47 +++++++
 ld/testsuite/ld-elf/non-contiguous.s               |  21 +++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d   |   5 +
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld  |  22 ++++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s   |   8 ++
 ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d |   5 +
 ld/testsuite/ld-powerpc/powerpc.exp                |   3 +
 43 files changed, 1118 insertions(+), 11 deletions(-)
 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
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.d
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.ld
 create mode 100644 ld/testsuite/ld-elf/non-contiguous.s
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
 create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 2d56fda..7e4d1db 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1192,6 +1192,10 @@ typedef struct bfd_section
     struct bfd_section *s;
     const char *linked_to_symbol_name;
   } map_head, map_tail;
+ /* Points to the output section this section is already assigned to, if any.
+    This is used when support for non-contiguous memory regions is enabled.  */
+ struct bfd_section *already_assigned;
+
 } asection;
 
 /* Relax table contains information about instructions which can
@@ -1373,7 +1377,10 @@ discarded_section (const asection *sec)
      (struct bfd_symbol *) SYM, &SEC.symbol,                           \
                                                                        \
   /* map_head, map_tail                                            */  \
-     { NULL }, { NULL }                                                \
+     { NULL }, { NULL },                                               \
+                                                                       \
+  /* already_assigned                                              */  \
+     NULL                                                              \
     }
 
 /* We use a macro to initialize the static asymbol structures because
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 9e2efac..592a225 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -78,8 +78,10 @@ static asection bfd_debug_section =
      NULL,
   /* symbol_ptr_ptr,						   */
      NULL,
-  /* map_head, map_tail						   */
-     { NULL }, { NULL }
+  /* map_head, map_tail,					   */
+     { NULL }, { NULL },
+  /* already_assigned 						   */
+     NULL,
 };
 
 /* Create an ECOFF object.  */
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index a35dc99..0bcafe4 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5064,6 +5064,17 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   globals = elf32_arm_hash_table (info);
   if (globals == NULL)
     return FALSE;
diff --git a/bfd/elf32-csky.c b/bfd/elf32-csky.c
index f91d05b..ed8ab37 100644
--- a/bfd/elf32-csky.c
+++ b/bfd/elf32-csky.c
@@ -3621,6 +3621,17 @@ csky_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_csky_stub_hash_entry *)gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   globals = csky_elf_hash_table (info);
   if (globals == NULL)
     return FALSE;
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index b1b0f82..9760b75 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -731,6 +731,17 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
   switch (hsh->stub_type)
     {
     case hppa_stub_long_branch:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
+
       /* Create the long branch.  A long branch is formed with "ldil"
 	 loading the upper bits of the target address into a register,
 	 then branching with "be" which adds in the lower bits.
@@ -751,6 +762,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
       break;
 
     case hppa_stub_long_branch_shared:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
       /* Branches are relative.  This is where we are going to.  */
       sym_value = (hsh->target_value
 		   + hsh->target_section->output_offset
@@ -823,6 +844,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
       break;
 
     case hppa_stub_export:
+      /* Fail if the target section could not be assigned to an output
+	 section.  The user should fix his linker script.  */
+      if (hsh->target_section->output_section == NULL
+	  && info->non_contiguous_regions)
+	{
+	  _bfd_error_handler (_("Could not assign %pA to an output section. "
+				"Retry without --enable-non-contiguous-regions.\n"),
+			      hsh->target_section);
+	  abort();
+    }
       /* Branches are relative.  This is where we are going to.  */
       sym_value = (hsh->target_value
 		   + hsh->target_section->output_offset
diff --git a/bfd/elf32-m68hc11.c b/bfd/elf32-m68hc11.c
index 8d4d227..3e12ae5 100644
--- a/bfd/elf32-m68hc11.c
+++ b/bfd/elf32-m68hc11.c
@@ -415,6 +415,17 @@ m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = m68hc11_elf_hash_table (info);
   if (htab == NULL)
     return FALSE;
diff --git a/bfd/elf32-m68hc12.c b/bfd/elf32-m68hc12.c
index e41b4c7..a04efd8 100644
--- a/bfd/elf32-m68hc12.c
+++ b/bfd/elf32-m68hc12.c
@@ -535,6 +535,17 @@ m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = m68hc11_elf_hash_table (info);
 
   stub_sec = stub_entry->stub_sec;
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 07e9856..3f30d6d 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -3459,7 +3459,7 @@ metag_type_of_stub (asection *input_sec,
 #define MOV_PC_A0_3	0xa3180ca0
 
 static bfd_boolean
-metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_UNUSED)
+metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 {
   struct elf_metag_stub_hash_entry *hsh;
   asection *stub_sec;
@@ -3467,9 +3467,22 @@ metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
   bfd_byte *loc;
   bfd_vma sym_value;
   int size;
+  struct bfd_link_info *info;
 
   /* Massage our args to the form they really have.  */
   hsh = (struct elf_metag_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (hsh->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  hsh->target_section);
+      abort();
+    }
 
   stub_sec = hsh->stub_sec;
 
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index fd05fb0..cba9270 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -2490,7 +2490,20 @@ nios2_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
     = (struct elf32_nios2_stub_hash_entry *) gen_entry;
   asection *stub_sec = hsh->stub_sec;
   bfd_vma sym_value;
+  struct bfd_link_info *info;
+
+  info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (hsh->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  hsh->target_section);
+      abort();
+    }
   /* Make a note of the offset within the stubs for this entry.  */
   hsh->stub_offset = stub_sec->size;
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 1ea4c40..24671d4 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11349,6 +11349,31 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
   info = in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section != NULL
+      && stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
+  /* Same for the group.  */
+  if (stub_entry->group->stub_sec != NULL
+      && stub_entry->group->stub_sec->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign group %pA target %pA to an "
+			    "output section. Retry without "
+			    "--enable-non-contiguous-regions.\n"),
+			  stub_entry->group->stub_sec,
+			  stub_entry->target_section);
+      abort();
+    }
+
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
@@ -11874,6 +11899,31 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   if (htab == NULL)
     return FALSE;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section != NULL
+      && stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign %pA to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
+  /* Same for the group.  */
+  if (stub_entry->group->stub_sec != NULL
+      && stub_entry->group->stub_sec->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign group %pA target %pA to an "
+			    "output section. Retry without "
+			    "--enable-non-contiguous-regions.\n"),
+			  stub_entry->group->stub_sec,
+			  stub_entry->target_section);
+      abort();
+    }
+
   /* Make a note of the offset within the stubs for this entry.  */
   stub_entry->stub_offset = stub_entry->group->stub_sec->size;
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 8e7ae2a..a8f55a0 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10561,6 +10561,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 	 discarding, we don't need to keep it.  */
       if (isym->st_shndx != SHN_UNDEF
 	  && isym->st_shndx < SHN_LORESERVE
+	  && isec->output_section == NULL
+	  && flinfo->info->non_contiguous_regions
+	  && flinfo->info->non_contiguous_regions_warnings)
+	{
+	  _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+				"discards section `%s' from '%s'\n"),
+			      isec->name, isec->owner->filename);
+	  continue;
+	}
+
+      if (isym->st_shndx != SHN_UNDEF
+	  && isym->st_shndx < SHN_LORESERVE
 	  && bfd_section_removed_from_list (output_bfd,
 					    isec->output_section))
 	continue;
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 2191b5d..092a06b 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -3278,7 +3278,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name,
 
 static bfd_boolean
 aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
-			void *in_arg ATTRIBUTE_UNUSED)
+			void *in_arg)
 {
   struct elf_aarch64_stub_hash_entry *stub_entry;
   asection *stub_sec;
@@ -3291,10 +3291,24 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
   unsigned int template_size;
   const uint32_t *template;
   unsigned int i;
+  struct bfd_link_info *info;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
 
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    {
+      _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+			    "Retry without --enable-non-contiguous-regions.\n"),
+			  stub_entry->target_section);
+      abort();
+    }
+
   stub_sec = stub_entry->stub_sec;
 
   /* Make a note of the offset within the stubs for this entry.  */
diff --git a/bfd/section.c b/bfd/section.c
index 7de0a2d..eef118f 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -551,6 +551,10 @@ CODE_FRAGMENT
 .    struct bfd_section *s;
 .    const char *linked_to_symbol_name;
 .  } map_head, map_tail;
+. {* Points to the output section this section is already assigned to, if any.
+.    This is used when support for non-contiguous memory regions is enabled.  *}
+. struct bfd_section *already_assigned;
+.
 .} asection;
 .
 .{* Relax table contains information about instructions which can
@@ -732,7 +736,10 @@ CODE_FRAGMENT
 .     (struct bfd_symbol *) SYM, &SEC.symbol,				\
 .									\
 .  {* map_head, map_tail                                            *}	\
-.     { NULL }, { NULL }						\
+.     { NULL }, { NULL },						\
+.									\
+.  {* already_assigned                                             *}	\
+.     NULL								\
 .    }
 .
 .{* We use a macro to initialize the static asymbol structures because
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 8d85530..529ea6e 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -501,6 +501,14 @@ struct bfd_link_info
   /* TRUE if "-Map map" is passed to linker.  */
   unsigned int has_map_file : 1;
 
+  /* TRUE if "--enable-non-contiguous-regions" is passed to the
+     linker.  */
+  unsigned int non_contiguous_regions : 1;
+
+  /* TRUE if "--enable-non-contiguous-regions-warnings" is passed to
+     the linker.  */
+  unsigned int non_contiguous_regions_warnings : 1;
+
   /* Char that may appear as the first char of a symbol, but should be
      skipped (like symbol_leading_char) when looking up symbols in
      wrap_hash.  Used by PowerPC Linux for 'dot' symbols.  */
diff --git a/ld/NEWS b/ld/NEWS
index f659ccf..2611a3e 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add command-line options --enable-non-contiguous-regions and
+  --enable-non-contiguous-regions-warnings.
+
 Changes in 2.34:
 
 * cr16c support removed.
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index efdcf5a..fb5bbf8 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -227,7 +227,8 @@ elf32_arm_add_stub_section (const char * stub_sec_name,
   struct hook_stub_info info;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
-	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP
+	   | SEC_LINKER_CREATED);
   stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
 						 stub_sec_name, flags);
   if (stub_sec == NULL)
diff --git a/ld/emultempl/xtensaelf.em b/ld/emultempl/xtensaelf.em
index 1aca7b7..74bd11c 100644
--- a/ld/emultempl/xtensaelf.em
+++ b/ld/emultempl/xtensaelf.em
@@ -1224,6 +1224,12 @@ ld_build_required_section_dependence (lang_statement_union_type *s)
     {
       lang_statement_union_type *l = iter_stack_current (&stack);
 
+      if (l == NULL && link_info.non_contiguous_regions)
+	{
+	  einfo (_("Relaxation not supported with --enable-non-contiguous-regions.\n"));
+	  abort();
+	}
+
       if (l->header.type == lang_input_section_enum)
 	{
 	  lang_input_section_type *input;
diff --git a/ld/ld.texi b/ld/ld.texi
index 9bb3d55..07933b2 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -459,6 +459,48 @@ will contain a colon separated list of audit interfaces to use.  This
 option is only meaningful on ELF platforms supporting the rtld-audit interface.
 The -P option is provided for Solaris compatibility.
 
+@kindex --enable-non-contiguous-regions
+@item --enable-non-contiguous-regions
+This option avoids generating an error if an input section does not
+fit a matching output section. The linker tries to allocate the input
+section to subseque nt matching output sections, and generates an
+error only if no output section is large enough.  This is useful when
+several non-contiguous memory regions are available and the input
+section does not require a particular one.  The order in which input
+sections are evaluated does not change, for instance:
+
+@smallexample
+  MEMORY @{
+    MEM1 (rwx) : ORIGIN : 0x1000, LENGTH = 0x14
+    MEM2 (rwx) : ORIGIN : 0x1000, LENGTH = 0x40
+    MEM3 (rwx) : ORIGIN : 0x2000, LENGTH = 0x40
+  @}
+  SECTIONS @{
+    mem1 : @{ *(.data.*); @} > MEM1
+    mem2 : @{ *(.data.*); @} > MEM2
+    mem3 : @{ *(.data.*); @} > MEM2
+  @}
+
+  with input sections:
+  .data.1: size 8
+  .data.2: size 0x10
+  .data.3: size 4
+
+  results in .data.1 affected to mem1, and .data.2 and .data.3
+  affected to mem2, even though .data.3 would fit in mem3.
+@end smallexample
+
+This option is incompatible with INSERT statements because it changes
+the way input sections are mapped to output sections.
+
+@kindex --enable-non-contiguous-regions-warnings
+@item --enable-non-contiguous-regions-warnings
+This option enables warnings when
+@code{--enable-non-contiguous-regions} allows possibly unexpected
+matches in sections mapping, potentially leading to silently
+discarding a section instead of failing because it does not fit any
+output region.
+
 @cindex entry point, from command line
 @kindex -e @var{entry}
 @kindex --entry=@var{entry}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 528ed22..83d42a6 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2537,6 +2537,11 @@ lang_add_section (lang_statement_list_type *ptr,
 	  /* This prevents future calls from assigning this section.  */
 	  section->output_section = bfd_abs_section_ptr;
 	}
+      else if (link_info.non_contiguous_regions_warnings)
+	einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
+		 "section `%pA' from '%pB' match /DISCARD/ clause.\n"),
+	       NULL, section, section->owner);
+
       return;
     }
 
@@ -2550,7 +2555,33 @@ lang_add_section (lang_statement_list_type *ptr,
     }
 
   if (section->output_section != NULL)
-    return;
+    {
+      if (!link_info.non_contiguous_regions)
+	return;
+
+      /* SECTION has already been handled in a special way
+	 (eg. LINK_ONCE): skip it.  */
+      if (bfd_is_abs_section (section->output_section))
+	return;
+
+      /* Already assigned to the same output section, do not process
+	 it again, to avoid creating loops between duplicate sections
+	 later.  */
+      if (section->output_section == output->bfd_section)
+	return;
+
+      if (link_info.non_contiguous_regions_warnings && output->bfd_section)
+	einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
+		 "change behaviour for section `%pA' from '%pB' (assigned to "
+		 "%pA, but additional match: %pA)\n"),
+	       NULL, section, section->owner, section->output_section,
+	       output->bfd_section);
+
+      /* SECTION has already been assigned to an output section, but
+	 the user allows it to be mapped to another one in case it
+	 overflows. We'll later update the actual output section in
+	 size_input_section as appropriate.  */
+    }
 
   /* We don't copy the SEC_NEVER_LOAD flag from an input section
      to an output section, because we want to be able to include a
@@ -4194,6 +4225,12 @@ process_insert_statements (lang_statement_union_type **start)
 	  lang_statement_union_type **ptr;
 	  lang_statement_union_type *first;
 
+	  if (link_info.non_contiguous_regions)
+	    {
+	      einfo (_("warning: INSERT statement in linker script is "
+		       "incompatible with --enable-non-contiguous-regions.\n"));
+	    }
+
 	  where = lang_output_section_find (i->where);
 	  if (where != NULL && i->is_before)
 	    {
@@ -5116,11 +5153,27 @@ size_input_section
   (lang_statement_union_type **this_ptr,
    lang_output_section_statement_type *output_section_statement,
    fill_type *fill,
+   bfd_boolean *removed,
    bfd_vma dot)
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
   asection *o = output_section_statement->bfd_section;
+  *removed = 0;
+
+  if (link_info.non_contiguous_regions)
+    {
+      /* If the input section I has already been successfully assigned
+	 to an output section other than O, don't bother with it and
+	 let the caller remove it from the list.  Keep processing in
+	 case we have already handled O, because the repeated passes
+	 have reinitialized its size.  */
+      if (i->already_assigned && i->already_assigned != o)
+	{
+	  *removed = 1;
+	  return dot;
+	}
+    }
 
   if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
     i->output_offset = i->vma - o->vma;
@@ -5152,6 +5205,42 @@ size_input_section
 	  dot += alignment_needed;
 	}
 
+      if (link_info.non_contiguous_regions)
+	{
+	  /* If I would overflow O, let the caller remove I from the
+	     list.  */
+	  if (output_section_statement->region)
+	    {
+	      bfd_vma end = output_section_statement->region->origin
+		+ output_section_statement->region->length;
+
+	      if (dot + TO_ADDR (i->size) > end)
+		{
+		  if (i->flags & SEC_LINKER_CREATED)
+		    {
+		      einfo (_("Output section '%s' not large enough for the "
+			       "linker-created stubs section '%s'.\n"),
+			     i->output_section->name, i->name);
+		      abort();
+		    }
+
+		  if (i->rawsize && i->rawsize != i->size)
+		    {
+		      einfo (_("Relaxation not supported with "
+			       "--enable-non-contiguous-regions (section '%s' "
+			       "would overflow '%s' after it changed size).\n"),
+			     i->name, i->output_section->name);
+		      abort();
+		    }
+
+		  *removed = 1;
+		  dot = end;
+		  i->output_section = NULL;
+		  return dot;
+		}
+	    }
+	}
+
       /* Remember where in the output section this input section goes.  */
       i->output_offset = dot - o->vma;
 
@@ -5159,6 +5248,14 @@ size_input_section
       dot += TO_ADDR (i->size);
       if (!(o->flags & SEC_FIXED_SIZE))
 	o->size = TO_SIZE (dot - o->vma);
+
+      if (link_info.non_contiguous_regions)
+	{
+	  /* Record that I was successfully assigned to O, and update
+	     its actual output section too.  */
+	  i->already_assigned = o;
+	  i->output_section = o;
+	}
     }
 
   return dot;
@@ -5445,10 +5542,14 @@ lang_size_sections_1
    bfd_boolean check_regions)
 {
   lang_statement_union_type *s;
+  lang_statement_union_type *prev_s = NULL;
+  bfd_boolean removed_prev_s = FALSE;
 
   /* Size up the sections from their constituent parts.  */
-  for (s = *prev; s != NULL; s = s->header.next)
+  for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
     {
+      bfd_boolean removed=FALSE;
+
       switch (s->header.type)
 	{
 	case lang_output_section_statement_enum:
@@ -5874,7 +5975,7 @@ lang_size_sections_1
 		  *relax = TRUE;
 	      }
 	    dot = size_input_section (prev, output_section_statement,
-				      fill, dot);
+				      fill, &removed, dot);
 	  }
 	  break;
 
@@ -5979,7 +6080,43 @@ lang_size_sections_1
 	  FAIL ();
 	  break;
 	}
-      prev = &s->header.next;
+
+      /* If an input section doesn't fit in the current output
+	 section, remove it from the list.  Handle the case where we
+	 have to remove an input_section statement here: there is a
+	 special case to remove the first element of the list.  */
+      if (link_info.non_contiguous_regions && removed)
+	{
+	  /* If we removed the first element during the previous
+	     iteration, override the loop assignment of prev_s.  */
+	  if (removed_prev_s)
+	      prev_s = NULL;
+
+	  if (prev_s)
+	    {
+	      /* If there was a real previous input section, just skip
+		 the current one.  */
+	      prev_s->header.next=s->header.next;
+	      s = prev_s;
+	      removed_prev_s = FALSE;
+	    }
+	  else
+	    {
+	      /* Remove the first input section of the list.  */
+	      *prev = s->header.next;
+	      removed_prev_s = TRUE;
+	    }
+
+	  /* Move to next element, unless we removed the head of the
+	     list.  */
+	  if (!removed_prev_s)
+	    prev = &s->header.next;
+	}
+      else
+	{
+	  prev = &s->header.next;
+	  removed_prev_s = FALSE;
+	}
     }
   return dot;
 }
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 5287f19..22b928d 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -150,6 +150,8 @@ enum option_values
   OPTION_FORCE_GROUP_ALLOCATION,
   OPTION_PRINT_MAP_DISCARDED,
   OPTION_NO_PRINT_MAP_DISCARDED,
+  OPTION_NON_CONTIGUOUS_REGIONS,
+  OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS,
 };
 
 /* The initial parser states.  */
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 3d15cc4..2597e2d 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -122,6 +122,10 @@ static const struct ld_option ld_options[] =
     'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
   { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
     '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
+  { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS},
+    '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES },
+  { {"enable-non-contiguous-regions-warnings", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS},
+    '\0', NULL, N_("Enable warnings when --enable-non-contiguous-regions may cause unexpected behaviour"), TWO_DASHES },
   { {"EB", no_argument, NULL, OPTION_EB},
     '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
   { {"EL", no_argument, NULL, OPTION_EL},
@@ -845,6 +849,12 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_NO_EXPORT_DYNAMIC:
 	  link_info.export_dynamic = FALSE;
 	  break;
+	case OPTION_NON_CONTIGUOUS_REGIONS:
+	  link_info.non_contiguous_regions = TRUE;
+	  break;
+	case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
+	  link_info.non_contiguous_regions_warnings = TRUE;
+	  break;
 	case 'e':
 	  lang_add_entry (optarg, TRUE);
 	  break;
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..d0e5fab
--- /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..af40e84
--- /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  .*  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..6373922
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm3.d
@@ -0,0 +1,83 @@
+#name: non-contiguous-arm3
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm3.ld
+#objdump: -rdth
+#xfail: [is_generic]
+#skip: arm*nacl
+
+.*:     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..28417c0
--- /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..dc85d1e
--- /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  .*  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..605d846
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm6.d
@@ -0,0 +1,77 @@
+#name: non-contiguous-arm6
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm6.ld
+#objdump: -rdth
+#xfail: [is_generic]
+#skip: arm*nacl
+
+.*:     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
+}
diff --git a/ld/testsuite/ld-elf/non-contiguous.d b/ld/testsuite/ld-elf/non-contiguous.d
new file mode 100644
index 0000000..9694bcf
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.d
@@ -0,0 +1,29 @@
+#name: non-contiguous
+#source: non-contiguous.s
+#ld: --enable-non-contiguous-regions -T non-contiguous.ld
+#objdump: -rdsh
+#xfail: [is_generic]
+#skip: xtensa*
+
+.*:     file format .*
+
+Sections:
+Idx Name          Size      VMA  *     LMA  *     File off  Algn
+  0 \.raml         0000000c  0*1fff0000  0*1fff0000  .*  2\*\*.
+                  CONTENTS, ALLOC, LOAD, DATA
+  1 \.ramu         00000014  0*20000000  0*1fff000c  .*  2\*\*.
+                  CONTENTS, ALLOC, LOAD, DATA
+  2 \.ramz         0000003c  0*20040000  0*20000014  .*  2\*\*.
+                  CONTENTS, ALLOC, LOAD, DATA
+
+
+Contents of section .raml:
+ 1fff0000 (010+ 020+ 030+|0+01 0+02 0+03)           ............    
+Contents of section .ramu:
+ 20000000 (040+ 050+ 060+ 070+|0+04 0+05 0+06 0+07)  ................
+ 20000010 (080+|0+08)                             ....            
+Contents of section .ramz:
+ 20040000 09090909 09090909 09090909 09090909  ................
+ 20040010 09090909 09090909 09090909 09090909  ................
+ 20040020 09090909 09090909 09090909 09090909  ................
+ 20040030 09090909 09090909 09090909           ............    
diff --git a/ld/testsuite/ld-elf/non-contiguous.ld b/ld/testsuite/ld-elf/non-contiguous.ld
new file mode 100644
index 0000000..fc72253
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.ld
@@ -0,0 +1,47 @@
+/*
+ section .data.1 fits in .raml
+ sections .data.2 .data.3 fit in .ramu
+ section .data.4 fits in .ramz
+*/
+MEMORY
+{
+  RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00014
+  RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040
+  RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00040
+}
+
+SECTIONS
+{
+   /* Ignore this target specific info in output comparison.  */
+   /DISCARD/ : {
+             *(.ARM.attributes)
+	     *(.ARC.attributes)
+	     *(.riscv.attributes)
+	     *(.c6xabi.attributes)
+	     *(.trampolines)
+	     *(.reginfo)
+	     *(.note.renesas)
+	     *(.MIPS.abiflags)
+	     *(.MSP430.attributes)
+	     *(.gnu.attributes)
+   }
+
+   .raml : /*AT ( ADDR (.text) + SIZEOF (.text) )*/
+   {  _raml_start = . ;
+      *(.boot) ;
+      *(.data) *(.data.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _ramu_start = . ;
+      *(.data) *(.data.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _ramz_start = . ;
+      *(.data) *(.data.*) ;
+     _ramz_end = . ;
+   } > RAMZ
+}
diff --git a/ld/testsuite/ld-elf/non-contiguous.s b/ld/testsuite/ld-elf/non-contiguous.s
new file mode 100644
index 0000000..19bc2b1
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.s
@@ -0,0 +1,21 @@
+	.section .data.1, "a", %progbits
+	# Fit in RAML
+	.4byte 1
+	.4byte 2
+	.4byte 3
+
+	.section .data.2, "a", %progbits
+	# Fit in RAMU
+	.4byte 4
+	.4byte 5
+	.4byte 6
+
+	.section .data.3, "a", %progbits
+	# Fit in RAMU
+	.4byte 7
+	.4byte 8
+
+	.section .data.4, "a", %progbits
+	# Fit in RAMZ
+	.fill 0x3c, 1, 9
+
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
new file mode 100644
index 0000000..858e353
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
@@ -0,0 +1,5 @@
+#name: non-contiguous-powerpc
+#source: non-contiguous-powerpc.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-powerpc.ld
+#error: \ARelaxation not supported with --enable-non-contiguous-regions.*
+#skip: powerpc64*-*
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
new file mode 100644
index 0000000..744d246
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
@@ -0,0 +1,22 @@
+/* Distance between 'one' and 'two' means that relaxation implies that
+   .text.one's size increases. Even though the result would fit in
+   'oneandhalf', this is not supported by
+   --enable-non-contiguous-regions.  */
+
+MEMORY {
+       one (RXAI) : ORIGIN = 0x00000000, LENGTH = 0x00000010
+       oneandhalf (RXAI) : ORIGIN = 0x00001000, LENGTH = 0x00001010
+       two (RXAI) : ORIGIN = 0x20000000, LENGTH = 0x10000000
+}
+
+SECTIONS {
+      one : {
+         *(.text.one)
+      } > one
+      oneandhalf : {
+         *(.text.one)
+      } > oneandhalf
+      two : {
+      *(.text.two)
+      } > two
+}
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
new file mode 100644
index 0000000..e02b322
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
@@ -0,0 +1,8 @@
+	.machine "ppc"
+
+	.section .text.one
+	b	2f
+
+	.section .text.two
+2:
+	nop
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d b/ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d
new file mode 100644
index 0000000..ff0e3fc
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d
@@ -0,0 +1,5 @@
+#name: non-contiguous-powerpc64
+#source: non-contiguous-powerpc.s
+#as: -a64
+#ld: -melf64ppc --enable-non-contiguous-regions -T non-contiguous-powerpc.ld
+#error: .*Could not assign group.*
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 94b2fac..84d7c9c 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -405,6 +405,7 @@ if [ supports_ppc64 ] then {
     run_dump_test "tlsgd"
     run_dump_test "tlsld"
     run_dump_test "tlsie"
+    run_dump_test "non-contiguous-powerpc64"
 }
 
 run_dump_test "localgot"
@@ -443,3 +444,5 @@ run_dump_test "vle-multiseg-6"
 
 run_dump_test "ppc476-shared"
 run_dump_test "ppc476-shared2"
+
+run_dump_test "non-contiguous-powerpc"
-- 
2.7.4


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-02-28 17:31                 ` Christophe Lyon
@ 2020-03-09 13:10                   ` Christophe Lyon
  2020-03-13 14:21                     ` Nick Clifton
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-03-09 13:10 UTC (permalink / raw)
  To: binutils

Ping?

https://sourceware.org/pipermail/binutils/2020-February/109942.html

Christophe


On Fri, 28 Feb 2020 at 18:30, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
>
> Hi,
>
> Here is an updated patch.
>
> Changes between v4 and v5:
> * Added sanity checks for powerpc64 and xtensa
> (--enable-non-contiguous-regions does not work with relaxation), to
> emit an error message rather than crash
> * Removed a bogus assert in size_input_section
> * Added quotes around section names in error messages
> * Updated tests:
> - ld-arm/non-contiguous-arm[25] now pass on arm-nacl
> - ld-arm/non-contiguous-arm[36] are now skipped on arm-nacl because
> the stub code is different from the expected one and a dedicated test
> didn't seem mandatory
> - ld-arm/non-contiguous-arm4 updated expected error message
> - ld-elf/non-contiguous: do not require little-endian, accept both
> endiannesses, discard target-specific sections to make expected output
> matching possible. Skip on xtensa where relaxation is enabled by
> default and conflicts with the new option
> - ld-powerpc/non-contiguous-powerpc: skip on powerpc64 (because the
> error message is different)
> - ld/powerpc/non-contiguous-powerpc64: new test, with the error
> message expected on powerpc64
> * Squashed all patches into one
>
> Tested for non-regression on the list of 163 targets provided by Alan.
> I left the error on mep-elf, because many other tests fails on that
> target with the same error message (selected target format
> 'elf32-mep-little' unknown)
>
> Christophe
>
>
> On Thu, 20 Feb 2020 at 09:59, Christophe Lyon
> <christophe.lyon@linaro.org> wrote:
> >
> > On Thu, 20 Feb 2020 at 09:15, Alan Modra <amodra@gmail.com> wrote:
> > >
> > > On Thu, Feb 20, 2020 at 05:37:03AM +0100, Christophe Lyon wrote:
> > > > Or should I just copy & paste that list from your email and
> > > > for i in <that-list>
> > > > do
> > > >   configure --target=$i
> > > >   make all check
> > > > done
> > >
> > > Yes, more or less.  No need to build gdb though for binutils changes,
> > > unless you're messing with libbfd or libopcodes API.  I build with
> > > --disable-nls --enable-plugins \
> > > --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> > > --disable-libdecnumber --enable-obsolete --target=$i
> > > Parallel builds work too, except for m68hc11 and m68hc12 which write
> > > to source directories.
> > >
> > > I also build --enable-targets=all --enable-nls with a recent 64-bit
> > > gcc, an older gcc, and with gcc -m32 to pick up any 32 bit problems.
> > > My current target list is:
> > >
> > Thanks, I'm looking at all these targets, then. I'll update my patches
> > as needed.
> >
> >
> > > aarch64-elf
> > > aarch64-linux
> > > aarch64_be-linux-gnu_ilp32
> > > alpha-dec-vms
> > > alpha-linux
> > > alpha-linuxecoff
> > > alpha-netbsd
> > > alpha-unknown-freebsd4.7
> > > am33_2.0-linux
> > > arc-elf
> > > arc-linux-uclibc
> > > arm-elf
> > > arm-linuxeabi
> > > arm-nacl
> > > arm-netbsdelf
> > > arm-nto
> > > arm-pe
> > > arm-symbianelf
> > > arm-vxworks
> > > arm-wince-pe
> > > armeb-linuxeabi
> > > avr-elf
> > > bfin-elf
> > > bfin-linux-uclibc
> > > bpf-none
> > > cr16-elf
> > > cris-elf
> > > cris-linux
> > > crisv32-linux
> > > crx-elf
> > > csky-elf
> > > csky-linux
> > > d10v-elf
> > > d30v-elf
> > > dlx-elf
> > > epiphany-elf
> > > fr30-elf
> > > frv-elf
> > > frv-linux
> > > ft32-elf
> > > h8300-elf
> > > h8300-linux
> > > hppa-hp-hpux10
> > > hppa-linux
> > > hppa64-hp-hpux11.23
> > > hppa64-linux
> > > i386-bsd
> > > i386-darwin
> > > i386-lynxos
> > > i586-linux
> > > i686-nacl
> > > i686-nto
> > > i686-pc-beos
> > > i686-pc-elf
> > > i686-pe
> > > i686-vxworks
> > > ia64-elf
> > > ia64-freebsd5
> > > ia64-hpux
> > > ia64-linux
> > > ia64-netbsd
> > > ia64-vms
> > > ip2k-elf
> > > iq2000-elf
> > > lm32-elf
> > > lm32-linux
> > > m32c-elf
> > > m32r-elf
> > > m32r-linux
> > > m68hc11-elf
> > > m68hc12-elf
> > > m68k-elf
> > > m68k-linux
> > > mcore-elf
> > > mcore-pe
> > > mep-elf
> > > metag-linux
> > > microblaze-elf
> > > microblaze-linux
> > > mips-linux
> > > mips-sgi-irix6
> > > mips-vxworks
> > > mips64-linux
> > > mips64-openbsd
> > > mips64el-openbsd
> > > mipsel-linux-gnu
> > > mipsisa32el-linux
> > > mipstx39-elf
> > > mmix
> > > mn10200-elf
> > > mn10300-elf
> > > moxie-elf
> > > msp430-elf
> > > mt-elf
> > > nds32be-elf
> > > nds32le-linux
> > > nios2-linux
> > > ns32k-netbsd
> > > ns32k-pc532-mach
> > > or1k-elf
> > > or1k-linux
> > > pdp11-dec-aout
> > > pj-elf
> > > powerpc-aix5.1
> > > powerpc-aix5.2
> > > powerpc-eabisim
> > > powerpc-eabivle
> > > powerpc-freebsd
> > > powerpc-linux
> > > powerpc-nto
> > > powerpc-wrs-vxworks
> > > powerpc64-freebsd
> > > powerpc64-linux
> > > powerpc64le-linux
> > > powerpcle-cygwin
> > > powerpcle-elf
> > > pru-elf
> > > riscv32-elf
> > > riscv64-linux
> > > rl78-elf
> > > rs6000-aix4.3.3
> > > rs6000-aix5.1
> > > rs6000-aix5.2
> > > rx-elf
> > > s12z-elf
> > > s390-linux
> > > s390x-linux
> > > score-elf
> > > sh-linux
> > > sh-nto
> > > sh-pe
> > > sh-rtems
> > > sh-vxworks
> > > shle-unknown-netbsdelf
> > > sparc-elf
> > > sparc-linux
> > > sparc-sun-solaris2
> > > sparc-vxworks
> > > sparc64-linux
> > > spu-elf
> > > tic30-unknown-coff
> > > tic4x-coff
> > > tic54x-coff
> > > tic6x-elf
> > > tilegx-linux
> > > tilepro-linux
> > > v850-elf
> > > vax-netbsdelf
> > > visium-elf
> > > wasm32
> > > x86_64-cloudabi
> > > x86_64-linux
> > > x86_64-nacl
> > > x86_64-pc-linux-gnux32
> > > x86_64-rdos
> > > x86_64-w64-mingw32
> > > xc16x-elf
> > > xgate-elf
> > > xstormy16-elf
> > > xtensa-elf
> > > z80-coff
> > > z80-elf
> > > z8k-coff
> > >
> > > --
> > > Alan Modra
> > > Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-03-09 13:10                   ` Christophe Lyon
@ 2020-03-13 14:21                     ` Nick Clifton
  2020-03-13 14:46                       ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Clifton @ 2020-03-13 14:21 UTC (permalink / raw)
  To: Christophe Lyon, binutils

Hi Christophe,

> Ping?
> 
> https://sourceware.org/pipermail/binutils/2020-February/109942.html

Oops - sorry - the patch is good.  Approved - please apply.

Cheers
  Nick


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-03-13 14:21                     ` Nick Clifton
@ 2020-03-13 14:46                       ` Christophe Lyon
  2020-06-02 12:49                         ` Alexander Fedotov
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2020-03-13 14:46 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

On Fri, 13 Mar 2020 at 15:21, Nick Clifton <nickc@redhat.com> wrote:
>
> Hi Christophe,
>
> > Ping?
> >
> > https://sourceware.org/pipermail/binutils/2020-February/109942.html
>
> Oops - sorry - the patch is good.  Approved - please apply.
>

Thanks!
Pushed as abf874aafe3d717573e4a48bf0e3c6334e666a55

Christophe

> Cheers
>   Nick
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-03-13 14:46                       ` Christophe Lyon
@ 2020-06-02 12:49                         ` Alexander Fedotov
  2020-06-03 12:48                           ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Alexander Fedotov @ 2020-06-02 12:49 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Nick Clifton, binutils

Hello Christophe

I found it very useful feature.
But I'm just curious if it is possible to extend linker syntax to support
syntax with output regions separated by OR :

text : { *(.text*) }  > REGION0 | REGION1 | REGION2

It is more convenient in some cases. For example CMSIS has linker script
like this:

  .text :
  {
    KEEP(*(.vectors))
    *(.text*)

    KEEP(*(.init))
    KEEP(*(.fini))

    /* .ctors */
    *crtbegin.o(.ctors)
    *crtbegin?.o(.ctors)
    *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
    *(SORT(.ctors.*))
    *(.ctors)

    /* .dtors */
     *crtbegin.o(.dtors)
     *crtbegin?.o(.dtors)
     *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
     *(SORT(.dtors.*))
     *(.dtors)

    *(.rodata*)
    KEEP(*(.eh_frame*))
  } > FLASH

So that we have to duplicate this rather than use | in output regions.

What do you think?

Alex


On Fri, Mar 13, 2020 at 5:46 PM Christophe Lyon via Binutils <
binutils@sourceware.org> wrote:

> On Fri, 13 Mar 2020 at 15:21, Nick Clifton <nickc@redhat.com> wrote:
> >
> > Hi Christophe,
> >
> > > Ping?
> > >
> > > https://sourceware.org/pipermail/binutils/2020-February/109942.html
> >
> > Oops - sorry - the patch is good.  Approved - please apply.
> >
>
> Thanks!
> Pushed as abf874aafe3d717573e4a48bf0e3c6334e666a55
>
> Christophe
>
> > Cheers
> >   Nick
> >
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Add support for non-contiguous memory regions
  2020-06-02 12:49                         ` Alexander Fedotov
@ 2020-06-03 12:48                           ` Christophe Lyon
  0 siblings, 0 replies; 15+ messages in thread
From: Christophe Lyon @ 2020-06-03 12:48 UTC (permalink / raw)
  To: Alexander Fedotov; +Cc: Nick Clifton, binutils

On Tue, 2 Jun 2020 at 14:49, Alexander Fedotov <alfedotov@gmail.com> wrote:
>
> Hello Christophe
>
> I found it very useful feature.

Thanks for the positive feedback, that's good to read.

> But I'm just curious if it is possible to extend linker syntax to support syntax with output regions separated by OR :
>
> text : { *(.text*) }  > REGION0 | REGION1 | REGION2
>

I think this was discussed in the original thread, eg
https://sourceware.org/legacy-ml/binutils/2017-02/msg00250.html and
https://sourceware.org/legacy-ml/binutils/2017-03/msg00020.html

I would look nice indeed, I just fear unexpected complications since
this modifies the linker script language.

Maybe some main maintainers have thoughts on the difficulty and risks
of implementing this? Nick?

Thanks,

Christophe

> It is more convenient in some cases. For example CMSIS has linker script like this:
>
>   .text :
>   {
>     KEEP(*(.vectors))
>     *(.text*)
>
>     KEEP(*(.init))
>     KEEP(*(.fini))
>
>     /* .ctors */
>     *crtbegin.o(.ctors)
>     *crtbegin?.o(.ctors)
>     *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
>     *(SORT(.ctors.*))
>     *(.ctors)
>
>     /* .dtors */
>      *crtbegin.o(.dtors)
>      *crtbegin?.o(.dtors)
>      *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
>      *(SORT(.dtors.*))
>      *(.dtors)
>
>     *(.rodata*)
>     KEEP(*(.eh_frame*))
>   } > FLASH
>
> So that we have to duplicate this rather than use | in output regions.
>
> What do you think?
>
> Alex
>
>
> On Fri, Mar 13, 2020 at 5:46 PM Christophe Lyon via Binutils <binutils@sourceware.org> wrote:
>>
>> On Fri, 13 Mar 2020 at 15:21, Nick Clifton <nickc@redhat.com> wrote:
>> >
>> > Hi Christophe,
>> >
>> > > Ping?
>> > >
>> > > https://sourceware.org/pipermail/binutils/2020-February/109942.html
>> >
>> > Oops - sorry - the patch is good.  Approved - please apply.
>> >
>>
>> Thanks!
>> Pushed as abf874aafe3d717573e4a48bf0e3c6334e666a55
>>
>> Christophe
>>
>> > Cheers
>> >   Nick
>> >

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-06-03 12:49 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-14 12:34 [PATCH] Add support for non-contiguous memory regions Christophe Lyon
2020-02-14 13:02 ` Tamar Christina
2020-02-14 13:54   ` Christophe Lyon
2020-02-19  7:19     ` Alan Modra
2020-02-19 12:28       ` Christophe Lyon
2020-02-19 22:23         ` Alan Modra
2020-02-20  4:37           ` Christophe Lyon
2020-02-20  8:15             ` Alan Modra
2020-02-20  9:00               ` Christophe Lyon
2020-02-28 17:31                 ` Christophe Lyon
2020-03-09 13:10                   ` Christophe Lyon
2020-03-13 14:21                     ` Nick Clifton
2020-03-13 14:46                       ` Christophe Lyon
2020-06-02 12:49                         ` Alexander Fedotov
2020-06-03 12:48                           ` Christophe Lyon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).