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


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

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


Hi,

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

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

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

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

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

Thoughts?

Thanks,

Christophe
From 01087e85dc598ce34db800f217ac206bc2d8075e 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.
	* elflink.c (elf_link_input_bfd): Likewise.
	* emultempl/armelf.em (elf32_arm_add_stub_section): Add
	SEC_LINKER_CREATED flag.

	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.

Change-Id: Iac2f395b3a1fbea4b3a732ba5a9b847e10b4b2f0
---
 bfd/bfd-in2.h          |   9 ++-
 bfd/ecoff.c            |   6 +-
 bfd/elf32-arm.c        |  11 ++++
 bfd/elflink.c          |  12 ++++
 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 ++++
 12 files changed, 252 insertions(+), 9 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..a32d5d2 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5085,6 +5085,17 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 
   stub_bfd = stub_sec->owner;
 
+  /* 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();
+    }
+
   /* This is the address of the stub destination.  */
   sym_value = (stub_entry->target_value
 	       + stub_entry->target_section->output_offset
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/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

From 7298bda0d21c96f5db7fb62f623f8795718dd10d 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  | 41 +++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-elf/non-contiguous.ld | 34 +++++++++++++++++++++++++++++
 ld/testsuite/ld-elf/non-contiguous.s  | 21 ++++++++++++++++++
 3 files changed, 96 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..7a11443
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.d
@@ -0,0 +1,41 @@
+#name: non-contiguous
+#source: non-contiguous.s
+#as: -mlittle-endian
+#ld: --enable-non-contiguous-regions -T non-contiguous.ld -EL
+#objdump: -rdtsh
+#xfail: [is_generic]
+
+.*:     file format .*
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 \.raml         0000000c  1fff0000  1fff0000  00010000  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+  1 \.ramu         00000014  20000000  1fff000c  00020000  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+  2 \.ramz         0000003c  20040000  20000014  00030000  2\*\*0
+                  CONTENTS, ALLOC, LOAD, DATA
+SYMBOL TABLE:
+1fff0000 l    d  .raml	00000000 .raml
+20000000 l    d  .ramu	00000000 .ramu
+20040000 l    d  .ramz	00000000 .ramz
+00000000 l    df \*ABS\*	00000000 .*/non-contiguous.o
+00000002 l       \*ABS\*	00000000 ALIGN
+1fff000c g       .raml	00000000 _raml_end
+2004003c g       .ramz	00000000 _ramz_end
+20000000 g       .ramu	00000000 _rmau_start
+1fff0000 g       .raml	00000000 _rmal_start
+20000014 g       .ramu	00000000 _ramu_end
+20040000 g       .ramz	00000000 _rmaz_start
+
+
+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..50c98b4
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.ld
@@ -0,0 +1,34 @@
+/*
+ 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
+{
+   /DISCARD/ : { *(.ARM.attributes) }
+   .raml : AT ( ADDR (.text) + SIZEOF (.text) )
+   {  _rmal_start = . ;
+      *(.boot) ;
+      *(.data) *(.data.*) ;
+      _raml_end = . ;
+   } > RAML
+
+   .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+   {  _rmau_start = . ;
+      *(.data) *(.data.*) ;
+      _ramu_end = . ;
+   } > RAMU
+
+   .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+   {  _rmaz_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

From d29c3b8ded98f629044fa85e94b0862c47df308b 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

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

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

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

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

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


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