Round up the memsize of PT_TLS.

This is cleaner than computing relocations as if we had done it.

While at it, keep a single Phdr variable instead of multiple fields of it.

llvm-svn: 252352
This commit is contained in:
Rafael Espindola 2015-11-06 22:14:44 +00:00
parent 8121b3f684
commit ea7a1e9092
5 changed files with 31 additions and 11 deletions

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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.

21
lld/test/elf2/tls-align.s Normal file
View File

@ -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: }