Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -46,6 +46,7 @@ SectionsCommandKind Kind; std::vector Expr; StringRef SectionName; + bool IsFromParser; }; // ScriptConfiguration holds linker script parse results. Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -207,6 +207,25 @@ } template +static typename ELFT::uint calculateSectionVA(typename ELFT::uint VA, + bool sectionIsFromParser, + OutputSectionBase *PrevSec, + OutputSectionBase *Sec) { + typedef typename ELFT::uint uintX_t; + uintX_t Alignment = Sec->getAlignment(); + if (PrevSec && !sectionIsFromParser) { + uintX_t secAttrs = Sec->getFlags() & (SHF_EXECINSTR | SHF_WRITE); + uintX_t prevSecAttrs = PrevSec->getFlags() & (SHF_EXECINSTR | SHF_WRITE); + + if (secAttrs != prevSecAttrs && + pageNo(VA) == pageNo(PrevSec->getVA() + PrevSec->getSize())) + Alignment = std::max(Alignment, static_cast(Target->PageSize)); + } + VA = alignTo(VA, Alignment); + return VA; +} + +template void LinkerScript::assignAddresses( ArrayRef *> Sections) { // Orphan sections are sections present in the input files which @@ -217,12 +236,13 @@ for (OutputSectionBase *Sec : Sections) { StringRef Name = Sec->getName(); if (getSectionIndex(Name) == INT_MAX) - Opt.Commands.push_back({SectionKind, {}, Name}); + Opt.Commands.push_back({SectionKind, {}, Name, false}); } // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); uintX_t MinVA = std::numeric_limits::max(); + OutputSectionBase *PrevSec = nullptr; uintX_t ThreadBssOffset = 0; for (SectionsCommand &Cmd : Opt.Commands) { @@ -247,10 +267,11 @@ } if (Sec->getFlags() & SHF_ALLOC) { - Dot = alignTo(Dot, Sec->getAlignment()); + Dot = calculateSectionVA(Dot, Cmd.IsFromParser, PrevSec, Sec); Sec->setVA(Dot); MinVA = std::min(MinVA, Dot); Dot += Sec->getSize(); + PrevSec = Sec; continue; } } @@ -496,7 +517,7 @@ void ScriptParser::readLocationCounterValue() { expect("."); expect("="); - Opt.Commands.push_back({ExprKind, {}, ""}); + Opt.Commands.push_back({ExprKind, {}, "", true}); SectionsCommand &Cmd = Opt.Commands.back(); while (!Error) { StringRef Tok = next(); @@ -510,7 +531,7 @@ void ScriptParser::readOutputSectionDescription() { StringRef OutSec = next(); - Opt.Commands.push_back({SectionKind, {}, OutSec}); + Opt.Commands.push_back({SectionKind, {}, OutSec, true}); expect(":"); expect("{"); Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -105,7 +105,11 @@ extern TargetInfo *Target; TargetInfo *createTarget(); + +template static inline T pageNo(T address) { + return address / Target->PageSize; } } +} #endif Index: test/ELF/end.s =================================================================== --- test/ELF/end.s +++ test/ELF/end.s @@ -36,13 +36,13 @@ // NOBSS-NEXT: SHF_ALLOC // NOBSS-NEXT: SHF_WRITE // NOBSS-NEXT: ] -// NOBSS-NEXT: Address: 0x159 +// NOBSS-NEXT: Address: 0x1000 // NOBSS-NEXT: Offset: // NOBSS-NEXT: Size: 2 // NOBSS: ] // NOBSS: Symbols [ // NOBSS: Name: _end -// NOBSS-NEXT: Value: 0x15B +// NOBSS-NEXT: Value: 0x1002 // NOBSS: ] // If the layout of the sections is changed, "_end" should point to the end of allocated address space. Index: test/ELF/linkerscript-repsection-va.s =================================================================== --- test/ELF/linkerscript-repsection-va.s +++ test/ELF/linkerscript-repsection-va.s @@ -9,7 +9,7 @@ # CHECK-NEXT: 0 00000000 0000000000000000 # CHECK-NEXT: 1 .foo 00000004 0000000000000158 DATA # CHECK-NEXT: 2 .foo 00000004 000000000000015c DATA -# CHECK-NEXT: 3 .text 00000001 0000000000000160 TEXT DATA +# CHECK-NEXT: 3 .text 00000001 0000000000001000 TEXT DATA .global _start _start: Index: test/ELF/linkerscript-sections-keep.s =================================================================== --- test/ELF/linkerscript-sections-keep.s +++ test/ELF/linkerscript-sections-keep.s @@ -43,7 +43,7 @@ # MIXED1-NEXT: 0 00000000 0000000000000000 # MIXED1-NEXT: 1 .keep 00000004 0000000000000120 DATA # MIXED1-NEXT: 2 .temp 00000004 0000000000000124 DATA -# MIXED1-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA +# MIXED1-NEXT: 3 .text 00000007 0000000000001000 TEXT DATA # MIXED1-NEXT: 4 .symtab 00000060 0000000000000000 # MIXED1-NEXT: 5 .shstrtab 0000002d 0000000000000000 # MIXED1-NEXT: 6 .strtab 00000012 0000000000000000 @@ -62,7 +62,7 @@ # MIXED2-NEXT: 0 00000000 0000000000000000 # MIXED2-NEXT: 1 .nokeep 00000004 0000000000000120 DATA # MIXED2-NEXT: 2 .temp 00000004 0000000000000124 DATA -# MIXED2-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA +# MIXED2-NEXT: 3 .text 00000007 0000000000001000 TEXT DATA # MIXED2-NEXT: 4 .symtab 00000060 0000000000000000 # MIXED2-NEXT: 5 .shstrtab 0000002f 0000000000000000 # MIXED2-NEXT: 6 .strtab 00000012 0000000000000000 Index: test/ELF/linkerscript-va.s =================================================================== --- test/ELF/linkerscript-va.s +++ test/ELF/linkerscript-va.s @@ -9,7 +9,7 @@ # CHECK-NEXT: 0 00000000 0000000000000000 # CHECK-NEXT: 1 .foo 00000004 0000000000000120 DATA # CHECK-NEXT: 2 .boo 00000004 0000000000000124 DATA -# CHECK-NEXT: 3 .text 00000001 0000000000000128 TEXT DATA +# CHECK-NEXT: 3 .text 00000001 0000000000001000 TEXT DATA .global _start _start: