Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -40,6 +40,11 @@ StringRef SectionPattern; }; +struct OutSection { + StringRef Name; + std::vector Filler; +}; + // This is a runner of the linker script. class LinkerScript { friend class ScriptParser; @@ -50,6 +55,7 @@ void read(MemoryBufferRef MB); template StringRef getOutputSection(InputSectionBase *S); + ArrayRef getFiller(StringRef Name); template bool isDiscarded(InputSectionBase *S); template bool shouldKeep(InputSectionBase *S); int compareSections(StringRef A, StringRef B); @@ -60,8 +66,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 @@ -54,13 +54,22 @@ return R && R->Keep; } +ArrayRef LinkerScript::getFiller(StringRef Name) { + for (OutSection &C : OutSections) + if (C.Name == Name) + return C.Filler; + return{}; +} + // 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, + [&](OutSection &C) { return C.Name == A; }); + auto J = std::find_if(OutSections.begin(), E, + [&](OutSection &C) { return C.Name == B; }); if (I == E || J == E) return 0; return I < J ? -1 : 1; @@ -109,6 +118,7 @@ static StringRef skipSpace(StringRef S); bool atEOF(); StringRef next(); + StringRef peek(); bool skip(StringRef Tok); void expect(StringRef Expect); @@ -129,6 +139,8 @@ void readOutputSectionDescription(); void readSectionPatterns(StringRef OutSec, bool Keep); + std::vector readHex(StringRef S); + StringSaver Saver; std::vector Tokens; const static StringMap Cmd; @@ -233,6 +245,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; @@ -394,24 +414,54 @@ Script->Sections.emplace_back(OutSec, next(), Keep); } +std::vector ScriptParser::readHex(StringRef S) { + std::vector Hex; + Hex.reserve((S.size() + 1) / 2); + + while (!S.empty()) { + StringRef B = S.substr(0, 2); + S = S.slice(2, S.size()); + uint8_t H; + if (B.getAsInteger(16, H)) { + setError("Not a HEX value: " + B); + return {}; + } + Hex.push_back(H); + } + return Hex; +} + void ScriptParser::readOutputSectionDescription() { - StringRef OutSec = next(); - Script->SectionOrder.push_back(OutSec); + OutSection OutSec; + OutSec.Name = next(); expect(":"); expect("{"); while (!Error && !skip("}")) { StringRef Tok = next(); if (Tok == "*") { - readSectionPatterns(OutSec, false); + readSectionPatterns(OutSec.Name, false); } else if (Tok == "KEEP") { expect("("); next(); // Skip * - readSectionPatterns(OutSec, true); + readSectionPatterns(OutSec.Name, true); expect(")"); } else { setError("Unknown command " + Tok); } } + StringRef Tok = peek(); + if (Tok[0] == '=') { + if (!Tok.startswith("=0x")) { + setError("Filler should be a HEX value"); + return; + } + Tok = Tok.substr(3); // Skip '=0x' + OutSec.Filler = readHex(Tok); + if (Error) + return; + 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" @@ -965,7 +966,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,44 @@ +# 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*) } =0x112233445566778899 }" > %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 22 33 44 55 66 77 88 99 11 22 33 44 55 66 77 + +## Confirming that address was correct: +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x998877665544332211 }" > %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 88 77 66 55 44 33 22 11 99 88 77 66 55 44 + +## Default padding value is 0x00: +# 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 00 00 00 00 00 00 00 00 00 00 00 00 + +## Filler should be a hex value (1): +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =99 }" > %t.script +# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \ +# RUN: | FileCheck --check-prefix=ERR %s +# ERR: Filler should be a HEX value + +## Filler should be a hex value (2): +# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99XX }" > %t.script +# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \ +# RUN: | FileCheck --check-prefix=ERR2 %s +# ERR2: Not a HEX value: XX + +.section .mysec.1,"a" +.align 16 +.byte 0x66 + +.section .mysec.2,"a" +.align 16 +.byte 0x66 + +.globl _start +_start: + nop