forked from OSchip/llvm-project
[ELF] ObjFile<ELFT>::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<Undefined>.
This commit is contained in:
parent
ebed0ca715
commit
509153f1e7
|
@ -1047,33 +1047,18 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
|
||||||
template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
|
template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
|
||||||
ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
|
ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
|
||||||
this->symbols.resize(eSyms.size());
|
this->symbols.resize(eSyms.size());
|
||||||
|
SymbolUnion *locals =
|
||||||
|
getSpecificAllocSingleton<SymbolUnion>().Allocate(firstGlobal);
|
||||||
|
|
||||||
// Fill in InputFile::symbols. Some entries have been initialized
|
for (size_t i = 0; i != firstGlobal; ++i) {
|
||||||
// because of LazyObjFile.
|
|
||||||
for (size_t i = 0, end = eSyms.size(); i != end; ++i) {
|
|
||||||
if (this->symbols[i])
|
|
||||||
continue;
|
|
||||||
const Elf_Sym &eSym = eSyms[i];
|
const Elf_Sym &eSym = eSyms[i];
|
||||||
uint32_t secIdx = getSectionIndex(eSym);
|
uint32_t secIdx = getSectionIndex(eSym);
|
||||||
if (secIdx >= this->sections.size())
|
if (secIdx >= this->sections.size())
|
||||||
fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
|
fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
|
||||||
if (eSym.getBinding() != STB_LOCAL) {
|
if (eSym.getBinding() != STB_LOCAL)
|
||||||
if (i < firstGlobal)
|
error(toString(this) + ": non-local symbol (" + Twine(i) +
|
||||||
error(toString(this) + ": non-local symbol (" + Twine(i) +
|
") found at index < .symtab's sh_info (" + Twine(firstGlobal) +
|
||||||
") 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) + ")");
|
|
||||||
|
|
||||||
InputSectionBase *sec = this->sections[secIdx];
|
InputSectionBase *sec = this->sections[secIdx];
|
||||||
uint8_t type = eSym.getType();
|
uint8_t type = eSym.getType();
|
||||||
|
@ -1083,27 +1068,36 @@ template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
|
||||||
fatal(toString(this) + ": invalid symbol name offset");
|
fatal(toString(this) + ": invalid symbol name offset");
|
||||||
StringRefZ name = this->stringTable.data() + eSym.st_name;
|
StringRefZ name = this->stringTable.data() + eSym.st_name;
|
||||||
|
|
||||||
if (eSym.st_shndx == SHN_UNDEF)
|
this->symbols[i] = reinterpret_cast<Symbol *>(locals + i);
|
||||||
this->symbols[i] =
|
if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded)
|
||||||
make<Undefined>(this, name, STB_LOCAL, eSym.st_other, type);
|
new (this->symbols[i])
|
||||||
else if (sec == &InputSection::discarded)
|
Undefined(this, name, STB_LOCAL, eSym.st_other, type,
|
||||||
this->symbols[i] =
|
/*discardedSecIdx=*/secIdx);
|
||||||
make<Undefined>(this, name, STB_LOCAL, eSym.st_other, type,
|
|
||||||
/*discardedSecIdx=*/secIdx);
|
|
||||||
else
|
else
|
||||||
this->symbols[i] = make<Defined>(this, name, STB_LOCAL, eSym.st_other,
|
new (this->symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type,
|
||||||
type, eSym.st_value, eSym.st_size, sec);
|
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<unsigned, 32> undefineds;
|
SmallVector<unsigned, 32> undefineds;
|
||||||
for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
|
for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
|
||||||
const Elf_Sym &eSym = eSyms[i];
|
const Elf_Sym &eSym = eSyms[i];
|
||||||
uint8_t binding = eSym.getBinding();
|
uint8_t binding = eSym.getBinding();
|
||||||
if (binding == STB_LOCAL)
|
if (binding == STB_LOCAL) {
|
||||||
continue; // Errored above.
|
errorOrWarn(toString(this) + ": STB_LOCAL symbol (" + Twine(i) +
|
||||||
|
") found at index >= .symtab's sh_info (" +
|
||||||
|
Twine(firstGlobal) + ")");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
uint32_t secIdx = getSectionIndex(eSym);
|
uint32_t secIdx = getSectionIndex(eSym);
|
||||||
|
if (secIdx >= this->sections.size())
|
||||||
|
fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
|
||||||
InputSectionBase *sec = this->sections[secIdx];
|
InputSectionBase *sec = this->sections[secIdx];
|
||||||
uint8_t stOther = eSym.st_other;
|
uint8_t stOther = eSym.st_other;
|
||||||
uint8_t type = eSym.getType();
|
uint8_t type = eSym.getType();
|
||||||
|
@ -1111,13 +1105,11 @@ template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
|
||||||
uint64_t size = eSym.st_size;
|
uint64_t size = eSym.st_size;
|
||||||
StringRefZ name = this->stringTable.data() + eSym.st_name;
|
StringRefZ name = this->stringTable.data() + eSym.st_name;
|
||||||
|
|
||||||
// Handle global undefined symbols.
|
|
||||||
if (eSym.st_shndx == SHN_UNDEF) {
|
if (eSym.st_shndx == SHN_UNDEF) {
|
||||||
undefineds.push_back(i);
|
undefineds.push_back(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle global common symbols.
|
|
||||||
if (eSym.st_shndx == SHN_COMMON) {
|
if (eSym.st_shndx == SHN_COMMON) {
|
||||||
if (value == 0 || value >= UINT32_MAX)
|
if (value == 0 || value >= UINT32_MAX)
|
||||||
fatal(toString(this) + ": common symbol '" + StringRef(name.data) +
|
fatal(toString(this) + ": common symbol '" + StringRef(name.data) +
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
# RUN: not ld.lld %t.o %t.o -o /dev/null 2>&1 | FileCheck %s
|
# 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: 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: error: duplicate symbol: _start
|
||||||
# CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0)
|
# CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0)
|
||||||
# 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
|
# 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)
|
# WARN: warning: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1)
|
||||||
|
|
Loading…
Reference in New Issue