[PATCH] Issue a linker error if TLS sections are not adjacent

H.J. Lu hjl.tools@gmail.com
Thu Jan 23 04:19:00 GMT 2014


On Wed, Jan 22, 2014 at 7:55 PM, Alan Modra <amodra@gmail.com> wrote:
> On Wed, Jan 22, 2014 at 11:30:13AM -0800, H.J. Lu wrote:
>>       PR ld/16498
>>       * elf.c (_bfd_elf_map_sections_to_segments): Issue a linker error
>>       if TLS sections are not adjacent.
>
> This part is OK.

I'd like to augment my patch like

---
index 3815e32..c0303fc 100644
--- 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;
---

So that user has a clue what went wrong.  This gives me:

./ld  -shared -T tbss.t -o tls.so x.o
./ld: tls.so: TLS sections are not adjacent:
./ld:         TLS: .tdata
./ld:     non-TLS: .data
./ld:         TLS: .tbss
./ld: map sections to segments failed: Bad value

>> +SECTIONS
>> +{
>> +  .tdata  : { *(.tdata) }
>> +  .data        : { *(.data)
>> +  }
>> +}
>
> On the other hand, the testcase is really showing a fault in orphan
> section handling.  If ld was a little more clever, it would put .tbss
> after .tdata and your testcase would no longer give an error.
>

I am enclosing a simple patch which does it.  However, it
doesn't solve the second testcase in the bug report since
it has a linker script:

---
SECTIONS
{
  tls_data_init  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
  }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
---

which is derived from the real application I got.  Since normally
we won't see this problem, I don't think it is worth the effect even
though the change is quite small.  I decided not to include it in
my fix since it doesn't solve my original problem.   I can include
it as well as the second testcase.

Thanks.

-- 
H.J.
-
--- /tmp/elf32.em   2014-01-22 09:49:47.335790428 -0800
+++ elf32.em    2014-01-22 10:14:47.147161310 -0800
@@ -1651,6 +1651,9 @@ gldelf_x86_64_place_orphan (asection *s,
       { ".rodata",
     SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
     0, 0, 0, 0 },
+      { ".tdata",
+    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_THREAD_LOCAL,
+    0, 0, 0, 0 },
       { ".data",
     SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
     0, 0, 0, 0 },
@@ -1674,6 +1677,7 @@ gldelf_x86_64_place_orphan (asection *s,
     {
       orphan_text = 0,
       orphan_rodata,
+      orphan_tdata,
       orphan_data,
       orphan_bss,
       orphan_rel,
@@ -1801,6 +1805,8 @@ gldelf_x86_64_place_orphan (asection *s,
     place = &hold[orphan_bss];
   else if ((s->flags & SEC_SMALL_DATA) != 0)
     place = &hold[orphan_sdata];
+  else if ((s->flags & SEC_THREAD_LOCAL) != 0)
+    place = &hold[orphan_tdata];
   else if ((s->flags & SEC_READONLY) == 0)
     place = &hold[orphan_data];
   else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))



More information about the Binutils mailing list