[ELF] Fix unnecessary inclusion of unreferenced provide symbols
Previously, linker was unnecessarily including a PROVIDE symbol which was referenced by another unused PROVIDE symbol. For example, if a linker script contained the below code and 'not_used_sym' provide symbol is not included, then linker was still unnecessarily including 'foo' PROVIDE symbol because it was referenced by 'not_used_sym'. This commit fixes this behavior. PROVIDE(not_used_sym = foo) PROVIDE(foo = 0x1000) This commit fixes this behavior by using dfs-like algorithm to find all the symbols referenced in provide expressions of included provide symbols. This commit also fixes the issue of unused section not being garbage-collected if a symbol of the section is referenced by an unused PROVIDE symbol. Closes #74771 Closes #84730 Co-authored-by: Fangrui Song <i@maskray.me>
This commit is contained in:
committed by
Fangrui Song
parent
b6dfaf4c29
commit
ebb326a51f
@@ -36,6 +36,7 @@
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
@@ -138,6 +139,10 @@ private:
|
||||
|
||||
// A set to detect an INCLUDE() cycle.
|
||||
StringSet<> seen;
|
||||
|
||||
// If we are currently parsing a PROVIDE|PROVIDE_HIDDEN command,
|
||||
// then this member is set to the PROVIDE symbol name.
|
||||
std::optional<llvm::StringRef> activeProvideSym;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -1055,6 +1060,9 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
|
||||
;
|
||||
return nullptr;
|
||||
}
|
||||
llvm::SaveAndRestore saveActiveProvideSym(activeProvideSym);
|
||||
if (provide)
|
||||
activeProvideSym = name;
|
||||
SymbolAssignment *cmd = readSymbolAssignment(name);
|
||||
cmd->provide = provide;
|
||||
cmd->hidden = hidden;
|
||||
@@ -1570,7 +1578,10 @@ Expr ScriptParser::readPrimary() {
|
||||
tok = unquote(tok);
|
||||
else if (!isValidSymbolName(tok))
|
||||
setError("malformed number: " + tok);
|
||||
script->referencedSymbols.push_back(tok);
|
||||
if (activeProvideSym)
|
||||
script->provideMap[*activeProvideSym].push_back(tok);
|
||||
else
|
||||
script->referencedSymbols.push_back(tok);
|
||||
return [=] { return script->getSymbolValue(tok, location); };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user