From: Christophe Lyon <christophe.lyon@linaro.org>
To: binutils <binutils@sourceware.org>
Subject: Re: [PATCH] Add support for non-contiguous memory regions
Date: Fri, 28 Feb 2020 17:31:00 -0000 [thread overview]
Message-ID: <CAKdteOZxihz00ZkPhbP96bLWkeni3LUH3EX0-axNNP2cS1RQbw@mail.gmail.com> (raw)
In-Reply-To: <CAKdteOYRurOfiL=P4ewNGFehTPSH8viM+=1yJBLYyezwKQm7-w@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5097 bytes --]
Hi,
Here is an updated patch.
Changes between v4 and v5:
* Added sanity checks for powerpc64 and xtensa
(--enable-non-contiguous-regions does not work with relaxation), to
emit an error message rather than crash
* Removed a bogus assert in size_input_section
* Added quotes around section names in error messages
* Updated tests:
- ld-arm/non-contiguous-arm[25] now pass on arm-nacl
- ld-arm/non-contiguous-arm[36] are now skipped on arm-nacl because
the stub code is different from the expected one and a dedicated test
didn't seem mandatory
- ld-arm/non-contiguous-arm4 updated expected error message
- ld-elf/non-contiguous: do not require little-endian, accept both
endiannesses, discard target-specific sections to make expected output
matching possible. Skip on xtensa where relaxation is enabled by
default and conflicts with the new option
- ld-powerpc/non-contiguous-powerpc: skip on powerpc64 (because the
error message is different)
- ld/powerpc/non-contiguous-powerpc64: new test, with the error
message expected on powerpc64
* Squashed all patches into one
Tested for non-regression on the list of 163 targets provided by Alan.
I left the error on mep-elf, because many other tests fails on that
target with the same error message (selected target format
'elf32-mep-little' unknown)
Christophe
On Thu, 20 Feb 2020 at 09:59, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
>
> On Thu, 20 Feb 2020 at 09:15, Alan Modra <amodra@gmail.com> wrote:
> >
> > On Thu, Feb 20, 2020 at 05:37:03AM +0100, Christophe Lyon wrote:
> > > Or should I just copy & paste that list from your email and
> > > for i in <that-list>
> > > do
> > > configure --target=$i
> > > make all check
> > > done
> >
> > Yes, more or less. No need to build gdb though for binutils changes,
> > unless you're messing with libbfd or libopcodes API. I build with
> > --disable-nls --enable-plugins \
> > --disable-gdb --disable-gdbserver --disable-sim --disable-readline \
> > --disable-libdecnumber --enable-obsolete --target=$i
> > Parallel builds work too, except for m68hc11 and m68hc12 which write
> > to source directories.
> >
> > I also build --enable-targets=all --enable-nls with a recent 64-bit
> > gcc, an older gcc, and with gcc -m32 to pick up any 32 bit problems.
> > My current target list is:
> >
> Thanks, I'm looking at all these targets, then. I'll update my patches
> as needed.
>
>
> > aarch64-elf
> > aarch64-linux
> > aarch64_be-linux-gnu_ilp32
> > alpha-dec-vms
> > alpha-linux
> > alpha-linuxecoff
> > alpha-netbsd
> > alpha-unknown-freebsd4.7
> > am33_2.0-linux
> > arc-elf
> > arc-linux-uclibc
> > arm-elf
> > arm-linuxeabi
> > arm-nacl
> > arm-netbsdelf
> > arm-nto
> > arm-pe
> > arm-symbianelf
> > arm-vxworks
> > arm-wince-pe
> > armeb-linuxeabi
> > avr-elf
> > bfin-elf
> > bfin-linux-uclibc
> > bpf-none
> > cr16-elf
> > cris-elf
> > cris-linux
> > crisv32-linux
> > crx-elf
> > csky-elf
> > csky-linux
> > d10v-elf
> > d30v-elf
> > dlx-elf
> > epiphany-elf
> > fr30-elf
> > frv-elf
> > frv-linux
> > ft32-elf
> > h8300-elf
> > h8300-linux
> > hppa-hp-hpux10
> > hppa-linux
> > hppa64-hp-hpux11.23
> > hppa64-linux
> > i386-bsd
> > i386-darwin
> > i386-lynxos
> > i586-linux
> > i686-nacl
> > i686-nto
> > i686-pc-beos
> > i686-pc-elf
> > i686-pe
> > i686-vxworks
> > ia64-elf
> > ia64-freebsd5
> > ia64-hpux
> > ia64-linux
> > ia64-netbsd
> > ia64-vms
> > ip2k-elf
> > iq2000-elf
> > lm32-elf
> > lm32-linux
> > m32c-elf
> > m32r-elf
> > m32r-linux
> > m68hc11-elf
> > m68hc12-elf
> > m68k-elf
> > m68k-linux
> > mcore-elf
> > mcore-pe
> > mep-elf
> > metag-linux
> > microblaze-elf
> > microblaze-linux
> > mips-linux
> > mips-sgi-irix6
> > mips-vxworks
> > mips64-linux
> > mips64-openbsd
> > mips64el-openbsd
> > mipsel-linux-gnu
> > mipsisa32el-linux
> > mipstx39-elf
> > mmix
> > mn10200-elf
> > mn10300-elf
> > moxie-elf
> > msp430-elf
> > mt-elf
> > nds32be-elf
> > nds32le-linux
> > nios2-linux
> > ns32k-netbsd
> > ns32k-pc532-mach
> > or1k-elf
> > or1k-linux
> > pdp11-dec-aout
> > pj-elf
> > powerpc-aix5.1
> > powerpc-aix5.2
> > powerpc-eabisim
> > powerpc-eabivle
> > powerpc-freebsd
> > powerpc-linux
> > powerpc-nto
> > powerpc-wrs-vxworks
> > powerpc64-freebsd
> > powerpc64-linux
> > powerpc64le-linux
> > powerpcle-cygwin
> > powerpcle-elf
> > pru-elf
> > riscv32-elf
> > riscv64-linux
> > rl78-elf
> > rs6000-aix4.3.3
> > rs6000-aix5.1
> > rs6000-aix5.2
> > rx-elf
> > s12z-elf
> > s390-linux
> > s390x-linux
> > score-elf
> > sh-linux
> > sh-nto
> > sh-pe
> > sh-rtems
> > sh-vxworks
> > shle-unknown-netbsdelf
> > sparc-elf
> > sparc-linux
> > sparc-sun-solaris2
> > sparc-vxworks
> > sparc64-linux
> > spu-elf
> > tic30-unknown-coff
> > tic4x-coff
> > tic54x-coff
> > tic6x-elf
> > tilegx-linux
> > tilepro-linux
> > v850-elf
> > vax-netbsdelf
> > visium-elf
> > wasm32
> > x86_64-cloudabi
> > x86_64-linux
> > x86_64-nacl
> > x86_64-pc-linux-gnux32
> > x86_64-rdos
> > x86_64-w64-mingw32
> > xc16x-elf
> > xgate-elf
> > xstormy16-elf
> > xtensa-elf
> > z80-coff
> > z80-elf
> > z8k-coff
> >
> > --
> > Alan Modra
> > Australia Development Lab, IBM
[-- Attachment #2: 0001-Add-support-for-non-contiguous-memory-regions.patch --]
[-- Type: text/x-patch, Size: 61044 bytes --]
From c76ce7778b90c533ca172731f99e2c2e80755e12 Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@linaro.org>
Date: Mon, 25 Nov 2019 08:55:37 +0000
Subject: [PATCH 1/1] Add support for non-contiguous memory regions
2020-01-06 Christophe Lyon <christophe.lyon@linaro.org>
bfd/
* bfd-in2.h: Regenerate.
* section.c (asection): Add already_assigned field.
(BFD_FAKE_SECTION): Add default initializer for it.
* ecoff.c (bfd_debug_section): Initialize already_assigned field.
* elf32-arm.c (arm_build_one_stub): Add support for
non_contiguous_regions.
* elf32-csky.c (csky_build_one_stub): Likewise.
* elf32-hppa.c (hppa_build_one_stub): Likewise.
* elf32-m68hc11.c (m68hc11_elf_build_one_stub): Likewise.
* elf32-m68hc12.c (m68hc12_elf_build_one_stub): Likewise.
* elf32-metag.c (metag_build_one_stub): Likewise.
* elf32-nios2.c (nios2_build_one_stub): Likewise.
* elf64-ppc.c (ppc_build_one_stub): Likewise.
(ppc_size_one_stub): Likewise.
* elfnn-aarch64.c (aarch64_build_one_stub): Likewise.
* elflink.c (elf_link_input_bfd): Likewise.
include/
* bfdlink.h (bfd_link_info): Add non_contiguous_regions and
non_contiguous_regions_warnings fields.
ld/
* ldlang.c (lang_add_section): Add support for
non_contiguous_regions.
(size_input_section): Likewise.
(lang_size_sections_1): Likewise.
(process_insert_statements): Likewise.
* ldlex.h (option_values): Add OPTION_NON_CONTIGUOUS_REGIONS and
OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS.
* lexsup.c (ld_options): Add entries for
--enable-non-contiguous-regions and
--enable-non-contiguous-regions-warnings.
(parse_args): Handle it.
* NEWS: Add --enable-non-contiguous-regions and
--enable-non-contiguous-regions-warnings.
* ld.texi: Add --enable-non-contiguous-regions and
--enable-non-contiguous-regions-warnings documentation.
* emultempl/armelf.em (elf32_arm_add_stub_section): Add
SEC_LINKER_CREATED flag.
* emultempl/xtensaelf.em (ld_build_required_section_dependence):
Emit an error when --enable-non-contiguous-regions is used.
* testsuite/ld-elf/non-contiguous.d: New.
* testsuite/ld-elf/non-contiguous.ld: New.
* testsuite/ld-elf/non-contiguous.s: New.
* testsuite/ld-arm/arm-elf.exp: Run the new tests.
* testsuite/ld-arm/arm-elf/non-contiguous-arm.s: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm.d: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm.ld: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm2.d: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm3.ld: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm3.d: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm3.ld: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm4.d: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm4.ld: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm5.d: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm5.ld: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm6.d: New.
* testsuite/ld-arm/arm-elf/non-contiguous-arm6.ld: New.
* testsuite/ld-powerpc/powerpc.exp: Run new tests.
* testsuite/ld-powerpc/non-contiguous-powerpc.d: New.
* testsuite/ld-powerpc/non-contiguous-powerpc.ld: New.
* testsuite/ld-powerpc/non-contiguous-powerpc.sd: New.
* testsuite/ld-powerpc/non-contiguous-powerpc64.d: New.
---
bfd/bfd-in2.h | 9 +-
bfd/ecoff.c | 6 +-
bfd/elf32-arm.c | 11 ++
bfd/elf32-csky.c | 11 ++
bfd/elf32-hppa.c | 31 +++++
bfd/elf32-m68hc11.c | 11 ++
bfd/elf32-m68hc12.c | 11 ++
bfd/elf32-metag.c | 15 ++-
bfd/elf32-nios2.c | 13 ++
bfd/elf64-ppc.c | 50 +++++++
bfd/elflink.c | 12 ++
bfd/elfnn-aarch64.c | 16 ++-
bfd/section.c | 9 +-
include/bfdlink.h | 8 ++
ld/NEWS | 3 +
ld/emultempl/armelf.em | 3 +-
ld/emultempl/xtensaelf.em | 6 +
ld/ld.texi | 42 ++++++
ld/ldlang.c | 145 ++++++++++++++++++++-
ld/ldlex.h | 2 +
ld/lexsup.c | 10 ++
ld/testsuite/ld-arm/arm-elf.exp | 7 +
ld/testsuite/ld-arm/non-contiguous-arm.d | 4 +
ld/testsuite/ld-arm/non-contiguous-arm.ld | 34 +++++
ld/testsuite/ld-arm/non-contiguous-arm.s | 35 +++++
ld/testsuite/ld-arm/non-contiguous-arm2.d | 77 +++++++++++
ld/testsuite/ld-arm/non-contiguous-arm2.ld | 33 +++++
ld/testsuite/ld-arm/non-contiguous-arm3.d | 83 ++++++++++++
ld/testsuite/ld-arm/non-contiguous-arm3.ld | 33 +++++
ld/testsuite/ld-arm/non-contiguous-arm4.d | 4 +
ld/testsuite/ld-arm/non-contiguous-arm4.ld | 34 +++++
ld/testsuite/ld-arm/non-contiguous-arm5.d | 77 +++++++++++
ld/testsuite/ld-arm/non-contiguous-arm5.ld | 34 +++++
ld/testsuite/ld-arm/non-contiguous-arm6.d | 77 +++++++++++
ld/testsuite/ld-arm/non-contiguous-arm6.ld | 33 +++++
ld/testsuite/ld-elf/non-contiguous.d | 29 +++++
ld/testsuite/ld-elf/non-contiguous.ld | 47 +++++++
ld/testsuite/ld-elf/non-contiguous.s | 21 +++
ld/testsuite/ld-powerpc/non-contiguous-powerpc.d | 5 +
ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld | 22 ++++
ld/testsuite/ld-powerpc/non-contiguous-powerpc.s | 8 ++
ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d | 5 +
ld/testsuite/ld-powerpc/powerpc.exp | 3 +
43 files changed, 1118 insertions(+), 11 deletions(-)
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm.d
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm.ld
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm.s
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm2.d
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm2.ld
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm3.d
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm3.ld
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm4.d
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm4.ld
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm5.d
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm5.ld
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm6.d
create mode 100644 ld/testsuite/ld-arm/non-contiguous-arm6.ld
create mode 100644 ld/testsuite/ld-elf/non-contiguous.d
create mode 100644 ld/testsuite/ld-elf/non-contiguous.ld
create mode 100644 ld/testsuite/ld-elf/non-contiguous.s
create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
create mode 100644 ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 2d56fda..7e4d1db 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1192,6 +1192,10 @@ typedef struct bfd_section
struct bfd_section *s;
const char *linked_to_symbol_name;
} map_head, map_tail;
+ /* Points to the output section this section is already assigned to, if any.
+ This is used when support for non-contiguous memory regions is enabled. */
+ struct bfd_section *already_assigned;
+
} asection;
/* Relax table contains information about instructions which can
@@ -1373,7 +1377,10 @@ discarded_section (const asection *sec)
(struct bfd_symbol *) SYM, &SEC.symbol, \
\
/* map_head, map_tail */ \
- { NULL }, { NULL } \
+ { NULL }, { NULL }, \
+ \
+ /* already_assigned */ \
+ NULL \
}
/* We use a macro to initialize the static asymbol structures because
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 9e2efac..592a225 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -78,8 +78,10 @@ static asection bfd_debug_section =
NULL,
/* symbol_ptr_ptr, */
NULL,
- /* map_head, map_tail */
- { NULL }, { NULL }
+ /* map_head, map_tail, */
+ { NULL }, { NULL },
+ /* already_assigned */
+ NULL,
};
/* Create an ECOFF object. */
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index a35dc99..0bcafe4 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5064,6 +5064,17 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
info = (struct bfd_link_info *) in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
globals = elf32_arm_hash_table (info);
if (globals == NULL)
return FALSE;
diff --git a/bfd/elf32-csky.c b/bfd/elf32-csky.c
index f91d05b..ed8ab37 100644
--- a/bfd/elf32-csky.c
+++ b/bfd/elf32-csky.c
@@ -3621,6 +3621,17 @@ csky_build_one_stub (struct bfd_hash_entry *gen_entry,
stub_entry = (struct elf32_csky_stub_hash_entry *)gen_entry;
info = (struct bfd_link_info *) in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
globals = csky_elf_hash_table (info);
if (globals == NULL)
return FALSE;
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index b1b0f82..9760b75 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -731,6 +731,17 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
switch (hsh->stub_type)
{
case hppa_stub_long_branch:
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (hsh->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ hsh->target_section);
+ abort();
+ }
+
/* Create the long branch. A long branch is formed with "ldil"
loading the upper bits of the target address into a register,
then branching with "be" which adds in the lower bits.
@@ -751,6 +762,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
break;
case hppa_stub_long_branch_shared:
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (hsh->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign %pA to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ hsh->target_section);
+ abort();
+ }
/* Branches are relative. This is where we are going to. */
sym_value = (hsh->target_value
+ hsh->target_section->output_offset
@@ -823,6 +844,16 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
break;
case hppa_stub_export:
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (hsh->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign %pA to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ hsh->target_section);
+ abort();
+ }
/* Branches are relative. This is where we are going to. */
sym_value = (hsh->target_value
+ hsh->target_section->output_offset
diff --git a/bfd/elf32-m68hc11.c b/bfd/elf32-m68hc11.c
index 8d4d227..3e12ae5 100644
--- a/bfd/elf32-m68hc11.c
+++ b/bfd/elf32-m68hc11.c
@@ -415,6 +415,17 @@ m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
info = (struct bfd_link_info *) in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
htab = m68hc11_elf_hash_table (info);
if (htab == NULL)
return FALSE;
diff --git a/bfd/elf32-m68hc12.c b/bfd/elf32-m68hc12.c
index e41b4c7..a04efd8 100644
--- a/bfd/elf32-m68hc12.c
+++ b/bfd/elf32-m68hc12.c
@@ -535,6 +535,17 @@ m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
info = (struct bfd_link_info *) in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
htab = m68hc11_elf_hash_table (info);
stub_sec = stub_entry->stub_sec;
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 07e9856..3f30d6d 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -3459,7 +3459,7 @@ metag_type_of_stub (asection *input_sec,
#define MOV_PC_A0_3 0xa3180ca0
static bfd_boolean
-metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_UNUSED)
+metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
{
struct elf_metag_stub_hash_entry *hsh;
asection *stub_sec;
@@ -3467,9 +3467,22 @@ metag_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
bfd_byte *loc;
bfd_vma sym_value;
int size;
+ struct bfd_link_info *info;
/* Massage our args to the form they really have. */
hsh = (struct elf_metag_stub_hash_entry *) gen_entry;
+ info = (struct bfd_link_info *) in_arg;
+
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (hsh->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ hsh->target_section);
+ abort();
+ }
stub_sec = hsh->stub_sec;
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index fd05fb0..cba9270 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -2490,7 +2490,20 @@ nios2_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
= (struct elf32_nios2_stub_hash_entry *) gen_entry;
asection *stub_sec = hsh->stub_sec;
bfd_vma sym_value;
+ struct bfd_link_info *info;
+
+ info = (struct bfd_link_info *) in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (hsh->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ hsh->target_section);
+ abort();
+ }
/* Make a note of the offset within the stubs for this entry. */
hsh->stub_offset = stub_sec->size;
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 1ea4c40..24671d4 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -11349,6 +11349,31 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
info = in_arg;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section != NULL
+ && stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
+ /* Same for the group. */
+ if (stub_entry->group->stub_sec != NULL
+ && stub_entry->group->stub_sec->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign group %pA target %pA to an "
+ "output section. Retry without "
+ "--enable-non-contiguous-regions.\n"),
+ stub_entry->group->stub_sec,
+ stub_entry->target_section);
+ abort();
+ }
+
htab = ppc_hash_table (info);
if (htab == NULL)
return FALSE;
@@ -11874,6 +11899,31 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
if (htab == NULL)
return FALSE;
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section != NULL
+ && stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign %pA to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
+ /* Same for the group. */
+ if (stub_entry->group->stub_sec != NULL
+ && stub_entry->group->stub_sec->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign group %pA target %pA to an "
+ "output section. Retry without "
+ "--enable-non-contiguous-regions.\n"),
+ stub_entry->group->stub_sec,
+ stub_entry->target_section);
+ abort();
+ }
+
/* Make a note of the offset within the stubs for this entry. */
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 8e7ae2a..a8f55a0 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10561,6 +10561,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
discarding, we don't need to keep it. */
if (isym->st_shndx != SHN_UNDEF
&& isym->st_shndx < SHN_LORESERVE
+ && isec->output_section == NULL
+ && flinfo->info->non_contiguous_regions
+ && flinfo->info->non_contiguous_regions_warnings)
+ {
+ _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+ "discards section `%s' from '%s'\n"),
+ isec->name, isec->owner->filename);
+ continue;
+ }
+
+ if (isym->st_shndx != SHN_UNDEF
+ && isym->st_shndx < SHN_LORESERVE
&& bfd_section_removed_from_list (output_bfd,
isec->output_section))
continue;
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 2191b5d..092a06b 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -3278,7 +3278,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name,
static bfd_boolean
aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
- void *in_arg ATTRIBUTE_UNUSED)
+ void *in_arg)
{
struct elf_aarch64_stub_hash_entry *stub_entry;
asection *stub_sec;
@@ -3291,10 +3291,24 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
unsigned int template_size;
const uint32_t *template;
unsigned int i;
+ struct bfd_link_info *info;
/* Massage our args to the form they really have. */
stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
+ info = (struct bfd_link_info *) in_arg;
+
+ /* Fail if the target section could not be assigned to an output
+ section. The user should fix his linker script. */
+ if (stub_entry->target_section->output_section == NULL
+ && info->non_contiguous_regions)
+ {
+ _bfd_error_handler (_("Could not assign '%pA' to an output section. "
+ "Retry without --enable-non-contiguous-regions.\n"),
+ stub_entry->target_section);
+ abort();
+ }
+
stub_sec = stub_entry->stub_sec;
/* Make a note of the offset within the stubs for this entry. */
diff --git a/bfd/section.c b/bfd/section.c
index 7de0a2d..eef118f 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -551,6 +551,10 @@ CODE_FRAGMENT
. struct bfd_section *s;
. const char *linked_to_symbol_name;
. } map_head, map_tail;
+. {* Points to the output section this section is already assigned to, if any.
+. This is used when support for non-contiguous memory regions is enabled. *}
+. struct bfd_section *already_assigned;
+.
.} asection;
.
.{* Relax table contains information about instructions which can
@@ -732,7 +736,10 @@ CODE_FRAGMENT
. (struct bfd_symbol *) SYM, &SEC.symbol, \
. \
. {* map_head, map_tail *} \
-. { NULL }, { NULL } \
+. { NULL }, { NULL }, \
+. \
+. {* already_assigned *} \
+. NULL \
. }
.
.{* We use a macro to initialize the static asymbol structures because
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 8d85530..529ea6e 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -501,6 +501,14 @@ struct bfd_link_info
/* TRUE if "-Map map" is passed to linker. */
unsigned int has_map_file : 1;
+ /* TRUE if "--enable-non-contiguous-regions" is passed to the
+ linker. */
+ unsigned int non_contiguous_regions : 1;
+
+ /* TRUE if "--enable-non-contiguous-regions-warnings" is passed to
+ the linker. */
+ unsigned int non_contiguous_regions_warnings : 1;
+
/* Char that may appear as the first char of a symbol, but should be
skipped (like symbol_leading_char) when looking up symbols in
wrap_hash. Used by PowerPC Linux for 'dot' symbols. */
diff --git a/ld/NEWS b/ld/NEWS
index f659ccf..2611a3e 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add command-line options --enable-non-contiguous-regions and
+ --enable-non-contiguous-regions-warnings.
+
Changes in 2.34:
* cr16c support removed.
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index efdcf5a..fb5bbf8 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -227,7 +227,8 @@ elf32_arm_add_stub_section (const char * stub_sec_name,
struct hook_stub_info info;
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
- | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+ | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP
+ | SEC_LINKER_CREATED);
stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
stub_sec_name, flags);
if (stub_sec == NULL)
diff --git a/ld/emultempl/xtensaelf.em b/ld/emultempl/xtensaelf.em
index 1aca7b7..74bd11c 100644
--- a/ld/emultempl/xtensaelf.em
+++ b/ld/emultempl/xtensaelf.em
@@ -1224,6 +1224,12 @@ ld_build_required_section_dependence (lang_statement_union_type *s)
{
lang_statement_union_type *l = iter_stack_current (&stack);
+ if (l == NULL && link_info.non_contiguous_regions)
+ {
+ einfo (_("Relaxation not supported with --enable-non-contiguous-regions.\n"));
+ abort();
+ }
+
if (l->header.type == lang_input_section_enum)
{
lang_input_section_type *input;
diff --git a/ld/ld.texi b/ld/ld.texi
index 9bb3d55..07933b2 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -459,6 +459,48 @@ will contain a colon separated list of audit interfaces to use. This
option is only meaningful on ELF platforms supporting the rtld-audit interface.
The -P option is provided for Solaris compatibility.
+@kindex --enable-non-contiguous-regions
+@item --enable-non-contiguous-regions
+This option avoids generating an error if an input section does not
+fit a matching output section. The linker tries to allocate the input
+section to subseque nt matching output sections, and generates an
+error only if no output section is large enough. This is useful when
+several non-contiguous memory regions are available and the input
+section does not require a particular one. The order in which input
+sections are evaluated does not change, for instance:
+
+@smallexample
+ MEMORY @{
+ MEM1 (rwx) : ORIGIN : 0x1000, LENGTH = 0x14
+ MEM2 (rwx) : ORIGIN : 0x1000, LENGTH = 0x40
+ MEM3 (rwx) : ORIGIN : 0x2000, LENGTH = 0x40
+ @}
+ SECTIONS @{
+ mem1 : @{ *(.data.*); @} > MEM1
+ mem2 : @{ *(.data.*); @} > MEM2
+ mem3 : @{ *(.data.*); @} > MEM2
+ @}
+
+ with input sections:
+ .data.1: size 8
+ .data.2: size 0x10
+ .data.3: size 4
+
+ results in .data.1 affected to mem1, and .data.2 and .data.3
+ affected to mem2, even though .data.3 would fit in mem3.
+@end smallexample
+
+This option is incompatible with INSERT statements because it changes
+the way input sections are mapped to output sections.
+
+@kindex --enable-non-contiguous-regions-warnings
+@item --enable-non-contiguous-regions-warnings
+This option enables warnings when
+@code{--enable-non-contiguous-regions} allows possibly unexpected
+matches in sections mapping, potentially leading to silently
+discarding a section instead of failing because it does not fit any
+output region.
+
@cindex entry point, from command line
@kindex -e @var{entry}
@kindex --entry=@var{entry}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 528ed22..83d42a6 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2537,6 +2537,11 @@ lang_add_section (lang_statement_list_type *ptr,
/* This prevents future calls from assigning this section. */
section->output_section = bfd_abs_section_ptr;
}
+ else if (link_info.non_contiguous_regions_warnings)
+ einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
+ "section `%pA' from '%pB' match /DISCARD/ clause.\n"),
+ NULL, section, section->owner);
+
return;
}
@@ -2550,7 +2555,33 @@ lang_add_section (lang_statement_list_type *ptr,
}
if (section->output_section != NULL)
- return;
+ {
+ if (!link_info.non_contiguous_regions)
+ return;
+
+ /* SECTION has already been handled in a special way
+ (eg. LINK_ONCE): skip it. */
+ if (bfd_is_abs_section (section->output_section))
+ return;
+
+ /* Already assigned to the same output section, do not process
+ it again, to avoid creating loops between duplicate sections
+ later. */
+ if (section->output_section == output->bfd_section)
+ return;
+
+ if (link_info.non_contiguous_regions_warnings && output->bfd_section)
+ einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
+ "change behaviour for section `%pA' from '%pB' (assigned to "
+ "%pA, but additional match: %pA)\n"),
+ NULL, section, section->owner, section->output_section,
+ output->bfd_section);
+
+ /* SECTION has already been assigned to an output section, but
+ the user allows it to be mapped to another one in case it
+ overflows. We'll later update the actual output section in
+ size_input_section as appropriate. */
+ }
/* We don't copy the SEC_NEVER_LOAD flag from an input section
to an output section, because we want to be able to include a
@@ -4194,6 +4225,12 @@ process_insert_statements (lang_statement_union_type **start)
lang_statement_union_type **ptr;
lang_statement_union_type *first;
+ if (link_info.non_contiguous_regions)
+ {
+ einfo (_("warning: INSERT statement in linker script is "
+ "incompatible with --enable-non-contiguous-regions.\n"));
+ }
+
where = lang_output_section_find (i->where);
if (where != NULL && i->is_before)
{
@@ -5116,11 +5153,27 @@ size_input_section
(lang_statement_union_type **this_ptr,
lang_output_section_statement_type *output_section_statement,
fill_type *fill,
+ bfd_boolean *removed,
bfd_vma dot)
{
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
asection *o = output_section_statement->bfd_section;
+ *removed = 0;
+
+ if (link_info.non_contiguous_regions)
+ {
+ /* If the input section I has already been successfully assigned
+ to an output section other than O, don't bother with it and
+ let the caller remove it from the list. Keep processing in
+ case we have already handled O, because the repeated passes
+ have reinitialized its size. */
+ if (i->already_assigned && i->already_assigned != o)
+ {
+ *removed = 1;
+ return dot;
+ }
+ }
if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
i->output_offset = i->vma - o->vma;
@@ -5152,6 +5205,42 @@ size_input_section
dot += alignment_needed;
}
+ if (link_info.non_contiguous_regions)
+ {
+ /* If I would overflow O, let the caller remove I from the
+ list. */
+ if (output_section_statement->region)
+ {
+ bfd_vma end = output_section_statement->region->origin
+ + output_section_statement->region->length;
+
+ if (dot + TO_ADDR (i->size) > end)
+ {
+ if (i->flags & SEC_LINKER_CREATED)
+ {
+ einfo (_("Output section '%s' not large enough for the "
+ "linker-created stubs section '%s'.\n"),
+ i->output_section->name, i->name);
+ abort();
+ }
+
+ if (i->rawsize && i->rawsize != i->size)
+ {
+ einfo (_("Relaxation not supported with "
+ "--enable-non-contiguous-regions (section '%s' "
+ "would overflow '%s' after it changed size).\n"),
+ i->name, i->output_section->name);
+ abort();
+ }
+
+ *removed = 1;
+ dot = end;
+ i->output_section = NULL;
+ return dot;
+ }
+ }
+ }
+
/* Remember where in the output section this input section goes. */
i->output_offset = dot - o->vma;
@@ -5159,6 +5248,14 @@ size_input_section
dot += TO_ADDR (i->size);
if (!(o->flags & SEC_FIXED_SIZE))
o->size = TO_SIZE (dot - o->vma);
+
+ if (link_info.non_contiguous_regions)
+ {
+ /* Record that I was successfully assigned to O, and update
+ its actual output section too. */
+ i->already_assigned = o;
+ i->output_section = o;
+ }
}
return dot;
@@ -5445,10 +5542,14 @@ lang_size_sections_1
bfd_boolean check_regions)
{
lang_statement_union_type *s;
+ lang_statement_union_type *prev_s = NULL;
+ bfd_boolean removed_prev_s = FALSE;
/* Size up the sections from their constituent parts. */
- for (s = *prev; s != NULL; s = s->header.next)
+ for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
{
+ bfd_boolean removed=FALSE;
+
switch (s->header.type)
{
case lang_output_section_statement_enum:
@@ -5874,7 +5975,7 @@ lang_size_sections_1
*relax = TRUE;
}
dot = size_input_section (prev, output_section_statement,
- fill, dot);
+ fill, &removed, dot);
}
break;
@@ -5979,7 +6080,43 @@ lang_size_sections_1
FAIL ();
break;
}
- prev = &s->header.next;
+
+ /* If an input section doesn't fit in the current output
+ section, remove it from the list. Handle the case where we
+ have to remove an input_section statement here: there is a
+ special case to remove the first element of the list. */
+ if (link_info.non_contiguous_regions && removed)
+ {
+ /* If we removed the first element during the previous
+ iteration, override the loop assignment of prev_s. */
+ if (removed_prev_s)
+ prev_s = NULL;
+
+ if (prev_s)
+ {
+ /* If there was a real previous input section, just skip
+ the current one. */
+ prev_s->header.next=s->header.next;
+ s = prev_s;
+ removed_prev_s = FALSE;
+ }
+ else
+ {
+ /* Remove the first input section of the list. */
+ *prev = s->header.next;
+ removed_prev_s = TRUE;
+ }
+
+ /* Move to next element, unless we removed the head of the
+ list. */
+ if (!removed_prev_s)
+ prev = &s->header.next;
+ }
+ else
+ {
+ prev = &s->header.next;
+ removed_prev_s = FALSE;
+ }
}
return dot;
}
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 5287f19..22b928d 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -150,6 +150,8 @@ enum option_values
OPTION_FORCE_GROUP_ALLOCATION,
OPTION_PRINT_MAP_DISCARDED,
OPTION_NO_PRINT_MAP_DISCARDED,
+ OPTION_NON_CONTIGUOUS_REGIONS,
+ OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS,
};
/* The initial parser states. */
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 3d15cc4..2597e2d 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -122,6 +122,10 @@ static const struct ld_option ld_options[] =
'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
{ {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
'\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
+ { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS},
+ '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES },
+ { {"enable-non-contiguous-regions-warnings", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS},
+ '\0', NULL, N_("Enable warnings when --enable-non-contiguous-regions may cause unexpected behaviour"), TWO_DASHES },
{ {"EB", no_argument, NULL, OPTION_EB},
'\0', NULL, N_("Link big-endian objects"), ONE_DASH },
{ {"EL", no_argument, NULL, OPTION_EL},
@@ -845,6 +849,12 @@ parse_args (unsigned argc, char **argv)
case OPTION_NO_EXPORT_DYNAMIC:
link_info.export_dynamic = FALSE;
break;
+ case OPTION_NON_CONTIGUOUS_REGIONS:
+ link_info.non_contiguous_regions = TRUE;
+ break;
+ case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
+ link_info.non_contiguous_regions_warnings = TRUE;
+ break;
case 'e':
lang_add_entry (optarg, TRUE);
break;
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 44e599f..18177d1 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -1261,3 +1261,10 @@ set arm_unwind_tests {
"unwind-mix"}
}
run_ld_link_tests $arm_unwind_tests
+
+run_dump_test "non-contiguous-arm"
+run_dump_test "non-contiguous-arm2"
+run_dump_test "non-contiguous-arm3"
+run_dump_test "non-contiguous-arm4"
+run_dump_test "non-contiguous-arm5"
+run_dump_test "non-contiguous-arm6"
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm.d b/ld/testsuite/ld-arm/non-contiguous-arm.d
new file mode 100644
index 0000000..d0e5fab
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm.d
@@ -0,0 +1,4 @@
+#name: non-contiguous-arm
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm.ld
+# error: \A.*Could not assign '.code.4' to an output section. Retry without --enable-non-contiguous-regions.*\Z
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm.ld b/ld/testsuite/ld-arm/non-contiguous-arm.ld
new file mode 100644
index 0000000..a50621b
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm.ld
@@ -0,0 +1,34 @@
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu
+ section .code.4 too large to fit
+ expect an error about .code.4
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+ RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040
+ RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00040
+}
+
+SECTIONS
+{
+ .raml :
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.code) *(.code.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.code) *(.code.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.code) *(.code.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm.s b/ld/testsuite/ld-arm/non-contiguous-arm.s
new file mode 100644
index 0000000..cdc8b00
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm.s
@@ -0,0 +1,35 @@
+ .syntax unified
+ .section .code.1, "ax", %progbits
+ .arm
+ # Fit in RAML
+ .global code1
+ .type code1, %function
+code1:
+ nop
+ nop
+ bl code2
+
+ .section .code.2, "ax", %progbits
+ # Fit in RAML
+ .global code2
+ .type code2, %function
+code2:
+ nop
+ nop
+ bl code3
+
+ .section .code.3, "ax", %progbits
+ # Fit in RAMU
+ .global code3
+ .type code3, %function
+code3:
+ nop
+ bl code4
+
+ .section .code.4, "ax", %progbits
+ # Fit in RAMZ
+ .global code4
+ .type code4, %function
+code4:
+$a:
+ .fill 20, 4, 0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm2.d b/ld/testsuite/ld-arm/non-contiguous-arm2.d
new file mode 100644
index 0000000..af40e84
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm2.d
@@ -0,0 +1,77 @@
+#name: non-contiguous-arm2
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm2.ld
+#objdump: -rdth
+#xfail: [is_generic]
+
+.*: file format elf32-(little|big)arm.*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 \.raml 00000018 1fff0000 1fff0000 00010000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 1 \.ramu 00000008 20000000 1fff0018 00020000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 2 \.ramz 00000050 20040000 20000008 00030000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 3 .ARM.attributes 00000012 00000000 00000000 .* 2\*\*0
+ CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l d .raml 00000000 .raml
+20000000 l d .ramu 00000000 .ramu
+20040000 l d .ramz 00000000 .ramz
+00000000 l d .ARM.attributes 00000000 .ARM.attributes
+00000000 l df \*ABS\* 00000000 .*/non-contiguous-arm.o
+1fff0018 g .raml 00000000 _raml_end
+20000000 g .ramu 00000000 _ramu_start
+1fff000c g F .raml 00000000 code2
+20040000 g .ramz 00000000 _ramz_start
+1fff0000 g .raml 00000000 _raml_start
+20000000 g F .ramu 00000000 code3
+1fff0000 g F .raml 00000000 code1
+20040050 g .ramz 00000000 _ramz_end
+20040000 g F .ramz 00000000 code4
+20000008 g .ramu 00000000 _ramu_end
+
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000: e1a00000 nop ; \(mov r0, r0\)
+1fff0004: e1a00000 nop ; \(mov r0, r0\)
+1fff0008: ebffffff bl 1fff000c \<code2\>
+
+1fff000c \<code2\>:
+1fff000c: e1a00000 nop ; \(mov r0, r0\)
+1fff0010: e1a00000 nop ; \(mov r0, r0\)
+1fff0014: eb003ff9 bl 20000000 \<code3\>
+
+Disassembly of section .ramu:
+
+20000000 \<code3\>:
+20000000: e1a00000 nop ; \(mov r0, r0\)
+20000004: eb00fffd bl 20040000 \<code4\>
+
+Disassembly of section .ramz:
+
+20040000 \<code4\>:
+20040000: e1a00000 .word 0xe1a00000
+20040004: e1a00000 .word 0xe1a00000
+20040008: e1a00000 .word 0xe1a00000
+2004000c: e1a00000 .word 0xe1a00000
+20040010: e1a00000 .word 0xe1a00000
+20040014: e1a00000 .word 0xe1a00000
+20040018: e1a00000 .word 0xe1a00000
+2004001c: e1a00000 .word 0xe1a00000
+20040020: e1a00000 .word 0xe1a00000
+20040024: e1a00000 .word 0xe1a00000
+20040028: e1a00000 .word 0xe1a00000
+2004002c: e1a00000 .word 0xe1a00000
+20040030: e1a00000 .word 0xe1a00000
+20040034: e1a00000 .word 0xe1a00000
+20040038: e1a00000 .word 0xe1a00000
+2004003c: e1a00000 .word 0xe1a00000
+20040040: e1a00000 .word 0xe1a00000
+20040044: e1a00000 .word 0xe1a00000
+20040048: e1a00000 .word 0xe1a00000
+2004004c: e1a00000 .word 0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm2.ld b/ld/testsuite/ld-arm/non-contiguous-arm2.ld
new file mode 100644
index 0000000..f13567e
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm2.ld
@@ -0,0 +1,33 @@
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu and does not need a farcall stub to jump to code4
+ section .code.4 fits in .ramz
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+ RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008
+ RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+ .raml :
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.code) *(.code.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.code) *(.code.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.code) *(.code.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm3.d b/ld/testsuite/ld-arm/non-contiguous-arm3.d
new file mode 100644
index 0000000..6373922
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm3.d
@@ -0,0 +1,83 @@
+#name: non-contiguous-arm3
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm3.ld
+#objdump: -rdth
+#xfail: [is_generic]
+#skip: arm*nacl
+
+.*: file format elf32-(little|big)arm
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 \.raml 00000018 1fff0000 1fff0000 00010000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 1 \.ramu 00000010 20000000 1fff0018 00020000 2\*\*3
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 2 \.ramz 00000050 30040000 20000010 00030000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 3 .ARM.attributes 00000012 00000000 00000000 00030050 2\*\*0
+ CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l d .raml 00000000 .raml
+20000000 l d .ramu 00000000 .ramu
+30040000 l d .ramz 00000000 .ramz
+00000000 l d .ARM.attributes 00000000 .ARM.attributes
+00000000 l df \*ABS\* 00000000 .*/non-contiguous-arm.o
+20000008 l F .ramu 00000008 __code4_veneer
+1fff0018 g .raml 00000000 _raml_end
+20000000 g .ramu 00000000 _ramu_start
+1fff000c g F .raml 00000000 code2
+30040000 g .ramz 00000000 _ramz_start
+1fff0000 g .raml 00000000 _raml_start
+20000000 g F .ramu 00000000 code3
+1fff0000 g F .raml 00000000 code1
+30040050 g .ramz 00000000 _ramz_end
+30040000 g F .ramz 00000000 code4
+20000010 g .ramu 00000000 _ramu_end
+
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000: e1a00000 nop ; \(mov r0, r0\)
+1fff0004: e1a00000 nop ; \(mov r0, r0\)
+1fff0008: ebffffff bl 1fff000c \<code2\>
+
+1fff000c \<code2\>:
+1fff000c: e1a00000 nop ; \(mov r0, r0\)
+1fff0010: e1a00000 nop ; \(mov r0, r0\)
+1fff0014: eb003ff9 bl 20000000 \<code3\>
+
+Disassembly of section .ramu:
+
+20000000 \<code3\>:
+20000000: e1a00000 nop ; \(mov r0, r0\)
+20000004: ebffffff bl 20000008 \<__code4_veneer\>
+
+20000008 \<__code4_veneer\>:
+20000008: e51ff004 ldr pc, \[pc, #-4\] ; 2000000c \<__code4_veneer\+0x4\>
+2000000c: 30040000 .word 0x30040000
+
+Disassembly of section .ramz:
+
+30040000 \<code4\>:
+30040000: e1a00000 .word 0xe1a00000
+30040004: e1a00000 .word 0xe1a00000
+30040008: e1a00000 .word 0xe1a00000
+3004000c: e1a00000 .word 0xe1a00000
+30040010: e1a00000 .word 0xe1a00000
+30040014: e1a00000 .word 0xe1a00000
+30040018: e1a00000 .word 0xe1a00000
+3004001c: e1a00000 .word 0xe1a00000
+30040020: e1a00000 .word 0xe1a00000
+30040024: e1a00000 .word 0xe1a00000
+30040028: e1a00000 .word 0xe1a00000
+3004002c: e1a00000 .word 0xe1a00000
+30040030: e1a00000 .word 0xe1a00000
+30040034: e1a00000 .word 0xe1a00000
+30040038: e1a00000 .word 0xe1a00000
+3004003c: e1a00000 .word 0xe1a00000
+30040040: e1a00000 .word 0xe1a00000
+30040044: e1a00000 .word 0xe1a00000
+30040048: e1a00000 .word 0xe1a00000
+3004004c: e1a00000 .word 0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm3.ld b/ld/testsuite/ld-arm/non-contiguous-arm3.ld
new file mode 100644
index 0000000..81bb695
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm3.ld
@@ -0,0 +1,33 @@
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu even with a farcall stub to jump to code4
+ section .code.4 fits in .ramz
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+ RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010
+ RAMZ (rwx) : ORIGIN = 0x30040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+ .raml :
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.code) *(.code.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.code) *(.code.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.code) *(.code.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm4.d b/ld/testsuite/ld-arm/non-contiguous-arm4.d
new file mode 100644
index 0000000..28417c0
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm4.d
@@ -0,0 +1,4 @@
+#name: non-contiguous-arm4
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm4.ld
+# error: \AOutput section '.ramu' not large enough for the linker-created stubs section '.code.3.__stub'.*\Z
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm4.ld b/ld/testsuite/ld-arm/non-contiguous-arm4.ld
new file mode 100644
index 0000000..1e0c376
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm4.ld
@@ -0,0 +1,34 @@
+/*
+ sections .code.1 and .code.2 fit in .raml
+ section .code.3 fits in .ramu but not its farcall stub to jump to code4
+ section .code.4 fits in .ramz
+ expect an error about .code.3
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x0001c
+ RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008
+ RAMZ (rwx) : ORIGIN = 0x30040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+ .raml :
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.code) *(.code.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.code) *(.code.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.code) *(.code.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm5.d b/ld/testsuite/ld-arm/non-contiguous-arm5.d
new file mode 100644
index 0000000..dc85d1e
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm5.d
@@ -0,0 +1,77 @@
+#name: non-contiguous-arm5
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm5.ld
+#objdump: -rdth
+#xfail: [is_generic]
+
+.*: file format elf32-(little|big)arm.*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 \.raml 0000000c 1fff0000 1fff0000 00010000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 1 \.ramu 00000014 20000000 1fff000c 00020000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 2 \.ramz 00000050 20040000 20000014 00030000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 3 .ARM.attributes 00000012 00000000 00000000 .* 2\*\*0
+ CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l d .raml 00000000 .raml
+20000000 l d .ramu 00000000 .ramu
+20040000 l d .ramz 00000000 .ramz
+00000000 l d .ARM.attributes 00000000 .ARM.attributes
+00000000 l df \*ABS\* 00000000 .*/non-contiguous-arm.o
+1fff000c g .raml 00000000 _raml_end
+20000000 g .ramu 00000000 _ramu_start
+20000000 g F .ramu 00000000 code2
+20040000 g .ramz 00000000 _ramz_start
+1fff0000 g .raml 00000000 _raml_start
+2000000c g F .ramu 00000000 code3
+1fff0000 g F .raml 00000000 code1
+20040050 g .ramz 00000000 _ramz_end
+20040000 g F .ramz 00000000 code4
+20000014 g .ramu 00000000 _ramu_end
+
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000: e1a00000 nop ; \(mov r0, r0\)
+1fff0004: e1a00000 nop ; \(mov r0, r0\)
+1fff0008: eb003ffc bl 20000000 \<code2\>
+
+Disassembly of section .ramu:
+
+20000000 \<code2\>:
+20000000: e1a00000 nop ; \(mov r0, r0\)
+20000004: e1a00000 nop ; \(mov r0, r0\)
+20000008: ebffffff bl 2000000c \<code3\>
+
+2000000c \<code3\>:
+2000000c: e1a00000 nop ; \(mov r0, r0\)
+20000010: eb00fffa bl 20040000 \<code4\>
+
+Disassembly of section .ramz:
+
+20040000 \<code4\>:
+20040000: e1a00000 .word 0xe1a00000
+20040004: e1a00000 .word 0xe1a00000
+20040008: e1a00000 .word 0xe1a00000
+2004000c: e1a00000 .word 0xe1a00000
+20040010: e1a00000 .word 0xe1a00000
+20040014: e1a00000 .word 0xe1a00000
+20040018: e1a00000 .word 0xe1a00000
+2004001c: e1a00000 .word 0xe1a00000
+20040020: e1a00000 .word 0xe1a00000
+20040024: e1a00000 .word 0xe1a00000
+20040028: e1a00000 .word 0xe1a00000
+2004002c: e1a00000 .word 0xe1a00000
+20040030: e1a00000 .word 0xe1a00000
+20040034: e1a00000 .word 0xe1a00000
+20040038: e1a00000 .word 0xe1a00000
+2004003c: e1a00000 .word 0xe1a00000
+20040040: e1a00000 .word 0xe1a00000
+20040044: e1a00000 .word 0xe1a00000
+20040048: e1a00000 .word 0xe1a00000
+2004004c: e1a00000 .word 0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm5.ld b/ld/testsuite/ld-arm/non-contiguous-arm5.ld
new file mode 100644
index 0000000..99c0234
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm5.ld
@@ -0,0 +1,34 @@
+/*
+ section .code.1 fits in .raml
+ section .code.2 does not fit in .raml and goes to .ramu
+ section .code.3 would fit in .raml, but goes to .ramu: Check that .code.2 and .code.3 are not swapped
+ section .code.4 fits in .ramz
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00014
+ RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020
+ RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+ .raml :
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.code) *(.code.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.code) *(.code.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.code) *(.code.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm6.d b/ld/testsuite/ld-arm/non-contiguous-arm6.d
new file mode 100644
index 0000000..605d846
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm6.d
@@ -0,0 +1,77 @@
+#name: non-contiguous-arm6
+#source: non-contiguous-arm.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-arm6.ld
+#objdump: -rdth
+#xfail: [is_generic]
+#skip: arm*nacl
+
+.*: file format elf32-(little|big)arm
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+ 0 \.raml 00000028 1fff0000 1fff0000 00010000 2\*\*3
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 1 \.ramz 00000050 40040000 30000000 00020000 2\*\*2
+ CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 2 .ARM.attributes 00000012 00000000 00000000 00020050 2\*\*0
+ CONTENTS, READONLY
+SYMBOL TABLE:
+1fff0000 l d .raml 00000000 .raml
+40040000 l d .ramz 00000000 .ramz
+00000000 l d .ARM.attributes 00000000 .ARM.attributes
+00000000 l df \*ABS\* 00000000 .*/non-contiguous-arm.o
+1fff0020 l F .raml 00000008 __code4_veneer
+1fff0028 g .raml 00000000 _raml_end
+30000000 g .raml 00000000 _ramu_start
+1fff000c g F .raml 00000000 code2
+40040000 g .ramz 00000000 _ramz_start
+1fff0000 g .raml 00000000 _raml_start
+1fff0018 g F .raml 00000000 code3
+1fff0000 g F .raml 00000000 code1
+40040050 g .ramz 00000000 _ramz_end
+40040000 g F .ramz 00000000 code4
+30000000 g .raml 00000000 _ramu_end
+
+Disassembly of section .raml:
+
+1fff0000 \<code1\>:
+1fff0000: e1a00000 nop ; \(mov r0, r0\)
+1fff0004: e1a00000 nop ; \(mov r0, r0\)
+1fff0008: ebffffff bl 1fff000c \<code2\>
+
+1fff000c \<code2\>:
+1fff000c: e1a00000 nop ; \(mov r0, r0\)
+1fff0010: e1a00000 nop ; \(mov r0, r0\)
+1fff0014: ebffffff bl 1fff0018 \<code3\>
+
+1fff0018 \<code3\>:
+1fff0018: e1a00000 nop ; \(mov r0, r0\)
+1fff001c: ebffffff bl 1fff0020 \<__code4_veneer\>
+
+1fff0020 \<__code4_veneer\>:
+1fff0020: e51ff004 ldr pc, \[pc, #-4\] ; 1fff0024 \<__code4_veneer\+0x4\>
+1fff0024: 40040000 .word 0x40040000
+
+Disassembly of section .ramz:
+
+40040000 \<code4\>:
+40040000: e1a00000 .word 0xe1a00000
+40040004: e1a00000 .word 0xe1a00000
+40040008: e1a00000 .word 0xe1a00000
+4004000c: e1a00000 .word 0xe1a00000
+40040010: e1a00000 .word 0xe1a00000
+40040014: e1a00000 .word 0xe1a00000
+40040018: e1a00000 .word 0xe1a00000
+4004001c: e1a00000 .word 0xe1a00000
+40040020: e1a00000 .word 0xe1a00000
+40040024: e1a00000 .word 0xe1a00000
+40040028: e1a00000 .word 0xe1a00000
+4004002c: e1a00000 .word 0xe1a00000
+40040030: e1a00000 .word 0xe1a00000
+40040034: e1a00000 .word 0xe1a00000
+40040038: e1a00000 .word 0xe1a00000
+4004003c: e1a00000 .word 0xe1a00000
+40040040: e1a00000 .word 0xe1a00000
+40040044: e1a00000 .word 0xe1a00000
+40040048: e1a00000 .word 0xe1a00000
+4004004c: e1a00000 .word 0xe1a00000
diff --git a/ld/testsuite/ld-arm/non-contiguous-arm6.ld b/ld/testsuite/ld-arm/non-contiguous-arm6.ld
new file mode 100644
index 0000000..6d6d6fe
--- /dev/null
+++ b/ld/testsuite/ld-arm/non-contiguous-arm6.ld
@@ -0,0 +1,33 @@
+/*
+ sections .code.1, .code.2 and .code.3 (+ farcall stub) fit in .raml
+ section .code.4 fits in .ramz
+ nothing fits in .ramu
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00030
+ RAMU (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00010
+ RAMZ (rwx) : ORIGIN = 0x40040000, LENGTH = 0x00400
+}
+
+SECTIONS
+{
+ .raml :
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.code) *(.code.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.code) *(.code.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.code) *(.code.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-elf/non-contiguous.d b/ld/testsuite/ld-elf/non-contiguous.d
new file mode 100644
index 0000000..9694bcf
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.d
@@ -0,0 +1,29 @@
+#name: non-contiguous
+#source: non-contiguous.s
+#ld: --enable-non-contiguous-regions -T non-contiguous.ld
+#objdump: -rdsh
+#xfail: [is_generic]
+#skip: xtensa*
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA * LMA * File off Algn
+ 0 \.raml 0000000c 0*1fff0000 0*1fff0000 .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+ 1 \.ramu 00000014 0*20000000 0*1fff000c .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+ 2 \.ramz 0000003c 0*20040000 0*20000014 .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+
+
+Contents of section .raml:
+ 1fff0000 (010+ 020+ 030+|0+01 0+02 0+03) ............
+Contents of section .ramu:
+ 20000000 (040+ 050+ 060+ 070+|0+04 0+05 0+06 0+07) ................
+ 20000010 (080+|0+08) ....
+Contents of section .ramz:
+ 20040000 09090909 09090909 09090909 09090909 ................
+ 20040010 09090909 09090909 09090909 09090909 ................
+ 20040020 09090909 09090909 09090909 09090909 ................
+ 20040030 09090909 09090909 09090909 ............
diff --git a/ld/testsuite/ld-elf/non-contiguous.ld b/ld/testsuite/ld-elf/non-contiguous.ld
new file mode 100644
index 0000000..fc72253
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.ld
@@ -0,0 +1,47 @@
+/*
+ section .data.1 fits in .raml
+ sections .data.2 .data.3 fit in .ramu
+ section .data.4 fits in .ramz
+*/
+MEMORY
+{
+ RAML (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 0x00014
+ RAMU (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040
+ RAMZ (rwx) : ORIGIN = 0x20040000, LENGTH = 0x00040
+}
+
+SECTIONS
+{
+ /* Ignore this target specific info in output comparison. */
+ /DISCARD/ : {
+ *(.ARM.attributes)
+ *(.ARC.attributes)
+ *(.riscv.attributes)
+ *(.c6xabi.attributes)
+ *(.trampolines)
+ *(.reginfo)
+ *(.note.renesas)
+ *(.MIPS.abiflags)
+ *(.MSP430.attributes)
+ *(.gnu.attributes)
+ }
+
+ .raml : /*AT ( ADDR (.text) + SIZEOF (.text) )*/
+ { _raml_start = . ;
+ *(.boot) ;
+ *(.data) *(.data.*) ;
+ _raml_end = . ;
+ } > RAML
+
+ .ramu : AT ( ADDR (.raml) + SIZEOF (.raml) )
+ { _ramu_start = . ;
+ *(.data) *(.data.*) ;
+ _ramu_end = . ;
+ } > RAMU
+
+ .ramz : AT ( ADDR (.ramu) + SIZEOF (.ramu) )
+ { _ramz_start = . ;
+ *(.data) *(.data.*) ;
+ _ramz_end = . ;
+ } > RAMZ
+}
diff --git a/ld/testsuite/ld-elf/non-contiguous.s b/ld/testsuite/ld-elf/non-contiguous.s
new file mode 100644
index 0000000..19bc2b1
--- /dev/null
+++ b/ld/testsuite/ld-elf/non-contiguous.s
@@ -0,0 +1,21 @@
+ .section .data.1, "a", %progbits
+ # Fit in RAML
+ .4byte 1
+ .4byte 2
+ .4byte 3
+
+ .section .data.2, "a", %progbits
+ # Fit in RAMU
+ .4byte 4
+ .4byte 5
+ .4byte 6
+
+ .section .data.3, "a", %progbits
+ # Fit in RAMU
+ .4byte 7
+ .4byte 8
+
+ .section .data.4, "a", %progbits
+ # Fit in RAMZ
+ .fill 0x3c, 1, 9
+
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
new file mode 100644
index 0000000..858e353
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.d
@@ -0,0 +1,5 @@
+#name: non-contiguous-powerpc
+#source: non-contiguous-powerpc.s
+#ld: --enable-non-contiguous-regions -T non-contiguous-powerpc.ld
+#error: \ARelaxation not supported with --enable-non-contiguous-regions.*
+#skip: powerpc64*-*
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
new file mode 100644
index 0000000..744d246
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.ld
@@ -0,0 +1,22 @@
+/* Distance between 'one' and 'two' means that relaxation implies that
+ .text.one's size increases. Even though the result would fit in
+ 'oneandhalf', this is not supported by
+ --enable-non-contiguous-regions. */
+
+MEMORY {
+ one (RXAI) : ORIGIN = 0x00000000, LENGTH = 0x00000010
+ oneandhalf (RXAI) : ORIGIN = 0x00001000, LENGTH = 0x00001010
+ two (RXAI) : ORIGIN = 0x20000000, LENGTH = 0x10000000
+}
+
+SECTIONS {
+ one : {
+ *(.text.one)
+ } > one
+ oneandhalf : {
+ *(.text.one)
+ } > oneandhalf
+ two : {
+ *(.text.two)
+ } > two
+}
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
new file mode 100644
index 0000000..e02b322
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc.s
@@ -0,0 +1,8 @@
+ .machine "ppc"
+
+ .section .text.one
+ b 2f
+
+ .section .text.two
+2:
+ nop
diff --git a/ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d b/ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d
new file mode 100644
index 0000000..ff0e3fc
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/non-contiguous-powerpc64.d
@@ -0,0 +1,5 @@
+#name: non-contiguous-powerpc64
+#source: non-contiguous-powerpc.s
+#as: -a64
+#ld: -melf64ppc --enable-non-contiguous-regions -T non-contiguous-powerpc.ld
+#error: .*Could not assign group.*
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 94b2fac..84d7c9c 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -405,6 +405,7 @@ if [ supports_ppc64 ] then {
run_dump_test "tlsgd"
run_dump_test "tlsld"
run_dump_test "tlsie"
+ run_dump_test "non-contiguous-powerpc64"
}
run_dump_test "localgot"
@@ -443,3 +444,5 @@ run_dump_test "vle-multiseg-6"
run_dump_test "ppc476-shared"
run_dump_test "ppc476-shared2"
+
+run_dump_test "non-contiguous-powerpc"
--
2.7.4
next prev parent reply other threads:[~2020-02-28 17:31 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-14 12:34 Christophe Lyon
2020-02-14 13:02 ` Tamar Christina
2020-02-14 13:54 ` Christophe Lyon
2020-02-19 7:19 ` Alan Modra
2020-02-19 12:28 ` Christophe Lyon
2020-02-19 22:23 ` Alan Modra
2020-02-20 4:37 ` Christophe Lyon
2020-02-20 8:15 ` Alan Modra
2020-02-20 9:00 ` Christophe Lyon
2020-02-28 17:31 ` Christophe Lyon [this message]
2020-03-09 13:10 ` Christophe Lyon
2020-03-13 14:21 ` Nick Clifton
2020-03-13 14:46 ` Christophe Lyon
2020-06-02 12:49 ` Alexander Fedotov
2020-06-03 12:48 ` Christophe Lyon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAKdteOZxihz00ZkPhbP96bLWkeni3LUH3EX0-axNNP2cS1RQbw@mail.gmail.com \
--to=christophe.lyon@linaro.org \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).