Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -24,6 +24,7 @@ #include "Target.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/Casting.h" @@ -113,6 +114,9 @@ // True if a script being read is in a subdirectory specified by -sysroot. bool IsUnderSysroot; + + // A set to detect an INCLUDE() cycle. + StringSet<> Seen; }; } // namespace @@ -318,6 +322,11 @@ void ScriptParser::readInclude() { StringRef Tok = unquote(next()); + if (!Seen.insert(Tok).second) { + setError("there is a cycle in linker script INCLUDEs"); + return; + } + // https://sourceware.org/binutils/docs/ld/File-Commands.html: // The file will be searched for in the current directory, and in any // directory specified with the -L option. Index: lld/trunk/test/ELF/linkerscript/include-cycle.s =================================================================== --- lld/trunk/test/ELF/linkerscript/include-cycle.s +++ lld/trunk/test/ELF/linkerscript/include-cycle.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# RUN: echo INCLUDE %t1.script > %t1.script +# RUN: not ld.lld %t.o %t1.script 2>&1 | FileCheck %s + +# RUN: echo INCLUDE %t2.script > %t1.script +# RUN: echo INCLUDE %t1.script > %t2.script +# RUN: not ld.lld %t.o %t1.script 2>&1 | FileCheck %s + +# CHECK: there is a cycle in linker script INCLUDEs + +.globl _start +_start: + ret