Files
nixpkgs/pkgs/development/compilers/llvm/20/lld/initialize-symbol-fields.patch
Amaan Qureshi 904e03b711 llvmPackages_{18,19,20,21}.lld: initialize Symbol fields in the constructor
lld relies on a memset that GCC 16 is allowed to optimize away, leaving
some symbol fields uninitialized. With lld 21, this makes `ld -r` emit
broken section symbols, which breaks LTO kernel module builds
(see ClangBuiltLinux/linux#2162). 18 through 20 should have the same
bug, but I haven't seen it break there myself.

This backports llvm/llvm-project@4d5dffb594 and
llvm/llvm-project@070e505ce2, which landed in 22.1.8.
2026-09-30 10:38:48 -04:00

102 lines
3.9 KiB
Diff

From 4d5dffb59420df29cc3b419a7fc90834aed7f7a9 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i@maskray.me>
Date: Sat, 16 May 2026 21:38:18 +0000
Subject: [PATCH] [ELF] Initialize Symbol fields in the constructor instead of
via memset (#198129)
`initSectionsAndLocalSyms` and `makeDefined` memset the storage to zero
and then placement-new a Symbol-derived object into it. Placement new
begins a new object's lifetime. The standard does not seem to guarantee
the memset bytes carry into members the constructor leaves
uninitialized.
lld built by GCC 16 can make Valgrind report reads of Symbol::flags
(via getSymSectionIndex during finalizeSections) as uses of
uninitialized values (ClangBuiltLinux/linux#2162).
This patch reinstates the per-field initialization that commit
778742760534 ("[ELF] Avoid redundant assignment to Symbol fields. NFC")
had replaced with a bulk memset.
(cherry picked from commit 905a88b923433eb8cd83677ea55bee82eb9ba498)
Squashed with 070e505ce21d ("[LLD][ELF] Add missing initialization of
Symbol `used` member.") and rebased onto 20.1.8.
---
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -1175,7 +1175,6 @@
if (!firstGlobal)
return;
SymbolUnion *locals = makeThreadLocalN<SymbolUnion>(firstGlobal);
- memset(locals, 0, sizeof(SymbolUnion) * firstGlobal);
ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
for (size_t i = 0, end = firstGlobal; i != end; ++i) {
@@ -1211,7 +1210,6 @@
else
new (symbols[i]) Defined(ctx, this, name, STB_LOCAL, eSym.st_other, type,
eSym.st_value, eSym.st_size, sec);
- symbols[i]->partition = 1;
symbols[i]->isUsedInRegularObj = true;
}
}
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -102,7 +102,7 @@
uint8_t symbolKind;
// The partition whose dynamic symbol table contains this symbol's definition.
- uint8_t partition;
+ uint8_t partition = 1;
// True if this symbol is preemptible at load time.
//
@@ -242,8 +242,13 @@
Symbol(Kind k, InputFile *file, StringRef name, uint8_t binding,
uint8_t stOther, uint8_t type)
: file(file), nameData(name.data()), nameSize(name.size()), type(type),
- binding(binding), stOther(stOther), symbolKind(k), ltoCanOmit(false),
- archSpecificBit(false) {}
+ binding(binding), stOther(stOther), symbolKind(k), isPreemptible(false),
+ isUsedInRegularObj(false), used(false), isExported(false),
+ ltoCanOmit(false), traced(false), hasVersionSuffix(false),
+ isInIplt(false), gotInIgot(false), folded(false),
+ archSpecificBit(false), scriptDefined(false), dsoDefined(false),
+ dsoProtected(false), versionScriptAssigned(false), thunkAccessed(false),
+ inDynamicList(false), referenced(false), referencedAfterWrap(false) {}
void overwrite(Symbol &sym, Kind k) const {
if (sym.traced)
@@ -302,18 +307,18 @@
// Temporary flags used to communicate which symbol entries need PLT and GOT
// entries during postScanRelocations();
- std::atomic<uint16_t> flags;
+ std::atomic<uint16_t> flags = 0;
// A ctx.symAux index used to access GOT/PLT entry indexes. This is allocated
// in postScanRelocations().
- uint32_t auxIdx;
- uint32_t dynsymIndex;
+ uint32_t auxIdx = 0;
+ uint32_t dynsymIndex = 0;
// If `file` is SharedFile (for SharedSymbol or copy-relocated Defined), this
// represents the Verdef index within the input DSO, which will be converted
// to a Verneed index in the output. Otherwise, this represents the Verdef
// index (VER_NDX_LOCAL, VER_NDX_GLOBAL, or a named version).
- uint16_t versionId;
+ uint16_t versionId = 0;
LLVM_PREFERRED_TYPE(bool)
uint8_t versionScriptAssigned : 1;
@@ -524,7 +529,6 @@
template <typename... T> Defined *makeDefined(T &&...args) {
auto *sym = getSpecificAllocSingleton<SymbolUnion>().Allocate();
- memset(sym, 0, sizeof(Symbol));
auto &s = *new (reinterpret_cast<Defined *>(sym)) Defined(std::forward<T>(args)...);
return &s;
}