diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 3f872c65897f..35b882543042 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -495,17 +495,22 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { } } -static bool isTbss(OutputSection *Sec) { - return (Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS; +uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) { + bool IsTbss = (CurOutSec->Flags & SHF_TLS) && CurOutSec->Type == SHT_NOBITS; + uint64_t Start = IsTbss ? Dot + ThreadBssOffset : Dot; + Start = alignTo(Start, Align); + uint64_t End = Start + Size; + + if (IsTbss) + ThreadBssOffset = End - Dot; + else + Dot = End; + return End; } void LinkerScript::output(InputSection *S) { - bool IsTbss = isTbss(CurOutSec); - - uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot; - Pos = alignTo(Pos, S->Alignment); - S->OutSecOff = Pos - CurOutSec->Addr; - Pos += S->getSize(); + uint64_t Pos = advance(S->getSize(), S->Alignment); + S->OutSecOff = Pos - S->getSize() - CurOutSec->Addr; // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: @@ -524,11 +529,6 @@ void LinkerScript::output(InputSection *S) { " bytes"); } } - - if (IsTbss) - ThreadBssOffset = Pos - Dot; - else - Dot = Pos; } void LinkerScript::switchTo(OutputSection *Sec) { @@ -536,9 +536,7 @@ void LinkerScript::switchTo(OutputSection *Sec) { return; CurOutSec = Sec; - - Dot = alignTo(Dot, CurOutSec->Alignment); - CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot; + CurOutSec->Addr = advance(0, CurOutSec->Alignment); // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index dd96d335a660..b4ca6535891a 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -228,6 +228,7 @@ protected: MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd); void switchTo(OutputSection *Sec); + uint64_t advance(uint64_t Size, unsigned Align); void output(InputSection *Sec); void process(BaseCommand &Base); diff --git a/lld/test/ELF/tls-offset.s b/lld/test/ELF/tls-offset.s index 062def4e14fc..75d9af7f5b72 100644 --- a/lld/test/ELF/tls-offset.s +++ b/lld/test/ELF/tls-offset.s @@ -10,7 +10,7 @@ // RUN: .tbss : { *(.tbss) } \ // RUN: .data.rel.ro : { *(.data.rel.ro) } \ // RUN: }" > %t.script - // RUN: ld.lld -T %t.script %t -o %tout2 +// RUN: ld.lld -T %t.script %t -o %tout2 // RUN: echo SCRIPT // RUN: llvm-readobj -s %tout2 | FileCheck %s .global _start @@ -61,6 +61,6 @@ _start: // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x202010 -// CHECK-NEXT: Offset: 0x2010 +// CHECK-NEXT: Address: 0x202004 +// CHECK-NEXT: Offset: 0x2004 // CHECK-NEXT: Size: 4