New user self-registration is disabled due to spam. For an account please email bugs-admin@lists.llvm.org with your e-mail address and full name.

Bug 29068 - Static TLS for i386: addend ignored
Summary: Static TLS for i386: addend ignored
Status: RESOLVED FIXED
Alias: None
Product: lld
Classification: Unclassified
Component: ELF (show other bugs)
Version: unspecified
Hardware: PC other
: P release blocker
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks: 28600
  Show dependency tree
 
Reported: 2016-08-20 03:18 PDT by Ed Schouten
Modified: 2016-08-23 02:02 PDT (History)
2 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Schouten 2016-08-20 03:18:45 PDT
Consider the following piece of code:

#include <stdio.h>

_Thread_local struct {
  int x, y, z;
} var = { .x = 12, .y = 34, .z = 56 };

void print(int);

int main() {
  print(var.y);
}

Compiling it for i686 will yield the following main() function (abbreviated):

main:
        movl    %gs:0, %eax
        pushl   var@NTPOFF+4(%eax)
        calll   print
        addl    $4, %esp
        xorl    %eax, %eax
        retl

Now, changing the call to print() to var.z, we get:

main:
        movl    %gs:0, %eax
        pushl   var@NTPOFF+8(%eax)
        calll   print
        addl    $4, %esp
        xorl    %eax, %eax
        retl

This is all good. Now this is where the interesting part starts. If we link it into a simple executable, we always generate the following code (as in, it doesn't matter if var.y or var.z is used):

00014750 <main>:
   14750:       65 a1 00 00 00 00       mov    %gs:0x0,%eax
   14756:       ff b0 dc ff ff ff       pushl  -0x24(%eax)
   1475c:       e8 0f 00 00 00          call   14770 <print>
   14761:       83 c4 04                add    $0x4,%esp
   14764:       31 c0                   xor    %eax,%eax
   14766:       c3                      ret

The value that is passed to print() is equal to twelve. In other words, the linker completely ignores the addend of the relocation, always making it use the first element in the structure.

I'll debug this issue in more detail. Marking this as a blocker for LLVM 3.9, as it makes PIE effectively broken when used in non-PIE code on i386. The issue is both present in trunk and 3.9rc1.
Comment 1 Ed Schouten 2016-08-20 03:41:42 PDT
Aha!

--- ELF/Target.cpp
+++ ELF/Target.cpp
@@ -436,6 +436,7 @@
   case R_386_GOTPC:
   case R_386_PC32:
   case R_386_PLT32:
+  case R_386_TLS_LE:
     return read32le(Buf);
   }
 }

Will come up with a test case and send it out for review in a bit.
Comment 2 Ed Schouten 2016-08-20 04:01:05 PDT
https://reviews.llvm.org/D23741
Comment 3 Ed Schouten 2016-08-20 06:04:43 PDT
Hans,

Would it still be possible to have this fix included in 3.9? If so, any preference for when I need to merge this to the release branch?

Thanks,
Ed
Comment 4 Hans Wennborg 2016-08-22 11:48:36 PDT
(In reply to comment #3)
> Would it still be possible to have this fix included in 3.9? If so, any
> preference for when I need to merge this to the release branch?

Let me think about this for a bit and get back to you. I suspect we'll want to merge this, but I need to figure out the timing.
Comment 5 Hans Wennborg 2016-08-22 16:17:07 PDT
Since we'll need to do another cycle after rc2 anyway, and this seems important and straight-forward, I've merged it to 3.9 in r279476.
Comment 6 Ed Schouten 2016-08-23 02:02:25 PDT
Thanks! :-)