mirror of
https://github.com/rui314/mold.git
synced 2024-12-29 11:24:36 +03:00
wip
This commit is contained in:
parent
bfa6204b2a
commit
2e645809e8
@ -651,47 +651,59 @@ void DynsymSection::add_symbol(Symbol *sym) {
|
|||||||
void DynsymSection::sort_symbols() {
|
void DynsymSection::sort_symbols() {
|
||||||
Timer t("sort_dynsyms");
|
Timer t("sort_dynsyms");
|
||||||
|
|
||||||
tbb::parallel_for((i64)1, (i64)symbols.size(), [&](i64 i) {
|
struct T {
|
||||||
symbols[i]->dynsym_idx = i;
|
Symbol *sym;
|
||||||
});
|
i32 idx;
|
||||||
|
u32 hash;
|
||||||
|
|
||||||
|
bool is_local() const {
|
||||||
|
return sym->esym->st_bind == STB_LOCAL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<T> vec(symbols.size());
|
||||||
|
|
||||||
|
for (i32 i = 1; i < symbols.size(); i++)
|
||||||
|
vec[i] = {symbols[i], i, 0};
|
||||||
|
|
||||||
// In any ELF file, local symbols should precede global symbols.
|
// In any ELF file, local symbols should precede global symbols.
|
||||||
tbb::parallel_sort(symbols.begin() + 1, symbols.end(),
|
tbb::parallel_sort(vec.begin() + 1, vec.end(), [](const T &a, const T &b) {
|
||||||
[](Symbol *a, Symbol *b) {
|
if (a.is_local() == b.is_local())
|
||||||
bool x = (a->esym->st_bind == STB_LOCAL);
|
return a.idx < b.idx;
|
||||||
bool y = (b->esym->st_bind == STB_LOCAL);
|
return a.is_local();
|
||||||
if (x == y)
|
|
||||||
return a->dynsym_idx < b->dynsym_idx;
|
|
||||||
return x;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto first_global = std::partition_point(
|
auto first_global = std::partition_point(vec.begin() + 1, vec.end(),
|
||||||
symbols.begin() + 1, symbols.end(),
|
[](const T &x) {
|
||||||
[](Symbol *sym) { return sym->esym->st_bind == STB_LOCAL; });
|
return x.is_local();
|
||||||
|
});
|
||||||
|
|
||||||
// In any ELF file, the index of the first global symbols can be
|
// In any ELF file, the index of the first global symbols can be
|
||||||
// found in the symtab's sh_info field.
|
// found in the symtab's sh_info field.
|
||||||
shdr.sh_info = first_global - symbols.begin();
|
shdr.sh_info = first_global - vec.begin();
|
||||||
|
|
||||||
// If we have .gnu.hash section, it imposes more constraints
|
// If we have .gnu.hash section, it imposes more constraints
|
||||||
// on the order of symbols.
|
// on the order of symbols.
|
||||||
if (out::gnu_hash) {
|
if (out::gnu_hash) {
|
||||||
i64 num_globals = symbols.end() - first_global;
|
i64 num_globals = vec.end() - first_global;
|
||||||
out::gnu_hash->num_buckets = num_globals / out::gnu_hash->LOAD_FACTOR + 1;
|
out::gnu_hash->num_buckets = num_globals / out::gnu_hash->LOAD_FACTOR + 1;
|
||||||
out::gnu_hash->symoffset = first_global - symbols.begin();
|
out::gnu_hash->symoffset = first_global - vec.begin();
|
||||||
|
|
||||||
tbb::parallel_sort(first_global, symbols.end(), [&](Symbol *a, Symbol *b) {
|
tbb::parallel_for_each(first_global, vec.end(), [](T &x) {
|
||||||
i64 x = gnu_hash(a->name) % out::gnu_hash->num_buckets;
|
x.hash = gnu_hash(x.sym->name) % out::gnu_hash->num_buckets;
|
||||||
i64 y = gnu_hash(b->name) % out::gnu_hash->num_buckets;
|
});
|
||||||
if (x == y)
|
|
||||||
return a->dynsym_idx < b->dynsym_idx;
|
tbb::parallel_sort(first_global, vec.end(), [&](const T &a, const T &b) {
|
||||||
return x < y;
|
if (a.hash == b.hash)
|
||||||
|
return a.idx < b.idx;
|
||||||
|
return a.hash < b.hash;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i64 i = 1; i < symbols.size(); i++) {
|
for (i64 i = 1; i < symbols.size(); i++) {
|
||||||
name_indices.push_back(out::dynstr->add_string(symbols[i]->name));
|
symbols[i] = vec[i].sym;
|
||||||
symbols[i]->dynsym_idx = i;
|
symbols[i]->dynsym_idx = i;
|
||||||
|
name_indices.push_back(out::dynstr->add_string(symbols[i]->name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user