Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -644,15 +644,6 @@ return Ret; } -template -static bool consumesVirtualAddressSpace(OutputSectionBase *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 void Writer::assignAddresses() { @@ -679,6 +670,9 @@ setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, getVAStart(), FileOff, Target->getPageSize()); + Elf_Phdr TlsPhdr; + TlsPhdr.p_vaddr = 0; + uintX_t ThreadBSSOffset = 0; // Create phdrs as we assign VAs and file offsets to all output sections. SmallPtrSet Closed; for (OutputSectionBase *Sec : OutputSections) { @@ -701,17 +695,38 @@ } } - if (consumesVirtualAddressSpace(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(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 @@ // Returns the number of PHDR entries. template int Writer::getPhdrsNum() const { + bool Tls = false; int I = 2; // 2 for PT_PHDR and the first PT_LOAD if (needsInterpSection()) ++I; @@ -741,12 +757,16 @@ for (OutputSectionBase *Sec : OutputSections) { if (!Sec->getSize() || !needsPhdr(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; } Index: test/elf2/tls.s =================================================================== --- test/elf2/tls.s +++ test/elf2/tls.s @@ -25,7 +25,7 @@ // 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 @@ // 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 @@ // 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 @@ // 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: }