Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -16,6 +16,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Regex.h" #include namespace lld { @@ -93,11 +94,11 @@ struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); - StringRef FilePattern; + std::unique_ptr FilePattern; SortKind SortOuter = SortNone; SortKind SortInner = SortNone; - std::vector ExcludedFiles; - std::vector SectionPatterns; + std::vector ExcludedFiles; + std::vector SectionPatterns; }; struct AssertCommand : BaseCommand { @@ -128,7 +129,7 @@ // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. - std::vector KeptSections; + std::vector KeptSections; }; extern ScriptConfiguration *ScriptConfig; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -92,22 +92,24 @@ template bool LinkerScript::shouldKeep(InputSectionBase *S) { - for (StringRef Pat : Opt.KeptSections) - if (globMatch(Pat, S->getSectionName())) + for (Regex *Pat : Opt.KeptSections) { + StringRef Name = S->getSectionName(); + if (Pat->match(Name)) return true; + } return false; } -static bool match(ArrayRef Patterns, StringRef S) { - for (StringRef Pat : Patterns) - if (globMatch(Pat, S)) +static bool match(ArrayRef Patterns, StringRef S) { + for (const Regex &Pat : Patterns) + if (const_cast(Pat).match(S)) return true; return false; } static bool fileMatches(const InputSectionDescription *Desc, StringRef Filename) { - if (!globMatch(Desc->FilePattern, Filename)) + if (Desc->FilePattern && !Desc->FilePattern->match(Filename)) return false; return Desc->ExcludedFiles.empty() || !match(Desc->ExcludedFiles, Filename); } @@ -116,7 +118,7 @@ template std::vector *> LinkerScript::getInputSections(const InputSectionDescription *I) { - ArrayRef Patterns = I->SectionPatterns; + ArrayRef Patterns = I->SectionPatterns; std::vector *> Ret; for (const std::unique_ptr> &F : Symtab::X->getObjectFiles()) { @@ -127,7 +129,9 @@ Ret.push_back(S); } - if (llvm::find(Patterns, "COMMON") != Patterns.end()) + if (llvm::find_if(Patterns, [](const Regex &P) { + return const_cast(P).match("COMMON"); + }) != Patterns.end()) Ret.push_back(CommonInputSection::X); return Ret; @@ -615,7 +619,7 @@ std::vector readOutputSectionFiller(); std::vector readOutputSectionPhdrs(); InputSectionDescription *readInputSectionDescription(StringRef Tok); - std::vector readInputFilePatterns(); + std::vector readInputFilePatterns(); InputSectionDescription *readInputSectionRules(StringRef FilePattern); unsigned readPhdrType(); SortKind readSortKind(); @@ -840,10 +844,10 @@ .Default(-1); } -std::vector ScriptParser::readInputFilePatterns() { - std::vector V; +std::vector ScriptParser::readInputFilePatterns() { + std::vector V; while (!Error && !skip(")")) - V.push_back(next()); + V.push_back(toRegex(next())); return V; } @@ -858,14 +862,14 @@ InputSectionDescription * ScriptParser::readInputSectionRules(StringRef FilePattern) { auto *Cmd = new InputSectionDescription; - Cmd->FilePattern = FilePattern; + Cmd->FilePattern = llvm::make_unique(toRegex(FilePattern)); expect("("); // Read EXCLUDE_FILE(). if (skip("EXCLUDE_FILE")) { expect("("); while (!Error && !skip(")")) - Cmd->ExcludedFiles.push_back(next()); + Cmd->ExcludedFiles.push_back(toRegex(next())); } // Read SORT(). @@ -897,9 +901,8 @@ StringRef FilePattern = next(); InputSectionDescription *Cmd = readInputSectionRules(FilePattern); expect(")"); - Opt.KeptSections.insert(Opt.KeptSections.end(), - Cmd->SectionPatterns.begin(), - Cmd->SectionPatterns.end()); + for (Regex &R : Cmd->SectionPatterns) + Opt.KeptSections.push_back(&R); return Cmd; } return readInputSectionRules(Tok); Index: ELF/Strings.h =================================================================== --- ELF/Strings.h +++ ELF/Strings.h @@ -11,11 +11,13 @@ #define LLD_COFF_STRINGS_H #include "lld/Core/LLVM.h" +#include "llvm/Support/Regex.h" #include namespace lld { namespace elf { -bool globMatch(StringRef S, StringRef T); +llvm::Regex toRegex(StringRef S); +bool hasWildcard(StringRef S); std::vector parseHex(StringRef S); bool isValidCIdentifier(StringRef S); Index: ELF/Strings.cpp =================================================================== --- ELF/Strings.cpp +++ ELF/Strings.cpp @@ -9,6 +9,7 @@ #include "Strings.h" #include "Error.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" @@ -22,28 +23,27 @@ using namespace lld; using namespace lld::elf; -// Returns true if S matches T. S can contain glob meta-characters. -// The asterisk ('*') matches zero or more characters, and the question -// mark ('?') matches one character. -bool elf::globMatch(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 (globMatch(S, T.substr(I))) - return true; - return false; - } - if (T.empty() || (S[0] != T[0] && S[0] != '?')) - return false; +bool elf::hasWildcard(StringRef S) { + return S.find_first_of("?*") != StringRef::npos; +} + +// This method converts glob pattern to a regex. +Regex elf::toRegex(StringRef S) { + std::string T = "^"; + while (!S.empty()) { + char F = S.front(); + if (F == '*') + T += ".*"; + else if (F == '?') + T += '.'; + else if (F == '.') + T += "\\."; + else + T += F; S = S.substr(1); - T = T.substr(1); } + T += "$"; + return Regex(T, Regex::BasicRegex); } // Converts a hex string (e.g. "deadbeef") to a vector. Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -13,6 +13,7 @@ #include "InputFiles.h" #include "LTO.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Regex.h" namespace lld { namespace elf { @@ -89,7 +90,7 @@ void wrap(StringRef Name); private: - std::vector findAll(StringRef Pattern); + std::vector findAll(const llvm::Regex &Pattern); std::pair insert(StringRef &Name); std::pair insert(StringRef &Name, uint8_t Type, uint8_t Visibility, bool CanOmitFromDynSym, Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -483,11 +483,12 @@ // Returns a list of defined symbols that match with a given glob pattern. template -std::vector SymbolTable::findAll(StringRef Pattern) { +std::vector SymbolTable::findAll(const Regex &Pattern) { std::vector Res; for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); - if (!B->isUndefined() && globMatch(Pattern, B->getName())) + StringRef Name = B->getName(); + if (!B->isUndefined() && const_cast(Pattern).match(Name)) Res.push_back(B); } return Res; @@ -576,10 +577,6 @@ B->symbol()->ExportDynamic = true; } -static bool hasWildcard(StringRef S) { - return S.find_first_of("?*") != StringRef::npos; -} - static void setVersionId(SymbolBody *Body, StringRef VersionName, StringRef Name, uint16_t Version) { if (!Body || Body->isUndefined()) { @@ -623,11 +620,11 @@ static std::vector findAllDemangled(const std::map &D, - StringRef Pattern) { + const Regex &Pattern) { std::vector Res; for (auto &P : D) { SymbolBody *Body = P.second; - if (!Body->isUndefined() && globMatch(Pattern, P.first)) + if (!Body->isUndefined() && const_cast(Pattern).match(P.first)) Res.push_back(Body); } return Res; @@ -680,8 +677,8 @@ if (!hasWildcard(Sym.Name)) continue; std::vector All = - Sym.IsExternCpp ? findAllDemangled(Demangled, Sym.Name) - : findAll(Sym.Name); + Sym.IsExternCpp ? findAllDemangled(Demangled, toRegex(Sym.Name)) + : findAll(toRegex(Sym.Name)); for (SymbolBody *B : All) if (B->symbol()->VersionId == Config->DefaultSymbolVersion) Index: test/ELF/wildcards2.s =================================================================== --- test/ELF/wildcards2.s +++ test/ELF/wildcards2.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Check that aabc is not included in text. +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.abc) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck %s +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000004 0000000000000120 TEXT DATA +# CHECK-NEXT: 2 aabc 00000004 0000000000000124 TEXT DATA + +.text +.section .abc,"ax",@progbits +.long 0 + +.text +.section aabc,"ax",@progbits +.long 0 + +.globl _start +_start: