Skip to content

Commit 8f72b0c

Browse files
committed
[ELF] Fix INCLUDE cycle detection
Fix #93947: the cycle detection mechanism added by https://reviews.llvm.org/D37524 also disallowed including a file twice, which is an unnecessary limitation. Now that we have an include stack #100493, supporting multiple inclusion is trivial. Note: a filename can be referenced with many different paths, e.g. a.lds, ./a.lds, ././a.lds. We don't attempt to detect the cycle in the earliest point.
1 parent aad2238 commit 8f72b0c

File tree

4 files changed

+14
-9
lines changed

4 files changed

+14
-9
lines changed

lld/ELF/ScriptLexer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ using namespace llvm;
3636
using namespace lld;
3737
using namespace lld::elf;
3838

39-
ScriptLexer::ScriptLexer(MemoryBufferRef mb) : curBuf(mb), mbs(1, mb) {}
39+
ScriptLexer::ScriptLexer(MemoryBufferRef mb) : curBuf(mb), mbs(1, mb) {
40+
activeFilenames.insert(mb.getBufferIdentifier());
41+
}
4042

4143
// Returns a whole line containing the current token.
4244
StringRef ScriptLexer::getLine() {
@@ -81,6 +83,7 @@ void ScriptLexer::lex() {
8183
eof = true;
8284
return;
8385
}
86+
activeFilenames.erase(curBuf.filename);
8487
curBuf = buffers.pop_back_val();
8588
continue;
8689
}

lld/ELF/ScriptLexer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLD_ELF_SCRIPT_LEXER_H
1111

1212
#include "lld/Common/LLVM.h"
13+
#include "llvm/ADT/DenseSet.h"
1314
#include "llvm/ADT/SmallVector.h"
1415
#include "llvm/ADT/StringRef.h"
1516
#include "llvm/Support/MemoryBufferRef.h"
@@ -33,6 +34,9 @@ class ScriptLexer {
3334
Buffer curBuf;
3435
SmallVector<Buffer, 0> buffers;
3536

37+
// Used to detect INCLUDE() cycles.
38+
llvm::DenseSet<StringRef> activeFilenames;
39+
3640
struct Token {
3741
StringRef str;
3842
explicit operator bool() const { return !str.empty(); }

lld/ELF/ScriptParser.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include "lld/Common/CommonLinkerContext.h"
2525
#include "llvm/ADT/SmallString.h"
2626
#include "llvm/ADT/StringRef.h"
27-
#include "llvm/ADT/StringSet.h"
2827
#include "llvm/ADT/StringSwitch.h"
2928
#include "llvm/BinaryFormat/ELF.h"
3029
#include "llvm/Support/Casting.h"
@@ -139,9 +138,6 @@ class ScriptParser final : ScriptLexer {
139138
// True if a script being read is in the --sysroot directory.
140139
bool isUnderSysroot = false;
141140

142-
// A set to detect an INCLUDE() cycle.
143-
StringSet<> seen;
144-
145141
// If we are currently parsing a PROVIDE|PROVIDE_HIDDEN command,
146142
// then this member is set to the PROVIDE symbol name.
147143
std::optional<llvm::StringRef> activeProvideSym;
@@ -406,7 +402,7 @@ void ScriptParser::readGroup() {
406402

407403
void ScriptParser::readInclude() {
408404
StringRef name = readName();
409-
if (!seen.insert(name).second) {
405+
if (!activeFilenames.insert(name).second) {
410406
setError("there is a cycle in linker script INCLUDEs");
411407
return;
412408
}

lld/test/ELF/linkerscript/include-cycle.s

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
# ERR1: error: 1.lds:1: there is a cycle in linker script INCLUDEs
77

88
# RUN: not ld.lld a.o -T 2a.lds 2>&1 | FileCheck %s --check-prefix=ERR2
9-
# ERR2: error: 2a.lds:1: there is a cycle in linker script INCLUDEs
9+
# ERR2: error: 2b.lds:1: there is a cycle in linker script INCLUDEs
1010

11-
# RUN: not ld.lld a.o -T 3.lds 2>&1 | FileCheck %s --check-prefix=ERR3
12-
# ERR3: error: 3.lds:2: there is a cycle in linker script INCLUDEs
11+
# RUN: ld.lld a.o -T 3.lds -o 3
12+
# RUN: llvm-objdump -s 3 | FileCheck %s --check-prefix=CHECK3
13+
# CHECK3: Contents of section foo:
14+
# CHECK3-NEXT: 0000 2a2a **
1315

1416
#--- 0.lds
1517
BYTE(42)

0 commit comments

Comments
 (0)