summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Config.h10
-rw-r--r--lld/ELF/OutputSections.cpp96
-rw-r--r--lld/ELF/OutputSections.h30
-rw-r--r--lld/ELF/SymbolListFile.cpp28
-rw-r--r--lld/ELF/SymbolListFile.h1
-rw-r--r--lld/ELF/SymbolTable.cpp26
-rw-r--r--lld/ELF/Symbols.cpp2
-rw-r--r--lld/ELF/Symbols.h18
-rw-r--r--lld/ELF/Writer.cpp13
9 files changed, 41 insertions, 183 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index d199db922cc..be8059b46a9 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -32,15 +32,6 @@ enum ELFKind {
enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
-// This struct contains symbols version definition that
-// can be found in version script if it is used for link.
-struct Version {
- Version(llvm::StringRef Name) : Name(Name) {}
- llvm::StringRef Name;
- std::vector<llvm::StringRef> Globals;
- size_t NameOff; // Offset in string table.
-};
-
// This struct contains the global configuration for the linker.
// Most fields are direct mapping from the command line options
// and such fields have the same name as the corresponding options.
@@ -59,7 +50,6 @@ struct Configuration {
llvm::StringRef SoName;
llvm::StringRef Sysroot;
std::string RPath;
- std::vector<Version> SymbolVersions;
std::vector<llvm::StringRef> DynamicList;
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> Undefined;
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 774860294db..040657a6b81 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -591,11 +591,6 @@ void GnuHashTableSection<ELFT>::addSymbols(
V.push_back({Sym.Body, Sym.STName});
}
-// Returns the number of version definition entries. Because the first entry
-// is for the version definition itself, it is the number of versioned symbols
-// plus one. Note that we don't support multiple versions yet.
-static unsigned getVerDefNum() { return Config->SymbolVersions.size() + 1; }
-
template <class ELFT>
DynamicSection<ELFT>::DynamicSection()
: OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE) {
@@ -698,16 +693,10 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
if (!Config->Entry.empty())
Add({DT_DEBUG, (uint64_t)0});
- bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
- if (HasVerNeed || Out<ELFT>::VerDef)
+ if (size_t NeedNum = Out<ELFT>::VerNeed->getNeedNum()) {
Add({DT_VERSYM, Out<ELFT>::VerSym});
- if (Out<ELFT>::VerDef) {
- Add({DT_VERDEF, Out<ELFT>::VerDef});
- Add({DT_VERDEFNUM, getVerDefNum()});
- }
- if (HasVerNeed) {
Add({DT_VERNEED, Out<ELFT>::VerNeed});
- Add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()});
+ Add({DT_VERNEEDNUM, NeedNum});
}
if (Config->EMachine == EM_MIPS) {
@@ -1444,68 +1433,6 @@ SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
}
template <class ELFT>
-VersionDefinitionSection<ELFT>::VersionDefinitionSection()
- : OutputSectionBase<ELFT>(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {}
-
-static StringRef getFileDefName() {
- if (!Config->SoName.empty())
- return Config->SoName;
- return Config->OutputFile;
-}
-
-template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
- FileDefNameOff = Out<ELFT>::DynStrTab->addString(getFileDefName());
- for (Version &V : Config->SymbolVersions)
- V.NameOff = Out<ELFT>::DynStrTab->addString(V.Name);
-
- this->Header.sh_size =
- (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
- this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
- this->Header.sh_addralign = sizeof(uint32_t);
-
- // sh_info should be set to the number of definitions. This fact is missed in
- // documentation, but confirmed by binutils community:
- // https://sourceware.org/ml/binutils/2014-11/msg00355.html
- this->Header.sh_info = getVerDefNum();
-}
-
-template <class Elf_Verdef, class Elf_Verdaux>
-static void writeDefinition(Elf_Verdef *&Verdef, Elf_Verdaux *&Verdaux,
- uint32_t Flags, uint32_t Index, StringRef Name,
- size_t StrTabOffset) {
- Verdef->vd_version = 1;
- Verdef->vd_cnt = 1;
- Verdef->vd_aux =
- reinterpret_cast<char *>(Verdaux) - reinterpret_cast<char *>(Verdef);
- Verdef->vd_next = sizeof(Elf_Verdef);
-
- Verdef->vd_flags = Flags;
- Verdef->vd_ndx = Index;
- Verdef->vd_hash = hashSysv(Name);
- ++Verdef;
-
- Verdaux->vda_name = StrTabOffset;
- Verdaux->vda_next = 0;
- ++Verdaux;
-}
-
-template <class ELFT>
-void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
- Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
- Elf_Verdaux *Verdaux =
- reinterpret_cast<Elf_Verdaux *>(Verdef + getVerDefNum());
-
- writeDefinition(Verdef, Verdaux, VER_FLG_BASE, 1, getFileDefName(),
- FileDefNameOff);
-
- uint32_t I = 2;
- for (Version &V : Config->SymbolVersions)
- writeDefinition(Verdef, Verdaux, 0 /* Flags */, I++, V.Name, V.NameOff);
-
- Verdef[-1].vd_next = 0;
-}
-
-template <class ELFT>
VersionTableSection<ELFT>::VersionTableSection()
: OutputSectionBase<ELFT>(".gnu.version", SHT_GNU_versym, SHF_ALLOC) {
this->Header.sh_addralign = sizeof(uint16_t);
@@ -1524,7 +1451,10 @@ template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
for (const std::pair<SymbolBody *, size_t> &P :
Out<ELFT>::DynSymTab->getSymbols()) {
- OutVersym->vs_index = P.first->symbol()->VersionId;
+ if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(P.first))
+ OutVersym->vs_index = SS->VersionId;
+ else
+ OutVersym->vs_index = VER_NDX_GLOBAL;
++OutVersym;
}
}
@@ -1533,17 +1463,12 @@ template <class ELFT>
VersionNeedSection<ELFT>::VersionNeedSection()
: OutputSectionBase<ELFT>(".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC) {
this->Header.sh_addralign = sizeof(uint32_t);
-
- // Identifiers in verneed section start at 2 because 0 and 1 are reserved
- // for VER_NDX_LOCAL and VER_NDX_GLOBAL.
- // First identifiers are reserved by verdef section if it exist.
- NextIndex = getVerDefNum() + 1;
}
template <class ELFT>
void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
if (!SS->Verdef) {
- SS->symbol()->VersionId = VER_NDX_GLOBAL;
+ SS->VersionId = VER_NDX_GLOBAL;
return;
}
SharedFile<ELFT> *F = SS->File;
@@ -1561,7 +1486,7 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
SS->File->getStringTable().data() + SS->Verdef->getAux()->vda_name);
NV.Index = NextIndex++;
}
- SS->symbol()->VersionId = NV.Index;
+ SS->VersionId = NV.Index;
}
template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
@@ -1817,11 +1742,6 @@ template class VersionNeedSection<ELF32BE>;
template class VersionNeedSection<ELF64LE>;
template class VersionNeedSection<ELF64BE>;
-template class VersionDefinitionSection<ELF32LE>;
-template class VersionDefinitionSection<ELF32BE>;
-template class VersionDefinitionSection<ELF64LE>;
-template class VersionDefinitionSection<ELF64BE>;
-
template class BuildIdSection<ELF32LE>;
template class BuildIdSection<ELF32BE>;
template class BuildIdSection<ELF64LE>;
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 7fe0e9c02d7..4b05e71dd4e 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -25,7 +25,6 @@ namespace elf {
class SymbolBody;
struct SectionPiece;
-struct Version;
template <class ELFT> class SymbolTable;
template <class ELFT> class SymbolTableSection;
template <class ELFT> class StringTableSection;
@@ -249,30 +248,10 @@ private:
// For more information about .gnu.version and .gnu.version_r see:
// https://www.akkadia.org/drepper/symbol-versioning
-// The .gnu.version_d section which has a section type of SHT_GNU_verdef shall
-// contain symbol version definitions. The number of entries in this section
-// shall be contained in the DT_VERDEFNUM entry of the .dynamic section.
-// The section shall contain an array of Elf_Verdef structures, optionally
-// followed by an array of Elf_Verdaux structures.
-template <class ELFT>
-class VersionDefinitionSection final : public OutputSectionBase<ELFT> {
- typedef typename ELFT::Verdef Elf_Verdef;
- typedef typename ELFT::Verdaux Elf_Verdaux;
-
- unsigned FileDefNameOff;
-
-public:
- VersionDefinitionSection();
- void finalize() override;
- void writeTo(uint8_t *Buf) override;
-};
-
// The .gnu.version section specifies the required version of each symbol in the
// dynamic symbol table. It contains one Elf_Versym for each dynamic symbol
// table entry. An Elf_Versym is just a 16-bit integer that refers to a version
-// identifier defined in the either .gnu.version_r or .gnu.version_d section.
-// The values 0 and 1 are reserved. All other values are used for versions in
-// the own object or in any of the dependencies.
+// identifier defined in the .gnu.version_r section.
template <class ELFT>
class VersionTableSection final : public OutputSectionBase<ELFT> {
typedef typename ELFT::Versym Elf_Versym;
@@ -297,8 +276,9 @@ class VersionNeedSection final : public OutputSectionBase<ELFT> {
// string table offsets of their sonames.
std::vector<std::pair<SharedFile<ELFT> *, size_t>> Needed;
- // The next available version identifier.
- unsigned NextIndex;
+ // The next available version identifier. Identifiers start at 2 because 0 and
+ // 1 are reserved.
+ unsigned NextIndex = 2;
public:
VersionNeedSection();
@@ -650,7 +630,6 @@ template <class ELFT> struct Out {
static StringTableSection<ELFT> *StrTab;
static SymbolTableSection<ELFT> *DynSymTab;
static SymbolTableSection<ELFT> *SymTab;
- static VersionDefinitionSection<ELFT> *VerDef;
static VersionTableSection<ELFT> *VerSym;
static VersionNeedSection<ELFT> *VerNeed;
static Elf_Phdr *TlsPhdr;
@@ -679,7 +658,6 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
-template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;
diff --git a/lld/ELF/SymbolListFile.cpp b/lld/ELF/SymbolListFile.cpp
index 2d5d1c52371..3d1377be438 100644
--- a/lld/ELF/SymbolListFile.cpp
+++ b/lld/ELF/SymbolListFile.cpp
@@ -77,21 +77,21 @@ public:
void run();
private:
- void parseVersion(StringRef Version);
+ void parseVersion();
void parseLocal();
- void parseVersionSymbols(StringRef Version);
+ void parseVersionSymbols();
};
-void VersionScriptParser::parseVersion(StringRef Version) {
+void VersionScriptParser::parseVersion() {
expect("{");
if (peek() == "global:") {
next();
- parseVersionSymbols(Version);
+ parseVersionSymbols();
}
if (peek() == "local:")
parseLocal();
else
- parseVersionSymbols(Version);
+ parseVersionSymbols();
expect("}");
expect(";");
@@ -104,21 +104,13 @@ void VersionScriptParser::parseLocal() {
Config->VersionScriptGlobalByDefault = false;
}
-void VersionScriptParser::parseVersionSymbols(StringRef Version) {
- std::vector<StringRef> *Globals;
- if (Version.empty()) {
- Globals = &Config->VersionScriptGlobals;
- } else {
- Config->SymbolVersions.push_back(elf::Version(Version));
- Globals = &Config->SymbolVersions.back().Globals;
- }
-
+void VersionScriptParser::parseVersionSymbols() {
for (;;) {
StringRef Cur = peek();
if (Cur == "}" || Cur == "local:")
return;
next();
- Globals->push_back(Cur);
+ Config->VersionScriptGlobals.push_back(Cur);
expect(";");
}
}
@@ -127,18 +119,18 @@ void VersionScriptParser::run() {
StringRef Msg = "anonymous version definition is used in "
"combination with other version definitions";
if (peek() == "{") {
- parseVersion("");
+ parseVersion();
if (!atEOF())
setError(Msg);
return;
}
while (!atEOF() && !Error) {
- if (peek() == "{") {
+ if (next() == "{") {
setError(Msg);
return;
}
- parseVersion(next());
+ parseVersion();
}
}
diff --git a/lld/ELF/SymbolListFile.h b/lld/ELF/SymbolListFile.h
index 8f826d2957e..60362a805ff 100644
--- a/lld/ELF/SymbolListFile.h
+++ b/lld/ELF/SymbolListFile.h
@@ -11,7 +11,6 @@
#define LLD_ELF_SYMBOL_LIST_FILE_H
#include "lld/Core/LLVM.h"
-#include "llvm/ADT/MapVector.h"
#include "llvm/Support/MemoryBuffer.h"
namespace lld {
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index c5d92325451..e9cee22c1bf 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -175,10 +175,7 @@ std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
- if (Config->VersionScriptGlobalByDefault)
- Sym->VersionId = VER_NDX_GLOBAL;
- else
- Sym->VersionId = VER_NDX_LOCAL;
+ Sym->VersionScriptGlobal = Config->VersionScriptGlobalByDefault;
SymVector.push_back(Sym);
} else {
Sym = SymVector[P.first->second];
@@ -517,24 +514,9 @@ template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
// symbols with the VersionScriptGlobal flag, which acts as a filter on the
// dynamic symbol table.
template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
- // If version script does not contain versions declarations,
- // we just should mark global symbols.
- if (!Config->VersionScriptGlobals.empty()) {
- for (StringRef S : Config->VersionScriptGlobals)
- if (SymbolBody *B = find(S))
- B->symbol()->VersionId = VER_NDX_GLOBAL;
- return;
- }
-
- // If we have symbols version declarations, we should
- // assign version references for each symbol.
- size_t I = 2;
- for (Version &V : Config->SymbolVersions) {
- for (StringRef Name : V.Globals)
- if (SymbolBody *B = find(Name))
- B->symbol()->VersionId = I;
- ++I;
- }
+ for (StringRef S : Config->VersionScriptGlobals)
+ if (SymbolBody *B = find(S))
+ B->symbol()->VersionScriptGlobal = true;
}
template class elf::SymbolTable<ELF32LE>;
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 9fd5de2220e..0ba571b7e9a 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -267,7 +267,7 @@ std::string elf::demangle(StringRef Name) {
bool Symbol::includeInDynsym() const {
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
return false;
- return (ExportDynamic && VersionId != VER_NDX_LOCAL) || body()->isShared() ||
+ return (ExportDynamic && VersionScriptGlobal) || body()->isShared() ||
(body()->isUndefined() && Config->Shared);
}
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 62ef088784d..8b103ae889a 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -30,7 +30,6 @@ class BitcodeFile;
class InputFile;
class LazyObjectFile;
class SymbolBody;
-struct Version;
template <class ELFT> class ObjectFile;
template <class ELFT> class OutputSection;
template <class ELFT> class OutputSectionBase;
@@ -303,8 +302,13 @@ public:
SharedFile<ELFT> *File;
const Elf_Sym &Sym;
- // This field is a pointer to the symbol's version definition.
- const Elf_Verdef *Verdef;
+ // This field is initially a pointer to the symbol's version definition. As
+ // symbols are added to the version table, this field is replaced with the
+ // version identifier to be stored in .gnu.version in the output file.
+ union {
+ const Elf_Verdef *Verdef;
+ uint16_t VersionId;
+ };
// OffsetInBss is significant only when needsCopy() is true.
uintX_t OffsetInBss = 0;
@@ -403,9 +407,6 @@ struct Symbol {
// it is weak.
uint8_t Binding;
- // Version definition index.
- uint16_t VersionId;
-
// Symbol visibility. This is the computed minimum visibility of all
// observed non-DSO symbols.
unsigned Visibility : 2;
@@ -422,6 +423,11 @@ struct Symbol {
// --export-dynamic, and by dynamic lists.
unsigned ExportDynamic : 1;
+ // This flag acts as an additional filter on the dynamic symbol list. It is
+ // set if there is no version script, or if the symbol appears in the global
+ // section of the version script.
+ unsigned VersionScriptGlobal : 1;
+
bool includeInDynsym() const;
bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d5761e79292..65ddb2010db 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -136,7 +136,6 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
std::unique_ptr<StringTableSection<ELFT>> StrTab;
std::unique_ptr<SymbolTableSection<ELFT>> SymTabSec;
std::unique_ptr<OutputSection<ELFT>> MipsRldMap;
- std::unique_ptr<VersionDefinitionSection<ELFT>> VerDef;
if (Config->BuildId == BuildIdKind::Fnv1)
BuildId.reset(new BuildIdFnv1<ELFT>);
@@ -171,8 +170,6 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
MipsRldMap->setSize(sizeof(uintX_t));
MipsRldMap->updateAlignment(sizeof(uintX_t));
}
- if (!Config->SymbolVersions.empty())
- VerDef.reset(new VersionDefinitionSection<ELFT>());
Out<ELFT>::Bss = &Bss;
Out<ELFT>::BuildId = BuildId.get();
@@ -192,7 +189,6 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
Out<ELFT>::ShStrTab = &ShStrTab;
Out<ELFT>::StrTab = StrTab.get();
Out<ELFT>::SymTab = SymTabSec.get();
- Out<ELFT>::VerDef = VerDef.get();
Out<ELFT>::VerSym = &VerSym;
Out<ELFT>::VerNeed = &VerNeed;
Out<ELFT>::MipsRldMap = MipsRldMap.get();
@@ -908,15 +904,10 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
Add(Out<ELFT>::StrTab);
if (isOutputDynamic()) {
Add(Out<ELFT>::DynSymTab);
-
- bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
- if (Out<ELFT>::VerDef || HasVerNeed)
+ if (Out<ELFT>::VerNeed->getNeedNum() != 0) {
Add(Out<ELFT>::VerSym);
- if (Out<ELFT>::VerDef)
- Add(Out<ELFT>::VerDef);
- if (HasVerNeed)
Add(Out<ELFT>::VerNeed);
-
+ }
Add(Out<ELFT>::GnuHashTab);
Add(Out<ELFT>::HashTab);
Add(Out<ELFT>::Dynamic);
OpenPOWER on IntegriCloud