[lld] r260745 - ELF: Add wildcard pattern matching to SECTIONS linker script command.
Sean Silva via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 12 17:29:21 PST 2016
Nice!
-- Sean Silva
On Fri, Feb 12, 2016 at 1:47 PM, Rui Ueyama via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: ruiu
> Date: Fri Feb 12 15:47:28 2016
> New Revision: 260745
>
> URL: http://llvm.org/viewvc/llvm-project?rev=260745&view=rev
> Log:
> ELF: Add wildcard pattern matching to SECTIONS linker script command.
>
> Each rule in SECTIONS commands is something like ".foo *(.baz.*)",
> which instructs the linker to collect all sections whose name matches
> ".baz.*" from all files and put them into .foo section.
>
> Previously, we didn't recognize the wildcard character. This patch
> adds that feature.
>
> Performance impact is a bit concerning because a linker script can
> contain hundreds of SECTIONS rules, and doing pattern matching against
> each rule would be too expensive. We could merge all patterns into
> single DFA so that it takes O(n) to the input size. However, it is
> probably too much at this moment -- we don't know whether the
> performance of pattern matching matters or not. So I chose to
> implement the simplest algorithm in this patch. I hope this simple
> pattern matcher is sufficient.
>
> Modified:
> lld/trunk/ELF/LinkerScript.cpp
> lld/trunk/ELF/LinkerScript.h
> lld/trunk/ELF/Writer.cpp
> lld/trunk/test/ELF/linkerscript-sections.s
>
> Modified: lld/trunk/ELF/LinkerScript.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=260745&r1=260744&r2=260745&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/LinkerScript.cpp (original)
> +++ lld/trunk/ELF/LinkerScript.cpp Fri Feb 12 15:47:28 2016
> @@ -16,6 +16,7 @@
> #include "LinkerScript.h"
> #include "Config.h"
> #include "Driver.h"
> +#include "InputSection.h"
> #include "SymbolTable.h"
> #include "llvm/Support/FileSystem.h"
> #include "llvm/Support/MemoryBuffer.h"
> @@ -23,17 +24,23 @@
> #include "llvm/Support/StringSaver.h"
>
> using namespace llvm;
> +using namespace llvm::object;
> using namespace lld;
> using namespace lld::elf2;
>
> LinkerScript *elf2::Script;
>
> -StringRef LinkerScript::getOutputSection(StringRef S) {
> - return Sections.lookup(S);
> +template <class ELFT>
> +StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) {
> + for (SectionRule &R : Sections)
> + if (R.match(S))
> + return R.Dest;
> + return "";
> }
>
> -bool LinkerScript::isDiscarded(StringRef S) {
> - return Sections.lookup(S) == "/DISCARD/";
> +template <class ELFT>
> +bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) {
> + return getOutputSection(S) == "/DISCARD/";
> }
>
> // A compartor to sort output sections. Returns -1 or 1 if both
> @@ -48,6 +55,33 @@ int LinkerScript::compareSections(String
> return I < J ? -1 : 1;
> }
>
> +// Returns true if S matches T. S may contain a meta character '*'
> +// which matches zero or more occurrences of any character.
> +static bool matchStr(StringRef S, StringRef T) {
> + for (;;) {
> + if (S.empty())
> + return T.empty();
> + if (S[0] == '*') {
> + S = S.substr(1);
> + if (S.empty())
> + // Fast path. If a pattern is '*', it matches anything.
> + return true;
> + for (size_t I = 0, E = T.size(); I < E; ++I)
> + if (matchStr(S, T.substr(I)))
> + return true;
> + return false;
> + }
> + if (T.empty() || S[0] != T[0])
> + return false;
> + S = S.substr(1);
> + T = T.substr(1);
> + }
> +}
> +
> +template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
> + return matchStr(SectionPattern, S->getSectionName());
> +}
> +
> class elf2::ScriptParser {
> public:
> ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
> @@ -352,7 +386,7 @@ void ScriptParser::readOutputSectionDesc
> next(); // Skip input file name.
> expect("(");
> while (!Error && !skip(")"))
> - Script->Sections[next()] = OutSec;
> + Script->Sections.push_back({OutSec, next()});
> }
> }
>
> @@ -370,3 +404,18 @@ void LinkerScript::read(MemoryBufferRef
> StringRef Path = MB.getBufferIdentifier();
> ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
> }
> +
> +template StringRef
> LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
> +template StringRef
> LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
> +template StringRef
> LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
> +template StringRef
> LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
> +
> +template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
> +template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
> +template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
> +template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
> +
> +template bool SectionRule::match(InputSectionBase<ELF32LE> *);
> +template bool SectionRule::match(InputSectionBase<ELF32BE> *);
> +template bool SectionRule::match(InputSectionBase<ELF64LE> *);
> +template bool SectionRule::match(InputSectionBase<ELF64BE> *);
>
> Modified: lld/trunk/ELF/LinkerScript.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=260745&r1=260744&r2=260745&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/LinkerScript.h (original)
> +++ lld/trunk/ELF/LinkerScript.h Fri Feb 12 15:47:28 2016
> @@ -20,7 +20,23 @@ namespace lld {
> namespace elf2 {
>
> class ScriptParser;
> +template <class ELFT> class InputSectionBase;
>
> +// This class represents each rule in SECTIONS command.
> +class SectionRule {
> +public:
> + SectionRule(StringRef D, StringRef S) : Dest(D), SectionPattern(S) {}
> +
> + // Returns true if S should be in Dest section.
> + template <class ELFT> bool match(InputSectionBase<ELFT> *S);
> +
> + StringRef Dest;
> +
> +private:
> + StringRef SectionPattern;
> +};
> +
> +// This is a runner of the linker script.
> class LinkerScript {
> friend class ScriptParser;
>
> @@ -29,14 +45,13 @@ public:
> // this object and Config.
> void read(MemoryBufferRef MB);
>
> - StringRef getOutputSection(StringRef InputSection);
> - bool isDiscarded(StringRef InputSection);
> + template <class ELFT> StringRef getOutputSection(InputSectionBase<ELFT>
> *S);
> + template <class ELFT> bool isDiscarded(InputSectionBase<ELFT> *S);
> int compareSections(StringRef A, StringRef B);
>
> private:
> - // A map for SECTIONS command. The key is input section name
> - // and the value is the corresponding output section name.
> - llvm::DenseMap<StringRef, StringRef> Sections;
> + // SECTIONS commands.
> + std::vector<SectionRule> Sections;
>
> // Output sections are sorted by this order.
> std::vector<StringRef> SectionOrder;
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=260745&r1=260744&r2=260745&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Fri Feb 12 15:47:28 2016
> @@ -74,7 +74,7 @@ private:
> void writeHeader();
> void writeSections();
> bool isDiscarded(InputSectionBase<ELFT> *IS) const;
> - StringRef getOutputSectionName(StringRef S) const;
> + StringRef getOutputSectionName(InputSectionBase<ELFT> *S) const;
> bool needsInterpSection() const {
> return !Symtab.getSharedFiles().empty() &&
> !Config->DynamicLinker.empty();
> }
> @@ -726,16 +726,17 @@ void Writer<ELFT>::addCopyRelSymbols(std
> }
>
> template <class ELFT>
> -StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
> - StringRef Out = Script->getOutputSection(S);
> - if (!Out.empty())
> - return Out;
> +StringRef Writer<ELFT>::getOutputSectionName(InputSectionBase<ELFT> *S)
> const {
> + StringRef Dest = Script->getOutputSection<ELFT>(S);
> + if (!Dest.empty())
> + return Dest;
>
> + StringRef Name = S->getSectionName();
> for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.",
> ".bss.",
> ".init_array.", ".fini_array.", ".ctors.",
> ".dtors."})
> - if (S.startswith(V))
> + if (Name.startswith(V))
> return V.drop_back();
> - return S;
> + return Name;
> }
>
> template <class ELFT>
> @@ -750,7 +751,7 @@ void reportDiscarded(InputSectionBase<EL
> template <class ELFT>
> bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {
> return !S || !S->isLive() || S == &InputSection<ELFT>::Discarded ||
> - Script->isDiscarded(S->getSectionName());
> + Script->isDiscarded(S);
> }
>
> // The beginning and the ending of .rel[a].plt section are marked
> @@ -934,8 +935,7 @@ template <class ELFT> bool Writer<ELFT>:
> }
> OutputSectionBase<ELFT> *Sec;
> bool IsNew;
> - std::tie(Sec, IsNew) =
> - Factory.create(C, getOutputSectionName(C->getSectionName()));
> + std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C));
> if (IsNew) {
> OwningSections.emplace_back(Sec);
> OutputSections.push_back(Sec);
>
> Modified: lld/trunk/test/ELF/linkerscript-sections.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-sections.s?rev=260745&r1=260744&r2=260745&view=diff
>
> ==============================================================================
> --- lld/trunk/test/ELF/linkerscript-sections.s (original)
> +++ lld/trunk/test/ELF/linkerscript-sections.s Fri Feb 12 15:47:28 2016
> @@ -38,6 +38,20 @@
> # RUN: llvm-objdump -section-headers %t3 | \
> # RUN: FileCheck -check-prefix=SEC-ORDER %s
>
> +# The same test as above but with wildcard patterns.
> +# RUN: echo "SECTIONS { \
> +# RUN: .bss : { *(.bss) } \
> +# RUN: other : { *(o*er) } \
> +# RUN: .shstrtab : { *(.shstrt*) } \
> +# RUN: .symtab : { *(.symtab) } \
> +# RUN: .strtab : { *(.strtab) } \
> +# RUN: .data : { *(*data) } \
> +# RUN: .text : { *(.text) } }" > %t.script
> +# RUN: cp %t %t.abc
> +# RUN: ld.lld -o %t3 --script %t.script %t.abc
> +# RUN: llvm-objdump -section-headers %t3 | \
> +# RUN: FileCheck -check-prefix=SEC-ORDER %s
> +
> # Idx Name Size
> # SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
> # SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160212/57d0b426/attachment.html>
More information about the llvm-commits
mailing list