[elf2] Generate PT_TLS.

Differential Revision: http://reviews.llvm.org/D14167

llvm-svn: 251872
This commit is contained in:
Michael J. Spencer 2015-11-03 00:34:39 +00:00
parent 1ef2cb9f71
commit 78aa1de3ae
2 changed files with 61 additions and 13 deletions

View File

@ -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() {
@ -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) {
@ -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];
@ -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;
@ -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;
}

View File

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