From 8ec77e64fcd419df30e09989bcba62c5cb9fd172 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 21 Apr 2016 22:00:51 +0000 Subject: ELF: Change how to handle KEEP linker script command. You can instruct the linker to not discard sections even if they are unused and --gc-sections option is given. The linker script command for doing that is KEEP. The syntax is KEEP(foo) where foo is a section name. KEEP commands are written in SECTIONS command, so you can specify the order of sections *and* which sections will be kept. Each sub-command in SECTIONS command are translated into SectionRule object. Previously, each SectionRule has `Keep` bit. However, if you think about it, this hid information in too deep in elements of a list. Semantically, KEEP commands aren't really related to SECTIONS subcommands. We can keep the section list for KEEP in a separate list. This patch does that. llvm-svn: 267065 --- lld/ELF/LinkerScript.cpp | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'lld/ELF/LinkerScript.cpp') diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index d16559f1a10..6457bc338cf 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -35,6 +35,8 @@ using namespace lld::elf; ScriptConfiguration *elf::ScriptConfig; +static bool matchStr(StringRef S, StringRef T); + static uint64_t getInteger(StringRef S) { uint64_t V; if (S.getAsInteger(0, V)) { @@ -159,17 +161,11 @@ static uint64_t evaluate(ArrayRef Tokens, uint64_t Dot) { } template -SectionRule *LinkerScript::find(InputSectionBase *S) { +StringRef LinkerScript::getOutputSection(InputSectionBase *S) { for (SectionRule &R : Opt.Sections) if (R.match(S)) - return &R; - return nullptr; -} - -template -StringRef LinkerScript::getOutputSection(InputSectionBase *S) { - SectionRule *R = find(S); - return R ? R->Dest : ""; + return R.Dest; + return ""; } template @@ -179,8 +175,10 @@ bool LinkerScript::isDiscarded(InputSectionBase *S) { template bool LinkerScript::shouldKeep(InputSectionBase *S) { - SectionRule *R = find(S); - return R && R->Keep; + for (StringRef Pat : Opt.KeptSections) + if (matchStr(Pat, S->getSectionName())) + return true; + return false; } template @@ -326,7 +324,7 @@ private: void readLocationCounterValue(); void readOutputSectionDescription(); - void readSectionPatterns(StringRef OutSec, bool Keep); + void readSectionPatterns(StringRef OutSec); const static StringMap Cmd; ScriptConfiguration &Opt = *ScriptConfig; @@ -497,10 +495,10 @@ void ScriptParser::readSections() { } } -void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { +void ScriptParser::readSectionPatterns(StringRef OutSec) { expect("("); while (!Error && !skip(")")) - Opt.Sections.emplace_back(OutSec, next(), Keep); + Opt.Sections.emplace_back(OutSec, next()); } void ScriptParser::readLocationCounterValue() { @@ -523,19 +521,28 @@ void ScriptParser::readOutputSectionDescription() { Opt.Commands.push_back({SectionKind, {}, OutSec}); expect(":"); expect("{"); + while (!Error && !skip("}")) { StringRef Tok = next(); if (Tok == "*") { - readSectionPatterns(OutSec, false); + expect("("); + while (!Error && !skip(")")) + Opt.Sections.emplace_back(OutSec, next()); } else if (Tok == "KEEP") { expect("("); - next(); // Skip * - readSectionPatterns(OutSec, true); + expect("*"); + expect("("); + while (!Error && !skip(")")) { + StringRef Sec = next(); + Opt.Sections.emplace_back(OutSec, Sec); + Opt.KeptSections.push_back(Sec); + } expect(")"); } else { setError("unknown command " + Tok); } } + StringRef Tok = peek(); if (Tok.startswith("=")) { if (!Tok.startswith("=0x")) { -- cgit v1.2.3