Index: ELF/ScriptLexer.h =================================================================== --- ELF/ScriptLexer.h +++ ELF/ScriptLexer.h @@ -35,7 +35,7 @@ bool consumeLabel(StringRef Tok); std::string getCurrentLocation(); - std::vector MBs; + std::vector> MBs; std::vector Tokens; bool InExpr = false; size_t Pos = 0; @@ -47,6 +47,7 @@ size_t getColumnNumber(); MemoryBufferRef getCurrentMB(); + uint8_t getCurrentMBDepth(); }; } // namespace elf Index: ELF/ScriptLexer.cpp =================================================================== --- ELF/ScriptLexer.cpp +++ ELF/ScriptLexer.cpp @@ -88,7 +88,11 @@ // Split S into linker script tokens. void ScriptLexer::tokenize(MemoryBufferRef MB) { std::vector Vec; - MBs.push_back(MB); + uint8_t Depth = getCurrentMBDepth(); + if (++Depth > 10) + setError("maximum include nesting level of 10 exceeded"); + + MBs.push_back({MB, Depth}); StringRef S = MB.getBuffer(); StringRef Begin = S; @@ -272,14 +276,24 @@ return S.bytes_begin() <= T.bytes_begin() && T.bytes_end() <= S.bytes_end(); } -MemoryBufferRef ScriptLexer::getCurrentMB() { +static std::pair +getEnclosingMB(ArrayRef> V, StringRef Tok) { // Find input buffer containing the current token. + for (const std::pair &MB : V) + if (encloses(MB.first.getBuffer(), Tok)) + return MB; + llvm_unreachable("getCurrentMB: failed to find a token"); +} + +MemoryBufferRef ScriptLexer::getCurrentMB() { assert(!MBs.empty()); if (!Pos) - return MBs[0]; + return MBs[0].first; + return getEnclosingMB(MBs, Tokens[Pos - 1]).first; +} - for (MemoryBufferRef MB : MBs) - if (encloses(MB.getBuffer(), Tokens[Pos - 1])) - return MB; - llvm_unreachable("getCurrentMB: failed to find a token"); +uint8_t ScriptLexer::getCurrentMBDepth() { + if (MBs.empty() || !Pos) + return 0; + return getEnclosingMB(MBs, Tokens[Pos - 1]).second; } Index: test/ELF/linkerscript/linkerscript.s =================================================================== --- test/ELF/linkerscript/linkerscript.s +++ test/ELF/linkerscript/linkerscript.s @@ -44,9 +44,13 @@ # RUN: echo "FOO(BAR)" > %t.script # RUN: not ld.lld -o foo %t.script > %t.log 2>&1 # RUN: FileCheck -check-prefix=ERR1 %s < %t.log - # ERR1: unknown directive: FOO +# RUN: echo "INCLUDE \"%t.script3\"" > %t.script3 +# RUN: not ld.lld %t.script3 -o %t3 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR2 %s +# ERR2: error: {{.*}}:1: maximum include nesting level of 10 exceeded + .globl _start, _label _start: ret