[lld] [lld][ELF] Enable link script to support absolute path matching (PR #156353)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 1 18:24:12 PDT 2025
https://github.com/mykouHW updated https://github.com/llvm/llvm-project/pull/156353
>From c9aa1c621aaa8d1774a142e0823b6dfcf9c379ec Mon Sep 17 00:00:00 2001
From: koumeiyuan <koumeiyuan at huawei.com>
Date: Mon, 25 Aug 2025 17:34:40 +0000
Subject: [PATCH] [lld][ELF] Enable link script to support absolute path
matching
Fixing the vulnerability in LLVM lld regarding file matching in linker scripts:
There is a compatibility issue with filename matching. When input files use absolute paths, the matching results from mc lld do not meet expectations.
---
lld/ELF/LinkerScript.cpp | 31 +++++++++---
lld/ELF/LinkerScript.h | 2 +-
lld/test/ELF/linkerscript/abs-path-match.s | 56 ++++++++++++++++++++++
3 files changed, 81 insertions(+), 8 deletions(-)
create mode 100644 lld/test/ELF/linkerscript/abs-path-match.s
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 921128dae2bdb..c325f18616fe3 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -411,7 +411,17 @@ void LinkerScript::assignSymbol(SymbolAssignment *cmd, bool inSec) {
cmd->sym->type = v.type;
}
-bool InputSectionDescription::matchesFile(const InputFile &file) const {
+// Convert an absolute address to a filename
+static inline StringRef getExtractFilename(StringRef filename) {
+ size_t pos = filename.rfind("/");
+ if (pos != std::string::npos) {
+ return filename.substr(pos + 1);
+ }
+ return filename;
+}
+
+bool InputSectionDescription::matchesFile(const InputFile &file,
+ bool ExtractFlag) const {
if (filePat.isTrivialMatchAll())
return true;
@@ -419,10 +429,17 @@ bool InputSectionDescription::matchesFile(const InputFile &file) const {
if (matchType == MatchType::WholeArchive) {
matchesFileCache.emplace(&file, filePat.match(file.archiveName));
} else {
- if (matchType == MatchType::ArchivesExcluded && !file.archiveName.empty())
+ if (matchType == MatchType::ArchivesExcluded && !file.archiveName.empty()){
matchesFileCache.emplace(&file, false);
- else
- matchesFileCache.emplace(&file, filePat.match(file.getNameForScript()));
+ } else {
+ bool MatchFilename = filePat.match(file.getNameForScript());
+ StringRef ExtractFilename = getExtractFilename(file.getNameForScript());
+ // only use for computeInputSections
+ if (ExtractFlag) {
+ MatchFilename = MatchFilename || filePat.match(ExtractFilename);
+ }
+ matchesFileCache.emplace(&file, MatchFilename);
+ }
}
}
@@ -442,7 +459,7 @@ bool SectionPattern::excludesFile(const InputFile &file) const {
bool LinkerScript::shouldKeep(InputSectionBase *s) {
for (InputSectionDescription *id : keptSections)
- if (id->matchesFile(*s->file))
+ if (id->matchesFile(*s->file, false))
for (SectionPattern &p : id->sectionPatterns)
if (p.sectionPat.match(s->name) &&
(s->flags & id->withFlags) == id->withFlags &&
@@ -571,8 +588,8 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
if (!pat.sectionPat.match(sec->name))
continue;
- if (!cmd->matchesFile(*sec->file) || pat.excludesFile(*sec->file) ||
- !flagsMatch(sec))
+ if (!cmd->matchesFile(*sec->file, true) ||
+ pat.excludesFile(*sec->file) || !flagsMatch(sec))
continue;
if (sec->parent) {
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 80c4f564afabc..452cfbcd9b777 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -227,7 +227,7 @@ class InputSectionDescription : public SectionCommand {
return c->kind == InputSectionKind;
}
- bool matchesFile(const InputFile &file) const;
+ bool matchesFile(const InputFile &file, bool ExtractFilename) const;
// Input sections that matches at least one of SectionPatterns
// will be associated with this InputSectionDescription.
diff --git a/lld/test/ELF/linkerscript/abs-path-match.s b/lld/test/ELF/linkerscript/abs-path-match.s
new file mode 100644
index 0000000000000..cc31dcd1e8031
--- /dev/null
+++ b/lld/test/ELF/linkerscript/abs-path-match.s
@@ -0,0 +1,56 @@
+# REQUIRES: x86
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 main.s -o main.o
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 foo.s -o foo.o
+# RUN: llvm-objcopy --rename-section .text=.text_foo foo.o foo.o
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 bar.s -o bar.o
+# RUN: llvm-objcopy --rename-section .text=.text_bar bar.o bar.o
+
+# RUN: ld.lld -r main.o %t/foo.o %t/bar.o -T script.ld -o main_abs.o
+
+# RUN: llvm-objdump -S main_abs.o > main_abs
+# RUN: llvm-objdump -S main_abs.o | FileCheck %s
+# CHECK: Disassembly of section .goo:
+
+
+#--- foo.s
+ .text
+ .globl foo
+ .p2align 4
+ .type foo, at function
+foo:
+ nop
+
+
+#--- bar.s
+ .text
+ .globl bar
+ .p2align 4
+ .type bar, at function
+bar:
+ nop
+
+
+#--- main.s
+ .text
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ callq foo at PLT
+ callq bar at PLT
+ retq
+
+
+#--- script.ld
+SECTIONS {
+ .text : { *(.text) }
+ .goo : {
+ bar.o(.text_bar);
+ foo.o(.text_foo);
+ }
+}
\ No newline at end of file
More information about the llvm-commits
mailing list