diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 15 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript-diagnostic.s | 48 |
2 files changed, 61 insertions, 2 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index d75ebb0ed4d..abd8d0a8344 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -106,7 +106,7 @@ class elf::ScriptParser { public: ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) - : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {} + : Saver(*A), Input(S), Tokens(tokenize(S)), IsUnderSysroot(B) {} void run(); @@ -137,9 +137,11 @@ private: void readOutputSectionDescription(); void readSectionPatterns(StringRef OutSec, bool Keep); + size_t getPos(); std::vector<uint8_t> parseHex(StringRef S); StringSaver Saver; + StringRef Input; std::vector<StringRef> Tokens; const static StringMap<Handler> Cmd; size_t Pos = 0; @@ -174,7 +176,7 @@ void ScriptParser::run() { void ScriptParser::setError(const Twine &Msg) { if (Error) return; - error(Msg); + error("line " + Twine(getPos()) + ": " + Msg); Error = true; } @@ -412,6 +414,15 @@ void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { Script->Sections.emplace_back(OutSec, next(), Keep); } +// Returns the current line number. +size_t ScriptParser::getPos() { + if (Pos == 0) + return 1; + const char *Begin = Input.data(); + const char *Tok = Tokens[Pos - 1].data(); + return StringRef(Begin, Tok - Begin).count('\n') + 1; +} + std::vector<uint8_t> ScriptParser::parseHex(StringRef S) { std::vector<uint8_t> Hex; while (!S.empty()) { diff --git a/lld/test/ELF/linkerscript-diagnostic.s b/lld/test/ELF/linkerscript-diagnostic.s new file mode 100644 index 00000000000..548b43666cf --- /dev/null +++ b/lld/test/ELF/linkerscript-diagnostic.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Take some valid script with multiline comments +## and check it actually works: +# RUN: rm -f %t.script +# RUN: echo "SECTIONS {" >> %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: ld.lld -shared %t -o %t1 --script %t.script + +## Change ":" to "+" at line 2, check that error +## message starts from correct line number: +# RUN: rm -f %t.script +# RUN: echo "SECTIONS {" >> %t.script +# RUN: echo ".text + { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR1 %s +# ERR1: line 2: + +## Change ":" to "+" at line 3 now, check correct error line number: +# RUN: rm -f %t.script +# RUN: echo "SECTIONS {" >> %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep + { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp : { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR2 %s +# ERR2: line 3: + +## Change ":" to "+" at line 6, after multiline comment, +## check correct error line number: +# RUN: rm -f %t.script +# RUN: echo "SECTIONS {" >> %t.script +# RUN: echo ".text : { *(.text) }" >> %t.script +# RUN: echo ".keep : { *(.keep) } /*" >> %t.script +# RUN: echo "comment line 1" >> %t.script +# RUN: echo "comment line 2 */" >> %t.script +# RUN: echo ".temp + { *(.temp) } }" >> %t.script +# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR5 %s +# ERR5: line 6: |