mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-09 09:32:20 +00:00
[lld/ELF] PR44498: Support input filename in double quote
Summary: Linker scripts allow filenames to be put in double quotes to prevent characters in filenames that are part of the linker script syntax from having their special meaning. Case in point the * wildcard character. Availability of double quoting filenames also allows to fix a failure in ELF/linkerscript/filename-spec.s when the path contain a @ which the lexer consider as a special characters and thus break up a filename containing it. This may happens under Jenkins which createspath such as pipeline@2. To avoid the need for escaping GlobPattern metacharacters in filename in double quotes, GlobPattern::create is augmented with a new parameter to request literal matching instead of relying on the presence of a wildcard character in the pattern. Reviewers: jhenderson, MaskRay, evgeny777, espindola, alexshap Reviewed By: MaskRay Subscribers: peter.smith, grimar, ruiu, emaste, arichardson, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D72517
This commit is contained in:
parent
cdcc4f2a44
commit
c42fe24754
@ -31,18 +31,28 @@ std::string lld::demangleItanium(StringRef name) {
|
||||
return demangle(name);
|
||||
}
|
||||
|
||||
StringMatcher::StringMatcher(ArrayRef<StringRef> pat) {
|
||||
for (StringRef s : pat) {
|
||||
Expected<GlobPattern> pat = GlobPattern::create(s);
|
||||
if (!pat)
|
||||
error(toString(pat.takeError()));
|
||||
else
|
||||
patterns.push_back(*pat);
|
||||
SingleStringMatcher::SingleStringMatcher(StringRef Pattern) {
|
||||
if (Pattern.size() > 2 && Pattern.startswith("\"") &&
|
||||
Pattern.endswith("\"")) {
|
||||
ExactMatch = true;
|
||||
ExactPattern = Pattern.substr(1, Pattern.size() - 2);
|
||||
} else {
|
||||
Expected<GlobPattern> Glob = GlobPattern::create(Pattern);
|
||||
if (!Glob) {
|
||||
error(toString(Glob.takeError()));
|
||||
return;
|
||||
}
|
||||
ExactMatch = false;
|
||||
GlobPatternMatcher = *Glob;
|
||||
}
|
||||
}
|
||||
|
||||
bool SingleStringMatcher::match(StringRef s) const {
|
||||
return ExactMatch ? (ExactPattern == s) : GlobPatternMatcher.match(s);
|
||||
}
|
||||
|
||||
bool StringMatcher::match(StringRef s) const {
|
||||
for (const GlobPattern &pat : patterns)
|
||||
for (const SingleStringMatcher &pat : patterns)
|
||||
if (pat.match(s))
|
||||
return true;
|
||||
return false;
|
||||
|
@ -164,7 +164,7 @@ struct InputSectionDescription : BaseCommand {
|
||||
return c->kind == InputSectionKind;
|
||||
}
|
||||
|
||||
StringMatcher filePat;
|
||||
SingleStringMatcher filePat;
|
||||
|
||||
// Input sections that matches at least one of SectionPatterns
|
||||
// will be associated with this InputSectionDescription.
|
||||
|
@ -597,10 +597,11 @@ static int precedence(StringRef op) {
|
||||
}
|
||||
|
||||
StringMatcher ScriptParser::readFilePatterns() {
|
||||
std::vector<StringRef> v;
|
||||
StringMatcher Matcher;
|
||||
|
||||
while (!errorCount() && !consume(")"))
|
||||
v.push_back(next());
|
||||
return StringMatcher(v);
|
||||
Matcher.addPattern(SingleStringMatcher(next()));
|
||||
return Matcher;
|
||||
}
|
||||
|
||||
SortSectionPolicy ScriptParser::readSortKind() {
|
||||
@ -637,12 +638,12 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
|
||||
excludeFilePat = readFilePatterns();
|
||||
}
|
||||
|
||||
std::vector<StringRef> v;
|
||||
StringMatcher SectionMatcher;
|
||||
while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")
|
||||
v.push_back(unquote(next()));
|
||||
SectionMatcher.addPattern(unquote(next()));
|
||||
|
||||
if (!v.empty())
|
||||
ret.push_back({std::move(excludeFilePat), StringMatcher(v)});
|
||||
if (!SectionMatcher.empty())
|
||||
ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)});
|
||||
else
|
||||
setError("section pattern is expected");
|
||||
}
|
||||
@ -864,7 +865,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
|
||||
// handle this case here as it will already have been matched by the
|
||||
// case above.
|
||||
auto *isd = make<InputSectionDescription>(tok);
|
||||
isd->sectionPatterns.push_back({{}, StringMatcher({"*"})});
|
||||
isd->sectionPatterns.push_back({{}, StringMatcher("*")});
|
||||
cmd->sectionCommands.push_back(isd);
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
|
||||
|
||||
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) {
|
||||
std::vector<Symbol *> res;
|
||||
StringMatcher m(ver.name);
|
||||
SingleStringMatcher m(ver.name);
|
||||
|
||||
if (ver.isExternCpp) {
|
||||
for (auto &p : getDemangledSyms())
|
||||
|
@ -27,16 +27,52 @@ bool isValidCIdentifier(llvm::StringRef s);
|
||||
// Write the contents of the a buffer to a file
|
||||
void saveBuffer(llvm::StringRef buffer, const llvm::Twine &path);
|
||||
|
||||
// This class represents multiple glob patterns.
|
||||
class StringMatcher {
|
||||
// A single pattern to match against. A pattern can either be double-quoted
|
||||
// text that should be matched exactly after removing the quoting marks or a
|
||||
// glob pattern in the sense of GlobPattern.
|
||||
class SingleStringMatcher {
|
||||
public:
|
||||
StringMatcher() = default;
|
||||
explicit StringMatcher(llvm::ArrayRef<llvm::StringRef> pat);
|
||||
// Create a StringPattern from Pattern to be matched exactly irregardless
|
||||
// of globbing characters if ExactMatch is true.
|
||||
SingleStringMatcher(llvm::StringRef Pattern);
|
||||
|
||||
// Match s against this pattern, exactly if ExactMatch is true.
|
||||
bool match(llvm::StringRef s) const;
|
||||
|
||||
private:
|
||||
std::vector<llvm::GlobPattern> patterns;
|
||||
// Whether to do an exact match irregardless of the presence of wildcard
|
||||
// character.
|
||||
bool ExactMatch;
|
||||
|
||||
// GlobPattern object if not doing an exact match.
|
||||
llvm::GlobPattern GlobPatternMatcher;
|
||||
|
||||
// StringRef to match exactly if doing an exact match.
|
||||
llvm::StringRef ExactPattern;
|
||||
};
|
||||
|
||||
// This class represents multiple patterns to match against. A pattern can
|
||||
// either be a double-quoted text that should be matched exactly after removing
|
||||
// the quoted marks or a glob pattern.
|
||||
class StringMatcher {
|
||||
private:
|
||||
// Patterns to match against.
|
||||
std::vector<SingleStringMatcher> patterns;
|
||||
|
||||
public:
|
||||
StringMatcher() = default;
|
||||
|
||||
// Matcher for a single pattern.
|
||||
StringMatcher(llvm::StringRef Pattern)
|
||||
: patterns({SingleStringMatcher(Pattern)}) {}
|
||||
|
||||
// Add a new pattern to the existing ones to match against.
|
||||
void addPattern(SingleStringMatcher Matcher) { patterns.push_back(Matcher); }
|
||||
|
||||
bool empty() { return patterns.empty(); }
|
||||
|
||||
// Match s against the patterns.
|
||||
bool match(llvm::StringRef s) const;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
@ -30,12 +30,12 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
|
||||
# RUN: %p/Inputs/filename-spec.s -o %t.dir/filename-spec2.o
|
||||
|
||||
# RUN: echo "SECTIONS{.foo :{ %/t.dir/filename-spec2.o(.foo) %/t.dir/filename-spec1.o(.foo) }}" > %t5.script
|
||||
# RUN: echo "SECTIONS{.foo :{ \"%/t.dir/filename-spec2.o\"(.foo) \"%/t.dir/filename-spec1.o\"(.foo) }}" > %t5.script
|
||||
# RUN: ld.lld -o %t5 --script %t5.script \
|
||||
# RUN: %/t.dir/filename-spec1.o %/t.dir/filename-spec2.o
|
||||
# RUN: llvm-objdump -s %t5 | FileCheck --check-prefix=SECONDFIRST %s
|
||||
|
||||
# RUN: echo "SECTIONS{.foo :{ %/t.dir/filename-spec1.o(.foo) %/t.dir/filename-spec2.o(.foo) }}" > %t6.script
|
||||
# RUN: echo "SECTIONS{.foo :{ \"%/t.dir/filename-spec1.o\"(.foo) \"%/t.dir/filename-spec2.o\"(.foo) }}" > %t6.script
|
||||
# RUN: ld.lld -o %t6 --script %t6.script \
|
||||
# RUN: %/t.dir/filename-spec1.o %/t.dir/filename-spec2.o
|
||||
# RUN: llvm-objdump -s %t6 | FileCheck --check-prefix=FIRSTY %s
|
||||
|
Loading…
Reference in New Issue
Block a user