[PATCH v2 3/5] ld: fix segfault on discarded input sections not fitting in memory regions

Christophe Lyon christophe.lyon@linaro.org
Wed Oct 15 11:31:24 GMT 2025


On Tue, 14 Oct 2025 at 12:56, Matthieu Longo <matthieu.longo@arm.com> wrote:
>
> In the case of non-contiguous memory regions, if an input section did not
> fit in any of the designated memory regions, the linker marked it as
> discarded, and warn_non_contiguous_discards() would only issue warning on
> it, relying on later unresolved symbol errors to terminate the process
> before a crash occur. This approach was insufficient, and crashes did occur
> on AArch64.

Thanks for the fix, when I added this support the target was really
arm (aarch32), and aarch64 got only minimal testing, which was
insufficient.

Christophe

>
> This patch renames warn_non_contiguous_discards () to a name that does not
> contain "discard" as it created some confusion with the /DISCARD/ output
> section. It also promotes the warnings to errors, and ensures that the
> link process terminates cleanly if any input section is not allocated to
> an output section.
> It also updates an AArch32 test expectations to match the corrected
> behavior. Tests for the crash cases are added in a subsequent patch.
> ---
>  ld/ldlang.c                                 | 30 ++++++++++++++-------
>  ld/testsuite/ld-arm/non-contiguous-arm7.err |  9 +++----
>  2 files changed, 24 insertions(+), 15 deletions(-)
>
> diff --git a/ld/ldlang.c b/ld/ldlang.c
> index bdda599a7a4..c7c4ba8a019 100644
> --- a/ld/ldlang.c
> +++ b/ld/ldlang.c
> @@ -5576,7 +5576,7 @@ size_input_section
>    lang_input_section_type *is = &((*this_ptr)->input_section);
>    asection *i = is->section;
>    asection *o = output_section_statement->bfd_section;
> -  *removed = 0;
> +  *removed = false;
>
>    if (link_info.non_contiguous_regions)
>      {
> @@ -5587,7 +5587,7 @@ size_input_section
>          have reinitialized its size.  */
>        if (i->already_assigned && i->already_assigned != o)
>         {
> -         *removed = 1;
> +         *removed = true;
>           return dot;
>         }
>      }
> @@ -5650,7 +5650,7 @@ size_input_section
>                              "would overflow `%pA' after it changed size).\n"),
>                            i, i->output_section);
>
> -                 *removed = 1;
> +                 *removed = true;
>                   dot = end;
>                   i->output_section = NULL;
>                   return dot;
> @@ -8231,9 +8231,14 @@ lang_propagate_lma_regions (void)
>      }
>  }
>
> +/* Checks whether any input section was not allocated to an output section.
> +   If such a case is found, emits an error for the corresponding input section
> +   and stops the link process.  */
> +
>  static void
> -warn_non_contiguous_discards (void)
> +error_non_contiguous_unallocated_sections (void)
>  {
> +  bool removed_section = false;
>    LANG_FOR_EACH_INPUT_STATEMENT (file)
>      {
>        if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
> @@ -8242,10 +8247,16 @@ warn_non_contiguous_discards (void)
>
>        for (asection *s = file->the_bfd->sections; s != NULL; s = s->next)
>         if (s->output_section == NULL && !s->veneer)
> -         einfo (_("%P: warning: --enable-non-contiguous-regions "
> -                  "discards section `%pA' from `%pB'\n"),
> -                s, file->the_bfd);
> +         {
> +           einfo (_("%P: error: --enable-non-contiguous-regions was not able "
> +                    "to allocate the input section `%pA' (%pB) to an output "
> +                    "section\n"),
> +                  s, file->the_bfd);
> +           removed_section = true;
> +         }
>      }
> +  if (removed_section)
> +    fatal (_("%P: final link failed\n"));
>  }
>
>  static void
> @@ -8663,9 +8674,8 @@ lang_process (void)
>    if (command_line.check_section_addresses)
>      lang_check_section_addresses ();
>
> -  if (link_info.non_contiguous_regions
> -      && link_info.non_contiguous_regions_warnings)
> -    warn_non_contiguous_discards ();
> +  if (link_info.non_contiguous_regions)
> +    error_non_contiguous_unallocated_sections ();
>
>    /* Check any required symbols are known.  */
>    ldlang_check_require_defined_symbols ();
> diff --git a/ld/testsuite/ld-arm/non-contiguous-arm7.err b/ld/testsuite/ld-arm/non-contiguous-arm7.err
> index 7b3a3d8c3c9..21f71898eb1 100644
> --- a/ld/testsuite/ld-arm/non-contiguous-arm7.err
> +++ b/ld/testsuite/ld-arm/non-contiguous-arm7.err
> @@ -1,5 +1,4 @@
> -.* may change behaviour for section .?\.bss.? from .*
> -.* may change behaviour for section .?\.bss\.MY_BUF.? from .*
> -.* discards section .?\.bss\.MY_BUF.? from .*
> -.* unresolvable R_ARM_ABS32 relocation against symbol .?MY_BUF.?
> -.* final link failed
> +.*: warning: --enable-non-contiguous-regions may change behaviour for section `\.bss' from `.*non-contiguous-arm7\.o' \(assigned to \.bss, but additional match: \.bss_ram2\)
> +.*: warning: --enable-non-contiguous-regions may change behaviour for section `\.bss\.MY_BUF' from `.*non-contiguous-arm7\.o' \(assigned to \.bss, but additional match: \.bss_ram2\)
> +.*: error: --enable-non-contiguous-regions was not able to allocate the input section `\.bss\.MY_BUF' \(.*non-contiguous-arm7\.o\) to an output section
> +.*: final link failed
> --
> 2.51.0
>


More information about the Binutils mailing list