[ELF] Fix wrong TBSS size

This patch fixes the wrong .tbss segment size generated for cases where
multiple modules have non initialized threads variables.  For instance:

* t0.c

__thread int x0;
__thread int x1;
__thread int x2;

extern __thread int e0;
extern __thread int e1;
extern __thread int e2;
extern __thread int e3;

int foo0 ()
{
  return x0;
}

int main ()
{
  return x0;
}

* t1.c

__thread int e0;
__thread int e1;
__thread int e2;
__thread int e3;


lld is generating (for aarch64):

  [14] .tbss             NOBITS           0000000000401000  00001000
       0000000000000010  0000000000000000 WAT       0     0     4

Where is just taking in consideration the largest tbss segment, not all
from all objects.  ld generates a correct output:

  [17] .tbss             NOBITS           0000000000410dec  00000dec
       000000000000001c  0000000000000000 WAT       0     0     4

This issue is at 'lib/ReaderWriter/ELF/SegmentChunks.cpp' where
Segment<ELFT>::assignVirtualAddress is setting wrong slice values, not taking care
of although tbss segments file size does noy play role in other segment virtual
address placement, its size should still be considered.

llvm-svn: 239906
This commit is contained in:
Adhemerval Zanella 2015-06-17 13:46:07 +00:00
parent 1a1083285c
commit 9c5831f3de
3 changed files with 256 additions and 4 deletions

View File

@ -188,6 +188,7 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
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 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
// 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<ELFT>::ORDER_TBSS)
if ((*si)->order() != TargetLayout<ELFT>::ORDER_TBSS) {
curSliceSize = (*si)->memSize();
tbssMemsize = 0;
} else {
tbssMemsize = (*si)->memSize();
}
++currSection;
++si;
}
@ -292,6 +297,8 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
slice->setVirtualAddr(curSliceAddress);
// Start new slice
curSliceAddress = newAddr;
if ((*si)->order() == TargetLayout<ELFT>::ORDER_TBSS)
curSliceAddress += tbssMemsize;
(*si)->setVirtualAddr(curSliceAddress);
startSectionIter = si;
startSection = currSection;
@ -302,6 +309,8 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
} else {
if (sliceAlign < (*si)->alignment())
sliceAlign = (*si)->alignment();
if ((*si)->order() == TargetLayout<ELFT>::ORDER_TBSS)
newAddr += tbssMemsize;
(*si)->setVirtualAddr(newAddr);
// Handle TLS.
if (auto section = dyn_cast<Section<ELFT>>(*si)) {
@ -318,10 +327,16 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
// 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<ELFT>::ORDER_TBSS)
if ((*si)->order() != TargetLayout<ELFT>::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;

View File

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

View File

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