[lld] r276267 - Simplify symbol version handling.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 21 06:13:22 PDT 2016
Author: ruiu
Date: Thu Jul 21 08:13:21 2016
New Revision: 276267
URL: http://llvm.org/viewvc/llvm-project?rev=276267&view=rev
Log:
Simplify symbol version handling.
r275711 for "speedng up symbol version handling" was committed
by misunderstanding; the benchmark number was measured with
a debug build. The number with a release build didn't actually change.
This patch removes false optimizations added in that patch.
Modified:
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=276267&r1=276266&r2=276267&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Jul 21 08:13:21 2016
@@ -556,7 +556,6 @@ template <class ELFT> void LinkerDriver:
Symtab.scanShlibUndefined();
Symtab.scanDynamicList();
Symtab.scanVersionScript();
- Symtab.scanSymbolVersions();
Symtab.addCombinedLtoObject();
if (HasError)
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=276267&r1=276266&r2=276267&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Thu Jul 21 08:13:21 2016
@@ -171,9 +171,39 @@ static uint8_t getMinVisibility(uint8_t
return std::min(VA, VB);
}
+// Parses a symbol in the form of <name>@<version> or <name>@@<version>.
+static std::pair<StringRef, uint16_t> getSymbolVersion(StringRef S) {
+ if (Config->VersionDefinitions.empty())
+ return {S, Config->DefaultSymbolVersion};
+
+ size_t Pos = S.find('@');
+ if (Pos == 0 || Pos == StringRef::npos)
+ return {S, Config->DefaultSymbolVersion};
+
+ StringRef Name = S.substr(0, Pos);
+ StringRef Verstr = S.substr(Pos + 1);
+ if (Verstr.empty())
+ return {S, Config->DefaultSymbolVersion};
+
+ // '@@' in a symbol name means the default version.
+ // It is usually the most recent one.
+ bool IsDefault = (Verstr[0] == '@');
+ if (IsDefault)
+ Verstr = Verstr.substr(1);
+
+ for (VersionDefinition &V : Config->VersionDefinitions) {
+ if (V.Name == Verstr)
+ return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
+ }
+
+ // It is an error if the specified version was not defined.
+ error("symbol " + S + " has undefined version " + Verstr);
+ return {S, Config->DefaultSymbolVersion};
+}
+
// Find an existing symbol or create and insert a new one.
template <class ELFT>
-std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
+std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
auto P = Symtab.insert({Name, SymIndex((int)SymVector.size(), false)});
SymIndex &V = P.first->second;
bool IsNew = P.second;
@@ -190,8 +220,8 @@ std::pair<Symbol *, bool> SymbolTable<EL
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
- Sym->VersionId = Config->DefaultSymbolVersion;
Sym->Traced = V.Traced;
+ std::tie(Name, Sym->VersionId) = getSymbolVersion(Name);
SymVector.push_back(Sym);
} else {
Sym = SymVector[V.Idx];
@@ -203,7 +233,7 @@ std::pair<Symbol *, bool> SymbolTable<EL
// attributes.
template <class ELFT>
std::pair<Symbol *, bool>
-SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility,
+SymbolTable<ELFT>::insert(StringRef &Name, uint8_t Type, uint8_t Visibility,
bool CanOmitFromDynSym, bool IsUsedInRegularObj,
InputFile *File) {
Symbol *S;
@@ -465,7 +495,8 @@ void SymbolTable<ELFT>::addLazyArchive(A
const object::Archive::Symbol Sym) {
Symbol *S;
bool WasInserted;
- std::tie(S, WasInserted) = insert(Sym.getName());
+ StringRef Name = Sym.getName();
+ std::tie(S, WasInserted) = insert(Name);
if (WasInserted) {
replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType);
return;
@@ -629,84 +660,6 @@ template <class ELFT> void SymbolTable<E
}
}
-// Returns the size of the longest version name.
-static int getMaxVersionLen() {
- size_t Len = 0;
- for (VersionDefinition &V : Config->VersionDefinitions)
- Len = std::max(Len, V.Name.size());
- return Len;
-}
-
-// Parses a symbol name in the form of <name>@<version> or <name>@@<version>.
-static std::pair<StringRef, uint16_t>
-getSymbolVersion(SymbolBody *B, int MaxVersionLen) {
- StringRef S = B->getName();
-
- // MaxVersionLen was passed so that we don't need to scan
- // all characters in a symbol name. It is effective because
- // versions are usually short and symbol names can be very long.
- size_t Pos = S.find('@', std::max(0, int(S.size()) - MaxVersionLen - 2));
- if (Pos == 0 || Pos == StringRef::npos)
- return {"", 0};
-
- StringRef Name = S.substr(0, Pos);
- StringRef Verstr = S.substr(Pos + 1);
- if (Verstr.empty())
- return {"", 0};
-
- // '@@' in a symbol name means the default version.
- // It is usually the most recent one.
- bool IsDefault = (Verstr[0] == '@');
- if (IsDefault)
- Verstr = Verstr.substr(1);
-
- for (VersionDefinition &V : Config->VersionDefinitions) {
- if (V.Name == Verstr)
- return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
- }
-
- // It is an error if the specified version was not defined.
- error("symbol " + S + " has undefined version " + Verstr);
- return {"", 0};
-}
-
-// Versions are usually assigned to symbols using version scripts,
-// but there's another way to assign versions to symbols.
-// If a symbol name contains '@', the string after it is not
-// actually a part of the symbol name but specifies a version.
-// This function takes care of it.
-template <class ELFT> void SymbolTable<ELFT>::scanSymbolVersions() {
- if (Config->VersionDefinitions.empty())
- return;
-
- int MaxVersionLen = getMaxVersionLen();
-
- // Unfortunately there's no way other than iterating over all
- // symbols to look for '@' characters in symbol names.
- // So this is inherently slow. A good news is that we do this
- // only when versions have been defined.
- for (Symbol *Sym : SymVector) {
- // Symbol versions for exported symbols are by nature
- // only for defined global symbols.
- SymbolBody *B = Sym->body();
- if (!B->isDefined())
- continue;
- uint8_t Visibility = B->getVisibility();
- if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
- continue;
-
- // Look for '@' in the symbol name.
- StringRef Name;
- uint16_t Version;
- std::tie(Name, Version) = getSymbolVersion(B, MaxVersionLen);
- if (Name.empty())
- continue;
-
- B->setName(Name);
- Sym->VersionId = Version;
- }
-}
-
template class elf::SymbolTable<ELF32LE>;
template class elf::SymbolTable<ELF32BE>;
template class elf::SymbolTable<ELF64LE>;
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=276267&r1=276266&r2=276267&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Thu Jul 21 08:13:21 2016
@@ -82,7 +82,6 @@ public:
void scanShlibUndefined();
void scanDynamicList();
void scanVersionScript();
- void scanSymbolVersions();
SymbolBody *find(StringRef Name);
@@ -91,8 +90,8 @@ public:
private:
std::vector<SymbolBody *> findAll(StringRef Pattern);
- std::pair<Symbol *, bool> insert(StringRef Name);
- std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type,
+ std::pair<Symbol *, bool> insert(StringRef &Name);
+ std::pair<Symbol *, bool> insert(StringRef &Name, uint8_t Type,
uint8_t Visibility, bool CanOmitFromDynSym,
bool IsUsedInRegularObj, InputFile *File);
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=276267&r1=276266&r2=276267&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Jul 21 08:13:21 2016
@@ -101,11 +101,6 @@ StringRef SymbolBody::getName() const {
return StringRef(Name.S, Name.Len);
}
-void SymbolBody::setName(StringRef S) {
- Name.S = S.data();
- Name.Len = S.size();
-}
-
// Returns true if a symbol can be replaced at load-time by a symbol
// with the same name defined in other ELF executable or DSO.
bool SymbolBody::isPreemptible() const {
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=276267&r1=276266&r2=276267&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu Jul 21 08:13:21 2016
@@ -73,7 +73,6 @@ public:
bool isPreemptible() const;
StringRef getName() const;
- void setName(StringRef S);
uint32_t getNameOffset() const {
assert(isLocal());
More information about the llvm-commits
mailing list