Remove `Ignore` flag from SymbolAssignment class.
Previously, Ignore flag is set if we don't want to assign a value to symbols. It happens if a symbol assingment is in PROVIDE() and there's already a symbol with the same name. The previous code had a subtle but that we assume that the existing symbol is an absolute symbol even if it is not. This patch fixes the issue by always overwriting an absolute symbol. llvm-svn: 277115
This commit is contained in:
parent
130b9f99d6
commit
8d083e6a0a
|
@ -194,17 +194,6 @@ LinkerScript<ELFT>::filter(std::vector<OutputSectionBase<ELFT> *> &Sections) {
|
||||||
return Sections;
|
return Sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
|
||||||
void LinkerScript<ELFT>::dispatchAssignment(SymbolAssignment *Cmd) {
|
|
||||||
uint64_t Val = Cmd->Expression(Dot);
|
|
||||||
if (Cmd->Name == ".") {
|
|
||||||
Dot = Val;
|
|
||||||
} else if (!Cmd->Ignore) {
|
|
||||||
auto *D = cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd->Name));
|
|
||||||
D->Value = Val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void LinkerScript<ELFT>::assignAddresses(
|
void LinkerScript<ELFT>::assignAddresses(
|
||||||
ArrayRef<OutputSectionBase<ELFT> *> Sections) {
|
ArrayRef<OutputSectionBase<ELFT> *> Sections) {
|
||||||
|
@ -226,7 +215,11 @@ void LinkerScript<ELFT>::assignAddresses(
|
||||||
|
|
||||||
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
||||||
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
|
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
|
||||||
dispatchAssignment(Cmd);
|
if (Cmd->Name == ".") {
|
||||||
|
Dot = Cmd->Expression(Dot);
|
||||||
|
} else if (Cmd->Sym) {
|
||||||
|
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(Dot);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,22 +361,25 @@ int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
|
||||||
return I < J ? -1 : 1;
|
return I < J ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add symbols defined by linker scripts.
|
||||||
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
|
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
|
||||||
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
||||||
auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
|
auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
|
||||||
if (!Cmd || Cmd->Name == ".")
|
if (!Cmd || Cmd->Name == ".")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// If a symbol was in PROVIDE(), define it only when it is an
|
||||||
|
// undefined symbol.
|
||||||
SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
|
SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
|
||||||
// The semantic of PROVIDE is that of introducing a symbol only if
|
if (Cmd->Provide && !(B && B->isUndefined()))
|
||||||
// it's not defined and there's at least a reference to it.
|
continue;
|
||||||
if ((!B && !Cmd->Provide) || (B && B->isUndefined()))
|
|
||||||
Symtab<ELFT>::X->addAbsolute(Cmd->Name,
|
// Define an absolute symbol. The symbol value will be assigned later.
|
||||||
Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
|
// (At this point, we don't know the final address yet.)
|
||||||
else
|
Symbol *Sym = Symtab<ELFT>::X->addUndefined(Cmd->Name);
|
||||||
// Symbol already exists in symbol table. If it is provided
|
replaceBody<DefinedRegular<ELFT>>(Sym, Cmd->Name, STV_DEFAULT);
|
||||||
// then we can't override its value.
|
Sym->Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||||
Cmd->Ignore = Cmd->Provide;
|
Cmd->Sym = Sym->body();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
namespace elf {
|
namespace elf {
|
||||||
|
class SymbolBody;
|
||||||
template <class ELFT> class InputSectionBase;
|
template <class ELFT> class InputSectionBase;
|
||||||
template <class ELFT> class OutputSectionBase;
|
template <class ELFT> class OutputSectionBase;
|
||||||
template <class ELFT> class OutputSectionFactory;
|
template <class ELFT> class OutputSectionFactory;
|
||||||
|
@ -56,9 +57,8 @@ struct SymbolAssignment : BaseCommand {
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
Expr Expression;
|
Expr Expression;
|
||||||
bool Provide = false;
|
bool Provide = false;
|
||||||
// Hidden and Ignore can be true, only if Provide is true
|
|
||||||
bool Hidden = false;
|
bool Hidden = false;
|
||||||
bool Ignore = false;
|
SymbolBody *Sym = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Linker scripts allow additional constraints to be put on ouput sections.
|
// Linker scripts allow additional constraints to be put on ouput sections.
|
||||||
|
|
Loading…
Reference in New Issue