Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -14,6 +14,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" namespace lld { @@ -36,6 +37,11 @@ StringRef SectionPattern; }; +struct OutSection { + StringRef Name; + llvm::support::ubig32_t Filler = (llvm::support::ubig32_t)0; +}; + // This is a runner of the linker script. class LinkerScript { friend class ScriptParser; @@ -46,6 +52,7 @@ void read(MemoryBufferRef MB); template StringRef getOutputSection(InputSectionBase *S); + ArrayRef getFiller(StringRef Name); template bool isDiscarded(InputSectionBase *S); int compareSections(StringRef A, StringRef B); @@ -53,8 +60,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 @@ -43,13 +43,24 @@ return getOutputSection(S) == "/DISCARD/"; } +struct FindSec { + StringRef Val; + bool operator()(const OutSection &C) { return C.Name == Val; } +}; + +ArrayRef LinkerScript::getFiller(StringRef Name) { + auto I = std::find_if(OutSections.begin(), OutSections.end(), FindSec{Name}); + if (I == OutSections.end() || I->Filler == 0) + return ArrayRef(); + return ArrayRef((uint8_t *)&I->Filler, sizeof(I->Filler)); +} // 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.Filler = llvm::support::ubig32_t(Val); + next(); } + Script->OutSections.push_back(OutSec); } static bool isUnderSysroot(StringRef Path) { Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -9,6 +9,7 @@ #include "OutputSections.h" #include "Config.h" +#include "LinkerScript.h" #include "SymbolTable.h" #include "Target.h" #include "llvm/Support/Dwarf.h" @@ -938,7 +939,17 @@ return true; } +static void fill(uint8_t *Buf, size_t Size, ArrayRef A) { + size_t I = 0; + for (; I + A.size() < Size; I += A.size()) + memcpy(Buf + I, A.data(), A.size()); + memcpy(Buf + I, A.data(), Size - I); +} + template void OutputSection::writeTo(uint8_t *Buf) { + ArrayRef Filler = Script->getFiller(Name); + if (!Filler.empty()) + fill(Buf, getSize(), Filler); for (InputSection *C : Sections) C->writeTo(Buf); } 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*) } =0x90909090 }" > %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 90 90 90 66 + +## Confirming that address was correct: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x80808080 }" > %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 80 80 80 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