mirror of
https://github.com/rui314/mold.git
synced 2024-12-24 00:43:18 +03:00
wip
This commit is contained in:
parent
fe9d2dd365
commit
9cf193011f
4
main.cc
4
main.cc
@ -470,10 +470,10 @@ int do_main(int argc, char **argv) {
|
||||
ctx.dynsym->sort_symbols(ctx);
|
||||
|
||||
// Fill .gnu.version_d section contents.
|
||||
fill_verdef(ctx);
|
||||
ctx.verdef->construct(ctx);
|
||||
|
||||
// Fill .gnu.version_r section contents.
|
||||
fill_verneed(ctx);
|
||||
ctx.verneed->construct(ctx);
|
||||
|
||||
// Compute .symtab and .strtab sizes for each file.
|
||||
{
|
||||
|
4
mold.h
4
mold.h
@ -713,6 +713,7 @@ public:
|
||||
this->shdr.sh_addralign = E::wordsize;
|
||||
}
|
||||
|
||||
void construct(Context<E> &ctx);
|
||||
void update_shdr(Context<E> &ctx) override;
|
||||
void copy_buf(Context<E> &ctx) override;
|
||||
|
||||
@ -729,6 +730,7 @@ public:
|
||||
this->shdr.sh_addralign = 8;
|
||||
}
|
||||
|
||||
void construct(Context<E> &ctx);
|
||||
void update_shdr(Context<E> &ctx) override;
|
||||
void copy_buf(Context<E> &ctx) override;
|
||||
|
||||
@ -1174,8 +1176,6 @@ template <typename E> void scan_rels(Context<E> &ctx);
|
||||
template <typename E> void apply_version_script(Context<E> &ctx);
|
||||
template <typename E> void parse_symbol_version(Context<E> &ctx);
|
||||
template <typename E> void compute_import_export(Context<E> &ctx);
|
||||
template <typename E> void fill_verdef(Context<E> &ctx);
|
||||
template <typename E> void fill_verneed(Context<E> &ctx);
|
||||
template <typename E> void clear_padding(Context<E> &ctx, i64 filesize);
|
||||
template <typename E> i64 get_section_rank(Context<E> &ctx, OutputChunk<E> *chunk);
|
||||
template <typename E> i64 set_osec_offsets(Context<E> &ctx);
|
||||
|
132
output_chunks.cc
132
output_chunks.cc
@ -1320,6 +1320,87 @@ void VersymSection<E>::copy_buf(Context<E> &ctx) {
|
||||
write_vector(ctx.buf + this->shdr.sh_offset, contents);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void VerneedSection<E>::construct(Context<E> &ctx) {
|
||||
Timer t(ctx, "fill_verneed");
|
||||
|
||||
if (ctx.dynsym->symbols.empty())
|
||||
return;
|
||||
|
||||
// Create a list of versioned symbols and sort by file and version.
|
||||
std::vector<Symbol<E> *> syms(ctx.dynsym->symbols.begin() + 1,
|
||||
ctx.dynsym->symbols.end());
|
||||
|
||||
erase(syms, [](Symbol<E> *sym) {
|
||||
return !sym->file->is_dso || sym->ver_idx <= VER_NDX_LAST_RESERVED;
|
||||
});
|
||||
|
||||
if (syms.empty())
|
||||
return;
|
||||
|
||||
sort(syms, [](Symbol<E> *a, Symbol<E> *b) {
|
||||
return std::tuple(((SharedFile<E> *)a->file)->soname, a->ver_idx) <
|
||||
std::tuple(((SharedFile<E> *)b->file)->soname, b->ver_idx);
|
||||
});
|
||||
|
||||
// Resize of .gnu.version
|
||||
ctx.versym->contents.resize(ctx.dynsym->symbols.size(), 1);
|
||||
ctx.versym->contents[0] = 0;
|
||||
|
||||
// Allocate a large enough buffer for .gnu.version_r.
|
||||
contents.resize((sizeof(ElfVerneed<E>) + sizeof(ElfVernaux<E>)) *
|
||||
syms.size());
|
||||
|
||||
// Fill .gnu.version_r.
|
||||
u8 *buf = (u8 *)&contents[0];
|
||||
u8 *ptr = buf;
|
||||
ElfVerneed<E> *verneed = nullptr;
|
||||
ElfVernaux<E> *aux = nullptr;
|
||||
|
||||
u16 veridx = VER_NDX_LAST_RESERVED + ctx.arg.version_definitions.size();
|
||||
|
||||
auto start_group = [&](InputFile<E> *file) {
|
||||
this->shdr.sh_info++;
|
||||
if (verneed)
|
||||
verneed->vn_next = ptr - (u8 *)verneed;
|
||||
|
||||
verneed = (ElfVerneed<E> *)ptr;
|
||||
ptr += sizeof(*verneed);
|
||||
verneed->vn_version = 1;
|
||||
verneed->vn_file = ctx.dynstr->find_string(((SharedFile<E> *)file)->soname);
|
||||
verneed->vn_aux = sizeof(ElfVerneed<E>);
|
||||
aux = nullptr;
|
||||
};
|
||||
|
||||
auto add_entry = [&](Symbol<E> *sym) {
|
||||
verneed->vn_cnt++;
|
||||
|
||||
if (aux)
|
||||
aux->vna_next = sizeof(ElfVernaux<E>);
|
||||
aux = (ElfVernaux<E> *)ptr;
|
||||
ptr += sizeof(*aux);
|
||||
|
||||
std::string_view verstr = sym->get_version();
|
||||
aux->vna_hash = elf_hash(verstr);
|
||||
aux->vna_other = ++veridx;
|
||||
aux->vna_name = ctx.dynstr->add_string(verstr);
|
||||
};
|
||||
|
||||
for (i64 i = 0; i < syms.size(); i++) {
|
||||
if (i == 0 || syms[i - 1]->file != syms[i]->file) {
|
||||
start_group(syms[i]->file);
|
||||
add_entry(syms[i]);
|
||||
} else if (syms[i - 1]->ver_idx != syms[i]->ver_idx) {
|
||||
add_entry(syms[i]);
|
||||
}
|
||||
|
||||
ctx.versym->contents[syms[i]->get_dynsym_idx(ctx)] = veridx;
|
||||
}
|
||||
|
||||
// Resize .gnu.version_r to fit to its contents.
|
||||
contents.resize(ptr - buf);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void VerneedSection<E>::update_shdr(Context<E> &ctx) {
|
||||
this->shdr.sh_size = contents.size();
|
||||
@ -1331,6 +1412,57 @@ void VerneedSection<E>::copy_buf(Context<E> &ctx) {
|
||||
write_vector(ctx.buf + this->shdr.sh_offset, contents);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void VerdefSection<E>::construct(Context<E> &ctx) {
|
||||
Timer t(ctx, "fill_verdef");
|
||||
|
||||
if (ctx.arg.version_definitions.empty())
|
||||
return;
|
||||
|
||||
// Resize .gnu.version
|
||||
ctx.versym->contents.resize(ctx.dynsym->symbols.size(), 1);
|
||||
ctx.versym->contents[0] = 0;
|
||||
|
||||
// Allocate a buffer for .gnu.version_d.
|
||||
contents.resize((sizeof(ElfVerdef<E>) + sizeof(ElfVerdaux<E>)) *
|
||||
(ctx.arg.version_definitions.size() + 1));
|
||||
|
||||
u8 *buf = (u8 *)&contents[0];
|
||||
u8 *ptr = buf;
|
||||
ElfVerdef<E> *verdef = nullptr;
|
||||
|
||||
auto write = [&](std::string_view verstr, i64 idx, i64 flags) {
|
||||
this->shdr.sh_info++;
|
||||
if (verdef)
|
||||
verdef->vd_next = ptr - (u8 *)verdef;
|
||||
|
||||
verdef = (ElfVerdef<E> *)ptr;
|
||||
ptr += sizeof(ElfVerdef<E>);
|
||||
|
||||
verdef->vd_version = 1;
|
||||
verdef->vd_flags = flags;
|
||||
verdef->vd_ndx = idx;
|
||||
verdef->vd_cnt = 1;
|
||||
verdef->vd_hash = elf_hash(verstr);
|
||||
verdef->vd_aux = sizeof(ElfVerdef<E>);
|
||||
|
||||
ElfVerdaux<E> *aux = (ElfVerdaux<E> *)ptr;
|
||||
ptr += sizeof(ElfVerdaux<E>);
|
||||
aux->vda_name = ctx.dynstr->add_string(verstr);
|
||||
};
|
||||
|
||||
std::string_view basename = ctx.arg.soname.empty() ?
|
||||
ctx.arg.output : ctx.arg.soname;
|
||||
write(basename, 1, VER_FLG_BASE);
|
||||
|
||||
i64 idx = 2;
|
||||
for (std::string_view verstr : ctx.arg.version_definitions)
|
||||
write(verstr, idx++, 0);
|
||||
|
||||
for (Symbol<E> *sym : std::span<Symbol<E> *>(ctx.dynsym->symbols).subspan(1))
|
||||
ctx.versym->contents[sym->get_dynsym_idx(ctx)] = sym->ver_idx;
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void VerdefSection<E>::update_shdr(Context<E> &ctx) {
|
||||
this->shdr.sh_size = contents.size();
|
||||
|
134
passes.cc
134
passes.cc
@ -578,138 +578,6 @@ void compute_import_export(Context<E> &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void fill_verdef(Context<E> &ctx) {
|
||||
Timer t(ctx, "fill_verdef");
|
||||
|
||||
if (ctx.arg.version_definitions.empty())
|
||||
return;
|
||||
|
||||
// Resize .gnu.version
|
||||
ctx.versym->contents.resize(ctx.dynsym->symbols.size(), 1);
|
||||
ctx.versym->contents[0] = 0;
|
||||
|
||||
// Allocate a buffer for .gnu.version_d.
|
||||
ctx.verdef->contents.resize((sizeof(ElfVerdef<E>) + sizeof(ElfVerdaux<E>)) *
|
||||
(ctx.arg.version_definitions.size() + 1));
|
||||
|
||||
u8 *buf = (u8 *)&ctx.verdef->contents[0];
|
||||
u8 *ptr = buf;
|
||||
ElfVerdef<E> *verdef = nullptr;
|
||||
|
||||
auto write = [&](std::string_view verstr, i64 idx, i64 flags) {
|
||||
ctx.verdef->shdr.sh_info++;
|
||||
if (verdef)
|
||||
verdef->vd_next = ptr - (u8 *)verdef;
|
||||
|
||||
verdef = (ElfVerdef<E> *)ptr;
|
||||
ptr += sizeof(ElfVerdef<E>);
|
||||
|
||||
verdef->vd_version = 1;
|
||||
verdef->vd_flags = flags;
|
||||
verdef->vd_ndx = idx;
|
||||
verdef->vd_cnt = 1;
|
||||
verdef->vd_hash = elf_hash(verstr);
|
||||
verdef->vd_aux = sizeof(ElfVerdef<E>);
|
||||
|
||||
ElfVerdaux<E> *aux = (ElfVerdaux<E> *)ptr;
|
||||
ptr += sizeof(ElfVerdaux<E>);
|
||||
aux->vda_name = ctx.dynstr->add_string(verstr);
|
||||
};
|
||||
|
||||
std::string_view basename = ctx.arg.soname.empty() ?
|
||||
ctx.arg.output : ctx.arg.soname;
|
||||
write(basename, 1, VER_FLG_BASE);
|
||||
|
||||
i64 idx = 2;
|
||||
for (std::string_view verstr : ctx.arg.version_definitions)
|
||||
write(verstr, idx++, 0);
|
||||
|
||||
for (Symbol<E> *sym : std::span<Symbol<E> *>(ctx.dynsym->symbols).subspan(1))
|
||||
ctx.versym->contents[sym->get_dynsym_idx(ctx)] = sym->ver_idx;
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void fill_verneed(Context<E> &ctx) {
|
||||
Timer t(ctx, "fill_verneed");
|
||||
|
||||
if (ctx.dynsym->symbols.empty())
|
||||
return;
|
||||
|
||||
// Create a list of versioned symbols and sort by file and version.
|
||||
std::vector<Symbol<E> *> syms(ctx.dynsym->symbols.begin() + 1,
|
||||
ctx.dynsym->symbols.end());
|
||||
|
||||
erase(syms, [](Symbol<E> *sym) {
|
||||
return !sym->file->is_dso || sym->ver_idx <= VER_NDX_LAST_RESERVED;
|
||||
});
|
||||
|
||||
if (syms.empty())
|
||||
return;
|
||||
|
||||
sort(syms, [](Symbol<E> *a, Symbol<E> *b) {
|
||||
return std::tuple(((SharedFile<E> *)a->file)->soname, a->ver_idx) <
|
||||
std::tuple(((SharedFile<E> *)b->file)->soname, b->ver_idx);
|
||||
});
|
||||
|
||||
// Resize of .gnu.version
|
||||
ctx.versym->contents.resize(ctx.dynsym->symbols.size(), 1);
|
||||
ctx.versym->contents[0] = 0;
|
||||
|
||||
// Allocate a large enough buffer for .gnu.version_r.
|
||||
ctx.verneed->contents.resize((sizeof(ElfVerneed<E>) + sizeof(ElfVernaux<E>)) *
|
||||
syms.size());
|
||||
|
||||
// Fill .gnu.version_r.
|
||||
u8 *buf = (u8 *)&ctx.verneed->contents[0];
|
||||
u8 *ptr = buf;
|
||||
ElfVerneed<E> *verneed = nullptr;
|
||||
ElfVernaux<E> *aux = nullptr;
|
||||
|
||||
u16 veridx = VER_NDX_LAST_RESERVED + ctx.arg.version_definitions.size();
|
||||
|
||||
auto start_group = [&](InputFile<E> *file) {
|
||||
ctx.verneed->shdr.sh_info++;
|
||||
if (verneed)
|
||||
verneed->vn_next = ptr - (u8 *)verneed;
|
||||
|
||||
verneed = (ElfVerneed<E> *)ptr;
|
||||
ptr += sizeof(*verneed);
|
||||
verneed->vn_version = 1;
|
||||
verneed->vn_file = ctx.dynstr->find_string(((SharedFile<E> *)file)->soname);
|
||||
verneed->vn_aux = sizeof(ElfVerneed<E>);
|
||||
aux = nullptr;
|
||||
};
|
||||
|
||||
auto add_entry = [&](Symbol<E> *sym) {
|
||||
verneed->vn_cnt++;
|
||||
|
||||
if (aux)
|
||||
aux->vna_next = sizeof(ElfVernaux<E>);
|
||||
aux = (ElfVernaux<E> *)ptr;
|
||||
ptr += sizeof(*aux);
|
||||
|
||||
std::string_view verstr = sym->get_version();
|
||||
aux->vna_hash = elf_hash(verstr);
|
||||
aux->vna_other = ++veridx;
|
||||
aux->vna_name = ctx.dynstr->add_string(verstr);
|
||||
};
|
||||
|
||||
for (i64 i = 0; i < syms.size(); i++) {
|
||||
if (i == 0 || syms[i - 1]->file != syms[i]->file) {
|
||||
start_group(syms[i]->file);
|
||||
add_entry(syms[i]);
|
||||
} else if (syms[i - 1]->ver_idx != syms[i]->ver_idx) {
|
||||
add_entry(syms[i]);
|
||||
}
|
||||
|
||||
ctx.versym->contents[syms[i]->get_dynsym_idx(ctx)] = veridx;
|
||||
}
|
||||
|
||||
// Resize .gnu.version_r to fit to its contents.
|
||||
ctx.verneed->contents.resize(ptr - buf);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void clear_padding(Context<E> &ctx, i64 filesize) {
|
||||
Timer t(ctx, "clear_padding");
|
||||
@ -933,8 +801,6 @@ void fix_synthetic_symbols(Context<E> &ctx) {
|
||||
template void apply_version_script(Context<E> &ctx); \
|
||||
template void parse_symbol_version(Context<E> &ctx); \
|
||||
template void compute_import_export(Context<E> &ctx); \
|
||||
template void fill_verdef(Context<E> &ctx); \
|
||||
template void fill_verneed(Context<E> &ctx); \
|
||||
template void clear_padding(Context<E> &ctx, i64 filesize); \
|
||||
template i64 get_section_rank(Context<E> &ctx, OutputChunk<E> *chunk); \
|
||||
template i64 set_osec_offsets(Context<E> &ctx); \
|
||||
|
@ -17,7 +17,7 @@ clang -shared -fuse-ld=`pwd`/../mold -o $t/b.so $t/a.o
|
||||
readelf --dyn-syms $t/b.so > $t/log
|
||||
|
||||
grep -q '0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fn2' $t/log
|
||||
grep -q '000000000003311c 0 NOTYPE GLOBAL DEFAULT 15 fn1' $t/log
|
||||
grep -q '0000000000033119 0 NOTYPE GLOBAL DEFAULT 15 fn1' $t/log
|
||||
|
||||
cat <<EOF | clang -fPIC -c -o $t/c.o -xc -
|
||||
#include <stdio.h>
|
||||
|
Loading…
Reference in New Issue
Block a user