diff options
-rw-r--r-- | lld/ELF/OutputSections.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 7 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 10 | ||||
-rw-r--r-- | lld/test/elf2/tls-align.s | 21 |
5 files changed, 31 insertions, 11 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index c2310ca617f..cfd6133cfee 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -660,7 +660,7 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { InputSectionBase<ELFT> &SC = DR.Section; if (DR.Sym.getType() == STT_TLS) return SC.OutSec->getVA() + SC.getOffset(DR.Sym) - - Out<ELFT>::TlsInitImageVA; + Out<ELFT>::TlsPhdr->p_vaddr; return SC.OutSec->getVA() + SC.getOffset(DR.Sym); } case SymbolBody::DefinedCommonKind: diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index a30f9979274..1714f51990c 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -352,6 +352,7 @@ private: // until Writer is initialized. template <class ELFT> struct Out { typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; + typedef typename llvm::object::ELFFile<ELFT>::Elf_Phdr Elf_Phdr; static DynamicSection<ELFT> *Dynamic; static GnuHashTableSection<ELFT> *GnuHashTab; static GotPltSection<ELFT> *GotPlt; @@ -369,8 +370,7 @@ template <class ELFT> struct Out { static StringTableSection<ELFT> *StrTab; static SymbolTableSection<ELFT> *DynSymTab; static SymbolTableSection<ELFT> *SymTab; - static uintX_t TlsInitImageVA; - static size_t TlsInitImageAlignedSize; + static Elf_Phdr *TlsPhdr; }; template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic; @@ -390,8 +390,7 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab; template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab; template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab; template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab; -template <class ELFT> typename Out<ELFT>::uintX_t Out<ELFT>::TlsInitImageVA; -template <class ELFT> size_t Out<ELFT>::TlsInitImageAlignedSize; +template <class ELFT> typename Out<ELFT>::Elf_Phdr *Out<ELFT>::TlsPhdr; } // namespace elf2 } // namespace lld diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 96e7d04d304..31e38068863 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -351,7 +351,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, write32le(Loc, SA); break; case R_X86_64_TPOFF32: { - uint64_t Val = SA - Out<ELF64LE>::TlsInitImageAlignedSize; + uint64_t Val = SA - Out<ELF64LE>::TlsPhdr->p_memsz; if (!isInt<32>(Val)) error("R_X86_64_TPOFF32 out of range"); write32le(Loc, Val); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3ba94b156a2..9592ba48628 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -715,10 +715,8 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() { } if (Sec->getFlags() & SHF_TLS) { - if (!TlsPhdr.p_vaddr) { + if (!TlsPhdr.p_vaddr) setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign()); - Out<ELFT>::TlsInitImageVA = VA; - } if (Sec->getType() != SHT_NOBITS) VA = RoundUpToAlignment(VA, Sec->getAlign()); uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign()); @@ -750,9 +748,11 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() { } if (TlsPhdr.p_vaddr) { + // The TLS pointer goes after PT_TLS. At least glibc will align it, + // so round up the size to make sure the offsets are correct. + TlsPhdr.p_memsz = RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align); Phdrs[++PhdrIdx] = TlsPhdr; - Out<ELFT>::TlsInitImageAlignedSize = - RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align); + Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx]; } // Add an entry for .dynamic. diff --git a/lld/test/elf2/tls-align.s b/lld/test/elf2/tls-align.s new file mode 100644 index 00000000000..e8055627b39 --- /dev/null +++ b/lld/test/elf2/tls-align.s @@ -0,0 +1,21 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +// RUN: ld.lld2 %t -o %tout -shared +// RUN: llvm-readobj -program-headers %tout | FileCheck %s + + .section .tbss,"awT",@nobits + .align 8 + .long 0 + +// CHECK: ProgramHeader { +// CHECK: Type: PT_TLS +// CHECK-NEXT: Offset: +// CHECK-NEXT: VirtualAddress: +// CHECK-NEXT: PhysicalAddress: +// CHECK-NEXT: FileSize: 0 +// CHECK-NEXT: MemSize: 8 +// CHECK-NEXT: Flags [ +// CHECK-NEXT: PF_R (0x4) +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: 8 +// CHECK-NEXT: } |