Issue a linker error if TLS sections are not adjacent
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 23 Jan 2014 16:15:17 +0000 (08:15 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 23 Jan 2014 16:15:17 +0000 (08:15 -0800)
Bad linker script may lead to TLS sections separated by non-TLS sections
in output.  This patch changes linker assert to a linker error to
provide better linker diagnosis.

PR ld/16498
* elf.c (_bfd_elf_map_sections_to_segments): Issue a linker error
if TLS sections are not adjacent.

bfd/ChangeLog
bfd/elf.c

index 3996dfc..78aa794 100644 (file)
@@ -1,3 +1,9 @@
+2014-01-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/16498
+       * elf.c (_bfd_elf_map_sections_to_segments): Issue a linker error 
+       if TLS sections are not adjacent.
+
 2014-01-22  Alan Modra  <amodra@gmail.com>
 
        * elflink.c (elf_link_add_object_symbols): Call minfo for --as-needed.
index 3815e32..c0303fc 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4117,11 +4117,31 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          /* Mandated PF_R.  */
          m->p_flags = PF_R;
          m->p_flags_valid = 1;
+         s = first_tls;
          for (i = 0; i < (unsigned int) tls_count; ++i)
            {
-             BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
-             m->sections[i] = first_tls;
-             first_tls = first_tls->next;
+             if ((s->flags & SEC_THREAD_LOCAL) == 0)
+               {
+                 _bfd_error_handler
+                   (_("%B: TLS sections are not adjacent:"), abfd);
+                 s = first_tls;
+                 i = 0;
+                 while (i < (unsigned int) tls_count)
+                   {
+                     if ((s->flags & SEC_THREAD_LOCAL) != 0)
+                       {
+                         _bfd_error_handler (_("           TLS: %A"), s);
+                         i++;
+                       }
+                     else
+                       _bfd_error_handler (_(" non-TLS: %A"), s);
+                     s = s->next;
+                   }
+                 bfd_set_error (bfd_error_bad_value);
+                 goto error_return;
+               }
+             m->sections[i] = s;
+             s = s->next;
            }
 
          *pm = m;