Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -640,15 +640,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() { @@ -675,6 +666,9 @@ setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, getVAStart(), FileOff, Target->getPageSize()); + Elf_Phdr TlsPhdrStorage; + Elf_Phdr *TlsPhdr = nullptr; + uintX_t ThreadBSSOffset = 0; // Create phdrs as we assign VAs and file offsets to all output sections. SmallPtrSet Closed; for (OutputSectionBase *Sec : OutputSections) { @@ -697,17 +691,40 @@ } } - if (consumesVirtualAddressSpace(Sec)) { + if (Sec->getSize() && (Sec->getFlags() & SHF_ALLOC) && + (Sec->getFlags() & SHF_TLS)) { + if (!TlsPhdr) { + TlsPhdr = &TlsPhdrStorage; + 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; + ThreadBSSOffset += 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) + Phdrs[++PhdrIdx] = TlsPhdrStorage; + // Add an entry for .dynamic. if (isOutputDynamic()) { Elf_Phdr *PH = &Phdrs[++PhdrIdx]; @@ -728,6 +745,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; @@ -737,12 +755,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: }