Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -93,11 +93,11 @@ struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); - StringRef FilePattern; + StringRef FilePattern; // TODO: use std::regex instead SortKind SortOuter = SortNone; SortKind SortInner = SortNone; - std::vector ExcludedFiles; - std::vector SectionPatterns; + std::vector ExcludedFiles; // TODO: vector of std::regexs + std::vector SectionPatterns; // TODO: vector of std::regexs }; struct AssertCommand : BaseCommand { @@ -128,7 +128,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; // TODO: vector of regexs }; extern ScriptConfiguration *ScriptConfig; Index: ELF/Strings.cpp =================================================================== --- ELF/Strings.cpp +++ ELF/Strings.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" #include +#include #ifdef HAVE_CXXABI_H #include @@ -22,28 +23,54 @@ using namespace lld; using namespace lld::elf; +static std::regex toRegex(StringRef S) { + std::string T; + enum { Normal, Bracket } State = Normal; + + // This is a hand-written state machine to convert + // a glob pattern to a regex. + while (!S.empty()) { + // Handle backslash escape. + if (S[0] == '\\') { + if (S.size() == 1) { + T += '\\'; + break; + } + T += S[0]; + T += S[1]; + S = S.substr(2); + continue; + } + + switch (State) { + case Normal: + if (S[0] == '*') { + T += ".*"; + } else if (S[0] == '?') { + T += '.'; + } else if (S[0] == '[') { + T += '['; + State = Bracket; + } else { + T += S[0]; + } + break; + case Bracket: + if (S[0] == ']') + State = Normal; + T += S[0]; + break; + } + S = S.substr(1); + } + return std::regex(T, std::regex::basic | std::regex::optimize); +} + // 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; - S = S.substr(1); - T = T.substr(1); - } + return std::regex_match(T.begin(), T.end(), toRegex(S)); } // Converts a hex string (e.g. "deadbeef") to a vector.