[lld] r259557 - ELF: Do not use fatal in LinkerScript.cpp.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 2 12:27:59 PST 2016
Author: ruiu
Date: Tue Feb 2 14:27:59 2016
New Revision: 259557
URL: http://llvm.org/viewvc/llvm-project?rev=259557&view=rev
Log:
ELF: Do not use fatal in LinkerScript.cpp.
This patch adds "Error" field to LinkerScript class. That field
is false by default, and set to true if there is a syntax error
in an input file. The linker script parser is a recursive-descedent
parser. Each function returns if Error is true -- so that
eventually the whole parser returns to a caller.
http://reviews.llvm.org/D16667
Added:
lld/trunk/test/ELF/invalid-linkerscript.test
Modified:
lld/trunk/ELF/LinkerScript.cpp
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=259557&r1=259556&r2=259557&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue Feb 2 14:27:59 2016
@@ -33,11 +33,12 @@ public:
void run();
private:
+ void setError(const Twine &Msg);
static std::vector<StringRef> tokenize(StringRef S);
static StringRef skipSpace(StringRef S);
+ bool atEOF();
StringRef next();
bool skip(StringRef Tok);
- bool atEOF() { return Tokens.size() == Pos; }
void expect(StringRef Expect);
void addFile(StringRef Path);
@@ -57,6 +58,7 @@ private:
StringSaver Saver;
std::vector<StringRef> Tokens;
+ bool Error = false;
size_t Pos = 0;
bool IsUnderSysroot;
};
@@ -86,11 +88,20 @@ void LinkerScript::run() {
} else if (Tok == "SECTIONS") {
readSections();
} else {
- fatal("unknown directive: " + Tok);
+ setError("unknown directive: " + Tok);
+ return;
}
}
}
+// We don't want to record cascading errors. Keep only the first one.
+void LinkerScript::setError(const Twine &Msg) {
+ if (Error)
+ return;
+ error(Msg);
+ Error = true;
+}
+
// Split S into linker script tokens.
std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
std::vector<StringRef> Ret;
@@ -102,8 +113,10 @@ std::vector<StringRef> LinkerScript::tok
// Quoted token
if (S.startswith("\"")) {
size_t E = S.find("\"", 1);
- if (E == StringRef::npos)
- fatal("unclosed quote");
+ if (E == StringRef::npos) {
+ error("unclosed quote");
+ return {};
+ }
Ret.push_back(S.substr(1, E - 1));
S = S.substr(E + 1);
continue;
@@ -127,8 +140,10 @@ StringRef LinkerScript::skipSpace(String
for (;;) {
if (S.startswith("/*")) {
size_t E = S.find("*/", 2);
- if (E == StringRef::npos)
- fatal("unclosed comment in a linker script");
+ if (E == StringRef::npos) {
+ error("unclosed comment in a linker script");
+ return "";
+ }
S = S.substr(E + 2);
continue;
}
@@ -139,15 +154,26 @@ StringRef LinkerScript::skipSpace(String
}
}
+// An errneous token is handled as if it were the last token before EOF.
+bool LinkerScript::atEOF() { return Error || Tokens.size() == Pos; }
+
StringRef LinkerScript::next() {
- if (atEOF())
- fatal("unexpected EOF");
+ if (Error)
+ return "";
+ if (atEOF()) {
+ setError("unexpected EOF");
+ return "";
+ }
return Tokens[Pos++];
}
bool LinkerScript::skip(StringRef Tok) {
- if (atEOF())
- fatal("unexpected EOF");
+ if (Error)
+ return false;
+ if (atEOF()) {
+ setError("unexpected EOF");
+ return false;
+ }
if (Tok != Tokens[Pos])
return false;
++Pos;
@@ -155,9 +181,11 @@ bool LinkerScript::skip(StringRef Tok) {
}
void LinkerScript::expect(StringRef Expect) {
+ if (Error)
+ return;
StringRef Tok = next();
if (Tok != Expect)
- fatal(Expect + " expected, but got " + Tok);
+ setError(Expect + " expected, but got " + Tok);
}
void LinkerScript::addFile(StringRef S) {
@@ -184,8 +212,9 @@ void LinkerScript::addFile(StringRef S)
} else {
std::string Path = findFromSearchPaths(S);
if (Path.empty())
- fatal("Unable to find " + S);
- Driver->addFile(Saver.save(Path));
+ setError("Unable to find " + S);
+ else
+ Driver->addFile(Saver.save(Path));
}
}
@@ -193,7 +222,7 @@ void LinkerScript::readAsNeeded() {
expect("(");
bool Orig = Config->AsNeeded;
Config->AsNeeded = true;
- for (;;) {
+ while (!Error) {
StringRef Tok = next();
if (Tok == ")")
break;
@@ -213,7 +242,7 @@ void LinkerScript::readEntry() {
void LinkerScript::readExtern() {
expect("(");
- for (;;) {
+ while (!Error) {
StringRef Tok = next();
if (Tok == ")")
return;
@@ -223,7 +252,7 @@ void LinkerScript::readExtern() {
void LinkerScript::readGroup() {
expect("(");
- for (;;) {
+ while (!Error) {
StringRef Tok = next();
if (Tok == ")")
return;
@@ -238,7 +267,10 @@ void LinkerScript::readGroup() {
void LinkerScript::readInclude() {
StringRef Tok = next();
auto MBOrErr = MemoryBuffer::getFile(Tok);
- fatal(MBOrErr, "cannot open " + Tok);
+ if (!MBOrErr) {
+ setError("cannot open " + Tok);
+ return;
+ }
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
std::vector<StringRef> V = tokenize(S);
@@ -268,8 +300,10 @@ void LinkerScript::readOutputFormat() {
StringRef Tok = next();
if (Tok == ")")
return;
- if (Tok != ",")
- fatal("unexpected token: " + Tok);
+ if (Tok != ",") {
+ setError("unexpected token: " + Tok);
+ return;
+ }
next();
expect(",");
next();
@@ -284,7 +318,7 @@ void LinkerScript::readSearchDir() {
void LinkerScript::readSections() {
expect("{");
- while (!skip("}"))
+ while (!Error && !skip("}"))
readOutputSectionDescription();
}
@@ -294,10 +328,10 @@ void LinkerScript::readOutputSectionDesc
expect(":");
expect("{");
- while (!skip("}")) {
+ while (!Error && !skip("}")) {
next(); // Skip input file name.
expect("(");
- while (!skip(")"))
+ while (!Error && !skip(")"))
InputSections.push_back(next());
}
}
Added: lld/trunk/test/ELF/invalid-linkerscript.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid-linkerscript.test?rev=259557&view=auto
==============================================================================
--- lld/trunk/test/ELF/invalid-linkerscript.test (added)
+++ lld/trunk/test/ELF/invalid-linkerscript.test Tue Feb 2 14:27:59 2016
@@ -0,0 +1,45 @@
+# RUN: mkdir -p %t.dir
+
+## Note that we will see "no input files" error message after
+## error messages from the linker script parser, because the
+## linker keeps going when an error is found.
+
+# RUN: echo foobar > %t1
+# RUN: not ld.lld %t1 2>&1 | FileCheck -check-prefix=ERR1 %s
+# ERR1: unknown directive: foobar
+# ERR1: no input files
+
+# RUN: echo "foo \"bar" > %t2
+# RUN: not ld.lld %t2 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: unclosed quote
+# ERR2: no input files
+
+# RUN: echo "/*" > %t3
+# RUN: not ld.lld %t3 2>&1 | FileCheck -check-prefix=ERR3 %s
+# ERR3: unclosed comment
+# ERR3: no input files
+
+# RUN: echo "EXTERN (" > %t4
+# RUN: not ld.lld %t4 2>&1 | FileCheck -check-prefix=ERR4 %s
+# ERR4: unexpected EOF
+# ERR4: no input files
+
+# RUN: echo "EXTERN (" > %t5
+# RUN: not ld.lld %t5 2>&1 | FileCheck -check-prefix=ERR5 %s
+# ERR5: unexpected EOF
+# ERR5: no input files
+
+# RUN: echo "EXTERN xyz" > %t6
+# RUN: not ld.lld %t6 2>&1 | FileCheck -check-prefix=ERR6 %s
+# ERR6: ( expected, but got xyz
+# ERR6: no input files
+
+# RUN: echo "INCLUDE /no/such/file" > %t7
+# RUN: not ld.lld %t7 2>&1 | FileCheck -check-prefix=ERR7 %s
+# ERR7: cannot open /no/such/file
+# ERR7: no input files
+
+# RUN: echo "OUTPUT_FORMAT(x y z)" > %t8
+# RUN: not ld.lld %t8 2>&1 | FileCheck -check-prefix=ERR8 %s
+# ERR8: unexpected token: y
+# ERR8: no input files
More information about the llvm-commits
mailing list