[llvm-bugs] [Bug 32634] New: R_386_TLS_LDO_32 does not respect existing offset

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Apr 11 19:18:46 PDT 2017


https://bugs.llvm.org/show_bug.cgi?id=32634

            Bug ID: 32634
           Summary: R_386_TLS_LDO_32 does not respect existing offset
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: ELF
          Assignee: unassignedbugs at nondot.org
          Reporter: smeenai at fb.com
                CC: llvm-bugs at lists.llvm.org

% cat tls.cpp
struct s {
  int i;
  int j;
};
static __thread s t;

inline int geti() { return t.i; }
int callgeti() { return geti(); }

inline int getj() { return t.j; }
int callgetj() { return getj(); }

% clang++ -target i686-linux-gnu -fuse-ld=lld -shared -fPIC \
  -nostdlib -o libtls.so tls.cpp
% objdump -d libtls.so | grep -A 1 'call.*__tls_get_addr'
    1059:       e8 72 00 00 00          call   10d0 <___tls_get_addr at plt>
    105e:       8b 80 00 00 00 00       mov    0x0(%eax),%eax
--
    1089:       e8 42 00 00 00          call   10d0 <___tls_get_addr at plt>
    108e:       8b 80 00 00 00 00       mov    0x0(%eax),%eax

In other words, both t.i and t.j got resolved to the same memory location. (The
first __tls_get_addr call is from geti; the second from getj.) I apologize for
the inline functions song and dance in the C++ source; I wasn't able to get
clang to produce R_386_TLS_LDO_32 relocations without it.

Looking into the cause:

% clang++ -target i686-linux-gnu -fPIC -c tls.cpp
% objdump -dr tls.o | grep -B 1 R_386_TLS_LDO_32
  1e:   8b 80 00 00 00 00       mov    0x0(%eax),%eax
                        20: R_386_TLS_LDO_32    t
--
  1e:   8b 80 04 00 00 00       mov    0x4(%eax),%eax
                        20: R_386_TLS_LDO_32    t

Again, the first one is from geti, and the second from getj. It looks like the
bytes corresponding to the R_386_TLS_LDO_32 already contain the struct offset,
but lld isn't respecting that struct offset when processing the relocation.

This is only an issue on x86. Comparing to x86_64:

% clang++ -target x86_64-linux-gnu -fPIC -c tls.cpp
% objdump -dr tls.o | grep -B 1 R_X86_64_DTPOFF32
  10:   8b 80 00 00 00 00       mov    0x0(%rax),%eax
                        12: R_X86_64_DTPOFF32   t
--
  10:   8b 80 00 00 00 00       mov    0x0(%rax),%eax
                        12: R_X86_64_DTPOFF32   t+0x4

On x86_64, the bytes corresponding to the R_X86_64_DTPOFF32 are always 0, and
the struct offset seems to be part of the relocation itself, so lld is able to
handle it correctly.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20170412/753d4f13/attachment.html>


More information about the llvm-bugs mailing list