[lld] [ELF] --retain-symbols-file: keep listed symbols in .symtab, not .dynsym (PR #209063)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 23:59:12 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/209063
>From cc081f34c9088a0328859cc4a4bf022d6053fc3e Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 12 Jul 2026 15:24:20 -0700
Subject: [PATCH 1/3] [ELF] --retain-symbols-file: keep listed symbols in
.symtab, not .dynsym
Commit c0fc25307143dd06c12fb2f5ebdb1dade7290ccf (2017) implements
--retain-symbols-file with symbol version machinery
`{local: *; global: listed;}`, which removes unlisted symbols from
.dynsym and leaves .symtab untouched. GNU ld does the opposite: it keeps
only the listed symbols in .symtab and does not touch .dynsym.
Reuse the --discard-{locals,all} mechanism to reimplement the feature,
matching GNU ld.
Use --export-dynamic-symbol or a version script to control .dynsym.
Extend `markUsedSymbols` to mark referenced globals as well, so
--emit-relocs/-r keep a valid symbol index.
Fix #91055
---
lld/ELF/Config.h | 1 +
lld/ELF/Driver.cpp | 9 ++----
lld/ELF/MarkLive.cpp | 29 ++++++++++-------
lld/ELF/SymbolTable.cpp | 10 +-----
lld/ELF/Writer.cpp | 13 +++++++-
lld/docs/ReleaseNotes.rst | 3 ++
lld/docs/ld.lld.1 | 5 ++-
lld/test/ELF/retain-symbols-file.s | 50 ++++++++++++++++++++++--------
lld/test/ELF/retain-und.s | 15 ++++-----
lld/test/ELF/version-script-warn.s | 3 +-
10 files changed, 87 insertions(+), 51 deletions(-)
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 12b16ded61fca..863f3223094bb 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -299,6 +299,7 @@ struct Config {
llvm::StringRef thinLTOPrefixReplaceNativeObject;
std::string rpath;
llvm::SmallVector<VersionDefinition, 0> versionDefinitions;
+ std::optional<llvm::DenseSet<llvm::StringRef>> retainSymbols;
llvm::SmallVector<llvm::StringRef, 0> auxiliaryList;
llvm::SmallVector<llvm::StringRef, 0> filterList;
llvm::SmallVector<llvm::StringRef, 0> passPlugins;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..77821e8c813ef 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1961,15 +1961,12 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
ctx.arg.versionDefinitions.push_back(
{"global", (uint16_t)VER_NDX_GLOBAL, {}, {}});
- // If --retain-symbol-file is used, we'll keep only the symbols listed in
- // the file and discard all others.
+ // Keep only these symbols in .symtab (not .dynsym), matching GNU ld.
if (auto *arg = args.getLastArg(OPT_retain_symbols_file)) {
- ctx.arg.versionDefinitions[VER_NDX_LOCAL].nonLocalPatterns.push_back(
- {"*", /*isExternCpp=*/false, /*hasWildcard=*/true});
+ ctx.arg.retainSymbols.emplace();
if (std::optional<MemoryBufferRef> buffer = readFile(ctx, arg->getValue()))
for (StringRef s : args::getLines(*buffer))
- ctx.arg.versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(
- {s, /*isExternCpp=*/false, /*hasWildcard=*/false});
+ ctx.arg.retainSymbols->insert(s);
}
for (opt::Arg *arg : args.filtered(OPT_warn_backrefs_exclude)) {
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index d1e05b5eb9296..ef6d20c8e8137 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -339,10 +339,15 @@ void MarkLive<ELFT, TrackWhyLive>::markSymbol(Symbol *sym, StringRef reason) {
enqueue(isec, d->value, sym, {std::nullopt, reason});
}
-template <class ELFT> static void markUsedLocalSymbols(InputSectionBase &sec) {
+// If -r or --emit-relocs, ensure referenced symbols are preserved in .symtab.
+// --discard-* drops only locals; --retain-symbols-file also drops globals, so
+// mark those too.
+template <class ELFT>
+static void markUsedSymbols(Ctx &ctx, InputSectionBase &sec) {
+ bool retain = ctx.arg.retainSymbols.has_value();
auto mark = [&](const auto &rel) {
Symbol &sym = sec.file->getRelocTargetSym(rel);
- if (sym.isLocal())
+ if (sym.isLocal() || retain)
sym.setFlags(USED);
};
const RelsOrRelas<ELFT> rels = sec.template relsOrRelas<ELFT>();
@@ -385,7 +390,10 @@ void MarkLive<ELFT, TrackWhyLive>::run() {
// referenced by .eh_frame sections, so we scan them for that here.
for (EhInputSection *eh : ctx.ehInputSections)
scanEhFrameSection(*eh);
- bool markUsed = ctx.arg.copyRelocs && ctx.arg.discard != DiscardPolicy::None;
+ // See markUsedSymbols.
+ bool markUsed =
+ ctx.arg.copyRelocs &&
+ (ctx.arg.discard != DiscardPolicy::None || ctx.arg.retainSymbols);
for (InputSectionBase *sec : ctx.inputSections) {
if (sec->flags & SHF_GNU_RETAIN) {
enqueue(sec, /*offset=*/0, /*sym=*/nullptr, {std::nullopt, "retained"});
@@ -421,10 +429,8 @@ void MarkLive<ELFT, TrackWhyLive>::run() {
sec->markLive();
for (InputSection *isec : sec->dependentSections)
isec->markLive();
- // If -r or --emit-relocs, ensure referenced local symbols are
- // preserved by --discard-{locals,all} (see shouldKeepInSymtab).
if (markUsed)
- markUsedLocalSymbols<ELFT>(*sec);
+ markUsedSymbols<ELFT>(ctx, *sec);
}
}
@@ -602,14 +608,13 @@ template <class ELFT> void elf::markLive(Ctx &ctx) {
if (auto *s = dyn_cast<SharedSymbol>(sym))
if (s->isUsedInRegularObj && !s->isWeak())
cast<SharedFile>(s->file)->isNeeded = true;
- // If -r or --emit-relocs, ensure referenced local symbols are preserved so
- // that they won't be discarded by --discard-{locals,all} (see
- // shouldKeepInSymtab).
- if (ctx.arg.copyRelocs && ctx.arg.discard != DiscardPolicy::None)
- parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
+ // See markUsedSymbols.
+ if (ctx.arg.copyRelocs &&
+ (ctx.arg.discard != DiscardPolicy::None || ctx.arg.retainSymbols))
+ parallelForEach(ctx.objectFiles, [&ctx](ELFFileBase *file) {
for (InputSectionBase *sec : file->getSections())
if (sec)
- markUsedLocalSymbols<ELFT>(*sec);
+ markUsedSymbols<ELFT>(ctx, *sec);
});
return;
}
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index a76f5d4434a0d..c5ea3ee04ff4c 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -312,15 +312,7 @@ void SymbolTable::scanVersionScript() {
bool asteriskReported = false;
auto assignAsterisk = [&](SymbolVersion &pat, VersionDefinition *ver,
bool isLocal) {
- // Avoid issuing a warning if both '--retain-symbol-file' and a version
- // script with `global: *` are used.
- //
- // '--retain-symbol-file' adds a "*" pattern to
- // 'versionDefinitions[VER_NDX_LOCAL].nonLocalPatterns', see
- // 'readConfigs()' in 'Driver.cpp'. Note that it is not '.localPatterns',
- // and may seem counterintuitive, but still works as expected. Here we can
- // exploit that and skip analyzing the pattern added for this option.
- if (!asteriskReported && (isLocal || ver->id > VER_NDX_LOCAL)) {
+ if (!asteriskReported) {
if ((isLocal && globalAsteriskFound) ||
(!isLocal && localAsteriskFound)) {
Warn(ctx)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 7567e1923d944..99e748080d0c7 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -375,6 +375,12 @@ template <class ELFT> void Writer<ELFT>::run() {
}
}
+static bool retainKeepsInSymtab(Ctx &ctx, const Symbol &sym) {
+ if (sym.hasFlag(USED) && ctx.arg.copyRelocs)
+ return true;
+ return ctx.arg.retainSymbols->contains(sym.getName());
+}
+
static bool shouldKeepInSymtab(Ctx &ctx, const Defined &sym) {
if (sym.isSection())
return false;
@@ -407,6 +413,10 @@ static bool shouldKeepInSymtab(Ctx &ctx, const Defined &sym) {
(ctx.arg.discard == DiscardPolicy::Locals ||
(sym.section && (sym.section->flags & SHF_MERGE))))
return false;
+ // If --retain-symbols-file= is specified, keep in .symtab only listed symbols
+ // plus those referenced by emitted relocations.
+ if (LLVM_UNLIKELY(ctx.arg.retainSymbols))
+ return retainKeepsInSymtab(ctx, sym);
return true;
}
@@ -1934,7 +1944,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
continue;
if (!ctx.arg.relocatable)
sym->binding = sym->computeBinding(ctx);
- if (ctx.in.symTab)
+ if (ctx.in.symTab &&
+ (!ctx.arg.retainSymbols || retainKeepsInSymtab(ctx, *sym)))
ctx.in.symTab->addSymbol(sym);
// computeBinding might localize a symbol that was considered exported
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 058173413e41a..f01e5c451f43c 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -40,6 +40,9 @@ ELF Improvements
beats positional last-match-wins; default: positional). In ELF, the glob
matches input section names (e.g. ``.text.unlikely.code1``).
+* ``--retain-symbols-file`` now filters ``.symtab`` instead of ``.dynsym``,
+ matching GNU ld.
+
* When a ``SECTIONS`` command interleaves relro and non-relro sections, lld now
emits one ``PT_GNU_RELRO`` segment per contiguous run of relro sections
instead of reporting a ``not contiguous with other relro sections`` error.
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 70541cf786f64..7dedf69881b3f 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -582,7 +582,10 @@ version.txt containing the output of ld.lld --version.
The archive when
unpacked can be used to re-run the linker with the same options and input files.
.It Fl -retain-symbols-file Ns = Ns Ar file
-Retain only the symbols listed in the file.
+Keep only the symbols listed in
+.Ar file
+in the static symbol table, along with symbols referenced by emitted relocations.
+This does not affect the dynamic symbol table.
.It Fl -rpath Ns = Ns Ar value , Fl R Ar value
Add a
.Dv DT_RUNPATH
diff --git a/lld/test/ELF/retain-symbols-file.s b/lld/test/ELF/retain-symbols-file.s
index 903d5440e973f..ea72cf1962466 100644
--- a/lld/test/ELF/retain-symbols-file.s
+++ b/lld/test/ELF/retain-symbols-file.s
@@ -1,34 +1,58 @@
# REQUIRES: x86
-## --retain-symbols-file removes unlisted symbols from .dynsym.
+## --retain-symbols-file filters .symtab, not .dynsym, matching GNU ld.
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: echo foo > %t.retain
# RUN: echo bar >> %t.retain
# RUN: ld.lld -shared --retain-symbols-file=%t.retain %t.o -o %t.so
-# RUN: llvm-readelf --dyn-syms %t.so | FileCheck %s --check-prefix=DYN
+# RUN: llvm-readelf --dyn-syms -s %t.so | FileCheck %s --check-prefix=SYM
## Separate-argument form.
# RUN: ld.lld -shared --retain-symbols-file %t.retain %t.o -o %t2.so
# RUN: cmp %t.so %t2.so
-# DYN: Symbol table '.dynsym'
-# DYN-DAG: NOTYPE GLOBAL DEFAULT UND und
-# DYN-DAG: FUNC GLOBAL DEFAULT {{.*}} foo
-# DYN-DAG: FUNC GLOBAL DEFAULT {{.*}} bar
-# DYN-NOT: zed
-# DYN-NOT: _start
+## .dynsym keeps every exported symbol, including unlisted ones.
+# SYM-DAG: NOTYPE GLOBAL DEFAULT UND und
+# SYM-DAG: NOTYPE GLOBAL DEFAULT {{.*}} _start
+# SYM-DAG: FUNC GLOBAL DEFAULT {{.*}} zed
+# SYM-DAG: FUNC GLOBAL DEFAULT {{.*}} foo
+# SYM-DAG: FUNC GLOBAL DEFAULT {{.*}} bar
-## --emit-relocs/-r preserves symbols referenced by emitted relocations.
+## .symtab keeps only the listed foo and bar.
+# SYM: Symbol table '.symtab'
+# SYM-NOT: _start
+# SYM-NOT: zed
+# SYM-NOT: und
+# SYM-NOT: loc
+# SYM: FUNC GLOBAL DEFAULT {{.*}} foo
+# SYM: FUNC GLOBAL DEFAULT {{.*}} bar
+
+## --emit-relocs keeps unlisted symbols referenced by emitted relocations.
+# RUN: ld.lld -shared --emit-relocs --retain-symbols-file=%t.retain %t.o -o %t.er.so
+# RUN: llvm-readelf --symbols %t.er.so | FileCheck %s --check-prefix=EMIT
+# RUN: llvm-readelf -r %t.er.so | FileCheck %s --check-prefix=REL
+# EMIT: Symbol table '.symtab'
+# EMIT-DAG: FUNC GLOBAL DEFAULT {{.*}} zed
+# EMIT-DAG: NOTYPE GLOBAL DEFAULT UND und
+# EMIT-DAG: FUNC GLOBAL DEFAULT {{.*}} foo
+# EMIT-DAG: FUNC GLOBAL DEFAULT {{.*}} bar
+# REL-DAG: R_X86_64_PLT32 {{.*}} zed - 4
+# REL-DAG: R_X86_64_PLT32 {{.*}} und - 4
+
+## --discard-none: relocation-referenced symbols are kept by --retain-symbols-file
+## itself, not --discard-*.
# RUN: ld.lld -shared --emit-relocs --discard-none --retain-symbols-file=%t.retain %t.o -o %t.dn.so
# RUN: llvm-readelf -r %t.dn.so | FileCheck %s --check-prefix=REL
-# REL-DAG: R_X86_64_PLT32 {{.*}} zed - 4
-# REL-DAG: R_X86_64_PLT32 {{.*}} und - 4
-## An empty file lists nothing, localizing every defined symbol out of .dynsym.
+## An empty file drops every symbol from .symtab, unlike omitting the option.
# RUN: ld.lld -shared --retain-symbols-file=/dev/null %t.o -o %t.empty.so
-# RUN: llvm-readelf --dyn-syms %t.empty.so | FileCheck %s --check-prefix=EMPTY
+# RUN: llvm-readelf --dyn-syms --symbols %t.empty.so | FileCheck %s --check-prefix=EMPTY
# EMPTY: Symbol table '.dynsym'
+# EMPTY-DAG: FUNC GLOBAL DEFAULT {{.*}} foo
+# EMPTY-DAG: FUNC GLOBAL DEFAULT {{.*}} bar
+# EMPTY-DAG: FUNC GLOBAL DEFAULT {{.*}} zed
+# EMPTY: Symbol table '.symtab'
# EMPTY-NOT: foo
# EMPTY-NOT: bar
# EMPTY-NOT: zed
diff --git a/lld/test/ELF/retain-und.s b/lld/test/ELF/retain-und.s
index 7a45d92e540ac..b11e5a90fdff2 100644
--- a/lld/test/ELF/retain-und.s
+++ b/lld/test/ELF/retain-und.s
@@ -1,17 +1,18 @@
# REQUIRES: x86
-## An empty --retain-symbols-file behaves like a `{ local: *; }` version script,
-## keeping the R_X86_64_64 dynamic relocation to the weak undefined foo.
+## An unlisted undefined symbol referenced by a dynamic relocation stays in
+## .dynsym (keeping the relocation valid) but is dropped from .symtab.
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: echo > %t.retain
-# RUN: echo '{ local: *; };' > %t.script
-# RUN: ld.lld -shared --version-script %t.script %t.o -o %t1.so
-# RUN: ld.lld -shared --retain-symbols-file %t.retain %t.o -o %t2.so
-# RUN: llvm-readelf -r %t1.so | FileCheck %s
-# RUN: llvm-readelf -r %t2.so | FileCheck %s
+# RUN: ld.lld -shared --retain-symbols-file=%t.retain %t.o -o %t.so
+# RUN: llvm-readelf -r --dyn-syms --symbols %t.so | FileCheck %s
# CHECK: Relocation section '.rela.dyn' {{.+}} contains 1
# CHECK: R_X86_64_64 {{.*}} foo + 0
+# CHECK: Symbol table '.dynsym'
+# CHECK: NOTYPE WEAK DEFAULT UND foo
+# CHECK: Symbol table '.symtab'
+# CHECK-NOT: foo
.data
.quad foo
diff --git a/lld/test/ELF/version-script-warn.s b/lld/test/ELF/version-script-warn.s
index 9aba596165796..13bb734b2887b 100644
--- a/lld/test/ELF/version-script-warn.s
+++ b/lld/test/ELF/version-script-warn.s
@@ -20,8 +20,7 @@
# RUN: echo 'V1 { local: *; }; V2 { local: *;};' > %t.ver
# RUN: ld.lld --version-script %t.ver %t.o -shared -o %t.so --fatal-warnings
-## --retain-symbols-file uses the same internal infrastructure as the support
-## for version scripts. Do not show the warings if they both are used.
+## --retain-symbols-file with a version-script '*' must not warn.
# RUN: echo 'foo' > %t_retain.txt
# RUN: echo '{ local: *; };' > %t_local.ver
# RUN: echo '{ global: *; };' > %t_global.ver
>From 696df79c506d26a03a8672aa0fd6c6d1853c9898 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 13 Jul 2026 23:54:14 -0700
Subject: [PATCH 2/3] Simplify markUsedSymbols
---
lld/ELF/MarkLive.cpp | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index ef6d20c8e8137..fb2165a5126ef 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -339,16 +339,14 @@ void MarkLive<ELFT, TrackWhyLive>::markSymbol(Symbol *sym, StringRef reason) {
enqueue(isec, d->value, sym, {std::nullopt, reason});
}
-// If -r or --emit-relocs, ensure referenced symbols are preserved in .symtab.
-// --discard-* drops only locals; --retain-symbols-file also drops globals, so
-// mark those too.
+// If -r or --emit-relocs, mark symbols referenced by relocations as used so
+// .symtab retains them and the relocations keep valid symbol indices. Callers
+// invoke this only when .symtab filtering is active (--discard-* or
+// --retain-symbols-file); otherwise .symtab keeps every symbol anyway.
template <class ELFT>
-static void markUsedSymbols(Ctx &ctx, InputSectionBase &sec) {
- bool retain = ctx.arg.retainSymbols.has_value();
+static void markUsedSymbols(InputSectionBase &sec) {
auto mark = [&](const auto &rel) {
- Symbol &sym = sec.file->getRelocTargetSym(rel);
- if (sym.isLocal() || retain)
- sym.setFlags(USED);
+ sec.file->getRelocTargetSym(rel).setFlags(USED);
};
const RelsOrRelas<ELFT> rels = sec.template relsOrRelas<ELFT>();
for (const typename ELFT::Rel &rel : rels.rels)
@@ -430,7 +428,7 @@ void MarkLive<ELFT, TrackWhyLive>::run() {
for (InputSection *isec : sec->dependentSections)
isec->markLive();
if (markUsed)
- markUsedSymbols<ELFT>(ctx, *sec);
+ markUsedSymbols<ELFT>(*sec);
}
}
@@ -611,10 +609,10 @@ template <class ELFT> void elf::markLive(Ctx &ctx) {
// See markUsedSymbols.
if (ctx.arg.copyRelocs &&
(ctx.arg.discard != DiscardPolicy::None || ctx.arg.retainSymbols))
- parallelForEach(ctx.objectFiles, [&ctx](ELFFileBase *file) {
+ parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
for (InputSectionBase *sec : file->getSections())
if (sec)
- markUsedSymbols<ELFT>(ctx, *sec);
+ markUsedSymbols<ELFT>(*sec);
});
return;
}
>From a3f349c4827017641b6e812f3d1864de8843d8e7 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Mon, 13 Jul 2026 23:59:00 -0700
Subject: [PATCH 3/3] clang-format; release note link
---
lld/ELF/MarkLive.cpp | 3 +--
lld/docs/ReleaseNotes.rst | 5 +++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index fb2165a5126ef..2820818133d5c 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -343,8 +343,7 @@ void MarkLive<ELFT, TrackWhyLive>::markSymbol(Symbol *sym, StringRef reason) {
// .symtab retains them and the relocations keep valid symbol indices. Callers
// invoke this only when .symtab filtering is active (--discard-* or
// --retain-symbols-file); otherwise .symtab keeps every symbol anyway.
-template <class ELFT>
-static void markUsedSymbols(InputSectionBase &sec) {
+template <class ELFT> static void markUsedSymbols(InputSectionBase &sec) {
auto mark = [&](const auto &rel) {
sec.file->getRelocTargetSym(rel).setFlags(USED);
};
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 6991b0ec86c11..36f50db965f04 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -76,6 +76,9 @@ ELF Improvements
``.debug_info``), fixing DWARF corruption in the output.
(`#209035 <https://github.com/llvm/llvm-project/pull/209035>`_)
(`#209042 <https://github.com/llvm/llvm-project/pull/209042>`_)
+* ``--retain-symbols-file`` now filters ``.symtab`` instead of ``.dynsym``,
+ matching GNU ld.
+ (`#209063 <https://github.com/llvm/llvm-project/pull/209063>`_)
* ``INCLUDE`` in linker scripts now fully parses its own content instead of
sharing a lexer buffer stack with the includer, fixing spurious acceptance
of malformed scripts.
@@ -87,8 +90,6 @@ ELF Improvements
* Thunks are no longer reused across an ``OVERLAY`` boundary unless the
target output section is guaranteed to be resident at the same time.
(`#200415 <https://github.com/llvm/llvm-project/pull/200415>`_)
-* ``--retain-symbols-file`` now filters ``.symtab`` instead of ``.dynsym``,
- matching GNU ld.
* When a ``SECTIONS`` command interleaves relro and non-relro sections, lld now
emits one ``PT_GNU_RELRO`` segment per contiguous run of relro sections
instead of reporting a ``not contiguous with other relro sections`` error.
More information about the llvm-commits
mailing list