[lld] r334483 - [ELF][MIPS] Fix TLS GOT entries for local symbols in shared libraries

Alexander Richardson via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 12 01:00:39 PDT 2018


Author: arichardson
Date: Tue Jun 12 01:00:38 2018
New Revision: 334483

URL: http://llvm.org/viewvc/llvm-project?rev=334483&view=rev
Log:
[ELF][MIPS] Fix TLS GOT entries for local symbols in shared libraries

Summary:
Previously LLD would not add any dynamic relocations and write a module
index of 1 which is not correct for the shared library case.
This can happen when a thread-local global variable is marked as local with
a version script. With this change I am now able to link all of the FreeBSD
base system for MIPS64 with LLD.

Differential Revision: https://reviews.llvm.org/D48002

Added:
    lld/trunk/test/ELF/mips-tls-64-pic-local-variable.s
Modified:
    lld/trunk/ELF/SyntheticSections.cpp

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=334483&r1=334482&r2=334483&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Tue Jun 12 01:00:38 2018
@@ -922,9 +922,17 @@ template <class ELFT> void MipsGotSectio
           continue;
         InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
       } else {
-        if (!P.first->IsPreemptible)
+        // When building a shared library we still need a dynamic relocation
+        // for the module index. Therefore only checking for
+        // S->IsPreemptible is not sufficient (this happens e.g. for
+        // thread-locals that have been marked as local through a linker script)
+        if (!S->IsPreemptible && !Config->Pic)
           continue;
         InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
+        // However, we can skip writing the TLS offset reloc for non-preemptible
+        // symbols since it is known even in shared libraries
+        if (!S->IsPreemptible)
+          continue;
         Offset += Config->Wordsize;
         InX::RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S);
       }
@@ -1030,7 +1038,11 @@ void MipsGotSection::writeTo(uint8_t *Bu
       if (P.first == nullptr && !Config->Pic)
         Write(P.second, nullptr, 1);
       else if (P.first && !P.first->IsPreemptible) {
-        Write(P.second, nullptr, 1);
+        // If we are emitting PIC code with relocations we mustn't write
+        // anything to the GOT here. When using Elf_Rel relocations the value
+        // one will be treated as an addend and will cause crashes at runtime
+        if (!Config->Pic)
+          Write(P.second, nullptr, 1);
         Write(P.second + 1, P.first, -0x8000);
       }
     }

Added: lld/trunk/test/ELF/mips-tls-64-pic-local-variable.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-tls-64-pic-local-variable.s?rev=334483&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-tls-64-pic-local-variable.s (added)
+++ lld/trunk/test/ELF/mips-tls-64-pic-local-variable.s Tue Jun 12 01:00:38 2018
@@ -0,0 +1,49 @@
+# REQUIRES: mips
+# MIPS TLS variables that are marked as local by a version script were previously
+# writing values to the GOT that caused runtime crashes. This was happending when
+# linking jemalloc_tsd.c in FreeBSD libc. Check that we do the right thing now:
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %s -o %t.o
+# RUN: echo "{ global: foo; local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-objdump --section=.got -s %t.so | FileCheck %s -check-prefix GOT
+# RUN: llvm-readobj -r %t.so | FileCheck %s -check-prefix RELOCS
+
+# GOT:        Contents of section .got:
+# GOT-NEXT:   20000 00000000 00000000 80000000 00000000
+# GOT-NEXT:   20010 00000000 00000000 00000000 00000000
+# GOT-NEXT:   20020 ffffffff ffff8000
+
+# RELOCS:      Section ({{.+}}) .rel.dyn {
+# RELOCS-NEXT:  0x20018 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE
+# RELOCS-NEXT: }
+
+# Test case generated using clang -mcpu=mips4 -target mips64-unknown-freebsd12.0 -fpic -O -G0 -EB -mabi=n64 -msoft-float -std=gnu99 -S %s -o %t.s
+# from the following source:
+#
+# _Thread_local int x;
+# int foo() { return x; }
+#
+        .text
+        .globl  foo
+        .p2align        3
+        .type   foo, at function
+        .ent    foo
+foo:
+        lui     $1, %hi(%neg(%gp_rel(foo)))
+        daddu   $1, $1, $25
+        daddiu  $gp, $1, %lo(%neg(%gp_rel(foo)))
+        ld      $25, %call16(__tls_get_addr)($gp)
+        jalr    $25
+        daddiu  $4, $gp, %tlsgd(x)
+        .end    foo
+
+        .type   x, at object
+        .section        .tbss,"awT", at nobits
+        .globl  x
+        .p2align        2
+x:
+        .4byte  0
+        .size   x, 4
+
+




More information about the llvm-commits mailing list