[lld] r262020 - [ELF] - Implemented linkerscript sections padding.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 26 06:48:32 PST 2016
Author: grimar
Date: Fri Feb 26 08:48:31 2016
New Revision: 262020
URL: http://llvm.org/viewvc/llvm-project?rev=262020&view=rev
Log:
[ELF] - Implemented linkerscript sections padding.
BSD linker scripts contain special cases to add NOP
padding to code sections. Syntax is next:
.init:
{
KEEP (*(.init))
} =0x90909090
(0x90 is NOP)
This patch implements that functionality.
Added:
lld/trunk/test/ELF/linkerscript-sections-padding.s
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/LinkerScript.h
lld/trunk/ELF/OutputSections.cpp
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=262020&r1=262019&r2=262020&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Feb 26 08:48:31 2016
@@ -54,13 +54,22 @@ template <class ELFT> bool LinkerScript:
return R && R->Keep;
}
+ArrayRef<uint8_t> 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 @@ private:
static StringRef skipSpace(StringRef S);
bool atEOF();
StringRef next();
+ StringRef peek();
bool skip(StringRef Tok);
void expect(StringRef Expect);
@@ -129,6 +139,8 @@ private:
void readOutputSectionDescription();
void readSectionPatterns(StringRef OutSec, bool Keep);
+ std::vector<uint8_t> parseHex(StringRef S);
+
StringSaver Saver;
std::vector<StringRef> Tokens;
const static StringMap<Handler> Cmd;
@@ -233,6 +245,14 @@ StringRef ScriptParser::next() {
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,50 @@ void ScriptParser::readSectionPatterns(S
Script->Sections.emplace_back(OutSec, next(), Keep);
}
+std::vector<uint8_t> ScriptParser::parseHex(StringRef S) {
+ std::vector<uint8_t> Hex;
+ while (!S.empty()) {
+ StringRef B = S.substr(0, 2);
+ S = S.substr(2);
+ 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.startswith("=")) {
+ if (!Tok.startswith("=0x")) {
+ setError("Filler should be a HEX value");
+ return;
+ }
+ Tok = Tok.substr(3); // Skip '=0x'
+ OutSec.Filler = parseHex(Tok);
+ next();
+ }
+ Script->OutSections.push_back(OutSec);
}
static bool isUnderSysroot(StringRef Path) {
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=262020&r1=262019&r2=262020&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Fri Feb 26 08:48:31 2016
@@ -40,6 +40,11 @@ private:
StringRef SectionPattern;
};
+struct OutSection {
+ StringRef Name;
+ std::vector<uint8_t> Filler;
+};
+
// This is a runner of the linker script.
class LinkerScript {
friend class ScriptParser;
@@ -50,6 +55,7 @@ public:
void read(MemoryBufferRef MB);
template <class ELFT> StringRef getOutputSection(InputSectionBase<ELFT> *S);
+ ArrayRef<uint8_t> getFiller(StringRef Name);
template <class ELFT> bool isDiscarded(InputSectionBase<ELFT> *S);
template <class ELFT> bool shouldKeep(InputSectionBase<ELFT> *S);
int compareSections(StringRef A, StringRef B);
@@ -60,8 +66,9 @@ private:
// SECTIONS commands.
std::vector<SectionRule> Sections;
- // Output sections are sorted by this order.
- std::vector<StringRef> SectionOrder;
+ // Output sections information.
+ // They are sorted by the order of the container.
+ std::vector<OutSection> OutSections;
llvm::BumpPtrAllocator Alloc;
};
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=262020&r1=262019&r2=262020&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Fri Feb 26 08:48:31 2016
@@ -9,6 +9,7 @@
#include "OutputSections.h"
#include "Config.h"
+#include "LinkerScript.h"
#include "SymbolTable.h"
#include "Target.h"
#include "llvm/Support/Dwarf.h"
@@ -954,7 +955,17 @@ bool elf2::canBePreempted(const SymbolBo
return true;
}
+static void fill(uint8_t *Buf, size_t Size, ArrayRef<uint8_t> 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 <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ ArrayRef<uint8_t> Filler = Script->getFiller(this->Name);
+ if (!Filler.empty())
+ fill(Buf, this->getSize(), Filler);
for (InputSection<ELFT> *C : Sections)
C->writeTo(Buf);
}
Added: lld/trunk/test/ELF/linkerscript-sections-padding.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-sections-padding.s?rev=262020&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript-sections-padding.s (added)
+++ lld/trunk/test/ELF/linkerscript-sections-padding.s Fri Feb 26 08:48:31 2016
@@ -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
More information about the llvm-commits
mailing list