[lld] r260591 - ELF: Create LinkerScript class to move code out of Writer.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 11 13:18:00 PST 2016
Author: ruiu
Date: Thu Feb 11 15:17:59 2016
New Revision: 260591
URL: http://llvm.org/viewvc/llvm-project?rev=260591&view=rev
Log:
ELF: Create LinkerScript class to move code out of Writer.
Previously, we had code for linker scripts in Writer. This patch
separates that as LinkerScript class. The class provides a few
functions to query linker scripts and is also a container of some
linker-script-specific information.
Hopefully, Writer will only implement the default behavior and let
the new class handle gotchas regarding linker scripts.
Added:
lld/trunk/ELF/LinkerScript.h
Modified:
lld/trunk/ELF/Config.h
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Thu Feb 11 15:17:59 2016
@@ -48,7 +48,6 @@ struct Configuration {
llvm::StringRef SoName;
llvm::StringRef Sysroot;
std::string RPath;
- llvm::MapVector<llvm::StringRef, std::vector<llvm::StringRef>> OutputSections;
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> Undefined;
bool AllowMultipleDefinition;
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Feb 11 15:17:59 2016
@@ -11,6 +11,7 @@
#include "Config.h"
#include "Error.h"
#include "InputFiles.h"
+#include "LinkerScript.h"
#include "SymbolTable.h"
#include "Target.h"
#include "Writer.h"
@@ -34,8 +35,10 @@ bool elf2::link(ArrayRef<const char *> A
ErrorOS = &Error;
Configuration C;
LinkerDriver D;
+ LinkerScript LS;
Config = &C;
Driver = &D;
+ Script = &LS;
Driver->main(Args.slice(1));
return !HasError;
}
@@ -292,6 +295,7 @@ void LinkerDriver::createFiles(opt::Inpu
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
SymbolTable<ELFT> Symtab;
Target.reset(createTarget());
+ Script->finalize();
if (!Config->Shared) {
// Add entry symbol.
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Feb 11 15:17:59 2016
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+#include "LinkerScript.h"
#include "Config.h"
#include "Driver.h"
#include "SymbolTable.h"
@@ -25,10 +26,36 @@ using namespace llvm;
using namespace lld;
using namespace lld::elf2;
-namespace {
-class LinkerScript {
+LinkerScript *elf2::Script;
+
+void LinkerScript::finalize() {
+ for (const std::pair<StringRef, std::vector<StringRef>> &P : Sections)
+ for (StringRef S : P.second)
+ RevSections[S] = P.first;
+}
+
+StringRef LinkerScript::getOutputSection(StringRef S) {
+ return RevSections.lookup(S);
+}
+
+bool LinkerScript::isDiscarded(StringRef S) {
+ return RevSections.lookup(S) == "/DISCARD/";
+}
+
+int LinkerScript::compareSections(StringRef A, StringRef B) {
+ auto I = Sections.find(A);
+ auto E = Sections.end();
+ if (I == E)
+ return 0;
+ auto J = Sections.find(B);
+ if (J == E)
+ return 0;
+ return I < J ? -1 : 1;
+}
+
+class elf2::ScriptParser {
public:
- LinkerScript(BumpPtrAllocator *A, StringRef S, bool B)
+ ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
: Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
void run();
@@ -62,9 +89,8 @@ private:
size_t Pos = 0;
bool IsUnderSysroot;
};
-}
-void LinkerScript::run() {
+void ScriptParser::run() {
while (!atEOF()) {
StringRef Tok = next();
if (Tok == ";")
@@ -95,7 +121,7 @@ void LinkerScript::run() {
}
// We don't want to record cascading errors. Keep only the first one.
-void LinkerScript::setError(const Twine &Msg) {
+void ScriptParser::setError(const Twine &Msg) {
if (Error)
return;
error(Msg);
@@ -103,7 +129,7 @@ void LinkerScript::setError(const Twine
}
// Split S into linker script tokens.
-std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
+std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
std::vector<StringRef> Ret;
for (;;) {
S = skipSpace(S);
@@ -136,7 +162,7 @@ std::vector<StringRef> LinkerScript::tok
}
// Skip leading whitespace characters or /**/-style comments.
-StringRef LinkerScript::skipSpace(StringRef S) {
+StringRef ScriptParser::skipSpace(StringRef S) {
for (;;) {
if (S.startswith("/*")) {
size_t E = S.find("*/", 2);
@@ -155,9 +181,9 @@ StringRef LinkerScript::skipSpace(String
}
// An errneous token is handled as if it were the last token before EOF.
-bool LinkerScript::atEOF() { return Error || Tokens.size() == Pos; }
+bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
-StringRef LinkerScript::next() {
+StringRef ScriptParser::next() {
if (Error)
return "";
if (atEOF()) {
@@ -167,7 +193,7 @@ StringRef LinkerScript::next() {
return Tokens[Pos++];
}
-bool LinkerScript::skip(StringRef Tok) {
+bool ScriptParser::skip(StringRef Tok) {
if (Error)
return false;
if (atEOF()) {
@@ -180,7 +206,7 @@ bool LinkerScript::skip(StringRef Tok) {
return true;
}
-void LinkerScript::expect(StringRef Expect) {
+void ScriptParser::expect(StringRef Expect) {
if (Error)
return;
StringRef Tok = next();
@@ -188,7 +214,7 @@ void LinkerScript::expect(StringRef Expe
setError(Expect + " expected, but got " + Tok);
}
-void LinkerScript::addFile(StringRef S) {
+void ScriptParser::addFile(StringRef S) {
if (IsUnderSysroot && S.startswith("/")) {
SmallString<128> Path;
(Config->Sysroot + S).toStringRef(Path);
@@ -218,7 +244,7 @@ void LinkerScript::addFile(StringRef S)
}
}
-void LinkerScript::readAsNeeded() {
+void ScriptParser::readAsNeeded() {
expect("(");
bool Orig = Config->AsNeeded;
Config->AsNeeded = true;
@@ -231,7 +257,7 @@ void LinkerScript::readAsNeeded() {
Config->AsNeeded = Orig;
}
-void LinkerScript::readEntry() {
+void ScriptParser::readEntry() {
// -e <symbol> takes predecence over ENTRY(<symbol>).
expect("(");
StringRef Tok = next();
@@ -240,7 +266,7 @@ void LinkerScript::readEntry() {
expect(")");
}
-void LinkerScript::readExtern() {
+void ScriptParser::readExtern() {
expect("(");
while (!Error) {
StringRef Tok = next();
@@ -250,7 +276,7 @@ void LinkerScript::readExtern() {
}
}
-void LinkerScript::readGroup() {
+void ScriptParser::readGroup() {
expect("(");
while (!Error) {
StringRef Tok = next();
@@ -264,7 +290,7 @@ void LinkerScript::readGroup() {
}
}
-void LinkerScript::readInclude() {
+void ScriptParser::readInclude() {
StringRef Tok = next();
auto MBOrErr = MemoryBuffer::getFile(Tok);
if (!MBOrErr) {
@@ -277,7 +303,7 @@ void LinkerScript::readInclude() {
Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
}
-void LinkerScript::readOutput() {
+void ScriptParser::readOutput() {
// -o <file> takes predecence over OUTPUT(<file>).
expect("(");
StringRef Tok = next();
@@ -286,14 +312,14 @@ void LinkerScript::readOutput() {
expect(")");
}
-void LinkerScript::readOutputArch() {
+void ScriptParser::readOutputArch() {
// Error checking only for now.
expect("(");
next();
expect(")");
}
-void LinkerScript::readOutputFormat() {
+void ScriptParser::readOutputFormat() {
// Error checking only for now.
expect("(");
next();
@@ -310,29 +336,27 @@ void LinkerScript::readOutputFormat() {
expect(")");
}
-void LinkerScript::readSearchDir() {
+void ScriptParser::readSearchDir() {
expect("(");
Config->SearchPaths.push_back(next());
expect(")");
}
-void LinkerScript::readSections() {
+void ScriptParser::readSections() {
expect("{");
while (!Error && !skip("}"))
readOutputSectionDescription();
}
-void LinkerScript::readOutputSectionDescription() {
- StringRef Name = next();
- std::vector<StringRef> &InputSections = Config->OutputSections[Name];
-
+void ScriptParser::readOutputSectionDescription() {
+ std::vector<StringRef> &V = Script->Sections[next()];
expect(":");
expect("{");
while (!Error && !skip("}")) {
next(); // Skip input file name.
expect("(");
while (!Error && !skip(")"))
- InputSections.push_back(next());
+ V.push_back(next());
}
}
@@ -348,5 +372,5 @@ static bool isUnderSysroot(StringRef Pat
// Entry point. The other functions or classes are private to this file.
void elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
StringRef Path = MB.getBufferIdentifier();
- LinkerScript(A, MB.getBuffer(), isUnderSysroot(Path)).run();
+ ScriptParser(A, MB.getBuffer(), isUnderSysroot(Path)).run();
}
Added: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=260591&view=auto
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (added)
+++ lld/trunk/ELF/LinkerScript.h Thu Feb 11 15:17:59 2016
@@ -0,0 +1,45 @@
+//===- LinkerScript.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_LINKER_SCRIPT_H
+#define LLD_ELF_LINKER_SCRIPT_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
+
+namespace lld {
+namespace elf2 {
+
+class ScriptParser;
+
+class LinkerScript {
+ friend class ScriptParser;
+
+public:
+ StringRef getOutputSection(StringRef InputSection);
+ bool isDiscarded(StringRef InputSection);
+ int compareSections(StringRef A, StringRef B);
+ void finalize();
+
+private:
+ // Map for SECTIONS command. The key is output section name
+ // and a value is a list of input section names.
+ llvm::MapVector<StringRef, std::vector<StringRef>> Sections;
+
+ // Inverse map of Sections.
+ llvm::DenseMap<StringRef, StringRef> RevSections;
+};
+
+extern LinkerScript *Script;
+
+} // namespace elf2
+} // namespace lld
+
+#endif
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Feb 11 15:17:59 2016
@@ -9,6 +9,7 @@
#include "Writer.h"
#include "Config.h"
+#include "LinkerScript.h"
#include "OutputSections.h"
#include "SymbolTable.h"
#include "Target.h"
@@ -68,7 +69,6 @@ private:
void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
void createPhdrs();
void assignAddresses();
- void buildSectionMap();
void fixAbsoluteSymbols();
bool openFile();
void writeHeader();
@@ -111,8 +111,6 @@ private:
uintX_t FileSize;
uintX_t SectionHeaderOff;
- llvm::StringMap<llvm::StringRef> InputToOutputSection;
-
// Flag to force GOT to be in output if we have relocations
// that relies on its address.
bool HasGotOffRel = false;
@@ -190,7 +188,6 @@ template <class ELFT> void elf2::writeRe
// The main function of the writer.
template <class ELFT> void Writer<ELFT>::run() {
- buildSectionMap();
if (!Config->DiscardAll)
copyLocalSymbols();
addReservedSymbols();
@@ -595,10 +592,14 @@ template <class ELFT> static bool isRelr
// Output section ordering is determined by this function.
template <class ELFT>
-static bool compareOutputSections(OutputSectionBase<ELFT> *A,
- OutputSectionBase<ELFT> *B) {
+static bool compareSections(OutputSectionBase<ELFT> *A,
+ OutputSectionBase<ELFT> *B) {
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+ int Comp = Script->compareSections(A->getName(), B->getName());
+ if (Comp != 0)
+ return Comp < 0;
+
uintX_t AFlags = A->getFlags();
uintX_t BFlags = B->getFlags();
@@ -721,9 +722,9 @@ void Writer<ELFT>::addCopyRelSymbols(std
template <class ELFT>
StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
- auto It = InputToOutputSection.find(S);
- if (It != std::end(InputToOutputSection))
- return It->second;
+ StringRef Out = Script->getOutputSection(S);
+ if (!Out.empty())
+ return Out;
for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
".init_array.", ".fini_array.", ".ctors.", ".dtors."})
@@ -742,24 +743,9 @@ void reportDiscarded(InputSectionBase<EL
}
template <class ELFT>
-bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const {
- if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded)
- return true;
- return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/";
-}
-
-template <class ELFT>
-static bool compareSections(OutputSectionBase<ELFT> *A,
- OutputSectionBase<ELFT> *B) {
- auto ItA = Config->OutputSections.find(A->getName());
- auto ItEnd = std::end(Config->OutputSections);
- if (ItA == ItEnd)
- return compareOutputSections(A, B);
- auto ItB = Config->OutputSections.find(B->getName());
- if (ItB == ItEnd)
- return compareOutputSections(A, B);
-
- return std::distance(ItA, ItB) > 0;
+bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {
+ return !S || !S->isLive() || S == &InputSection<ELFT>::Discarded ||
+ Script->isDiscarded(S->getSectionName());
}
// The beginning and the ending of .rel[a].plt section are marked
@@ -1487,13 +1473,6 @@ template <class ELFT> void Writer<ELFT>:
Sec->writeTo(Buf + Sec->getFileOff());
}
-template <class ELFT> void Writer<ELFT>::buildSectionMap() {
- for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
- Config->OutputSections)
- for (StringRef Name : OutSec.second)
- InputToOutputSection[Name] = OutSec.first;
-}
-
template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
More information about the llvm-commits
mailing list