Add support for non-contiguous memory regions
authorChristophe Lyon <christophe.lyon@linaro.org>
Mon, 25 Nov 2019 08:55:37 +0000 (08:55 +0000)
committerChristophe Lyon <christophe.lyon@linaro.org>
Fri, 13 Mar 2020 14:44:45 +0000 (14:44 +0000)
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.

46 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/ecoff.c
bfd/elf32-arm.c
bfd/elf32-csky.c
bfd/elf32-hppa.c
bfd/elf32-m68hc11.c
bfd/elf32-m68hc12.c
bfd/elf32-metag.c
bfd/elf32-nios2.c
bfd/elf64-ppc.c
bfd/elflink.c
bfd/elfnn-aarch64.c
bfd/section.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/NEWS
ld/emultempl/armelf.em
ld/emultempl/xtensaelf.em
ld/ld.texi
ld/ldlang.c
ld/ldlex.h
ld/lexsup.c
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/non-contiguous-arm.d [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm.ld [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm.s [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm2.d [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm2.ld [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm3.d [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm3.ld [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm4.d [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm4.ld [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm5.d [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm5.ld [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm6.d [new file with mode: 0644]
ld/testsuite/ld-arm/non-contiguous-arm6.ld [new file with mode: 0644]
ld/testsuite/ld-elf/non-contiguous.d [new file with mode: 0644]
ld/testsuite/ld-elf/non-contiguous.ld [new file with mode: 0644]
ld/testsuite/ld-elf/non-contiguous.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/non-contiguous-powerpc.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld [new file with mode: 0644]
ld/testsuite/ld-powerpc/non-contiguous-powerpc.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/powerpc.exp

index 8b0909386242887218c2b5706dec7ed7a478afea..84bc1e116ba74d2f76fb16329a8a072a67007532 100644 (file)
@@ -1,3 +1,22 @@
+2020-03-13  Christophe Lyon  <christophe.lyon@linaro.org>
+
+       * 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.
+
 2020-03-13  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/24920
index 37114607b51521d51aecf36101e1b8e12efd027e..9859e514c19c402e9af3677911675e8739464bb6 100644 (file)
@@ -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
index 84eab99398339fa31aae67b68753ce184a212627..ce8eb89a57a0c4bd4d05599e0dc649e81f6daa30 100644 (file)
@@ -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.  */
index c899aeb8f6b3874eed404956ad882097bb16de01..e8b2ac4702ad6eec2271316461fa3d943866c088 100644 (file)
@@ -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;
index 6cf63f5e91f65e4e08eaa12e8ddacf63d50ceb04..8415f7c5ec875a50501eac78b52de6cd1feff6f5 100644 (file)
@@ -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;
index b1b0f8284c41f876e46bdc651f2bbe42bc07d76b..9760b751612b6dde409316e53b9d257f1e6622bd 100644 (file)
@@ -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
index 8d4d227a473b792b39cd74a5003f6fdb5c11e69d..3e12ae5e44031fd65399873574f0a406a6b4f08f 100644 (file)
@@ -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;
index e41b4c76236ca2db7a536cbd13dc7fe64004b6e9..a04efd84e0bd04cc861df1a85d92e4e11e0c5510 100644 (file)
@@ -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;
index 07e9856fa9060ffa33b2e473acc82f604df277c7..3f30d6dadd9e9afdef5a5b3fc55ef122384d712a 100644 (file)
@@ -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;
 
index 2fcfe6fd6c1957fcf04a1e8fc18e92ad6dd8ce6c..8c8bc0c8f8017d369c5c238bc69cd46230c0af67 100644 (file)
@@ -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;
 
index c804ab3d6af8c411c209acd0bc3b9b82d6a442fa..83eaadfb0d9559284d5842dcbb39357fe25f240b 100644 (file)
@@ -11362,6 +11362,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;
@@ -11887,6 +11912,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;
 
index 5852844498aa985fe2916f9a9def9809866ef50b..589550e11d288dd983d8b2db3cae5bbc6a57b72a 100644 (file)
@@ -10567,6 +10567,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
       /* If this symbol is defined in a section which we are
         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,
index ba3ad4546828feabc43f663dca0f6c6fbc90b3e1..b00b6c4818f9b2620849f5f91d2b7052bd1788b9 100644 (file)
@@ -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.  */
index 7de0a2d7a858b9b7e3b9948484886b9174bed388..eef118f3c3fd0e9e81e547d242c50b76f4428b05 100644 (file)
@@ -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
index 2fefb460c9538ee09ae2c7541b5df648c45659c8..45fedc40bbc0c8afb8ce7df405b7368a81aa8ef0 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-13  Christophe Lyon  <christophe.lyon@linaro.org>
+
+       * bfdlink.h (bfd_link_info): Add non_contiguous_regions and
+       non_contiguous_regions_warnings fields.
+
 2020-03-13  Christian Eggers  <ceggers@gmx.de>
 
        * bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to
index 40a6d4d40a6c1ac7a6739f9320dffc2f7ee2c2df..84b9dd7a0a0edf35c7d8bc9cfebe7a2802ae32ce 100644 (file)
@@ -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.  */
index 74d2f1b41fe60b2e7861d65a8e830d6f894e6ee8..e7b434623fb9a883c5c6418c084341d6f59ef244 100644 (file)
@@ -1,3 +1,47 @@
+2020-03-13  Christophe Lyon  <christophe.lyon@linaro.org>
+
+       * 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.
+
 2020-03-13  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/24920
diff --git a/ld/NEWS b/ld/NEWS
index 7734d23d5bb5034330de566c05e4059724540387..563af67a344480499797f49e43218c1cde88a868 100644 (file)
--- 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:
 
 * The ld check for "PHDR segment not covered by LOAD segment" is more
index efdcf5a2aa7b4d231eaede997bac09323746fb33..fb5bbf85f6f8f308b2fab645074dfff5c156877e 100644 (file)
@@ -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)
index 1aca7b77ace84c21a3ef9259a15ad3bfe386fca4..74bd11c6b00092ce08e0f626b358c5928bf60c7d 100644 (file)
@@ -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;
index 27343c798f39001fcae60306753fd94ed51a107e..9f562935bed06d67708e2cd72d276de5ec694f71 100644 (file)
@@ -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}
index 63f9d182eae416538ec9b2eda242d9cefb1577fb..8e56e8678fb16f0c87ac8062d3635ca92fb9a6f6 100644 (file)
@@ -2540,6 +2540,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;
     }
 
@@ -2553,7 +2558,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
@@ -4197,6 +4228,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)
            {
@@ -5119,11 +5156,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;
@@ -5155,6 +5208,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;
 
@@ -5162,6 +5251,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;
@@ -5448,10 +5545,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:
@@ -5885,7 +5986,7 @@ lang_size_sections_1
                  *relax = TRUE;
              }
            dot = size_input_section (prev, output_section_statement,
-                                     fill, dot);
+                                     fill, &removed, dot);
          }
          break;
 
@@ -5990,7 +6091,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;
 }
index 5287f19a7f6710ad10235d04edd7ae6b29e3be18..22b928d2d9049dbcd558eba94544fdf3e719e3b2 100644 (file)
@@ -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.  */
index 3d15cc491d566554e28f3febc59886641958384d..2597e2d6304a3414f63c8d87d152976eeb3f635e 100644 (file)
@@ -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;
index 44e599f4be3d3b5c80c7e57adb6c847f8b80f0e8..18177d19224f7d40c3c8832206615e758cb979af 100644 (file)
@@ -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 (file)
index 0000000..d0e5fab
--- /dev/null
@@ -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 (file)
index 0000000..a50621b
--- /dev/null
@@ -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 (file)
index 0000000..cdc8b00
--- /dev/null
@@ -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 (file)
index 0000000..af40e84
--- /dev/null
@@ -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 (file)
index 0000000..f13567e
--- /dev/null
@@ -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 (file)
index 0000000..6373922
--- /dev/null
@@ -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 (file)
index 0000000..81bb695
--- /dev/null
@@ -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 (file)
index 0000000..28417c0
--- /dev/null
@@ -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 (file)
index 0000000..1e0c376
--- /dev/null
@@ -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 (file)
index 0000000..dc85d1e
--- /dev/null
@@ -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 (file)
index 0000000..99c0234
--- /dev/null
@@ -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 (file)
index 0000000..605d846
--- /dev/null
@@ -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 (file)
index 0000000..6d6d6fe
--- /dev/null
@@ -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 (file)
index 0000000..9694bcf
--- /dev/null
@@ -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 (file)
index 0000000..fc72253
--- /dev/null
@@ -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 (file)
index 0000000..19bc2b1
--- /dev/null
@@ -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 (file)
index 0000000..858e353
--- /dev/null
@@ -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 (file)
index 0000000..744d246
--- /dev/null
@@ -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 (file)
index 0000000..e02b322
--- /dev/null
@@ -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 (file)
index 0000000..ff0e3fc
--- /dev/null
@@ -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.*
index 94b2fac6fbe12f3eaf81a9dba3f0e78ad8f1b263..84d7c9c42e3973b25a13da7f6f9d5b67867ef03c 100644 (file)
@@ -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"