[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