forked from OSchip/llvm-project
Replace SharedSymbols with Defined when creating copy relocations.
This is slightly simpler to read IMHO. Now if a symbol has a position in the file, it is Defined. The main motivation is that with this a SharedSymbol doesn't need a section, which reduces the size of SymbolUnion. With this the peak allocation when linking chromium goes from 568.1 to 564.2 MB. llvm-svn: 330966
This commit is contained in:
parent
b09308d82a
commit
ab0cce5f1f
|
@ -1111,8 +1111,8 @@ ExprValue LinkerScript::getSymbolValue(StringRef Name, const Twine &Loc) {
|
||||||
if (auto *DS = dyn_cast<Defined>(Sym))
|
if (auto *DS = dyn_cast<Defined>(Sym))
|
||||||
return {DS->Section, false, DS->Value, Loc};
|
return {DS->Section, false, DS->Value, Loc};
|
||||||
if (auto *SS = dyn_cast<SharedSymbol>(Sym))
|
if (auto *SS = dyn_cast<SharedSymbol>(Sym))
|
||||||
if (!ErrorOnMissingSection || SS->CopyRelSec)
|
if (!ErrorOnMissingSection)
|
||||||
return {SS->CopyRelSec, false, 0, Loc};
|
return {nullptr, false, 0, Loc};
|
||||||
}
|
}
|
||||||
|
|
||||||
error(Loc + ": symbol not found: " + Name);
|
error(Loc + ": symbol not found: " + Name);
|
||||||
|
|
|
@ -38,7 +38,7 @@ using namespace llvm::object;
|
||||||
using namespace lld;
|
using namespace lld;
|
||||||
using namespace lld::elf;
|
using namespace lld::elf;
|
||||||
|
|
||||||
typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy;
|
typedef DenseMap<const SectionBase *, SmallVector<Defined *, 4>> SymbolMapTy;
|
||||||
|
|
||||||
static const std::string Indent8 = " "; // 8 spaces
|
static const std::string Indent8 = " "; // 8 spaces
|
||||||
static const std::string Indent16 = " "; // 16 spaces
|
static const std::string Indent16 = " "; // 16 spaces
|
||||||
|
@ -53,44 +53,29 @@ static void writeHeader(raw_ostream &OS, uint64_t VMA, uint64_t LMA,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a list of all symbols that we want to print out.
|
// Returns a list of all symbols that we want to print out.
|
||||||
static std::vector<Symbol *> getSymbols() {
|
static std::vector<Defined *> getSymbols() {
|
||||||
std::vector<Symbol *> V;
|
std::vector<Defined *> V;
|
||||||
for (InputFile *File : ObjectFiles) {
|
for (InputFile *File : ObjectFiles)
|
||||||
for (Symbol *B : File->getSymbols()) {
|
for (Symbol *B : File->getSymbols())
|
||||||
if (auto *SS = dyn_cast<SharedSymbol>(B))
|
|
||||||
if (SS->CopyRelSec || SS->NeedsPltAddr)
|
|
||||||
V.push_back(SS);
|
|
||||||
if (auto *DR = dyn_cast<Defined>(B))
|
if (auto *DR = dyn_cast<Defined>(B))
|
||||||
if (DR->File == File && !DR->isSection() && DR->Section &&
|
if (!DR->isSection() && DR->Section && DR->Section->Live &&
|
||||||
DR->Section->Live)
|
(DR->File == File || DR->NeedsPltAddr || DR->Section->Bss))
|
||||||
V.push_back(DR);
|
V.push_back(DR);
|
||||||
}
|
|
||||||
}
|
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a map from sections to their symbols.
|
// Returns a map from sections to their symbols.
|
||||||
static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) {
|
static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {
|
||||||
SymbolMapTy Ret;
|
SymbolMapTy Ret;
|
||||||
for (Symbol *S : Syms) {
|
for (Defined *DR : Syms)
|
||||||
if (auto *DR = dyn_cast<Defined>(S)) {
|
Ret[DR->Section].push_back(DR);
|
||||||
Ret[DR->Section].push_back(S);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedSymbol *SS = cast<SharedSymbol>(S);
|
|
||||||
if (SS->CopyRelSec)
|
|
||||||
Ret[SS->CopyRelSec].push_back(S);
|
|
||||||
else
|
|
||||||
Ret[InX::Plt].push_back(S);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort symbols by address. We want to print out symbols in the
|
// Sort symbols by address. We want to print out symbols in the
|
||||||
// order in the output file rather than the order they appeared
|
// order in the output file rather than the order they appeared
|
||||||
// in the input files.
|
// in the input files.
|
||||||
for (auto &It : Ret) {
|
for (auto &It : Ret) {
|
||||||
SmallVectorImpl<Symbol *> &V = It.second;
|
SmallVectorImpl<Defined *> &V = It.second;
|
||||||
std::stable_sort(V.begin(), V.end(), [](Symbol *A, Symbol *B) {
|
std::stable_sort(V.begin(), V.end(), [](Defined *A, Defined *B) {
|
||||||
return A->getVA() < B->getVA();
|
return A->getVA() < B->getVA();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -101,7 +86,7 @@ static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) {
|
||||||
// Demangling symbols (which is what toString() does) is slow, so
|
// Demangling symbols (which is what toString() does) is slow, so
|
||||||
// we do that in batch using parallel-for.
|
// we do that in batch using parallel-for.
|
||||||
static DenseMap<Symbol *, std::string>
|
static DenseMap<Symbol *, std::string>
|
||||||
getSymbolStrings(ArrayRef<Symbol *> Syms) {
|
getSymbolStrings(ArrayRef<Defined *> Syms) {
|
||||||
std::vector<std::string> Str(Syms.size());
|
std::vector<std::string> Str(Syms.size());
|
||||||
parallelForEachN(0, Syms.size(), [&](size_t I) {
|
parallelForEachN(0, Syms.size(), [&](size_t I) {
|
||||||
raw_string_ostream OS(Str[I]);
|
raw_string_ostream OS(Str[I]);
|
||||||
|
@ -169,7 +154,7 @@ void elf::writeMapFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect symbol info that we want to print out.
|
// Collect symbol info that we want to print out.
|
||||||
std::vector<Symbol *> Syms = getSymbols();
|
std::vector<Defined *> Syms = getSymbols();
|
||||||
SymbolMapTy SectionSyms = getSectionSyms(Syms);
|
SymbolMapTy SectionSyms = getSectionSyms(Syms);
|
||||||
DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
|
DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
|
||||||
|
|
||||||
|
|
|
@ -461,6 +461,21 @@ static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol &SS) {
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value,
|
||||||
|
uint64_t Size) {
|
||||||
|
Symbol Old = Sym;
|
||||||
|
replaceSymbol<Defined>(&Sym, Sym.File, Sym.getName(), Sym.Binding,
|
||||||
|
Sym.StOther, Sym.Type, Value, Size, Sec);
|
||||||
|
Sym.PltIndex = Old.PltIndex;
|
||||||
|
Sym.GotIndex = Old.GotIndex;
|
||||||
|
Sym.VerdefIndex = Old.VerdefIndex;
|
||||||
|
Sym.IsInGlobalMipsGot = Old.IsInGlobalMipsGot;
|
||||||
|
Sym.IsPreemptible = true;
|
||||||
|
Sym.ExportDynamic = true;
|
||||||
|
Sym.IsUsedInRegularObj = true;
|
||||||
|
Sym.Used = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Reserve space in .bss or .bss.rel.ro for copy relocation.
|
// Reserve space in .bss or .bss.rel.ro for copy relocation.
|
||||||
//
|
//
|
||||||
// The copy relocation is pretty much a hack. If you use a copy relocation
|
// The copy relocation is pretty much a hack. If you use a copy relocation
|
||||||
|
@ -522,11 +537,8 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) {
|
||||||
// Look through the DSO's dynamic symbol table for aliases and create a
|
// Look through the DSO's dynamic symbol table for aliases and create a
|
||||||
// dynamic symbol for each one. This causes the copy relocation to correctly
|
// dynamic symbol for each one. This causes the copy relocation to correctly
|
||||||
// interpose any aliases.
|
// interpose any aliases.
|
||||||
for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) {
|
for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS))
|
||||||
Sym->CopyRelSec = Sec;
|
replaceWithDefined(*Sym, Sec, 0, Sym->Size);
|
||||||
Sym->IsUsedInRegularObj = true;
|
|
||||||
Sym->Used = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS);
|
InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS);
|
||||||
}
|
}
|
||||||
|
@ -828,10 +840,8 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the symbol is undefined we already reported any relevant errors.
|
// If the symbol is undefined we already reported any relevant errors.
|
||||||
if (!Sym.isShared()) {
|
if (Sym.isUndefined())
|
||||||
assert(Sym.isUndefined());
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (!canDefineSymbolInExecutable(Sym)) {
|
if (!canDefineSymbolInExecutable(Sym)) {
|
||||||
error("cannot preempt symbol: " + toString(Sym) +
|
error("cannot preempt symbol: " + toString(Sym) +
|
||||||
|
@ -841,14 +851,13 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,
|
||||||
|
|
||||||
if (Sym.isObject()) {
|
if (Sym.isObject()) {
|
||||||
// Produce a copy relocation.
|
// Produce a copy relocation.
|
||||||
auto &SS = cast<SharedSymbol>(Sym);
|
if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) {
|
||||||
if (!SS.CopyRelSec) {
|
|
||||||
if (!Config->ZCopyreloc)
|
if (!Config->ZCopyreloc)
|
||||||
error("unresolvable relocation " + toString(Type) +
|
error("unresolvable relocation " + toString(Type) +
|
||||||
" against symbol '" + toString(SS) +
|
" against symbol '" + toString(*SS) +
|
||||||
"'; recompile with -fPIC or remove '-z nocopyreloc'" +
|
"'; recompile with -fPIC or remove '-z nocopyreloc'" +
|
||||||
getLocation(Sec, Sym, Offset));
|
getLocation(Sec, Sym, Offset));
|
||||||
addCopyRelSymbol<ELFT>(SS);
|
addCopyRelSymbol<ELFT>(*SS);
|
||||||
}
|
}
|
||||||
Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
|
Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
|
||||||
return;
|
return;
|
||||||
|
@ -889,8 +898,10 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,
|
||||||
if (!Sym.isInPlt())
|
if (!Sym.isInPlt())
|
||||||
addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel,
|
addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel,
|
||||||
Sym);
|
Sym);
|
||||||
|
if (!Sym.isDefined())
|
||||||
|
replaceWithDefined(Sym, InX::Plt, Sym.getPltOffset(), 0);
|
||||||
Sym.NeedsPltAddr = true;
|
Sym.NeedsPltAddr = true;
|
||||||
Sec.Relocations.push_back({toPlt(Expr), Type, Offset, Addend, &Sym});
|
Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,14 +97,7 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
|
||||||
}
|
}
|
||||||
return VA;
|
return VA;
|
||||||
}
|
}
|
||||||
case Symbol::SharedKind: {
|
case Symbol::SharedKind:
|
||||||
auto &SS = cast<SharedSymbol>(Sym);
|
|
||||||
if (SS.CopyRelSec)
|
|
||||||
return SS.CopyRelSec->getVA(0);
|
|
||||||
if (SS.NeedsPltAddr)
|
|
||||||
return Sym.getPltVA();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case Symbol::UndefinedKind:
|
case Symbol::UndefinedKind:
|
||||||
return 0;
|
return 0;
|
||||||
case Symbol::LazyArchiveKind:
|
case Symbol::LazyArchiveKind:
|
||||||
|
@ -143,6 +136,11 @@ uint64_t Symbol::getPltVA() const {
|
||||||
return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex);
|
return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Symbol::getPltOffset() const {
|
||||||
|
assert(!this->IsInIplt);
|
||||||
|
return Target->getPltEntryOffset(PltIndex);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t Symbol::getSize() const {
|
uint64_t Symbol::getSize() const {
|
||||||
if (const auto *DR = dyn_cast<Defined>(this))
|
if (const auto *DR = dyn_cast<Defined>(this))
|
||||||
return DR->Size;
|
return DR->Size;
|
||||||
|
@ -157,13 +155,6 @@ OutputSection *Symbol::getOutputSection() const {
|
||||||
return Sec->Repl->getOutputSection();
|
return Sec->Repl->getOutputSection();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto *S = dyn_cast<SharedSymbol>(this)) {
|
|
||||||
if (S->CopyRelSec)
|
|
||||||
return S->CopyRelSec->getParent();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,9 @@ public:
|
||||||
uint32_t PltIndex = -1;
|
uint32_t PltIndex = -1;
|
||||||
uint32_t GlobalDynIndex = -1;
|
uint32_t GlobalDynIndex = -1;
|
||||||
|
|
||||||
|
// This field is a index to the symbol's version definition.
|
||||||
|
uint32_t VerdefIndex = -1;
|
||||||
|
|
||||||
// Version definition index.
|
// Version definition index.
|
||||||
uint16_t VersionId;
|
uint16_t VersionId;
|
||||||
|
|
||||||
|
@ -146,6 +149,7 @@ public:
|
||||||
uint64_t getGotPltOffset() const;
|
uint64_t getGotPltOffset() const;
|
||||||
uint64_t getGotPltVA() const;
|
uint64_t getGotPltVA() const;
|
||||||
uint64_t getPltVA() const;
|
uint64_t getPltVA() const;
|
||||||
|
uint64_t getPltOffset() const;
|
||||||
uint64_t getSize() const;
|
uint64_t getSize() const;
|
||||||
OutputSection *getOutputSection() const;
|
OutputSection *getOutputSection() const;
|
||||||
|
|
||||||
|
@ -225,8 +229,9 @@ public:
|
||||||
SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,
|
SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,
|
||||||
uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,
|
uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,
|
||||||
uint32_t Alignment, uint32_t VerdefIndex)
|
uint32_t Alignment, uint32_t VerdefIndex)
|
||||||
: Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value),
|
: Symbol(SharedKind, &File, Name, Binding, StOther, Type),
|
||||||
Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) {
|
Alignment(Alignment), Value(Value), Size(Size) {
|
||||||
|
this->VerdefIndex = VerdefIndex;
|
||||||
// GNU ifunc is a mechanism to allow user-supplied functions to
|
// GNU ifunc is a mechanism to allow user-supplied functions to
|
||||||
// resolve PLT slot values at load-time. This is contrary to the
|
// resolve PLT slot values at load-time. This is contrary to the
|
||||||
// regular symbol resolution scheme in which symbols are resolved just
|
// regular symbol resolution scheme in which symbols are resolved just
|
||||||
|
@ -251,16 +256,10 @@ public:
|
||||||
return *cast<SharedFile<ELFT>>(File);
|
return *cast<SharedFile<ELFT>>(File);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not null, there is a copy relocation to this section.
|
uint32_t Alignment;
|
||||||
InputSection *CopyRelSec = nullptr;
|
|
||||||
|
|
||||||
uint64_t Value; // st_value
|
uint64_t Value; // st_value
|
||||||
uint64_t Size; // st_size
|
uint64_t Size; // st_size
|
||||||
|
|
||||||
// This field is a index to the symbol's version definition.
|
|
||||||
uint32_t VerdefIndex;
|
|
||||||
|
|
||||||
uint32_t Alignment;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// LazyArchive and LazyObject represent a symbols that is not yet in the link,
|
// LazyArchive and LazyObject represent a symbols that is not yet in the link,
|
||||||
|
|
|
@ -1646,6 +1646,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
CommonSec = dyn_cast_or_null<BssSection>(D->Section);
|
CommonSec = dyn_cast_or_null<BssSection>(D->Section);
|
||||||
if (CommonSec)
|
if (CommonSec)
|
||||||
ESym->st_shndx = SHN_COMMON;
|
ESym->st_shndx = SHN_COMMON;
|
||||||
|
else if (Sym->NeedsPltAddr)
|
||||||
|
ESym->st_shndx = SHN_UNDEF;
|
||||||
else if (const OutputSection *OutSec = Sym->getOutputSection())
|
else if (const OutputSection *OutSec = Sym->getOutputSection())
|
||||||
ESym->st_shndx = OutSec->SectionIndex;
|
ESym->st_shndx = OutSec->SectionIndex;
|
||||||
else if (isa<Defined>(Sym))
|
else if (isa<Defined>(Sym))
|
||||||
|
@ -1688,8 +1690,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
if (isMicroMips()) {
|
if (isMicroMips()) {
|
||||||
// Set STO_MIPS_MICROMIPS flag and less-significant bit for
|
// Set STO_MIPS_MICROMIPS flag and less-significant bit for
|
||||||
// defined microMIPS symbols and shared symbols with PLT record.
|
// defined microMIPS symbols and shared symbols with PLT record.
|
||||||
if ((Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) ||
|
if (Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) {
|
||||||
(Sym->isShared() && Sym->NeedsPltAddr)) {
|
|
||||||
if (StrTabSec.isDynamic())
|
if (StrTabSec.isDynamic())
|
||||||
ESym->st_value |= 1;
|
ESym->st_value |= 1;
|
||||||
ESym->st_other |= STO_MIPS_MICROMIPS;
|
ESym->st_other |= STO_MIPS_MICROMIPS;
|
||||||
|
@ -1831,10 +1832,6 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) {
|
||||||
// its type correctly.
|
// its type correctly.
|
||||||
std::vector<SymbolTableEntry>::iterator Mid =
|
std::vector<SymbolTableEntry>::iterator Mid =
|
||||||
std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) {
|
std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) {
|
||||||
// Shared symbols that this executable preempts are special. The dynamic
|
|
||||||
// linker has to look them up, so they have to be in the hash table.
|
|
||||||
if (auto *SS = dyn_cast<SharedSymbol>(S.Sym))
|
|
||||||
return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr;
|
|
||||||
return !S.Sym->isDefined();
|
return !S.Sym->isDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2359,9 +2356,8 @@ VersionNeedSection<ELFT>::VersionNeedSection()
|
||||||
NextIndex = getVerDefNum() + 1;
|
NextIndex = getVerDefNum() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {
|
||||||
void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
|
auto &File = cast<SharedFile<ELFT>>(*SS->File);
|
||||||
SharedFile<ELFT> &File = SS->getFile<ELFT>();
|
|
||||||
if (SS->VerdefIndex == VER_NDX_GLOBAL) {
|
if (SS->VerdefIndex == VER_NDX_GLOBAL) {
|
||||||
SS->VersionId = VER_NDX_GLOBAL;
|
SS->VersionId = VER_NDX_GLOBAL;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -670,7 +670,7 @@ template <class ELFT> class VersionNeedSection final : public SyntheticSection {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VersionNeedSection();
|
VersionNeedSection();
|
||||||
void addSymbol(SharedSymbol *SS);
|
void addSymbol(Symbol *Sym);
|
||||||
void finalizeContents() override;
|
void finalizeContents() override;
|
||||||
void writeTo(uint8_t *Buf) override;
|
void writeTo(uint8_t *Buf) override;
|
||||||
size_t getSize() const override;
|
size_t getSize() const override;
|
||||||
|
|
|
@ -1570,9 +1570,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
||||||
|
|
||||||
if (InX::DynSymTab && Sym->includeInDynsym()) {
|
if (InX::DynSymTab && Sym->includeInDynsym()) {
|
||||||
InX::DynSymTab->addSymbol(Sym);
|
InX::DynSymTab->addSymbol(Sym);
|
||||||
if (auto *SS = dyn_cast<SharedSymbol>(Sym))
|
if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File))
|
||||||
if (cast<SharedFile<ELFT>>(Sym->File)->IsNeeded)
|
if (File->IsNeeded && !Sym->isUndefined())
|
||||||
In<ELFT>::VerNeed->addSymbol(SS);
|
In<ELFT>::VerNeed->addSymbol(Sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,8 @@ labs = 0x1AB5
|
||||||
// CHECK-NEXT: 20102c 20102c 0 1 baz
|
// CHECK-NEXT: 20102c 20102c 0 1 baz
|
||||||
// CHECK-NEXT: 201030 201030 30 16 .plt
|
// CHECK-NEXT: 201030 201030 30 16 .plt
|
||||||
// CHECK-NEXT: 201030 201030 30 16 <internal>:(.plt)
|
// CHECK-NEXT: 201030 201030 30 16 <internal>:(.plt)
|
||||||
// CHECK-NEXT: 201040 0 0 1 sharedFunc1
|
// CHECK-NEXT: 201040 201040 0 1 sharedFunc1
|
||||||
// CHECK-NEXT: 201050 0 0 1 sharedFunc2
|
// CHECK-NEXT: 201050 201050 0 1 sharedFunc2
|
||||||
// CHECK-NEXT: 202000 202000 28 8 .got.plt
|
// CHECK-NEXT: 202000 202000 28 8 .got.plt
|
||||||
// CHECK-NEXT: 202000 202000 28 8 <internal>:(.got.plt)
|
// CHECK-NEXT: 202000 202000 28 8 <internal>:(.got.plt)
|
||||||
// CHECK-NEXT: 203000 203000 100 8 .dynamic
|
// CHECK-NEXT: 203000 203000 100 8 .dynamic
|
||||||
|
|
Loading…
Reference in New Issue