[ELF] Fix wrong TBSS size
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Wed, 17 Jun 2015 13:46:07 +0000 (13:46 +0000)
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Wed, 17 Jun 2015 13:46:07 +0000 (13:46 +0000)
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

lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
lld/test/elf/Inputs/tls-tbss-size.yaml [new file with mode: 0644]
lld/test/elf/tls-tbss-size.test [new file with mode: 0644]

index ab92cf9..9f4c89f 100644 (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;
diff --git a/lld/test/elf/Inputs/tls-tbss-size.yaml b/lld/test/elf/Inputs/tls-tbss-size.yaml
new file mode 100644 (file)
index 0000000..db82f5f
--- /dev/null
@@ -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
+...
diff --git a/lld/test/elf/tls-tbss-size.test b/lld/test/elf/tls-tbss-size.test
new file mode 100644 (file)
index 0000000..52550f7
--- /dev/null
@@ -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
+...