Skip to content

Commit

Permalink
[elf2] Generate PT_TLS.
Browse files Browse the repository at this point in the history
Differential Revision: http://reviews.llvm.org/D14167

llvm-svn: 251872
  • Loading branch information
Bigcheese committed Nov 3, 2015
1 parent 1ef2cb9 commit 78aa1de
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
40 changes: 30 additions & 10 deletions lld/ELF/Writer.cpp
Expand Up @@ -644,15 +644,6 @@ static uint32_t toPhdrFlags(uint64_t Flags) {
return Ret;
}

template <class ELFT>
static bool consumesVirtualAddressSpace(OutputSectionBase<ELFT> *Sec) {
return (Sec->getFlags() & SHF_ALLOC) &&
// Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
// responsible for allocating space for them, not the PT_LOAD that
// contains the TLS initialization image.
!((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS);
}

// Visits all sections to create PHDRs and to assign incremental,
// non-overlapping addresses to output sections.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
Expand All @@ -679,6 +670,9 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, getVAStart(), FileOff,
Target->getPageSize());

Elf_Phdr TlsPhdr;
std::memset(&TlsPhdr, 0, sizeof(Elf_Phdr));
uintX_t ThreadBSSOffset = 0;
// Create phdrs as we assign VAs and file offsets to all output sections.
SmallPtrSet<Elf_Phdr *, 8> Closed;
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
Expand All @@ -701,17 +695,38 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
}

if (consumesVirtualAddressSpace<ELFT>(Sec)) {
if (Sec->getSize() && (Sec->getFlags() & SHF_ALLOC) &&
(Sec->getFlags() & SHF_TLS)) {
if (!TlsPhdr.p_vaddr) {
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
}
if (Sec->getType() != SHT_NOBITS)
VA = RoundUpToAlignment(VA, Sec->getAlign());
uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
Sec->setVA(TVA);
TlsPhdr.p_memsz += Sec->getSize();
if (Sec->getType() == SHT_NOBITS)
ThreadBSSOffset = TVA - VA + Sec->getSize();
else {
TlsPhdr.p_filesz += Sec->getSize();
VA += Sec->getSize();
}
TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
} else if (Sec->getFlags() & SHF_ALLOC) {
VA = RoundUpToAlignment(VA, Sec->getAlign());
Sec->setVA(VA);
VA += Sec->getSize();
}

FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
Sec->setFileOffset(FileOff);
if (Sec->getType() != SHT_NOBITS)
FileOff += Sec->getSize();
}

if (TlsPhdr.p_vaddr)
Phdrs[++PhdrIdx] = TlsPhdr;

// Add an entry for .dynamic.
if (isOutputDynamic()) {
Elf_Phdr *PH = &Phdrs[++PhdrIdx];
Expand All @@ -732,6 +747,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {

// Returns the number of PHDR entries.
template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
bool Tls = false;
int I = 2; // 2 for PT_PHDR and the first PT_LOAD
if (needsInterpSection())
++I;
Expand All @@ -741,12 +757,16 @@ template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
if (!Sec->getSize() || !needsPhdr<ELFT>(Sec))
continue;
if (Sec->getFlags() & SHF_TLS)
Tls = true;
uintX_t Flags = toPhdrFlags(Sec->getFlags());
if (Last != Flags) {
Last = Flags;
++I;
}
}
if (Tls)
++I;
return I;
}

Expand Down
34 changes: 31 additions & 3 deletions lld/test/elf2/tls.s
Expand Up @@ -25,7 +25,7 @@ _start:
// CHECK-NEXT: SHF_TLS
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address:
// CHECK-NEXT: Address: [[TDATA_ADDR:0x.*]]
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Link:
Expand Down Expand Up @@ -59,7 +59,7 @@ _start:
// CHECK-NEXT: SHF_TLS
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address:
// CHECK-NEXT: Address: [[TBSS_ADDR:0x.*]]
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Link:
Expand All @@ -76,9 +76,26 @@ _start:
// CHECK-NEXT: SHF_TLS
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address:

// 0x1100C = TBSS_ADDR + 4

// CHECK-NEXT: Address: 0x1100C
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment:
// CHECK-NEXT: EntrySize:
// CHECK-NEXT: }
// CHECK-NEXT: Section {
// CHECK-NEXT: Index:
// CHECK-NEXT: Name:
// CHECK-NEXT: Type:
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: [[TBSS_ADDR]]

// Check that the TLS NOBITS sections weren't added to the R/W PT_LOAD's size.

Expand All @@ -91,3 +108,14 @@ _start:
// CHECK-NEXT: PF_R
// CHECK-NEXT: PF_W
// CHECK-NEXT: ]
// CHECK: Type: PT_TLS
// CHECK-NEXT: Offset:
// CHECK-NEXT: VirtualAddress: [[TDATA_ADDR]]
// CHECK-NEXT: PhysicalAddress: [[TDATA_ADDR]]
// CHECK-NEXT: FileSize: 8
// CHECK-NEXT: MemSize: 16
// CHECK-NEXT: Flags [
// CHECK-NEXT: PF_R
// CHECK-NEXT: ]
// CHECK-NEXT: Alignment:
// CHECK-NEXT: }

0 comments on commit 78aa1de

Please sign in to comment.