PR ld/24709 [arm] linker crash and assertion failure with CMSE
authorChristophe Lyon <christophe.lyon@linaro.org>
Tue, 2 Jul 2019 13:09:02 +0000 (13:09 +0000)
committerChristophe Lyon <christophe.lyon@linaro.org>
Tue, 2 Jul 2019 13:09:02 +0000 (13:09 +0000)
As discussed in the PR, we do not support the case where CMSE stubs
are inserted too far from their destination. This would require an
intermediate long-branch stub, which is tricky in this context.

Instead of crashing, this patch emit an error message and exits.

2019-07-02  Christophe Lyon  <christophe.lyon@linaro.org>

* bfd/elf32-arm.c (CMSE_STUB_NAME): New define.
(elf32_arm_get_stub_entry): Do not try to emit long-branch stubs
for CMSE stubs.
(arm_dedicated_stub_output_section_name): Use CMSE_STUB_NAME.

Change-Id: I6d4e1c0fdee6bb9f4b07e5e1b46700b5ba31c62e

bfd/ChangeLog
bfd/elf32-arm.c

index 2d300759f69b5db90fa68cb2071d539e34b8fbb6..af25e433af55c872ee6d8f5a4b3f4cca927995b6 100644 (file)
@@ -1,3 +1,10 @@
+2019-07-02  Christophe Lyon  <christophe.lyon@linaro.org>
+
+       * bfd/elf32-arm.c (CMSE_STUB_NAME): New define.
+       (elf32_arm_get_stub_entry): Do not try to emit long-branch stubs
+       for CMSE stubs.
+       (arm_dedicated_stub_output_section_name): Use CMSE_STUB_NAME.
+
 2019-07-02  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>
 
        * elf32-arm.c (elf32_arm_gc_mark_extra_sections): Mark debug
index fc7a41c8d23daa869d645a11f7d7dac2754da4f2..6b6897692d2f2d473920f40a6345b8fc2fcdc2bd 100644 (file)
@@ -2300,6 +2300,8 @@ typedef unsigned short int insn16;
 
 #define CMSE_PREFIX "__acle_se_"
 
+#define CMSE_STUB_NAME ".gnu.sgstubs"
+
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
 #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
@@ -4583,6 +4585,27 @@ elf32_arm_get_stub_entry (const asection *input_section,
   if ((input_section->flags & SEC_CODE) == 0)
     return NULL;
 
+  /* If the input section is the CMSE stubs one and it needs a long
+     branch stub to reach it's final destination, give up with an
+     error message: this is not supported.  See PR ld/24709.  */
+  if (!strncmp (input_section->name, CMSE_STUB_NAME, strlen(CMSE_STUB_NAME)))
+    {
+      bfd *output_bfd = htab->obfd;
+      asection *out_sec = bfd_get_section_by_name (output_bfd, CMSE_STUB_NAME);
+
+      _bfd_error_handler (_("ERROR: CMSE stub (%s section) too far "
+                           "(%#" PRIx64 ") from destination (%#" PRIx64 ")"),
+                         CMSE_STUB_NAME,
+                         (uint64_t)out_sec->output_section->vma
+                           + out_sec->output_offset,
+                         (uint64_t)sym_sec->output_section->vma
+                           + sym_sec->output_offset
+                           + h->root.root.u.def.value);
+      /* Exit, rather than leave incompletely processed
+        relocations.  */
+      xexit(1);
+    }
+
   /* If this input section is part of a group of sections sharing one
      stub section, then use the id of the first section in the group.
      Stub names need to include a section id, as there may well be
@@ -4676,7 +4699,7 @@ arm_dedicated_stub_output_section_name (enum elf32_arm_stub_type stub_type)
   switch (stub_type)
     {
     case arm_stub_cmse_branch_thumb_only:
-      return ".gnu.sgstubs";
+      return CMSE_STUB_NAME;
 
     default:
       BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));