Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -184,8 +184,8 @@ // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`. uint64_t SymValue = Value.Sec ? 0 : Value.getValue(); - replaceSymbol(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, - STT_NOTYPE, SymValue, 0, Sec); + replaceSymbol(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, + STT_NOTYPE, SymValue, 0, Sec); Cmd->Sym = cast(Sym); } @@ -201,8 +201,8 @@ std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); - replaceSymbol(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, - STT_NOTYPE, 0, 0, nullptr); + replaceSymbol(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, + STT_NOTYPE, 0, 0, nullptr); Cmd->Sym = cast(Sym); Cmd->Provide = false; } Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -456,7 +456,7 @@ Bss->Live = !Config->GcSections; InputSections.push_back(Bss); - replaceSymbol(S, &File, N, Binding, StOther, Type, 0, Size, Bss); + replaceSymbol(S, &File, N, Binding, StOther, Type, 0, Size, Bss); return S; } @@ -530,8 +530,8 @@ int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, Section == nullptr, Value, Name); if (Cmp > 0) - replaceSymbol(S, File, Name, Binding, StOther, Type, Value, Size, - Section); + replaceSymbol(S, File, Name, Binding, StOther, Type, Value, Size, + Section); else if (Cmp == 0) reportDuplicate(S, File, dyn_cast_or_null(Section), Value); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -46,11 +46,21 @@ const uint32_t Size; }; +struct GlobalInfo { + uint32_t PltIndex = -1; + uint32_t GotPltIndex = -1; + uint32_t DynsymIndex = 0; + bool isInPlt() const { return PltIndex != -1U; } + + uint64_t getGotPltOffset() const; +}; + // The base class for real symbol classes. class Symbol { public: enum Kind { DefinedKind, + GlobalKind, SharedKind, UndefinedKind, LazyArchiveKind, @@ -67,10 +77,7 @@ mutable uint32_t NameSize; public: - uint32_t DynsymIndex = 0; uint32_t GotIndex = -1; - uint32_t GotPltIndex = -1; - uint32_t PltIndex = -1; uint32_t GlobalDynIndex = -1; // Version definition index. @@ -118,7 +125,9 @@ bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } bool isUndefined() const { return SymbolKind == UndefinedKind; } - bool isDefined() const { return SymbolKind == DefinedKind; } + bool isDefined() const { + return SymbolKind == DefinedKind || SymbolKind == GlobalKind; + } bool isShared() const { return SymbolKind == SharedKind; } bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; } @@ -138,7 +147,7 @@ void parseSymbolVersion(); bool isInGot() const { return GotIndex != -1U; } - bool isInPlt() const { return PltIndex != -1U; } + bool isInPlt() const; uint64_t getVA(int64_t Addend = 0) const; @@ -149,6 +158,10 @@ uint64_t getPltVA() const; uint64_t getSize() const; OutputSection *getOutputSection() const; + GlobalInfo *getGlobalInfo(); + const GlobalInfo *getGlobalInfo() const { + return const_cast(this)->getGlobalInfo(); + } protected: Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding, @@ -198,10 +211,16 @@ // Represents a symbol that is defined in the current output file. class Defined : public Symbol { public: + Defined(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding, + uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, + SectionBase *Section) + : Symbol(K, File, Name, Binding, StOther, Type), Value(Value), Size(Size), + Section(Section) {} + Defined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, SectionBase *Section) - : Symbol(DefinedKind, File, Name, Binding, StOther, Type), Value(Value), - Size(Size), Section(Section) {} + : Defined(DefinedKind, File, Name, Binding, StOther, Type, Value, Size, + Section) {} static bool classof(const Symbol *S) { return S->isDefined(); } @@ -210,12 +229,26 @@ SectionBase *Section; }; +class Global : public Defined { +public: + Global(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, + uint8_t Type, uint64_t Value, uint64_t Size, SectionBase *Section) + : Defined(GlobalKind, File, Name, Binding, StOther, Type, Value, Size, + Section) {} + + static bool classof(const Symbol *S) { return S->kind() == GlobalKind; } + + GlobalInfo Info; +}; + class Undefined : public Symbol { public: Undefined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, uint8_t Type) : Symbol(UndefinedKind, File, Name, Binding, StOther, Type) {} + GlobalInfo Info; + static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } }; @@ -252,6 +285,8 @@ return *cast>(File); } + GlobalInfo Info; + // If not null, there is a copy relocation to this section. InputSection *CopyRelSec = nullptr; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -40,8 +40,23 @@ Defined *ElfSym::MipsLocalGp; Defined *ElfSym::RelaIpltEnd; +GlobalInfo *Symbol::getGlobalInfo() { + if (auto *U = dyn_cast(this)) + return &U->Info; + if (auto *SS = dyn_cast(this)) + return &SS->Info; + if (auto *G = dyn_cast(this)) + return &G->Info; + return nullptr; +} + +uint64_t GlobalInfo::getGotPltOffset() const { + return GotPltIndex * Target->GotPltEntrySize; +} + static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { switch (Sym.kind()) { + case Symbol::GlobalKind: case Symbol::DefinedKind: { auto &D = cast(Sym); SectionBase *IS = D.Section; @@ -132,15 +147,22 @@ } uint64_t Symbol::getGotPltOffset() const { - return GotPltIndex * Target->GotPltEntrySize; + return getGlobalInfo()->getGotPltOffset(); } uint64_t Symbol::getPltVA() const { - if (this->IsInIplt) + uint32_t PltIndex = getGlobalInfo()->PltIndex; + if (IsInIplt) return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize; return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex); } +bool Symbol::isInPlt() const { + if (const GlobalInfo *Info = getGlobalInfo()) + return Info->isInPlt(); + return false; +} + uint64_t Symbol::getSize() const { if (const auto *DR = dyn_cast(this)) return DR->Size; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -887,7 +887,8 @@ Target->GotPltEntrySize, ".got.plt") {} void GotPltSection::addEntry(Symbol &Sym) { - Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); + Sym.getGlobalInfo()->GotPltIndex = + Target->GotPltHeaderEntriesNum + Entries.size(); Entries.push_back(&Sym); } @@ -922,7 +923,7 @@ void IgotPltSection::addEntry(Symbol &Sym) { Sym.IsInIgot = true; - Sym.GotPltIndex = Entries.size(); + Sym.getGlobalInfo()->GotPltIndex = Entries.size(); Entries.push_back(&Sym); } @@ -1177,7 +1178,7 @@ add(DT_MIPS_LOCAL_GOTNO, [] { return InX::MipsGot->getLocalEntriesNum(); }); if (const Symbol *B = InX::MipsGot->getFirstGlobalEntry()) - addInt(DT_MIPS_GOTSYM, B->DynsymIndex); + addInt(DT_MIPS_GOTSYM, B->getGlobalInfo()->DynsymIndex); else addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()); addInSec(DT_PLTGOT, InX::MipsGot); @@ -1218,7 +1219,7 @@ uint32_t DynamicReloc::getSymIndex() const { if (Sym && !UseSymVA) - return Sym->DynsymIndex; + return Sym->getGlobalInfo()->DynsymIndex; return 0; } @@ -1545,7 +1546,7 @@ size_t I = 0; for (const SymbolTableEntry &S : Symbols) - S.Sym->DynsymIndex = ++I; + S.Sym->getGlobalInfo()->DynsymIndex = ++I; } // The ELF spec requires that all local symbols precede global symbols, so we @@ -1811,7 +1812,7 @@ continue; // Write a hash bucket. Hash buckets contain indices in the following hash // value table. - write32(Buckets + I->BucketIdx, I->Sym->DynsymIndex); + write32(Buckets + I->BucketIdx, I->Sym->getGlobalInfo()->DynsymIndex); OldBucket = I->BucketIdx; } } @@ -1900,7 +1901,7 @@ for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { Symbol *Sym = S.Sym; StringRef Name = Sym->getName(); - unsigned I = Sym->DynsymIndex; + unsigned I = Sym->getGlobalInfo()->DynsymIndex; uint32_t Hash = hashSysV(Name) % NumSymbols; Chains[I] = Buckets[Hash]; write32(Buckets + Hash, I); @@ -1930,13 +1931,13 @@ unsigned RelOff = I.second + PltOff; uint64_t Got = B->getGotPltVA(); uint64_t Plt = this->getVA() + Off; - Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); + Target->writePlt(Buf + Off, Got, Plt, B->getGlobalInfo()->PltIndex, RelOff); Off += Target->PltEntrySize; } } template void PltSection::addEntry(Symbol &Sym) { - Sym.PltIndex = Entries.size(); + Sym.getGlobalInfo()->PltIndex = Entries.size(); RelocationBaseSection *PltRelocSection = InX::RelaPlt; if (IsIplt) { PltRelocSection = InX::RelaIplt;