Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -166,6 +166,10 @@ // to. The writer sets a value. uint64_t OutSecOff = 0; + // Amount of bytes padded from previous input section in the same output if + // any is exist. + uint64_t PadBehind = 0; + static bool classof(const InputSectionBase *S); }; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -246,6 +246,20 @@ template void InputSection::writeTo(uint8_t *Buf) { if (this->Header->sh_type == SHT_NOBITS) return; + + // If there is some padding behind and value for padding is + // not null, this one fills the space repeating 4 bytes of + // padding value. + if (PadBehind && OutSec->PaddingValue) { + llvm::support::ubig32_t Bytes(OutSec->PaddingValue); + int I = OutSecOff - PadBehind; + while (PadBehind) { + Buf[OutSecOff - PadBehind] = + ((uint8_t *)&Bytes)[(OutSecOff - PadBehind - I) % 4]; + --PadBehind; + } + } + // Copy section contents from source object file to output file. ArrayRef Data = this->getSectionData(); memcpy(Buf + OutSecOff, Data.data(), Data.size()); Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -36,6 +36,11 @@ StringRef SectionPattern; }; +struct OutSection { + StringRef Name; + uint32_t Padding = 0x0; +}; + // This is a runner of the linker script. class LinkerScript { friend class ScriptParser; @@ -45,7 +50,8 @@ // this object and Config. void read(MemoryBufferRef MB); - template StringRef getOutputSection(InputSectionBase *S); + template StringRef getOutSectionName(InputSectionBase *S); + const OutSection *getOutputSection(StringRef Name) const; template bool isDiscarded(InputSectionBase *S); int compareSections(StringRef A, StringRef B); @@ -53,8 +59,9 @@ // SECTIONS commands. std::vector Sections; - // Output sections are sorted by this order. - std::vector SectionOrder; + // Output sections information. + // They are sorted by the order of the container. + std::vector OutSections; llvm::BumpPtrAllocator Alloc; }; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -31,7 +31,7 @@ LinkerScript *elf2::Script; template -StringRef LinkerScript::getOutputSection(InputSectionBase *S) { +StringRef LinkerScript::getOutSectionName(InputSectionBase *S) { for (SectionRule &R : Sections) if (R.match(S)) return R.Dest; @@ -40,16 +40,27 @@ template bool LinkerScript::isDiscarded(InputSectionBase *S) { - return getOutputSection(S) == "/DISCARD/"; + return getOutSectionName(S) == "/DISCARD/"; } +struct FindSec { + StringRef Val; + bool operator()(const OutSection &C) { return C.Name == Val; } +}; + +const OutSection *LinkerScript::getOutputSection(StringRef Name) const { + auto I = std::find_if(OutSections.begin(), OutSections.end(), FindSec{Name}); + if (I == OutSections.end()) + return nullptr; + return &*I; +} // A compartor to sort output sections. Returns -1 or 1 if both // A and B are mentioned in linker scripts. Otherwise, returns 0 // to use the default rule which is implemented in Writer.cpp. int LinkerScript::compareSections(StringRef A, StringRef B) { - auto E = SectionOrder.end(); - auto I = std::find(SectionOrder.begin(), E, A); - auto J = std::find(SectionOrder.begin(), E, B); + auto E = OutSections.end(); + auto I = std::find_if(OutSections.begin(), E, FindSec{A}); + auto J = std::find_if(OutSections.begin(), E, FindSec{B}); if (I == E || J == E) return 0; return I < J ? -1 : 1; @@ -94,6 +105,7 @@ static StringRef skipSpace(StringRef S); bool atEOF(); StringRef next(); + StringRef peek(); bool skip(StringRef Tok); void expect(StringRef Expect); @@ -222,6 +234,14 @@ return Tokens[Pos++]; } +StringRef ScriptParser::peek() { + StringRef Tok = next(); + if (Error) + return ""; + --Pos; + return Tok; +} + bool ScriptParser::skip(StringRef Tok) { if (Error) return false; @@ -378,16 +398,28 @@ } void ScriptParser::readOutputSectionDescription() { - StringRef OutSec = next(); - Script->SectionOrder.push_back(OutSec); + OutSection OutSec; + OutSec.Name = next(); expect(":"); expect("{"); while (!Error && !skip("}")) { next(); // Skip input file name. expect("("); while (!Error && !skip(")")) - Script->Sections.push_back({OutSec, next()}); + Script->Sections.push_back({OutSec.Name, next()}); + } + StringRef Tok = peek(); + if (Tok[0] == '=') { + Tok = Tok.substr(1); + uint32_t Val; + if (Tok.getAsInteger(0, Val)) { + error("Integer can't be parsed: " + Tok); + return; + } + OutSec.Padding = Val; + next(); } + Script->OutSections.push_back(OutSec); } static bool isUnderSysroot(StringRef Path) { @@ -405,10 +437,10 @@ ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); } -template StringRef LinkerScript::getOutputSection(InputSectionBase *); -template StringRef LinkerScript::getOutputSection(InputSectionBase *); -template StringRef LinkerScript::getOutputSection(InputSectionBase *); -template StringRef LinkerScript::getOutputSection(InputSectionBase *); +template StringRef LinkerScript::getOutSectionName(InputSectionBase *); +template StringRef LinkerScript::getOutSectionName(InputSectionBase *); +template StringRef LinkerScript::getOutSectionName(InputSectionBase *); +template StringRef LinkerScript::getOutSectionName(InputSectionBase *); template bool LinkerScript::isDiscarded(InputSectionBase *); template bool LinkerScript::isDiscarded(InputSectionBase *); Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -76,6 +76,7 @@ virtual void addSection(InputSectionBase *C) {} unsigned SectionIndex; + uint32_t PaddingValue = 0x0; // Returns the size of the section in the output file. uintX_t getSize() const { return Header.sh_size; } Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -743,8 +743,8 @@ uint32_t Align = S->getAlign(); this->updateAlign(Align); - uintX_t Off = this->Header.sh_size; - Off = alignTo(Off, Align); + uintX_t Off = alignTo(this->Header.sh_size, Align); + S->PadBehind = Off - this->Header.sh_size; S->OutSecOff = Off; Off += S->getSize(); this->Header.sh_size = Off; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -727,7 +727,7 @@ template StringRef Writer::getOutputSectionName(InputSectionBase *S) const { - StringRef Dest = Script->getOutputSection(S); + StringRef Dest = Script->getOutSectionName(S); if (!Dest.empty()) return Dest; @@ -842,6 +842,10 @@ Sec = new MipsReginfoOutputSection(); break; } + + if (const OutSection *S = Script->getOutputSection(OutsecName)) + Sec->PaddingValue = S->Padding; + return {Sec, true}; } Index: test/ELF/linkerscript-sections-padding.s =================================================================== --- test/ELF/linkerscript-sections-padding.s +++ test/ELF/linkerscript-sections-padding.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Check that padding value works: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x11223344 }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: hexdump -C %t.out | FileCheck -check-prefix=YES %s +# YES: 00000120 66 11 22 33 66 + +## Confirming that address was correct: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x55667788 }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: hexdump -C %t.out | FileCheck -check-prefix=YES2 %s +# YES2: 00000120 66 55 66 77 66 + +## Default padding value is 0x00000000 +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: hexdump -C %t.out | FileCheck -check-prefix=NO %s +# NO: 00000120 66 00 00 00 66 + +.section .mysec.1,"a" +.align 4 +.byte 0x66 + +.section .mysec.2,"a" +.align 4 +.byte 0x66 + +.globl _start +_start: + nop