Index: lib/ReaderWriter/ELF/SegmentChunks.cpp =================================================================== --- lib/ReaderWriter/ELF/SegmentChunks.cpp +++ lib/ReaderWriter/ELF/SegmentChunks.cpp @@ -188,6 +188,7 @@ uint64_t tlsStartAddr = 0; bool alignSegments = this->_ctx.alignSegments(); StringRef prevOutputSectionName = StringRef(); + uint64_t tbssMemsize = 0; // If this is first section in the segment, page align the section start // address. The linker needs to align the data section to a page boundary @@ -231,8 +232,12 @@ // segment. If we see a tbss section, don't add memory size to addr The // fileOffset is automatically taken care of since TBSS section does not // end up using file size - if ((*si)->order() != TargetLayout::ORDER_TBSS) + if ((*si)->order() != TargetLayout::ORDER_TBSS) { curSliceSize = (*si)->memSize(); + tbssMemsize = 0; + } else { + tbssMemsize = (*si)->memSize(); + } ++currSection; ++si; } @@ -292,6 +297,8 @@ slice->setVirtualAddr(curSliceAddress); // Start new slice curSliceAddress = newAddr; + if ((*si)->order() == TargetLayout::ORDER_TBSS) + curSliceAddress += tbssMemsize; (*si)->setVirtualAddr(curSliceAddress); startSectionIter = si; startSection = currSection; @@ -302,6 +309,8 @@ } else { if (sliceAlign < (*si)->alignment()) sliceAlign = (*si)->alignment(); + if ((*si)->order() == TargetLayout::ORDER_TBSS) + newAddr += tbssMemsize; (*si)->setVirtualAddr(newAddr); // Handle TLS. if (auto section = dyn_cast>(*si)) { @@ -318,10 +327,16 @@ // any segment. If we see a tbss section, don't add memory size to addr // The fileOffset is automatically taken care of since TBSS section does // not end up using file size. - if ((*si)->order() != TargetLayout::ORDER_TBSS) + if ((*si)->order() != TargetLayout::ORDER_TBSS) { curSliceSize = newAddr - curSliceAddress + (*si)->memSize(); - else - curSliceSize = newAddr - curSliceAddress; + tbssMemsize = 0; + } else { + // Although TBSS section does not contribute to memory of any segment, + // we still need to keep track its total size to correct write it + // down. Since it is done based on curSliceAddress, we need to add + // add it to virtual address. + tbssMemsize = (*si)->memSize(); + } } prevOutputSectionName = curOutputSectionName; ++currSection; Index: test/elf/Inputs/tls-tbss-size.yaml =================================================================== --- /dev/null +++ test/elf/Inputs/tls-tbss-size.yaml @@ -0,0 +1,60 @@ +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_GNU + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .tbss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + AddressAlign: 0x0000000000000004 + Content: 00636C616E672076657273696F6E2033 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: t1.c + Type: STT_FILE + - Name: .tbss + Type: STT_TLS + Section: .tbss + Global: + - Name: t0 + Type: STT_TLS + Section: .tbss + Size: 0x0000000000000004 + - Name: t1 + Type: STT_TLS + Section: .tbss + Value: 0x0000000000000004 + Size: 0x0000000000000004 + - Name: t2 + Type: STT_TLS + Section: .tbss + Value: 0x0000000000000008 + Size: 0x0000000000000004 + - Name: t3 + Type: STT_TLS + Section: .tbss + Value: 0x000000000000000C + Size: 0x0000000000000004 +... Index: test/elf/tls-tbss-size.test =================================================================== --- /dev/null +++ test/elf/tls-tbss-size.test @@ -0,0 +1,177 @@ +# This test verify if external TLS non initialized variables (tbss) are +# accounted in TBSS segment size + +# The input file 'test/elf/Inputs/tls-tbss-size.yaml' declares: +# +# __thread int t0; +# __thread int t1; +# __thread int t2; +# __thread int t3; +# +# And the 'test/elf/tls-tbss-size.test' defines: +# +# __thread int t4; +# __thread int t5; +# __thread int t6; +# __thread int t7; +# +# __thread int t8 = 3; +# __thread int t9 = 4; +# __thread int t10 = 5; +# __thread int t11 = 6; + +#RUN: yaml2obj -format=elf -o=%t-t1.o %p/Inputs/tls-tbss-size.yaml +#RUN: yaml2obj -format=elf -o=%t-t0.o %s +#RUN: lld -flavor gnu -target x86_64-linux --noinhibit-exec -o %t.exe %t-t0.o %t-t1.o +#RUN: llvm-readobj --sections %t.exe | FileCheck %s + +#CHECK: Sections [ +#CHECK: Section { +#CHECK: Index: 9 +#CHECK: Name: .tdata (71) +#CHECK: Size: 16 +#CHECK: } +#CHECK: Section { +#CHECK: Index: 10 +#CHECK: Name: .tbss (78) +#CHECK: Size: 32 +#CHECK: } + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_GNU + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000010 + Content: 488B050000000064C70001000000488B050000000064C70002000000488B050000000064C70003000000488B050000000064C7000400000064C70425000000000500000064C70425000000000600000064C70425000000000700000064C70425000000000800000031C0C3 + - Name: .rela.text + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .text + Relocations: + - Offset: 0x0000000000000003 + Symbol: t0 + Type: R_X86_64_GOTTPOFF + Addend: -4 + - Offset: 0x0000000000000011 + Symbol: t1 + Type: R_X86_64_GOTTPOFF + Addend: -4 + - Offset: 0x000000000000001F + Symbol: t2 + Type: R_X86_64_GOTTPOFF + Addend: -4 + - Offset: 0x000000000000002D + Symbol: t3 + Type: R_X86_64_GOTTPOFF + Addend: -4 + - Offset: 0x000000000000003C + Symbol: t4 + Type: R_X86_64_TPOFF32 + - Offset: 0x0000000000000048 + Symbol: t5 + Type: R_X86_64_TPOFF32 + - Offset: 0x0000000000000054 + Symbol: t6 + Type: R_X86_64_TPOFF32 + - Offset: 0x0000000000000060 + Symbol: t7 + Type: R_X86_64_TPOFF32 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .tdata + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + AddressAlign: 0x0000000000000004 + Content: '03000000040000000500000006000000' + - Name: .tbss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + AddressAlign: 0x0000000000000004 + Content: 00636C616E672076657273696F6E2033 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x0000000000000008 + Content: 1400000000000000017A5200017810011B0C070890010000140000001C000000000000006B0000000000000000000000 +Symbols: + Local: + - Name: .tbss + Type: STT_TLS + Section: .tbss + - Name: .tdata + Type: STT_TLS + Section: .tdata + - Type: STT_SECTION + Section: .text + Global: + - Name: main + Type: STT_FUNC + Section: .text + Size: 0x000000000000006B + - Name: t0 + Type: STT_TLS + - Name: t1 + Type: STT_TLS + - Name: t10 + Type: STT_TLS + Section: .tdata + Value: 0x0000000000000008 + Size: 0x0000000000000004 + - Name: t11 + Type: STT_TLS + Section: .tdata + Value: 0x000000000000000C + Size: 0x0000000000000004 + - Name: t2 + Type: STT_TLS + - Name: t3 + Type: STT_TLS + - Name: t4 + Type: STT_TLS + Section: .tbss + Size: 0x0000000000000004 + - Name: t5 + Type: STT_TLS + Section: .tbss + Value: 0x0000000000000004 + Size: 0x0000000000000004 + - Name: t6 + Type: STT_TLS + Section: .tbss + Value: 0x0000000000000008 + Size: 0x0000000000000004 + - Name: t7 + Type: STT_TLS + Section: .tbss + Value: 0x000000000000000C + Size: 0x0000000000000004 + - Name: t8 + Type: STT_TLS + Section: .tdata + Size: 0x0000000000000004 + - Name: t9 + Type: STT_TLS + Section: .tdata + Value: 0x0000000000000004 + Size: 0x0000000000000004 +...