summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputSection.cpp5
-rw-r--r--lld/ELF/SyntheticSections.cpp28
-rw-r--r--lld/ELF/SyntheticSections.h4
3 files changed, 21 insertions, 16 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 338efcbea28..e7d1d2f67db 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -384,11 +384,6 @@ InputSectionBase *InputSection::getRelocatedSection() {
template <class ELFT, class RelTy>
void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
InputSectionBase *RelocatedSection = getRelocatedSection();
-
- // Loop is slow and have complexity O(N*M), where N - amount of
- // relocations and M - amount of symbols in symbol table.
- // That happens because getSymbolIndex(...) call below performs
- // simple linear search.
for (const RelTy &Rel : Rels) {
uint32_t Type = Rel.getType(Config->IsMips64EL);
SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel);
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 57d03ffdf16..f633e87d30e 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1355,18 +1355,24 @@ void SymbolTableBaseSection::addSymbol(SymbolBody *B) {
}
size_t SymbolTableBaseSection::getSymbolIndex(SymbolBody *Body) {
- auto I = llvm::find_if(Symbols, [&](const SymbolTableEntry &E) {
- if (E.Symbol == Body)
- return true;
- // This is used for -r, so we have to handle multiple section
- // symbols being combined.
- if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION)
- return Body->getOutputSection() == E.Symbol->getOutputSection();
- return false;
+ // Initializes symbol lookup tables lazily. This is used only
+ // for -r or -emit-relocs.
+ llvm::call_once(OnceFlag, [&] {
+ SymbolIndexMap.reserve(Symbols.size());
+ size_t I = 0;
+ for (const SymbolTableEntry &E : Symbols) {
+ if (E.Symbol->Type == STT_SECTION)
+ SectionIndexMap[E.Symbol->getOutputSection()] = ++I;
+ else
+ SymbolIndexMap[E.Symbol] = ++I;
+ }
});
- if (I == Symbols.end())
- return 0;
- return I - Symbols.begin() + 1;
+
+ // Section symbols are mapped based on their output sections
+ // to maintain their semantics.
+ if (Body->Type == STT_SECTION)
+ return SectionIndexMap.lookup(Body->getOutputSection());
+ return SymbolIndexMap.lookup(Body);
}
template <class ELFT>
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index dbd0724eaea..c494dc32974 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -418,6 +418,10 @@ protected:
std::vector<SymbolTableEntry> Symbols;
StringTableSection &StrTabSec;
+
+ llvm::once_flag OnceFlag;
+ llvm::DenseMap<SymbolBody *, size_t> SymbolIndexMap;
+ llvm::DenseMap<OutputSection *, size_t> SectionIndexMap;
};
template <class ELFT>
OpenPOWER on IntegriCloud