From 509153f1e7d1a50e24a057627643ad7dcd3384c5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 15 Dec 2021 12:54:38 -0800 Subject: [PATCH] [ELF] ObjFile::initializeSymbols: Batch allocate local symbols and detangle local/global symbol initialization. My x86-64 lld executable is 8k smaller due to the removal of SpecificAlloc. --- lld/ELF/InputFiles.cpp | 66 +++++++++----------- lld/test/ELF/invalid/symtab-sh-info-dup.test | 3 +- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index ddfa1c9bccd4..81cac483fc92 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1047,33 +1047,18 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, template void ObjFile::initializeSymbols() { ArrayRef eSyms = this->getELFSyms(); this->symbols.resize(eSyms.size()); + SymbolUnion *locals = + getSpecificAllocSingleton().Allocate(firstGlobal); - // Fill in InputFile::symbols. Some entries have been initialized - // because of LazyObjFile. - for (size_t i = 0, end = eSyms.size(); i != end; ++i) { - if (this->symbols[i]) - continue; + for (size_t i = 0; i != firstGlobal; ++i) { const Elf_Sym &eSym = eSyms[i]; uint32_t secIdx = getSectionIndex(eSym); if (secIdx >= this->sections.size()) fatal(toString(this) + ": invalid section index: " + Twine(secIdx)); - if (eSym.getBinding() != STB_LOCAL) { - if (i < firstGlobal) - error(toString(this) + ": non-local symbol (" + Twine(i) + - ") found at index < .symtab's sh_info (" + Twine(firstGlobal) + - ")"); - this->symbols[i] = - symtab->insert(CHECK(eSyms[i].getName(this->stringTable), this)); - continue; - } - - // Handle local symbols. Local symbols are not added to the symbol - // table because they are not visible from other object files. We - // allocate symbol instances and add their pointers to symbols. - if (i >= firstGlobal) - errorOrWarn(toString(this) + ": STB_LOCAL symbol (" + Twine(i) + - ") found at index >= .symtab's sh_info (" + - Twine(firstGlobal) + ")"); + if (eSym.getBinding() != STB_LOCAL) + error(toString(this) + ": non-local symbol (" + Twine(i) + + ") found at index < .symtab's sh_info (" + Twine(firstGlobal) + + ")"); InputSectionBase *sec = this->sections[secIdx]; uint8_t type = eSym.getType(); @@ -1083,27 +1068,36 @@ template void ObjFile::initializeSymbols() { fatal(toString(this) + ": invalid symbol name offset"); StringRefZ name = this->stringTable.data() + eSym.st_name; - if (eSym.st_shndx == SHN_UNDEF) - this->symbols[i] = - make(this, name, STB_LOCAL, eSym.st_other, type); - else if (sec == &InputSection::discarded) - this->symbols[i] = - make(this, name, STB_LOCAL, eSym.st_other, type, - /*discardedSecIdx=*/secIdx); + this->symbols[i] = reinterpret_cast(locals + i); + if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) + new (this->symbols[i]) + Undefined(this, name, STB_LOCAL, eSym.st_other, type, + /*discardedSecIdx=*/secIdx); else - this->symbols[i] = make(this, name, STB_LOCAL, eSym.st_other, - type, eSym.st_value, eSym.st_size, sec); + new (this->symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, + eSym.st_value, eSym.st_size, sec); } - // Symbol resolution of non-local symbols. + // Some entries have been filled by LazyObjFile. + for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) + if (!this->symbols[i]) + this->symbols[i] = + symtab->insert(CHECK(eSyms[i].getName(this->stringTable), this)); + + // Perform symbol resolution on non-local symbols. SmallVector undefineds; for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) { const Elf_Sym &eSym = eSyms[i]; uint8_t binding = eSym.getBinding(); - if (binding == STB_LOCAL) - continue; // Errored above. - + if (binding == STB_LOCAL) { + errorOrWarn(toString(this) + ": STB_LOCAL symbol (" + Twine(i) + + ") found at index >= .symtab's sh_info (" + + Twine(firstGlobal) + ")"); + continue; + } uint32_t secIdx = getSectionIndex(eSym); + if (secIdx >= this->sections.size()) + fatal(toString(this) + ": invalid section index: " + Twine(secIdx)); InputSectionBase *sec = this->sections[secIdx]; uint8_t stOther = eSym.st_other; uint8_t type = eSym.getType(); @@ -1111,13 +1105,11 @@ template void ObjFile::initializeSymbols() { uint64_t size = eSym.st_size; StringRefZ name = this->stringTable.data() + eSym.st_name; - // Handle global undefined symbols. if (eSym.st_shndx == SHN_UNDEF) { undefineds.push_back(i); continue; } - // Handle global common symbols. if (eSym.st_shndx == SHN_COMMON) { if (value == 0 || value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + StringRef(name.data) + diff --git a/lld/test/ELF/invalid/symtab-sh-info-dup.test b/lld/test/ELF/invalid/symtab-sh-info-dup.test index 130366beda20..36c7af0d66c6 100644 --- a/lld/test/ELF/invalid/symtab-sh-info-dup.test +++ b/lld/test/ELF/invalid/symtab-sh-info-dup.test @@ -9,10 +9,11 @@ # RUN: not ld.lld %t.o %t.o -o /dev/null 2>&1 | FileCheck %s # CHECK: error: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1) -# CHECK-NEXT: error: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1) # CHECK-NEXT: error: duplicate symbol: _start # CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0) # CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0) +# CHECK-EMPTY: +# CHECK-NEXT: error: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1) # RUN: ld.lld --noinhibit-exec %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN # WARN: warning: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1)