mirror of
https://github.com/rui314/mold.git
synced 2024-12-27 10:23:41 +03:00
wip
This commit is contained in:
parent
25200eb61c
commit
c074f8ade6
43
main.cc
43
main.cc
@ -351,48 +351,9 @@ static void eliminate_comdats() {
|
||||
static void handle_mergeable_strings() {
|
||||
Timer t("handle_mergeable_strings");
|
||||
|
||||
// Resolve mergeable string fragments
|
||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
||||
for (MergeableSection *isec : file->mergeable_sections) {
|
||||
for (SectionFragment *frag : isec->fragments) {
|
||||
if (!frag->is_alive)
|
||||
continue;
|
||||
MergeableSection *cur = frag->isec;
|
||||
while (!cur || cur->file->priority > isec->file->priority)
|
||||
if (frag->isec.compare_exchange_weak(cur, isec))
|
||||
break;
|
||||
}
|
||||
}
|
||||
tbb::parallel_for_each(MergedSection::instances, [](MergedSection *sec) {
|
||||
sec->assign_offsets();
|
||||
});
|
||||
|
||||
// Calculate the total bytes of mergeable strings for each input section.
|
||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
||||
for (MergeableSection *isec : file->mergeable_sections) {
|
||||
i64 offset = 0;
|
||||
for (SectionFragment *frag : isec->fragments) {
|
||||
if (frag->isec == isec && frag->offset == -1) {
|
||||
offset = align_to(offset, frag->alignment);
|
||||
frag->offset = offset;
|
||||
offset += frag->data.size();
|
||||
isec->alignment = std::max<u32>(isec->alignment, frag->alignment);
|
||||
}
|
||||
}
|
||||
isec->size = offset;
|
||||
}
|
||||
});
|
||||
|
||||
// Assign each mergeable input section a unique index.
|
||||
for (ObjectFile *file : out::objs) {
|
||||
for (MergeableSection *isec : file->mergeable_sections) {
|
||||
i64 offset = isec->parent.shdr.sh_size;
|
||||
isec->padding = align_to(offset, isec->alignment) - offset;
|
||||
isec->offset = offset + isec->padding;
|
||||
isec->parent.shdr.sh_size = offset + isec->padding + isec->size;
|
||||
|
||||
isec->parent.shdr.sh_addralign =
|
||||
std::max(isec->parent.shdr.sh_addralign, isec->shdr->sh_addralign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// So far, each input section has a pointer to its corresponding
|
||||
|
43
mold.h
43
mold.h
@ -209,14 +209,17 @@ public:
|
||||
//
|
||||
|
||||
struct SectionFragment {
|
||||
SectionFragment(std::string_view data) : data(data) {}
|
||||
SectionFragment(MergedSection *sec, std::string_view data)
|
||||
: output_section(*sec), data(data) {}
|
||||
|
||||
SectionFragment(const SectionFragment &other)
|
||||
: isec(other.isec.load()), data(other.data), offset(other.offset) {}
|
||||
: output_section(other.output_section), data(other.data),
|
||||
offset(other.offset), alignment(other.alignment.load()),
|
||||
is_alive(other.is_alive.load()) {}
|
||||
|
||||
inline u64 get_addr() const;
|
||||
|
||||
std::atomic<MergeableSection *> isec = nullptr;
|
||||
MergedSection &output_section;
|
||||
std::string_view data;
|
||||
u32 offset = -1;
|
||||
std::atomic_uint16_t alignment = 1;
|
||||
@ -435,7 +438,6 @@ public:
|
||||
MergedSection &parent;
|
||||
std::vector<SectionFragment *> fragments;
|
||||
std::vector<u32> frag_offsets;
|
||||
u32 alignment = 1;
|
||||
u32 size = 0;
|
||||
u32 padding = 0;
|
||||
};
|
||||
@ -752,27 +754,19 @@ public:
|
||||
|
||||
class MergedSection : public OutputChunk {
|
||||
public:
|
||||
static MergedSection *get_instance(std::string_view name, u64 type, u64 flags);
|
||||
static MergedSection *
|
||||
get_instance(std::string_view name, u64 type, u64 flags);
|
||||
|
||||
SectionFragment *insert(std::string_view data, i64 alignment);
|
||||
void assign_offsets();
|
||||
void copy_buf() override;
|
||||
|
||||
static inline std::vector<MergedSection *> instances;
|
||||
|
||||
SectionFragment *insert(std::string_view data, i64 alignment) {
|
||||
assert(alignment < UINT16_MAX);
|
||||
|
||||
typename decltype(map)::const_accessor acc;
|
||||
map.insert(acc, std::pair(data, SectionFragment(data)));
|
||||
SectionFragment *frag = const_cast<SectionFragment *>(&acc->second);
|
||||
|
||||
u16 cur = frag->alignment;
|
||||
while (cur < alignment)
|
||||
if (frag->alignment.compare_exchange_strong(cur, alignment))
|
||||
break;
|
||||
return frag;
|
||||
}
|
||||
|
||||
void copy_buf() override;
|
||||
|
||||
private:
|
||||
typedef tbb::concurrent_hash_map<std::string_view, SectionFragment> MapTy;
|
||||
static constexpr i64 NUM_SHARDS = 32;
|
||||
|
||||
MergedSection(std::string_view name, u64 flags, u32 type)
|
||||
: OutputChunk(SYNTHETIC) {
|
||||
this->name = name;
|
||||
@ -780,7 +774,8 @@ private:
|
||||
shdr.sh_type = type;
|
||||
}
|
||||
|
||||
tbb::concurrent_hash_map<std::string_view, SectionFragment> map;
|
||||
MapTy maps[NUM_SHARDS];
|
||||
std::vector<SectionFragment *> fragments;
|
||||
};
|
||||
|
||||
class EhFrameSection : public OutputChunk {
|
||||
@ -1391,9 +1386,7 @@ inline u64 Symbol::get_plt_addr() const {
|
||||
inline u64 SectionFragment::get_addr() const {
|
||||
if (!is_alive)
|
||||
return 0; // todo: remove
|
||||
|
||||
MergeableSection *is = isec.load();
|
||||
return is->parent.shdr.sh_addr + is->offset + offset;
|
||||
return output_section.shdr.sh_addr + offset;
|
||||
}
|
||||
|
||||
inline u64 InputChunk::get_addr() const {
|
||||
|
@ -794,38 +794,71 @@ MergedSection::get_instance(std::string_view name, u64 type, u64 flags) {
|
||||
return osec;
|
||||
}
|
||||
|
||||
void MergedSection::copy_buf() {
|
||||
u8 *base = out::buf + shdr.sh_offset;
|
||||
SectionFragment *MergedSection::insert(std::string_view data, i64 alignment) {
|
||||
assert(alignment < UINT16_MAX);
|
||||
|
||||
tbb::parallel_for_each(out::objs, [&](ObjectFile *file) {
|
||||
for (MergeableSection *isec : file->mergeable_sections) {
|
||||
if (&isec->parent != this)
|
||||
continue;
|
||||
std::string_view suffix = data;
|
||||
if (suffix.size() > 32)
|
||||
suffix = suffix.substr(suffix.size() - 32);
|
||||
i64 shard = std::hash<std::string_view>()(suffix) % NUM_SHARDS;
|
||||
|
||||
// Clear padding between input sections
|
||||
if (isec->padding)
|
||||
memset(base + isec->offset - isec->padding, 0, isec->padding);
|
||||
MapTy::const_accessor acc;
|
||||
bool inserted =
|
||||
maps[shard].insert(acc, std::pair(data, SectionFragment(this, data)));
|
||||
SectionFragment *frag = const_cast<SectionFragment *>(&acc->second);
|
||||
|
||||
i64 offset = 0;
|
||||
for (SectionFragment *frag : isec->fragments) {
|
||||
if (frag->isec != isec || !frag->is_alive || frag->offset < offset)
|
||||
continue;
|
||||
u16 cur = frag->alignment;
|
||||
while (cur < alignment)
|
||||
if (frag->alignment.compare_exchange_strong(cur, alignment))
|
||||
break;
|
||||
return frag;
|
||||
}
|
||||
|
||||
// Clear padding between section fragments
|
||||
if (offset < frag->offset) {
|
||||
memset(base + isec->offset + offset, 0, frag->offset - offset);
|
||||
offset = frag->offset;
|
||||
}
|
||||
void MergedSection::assign_offsets() {
|
||||
// Collect live section fragments.
|
||||
std::vector<std::vector<SectionFragment *>> vec(NUM_SHARDS);
|
||||
|
||||
memcpy(base + isec->offset + frag->offset,
|
||||
frag->data.data(), frag->data.size());
|
||||
offset += frag->data.size();
|
||||
}
|
||||
}
|
||||
tbb::parallel_for((i64)0, NUM_SHARDS, [&](i64 i) {
|
||||
MapTy &map = maps[i];
|
||||
for (auto it = map.begin(); it != map.end(); it++)
|
||||
if (SectionFragment &frag = it->second; frag.is_alive)
|
||||
vec[i].push_back(&frag);
|
||||
|
||||
std::sort(vec[i].begin(), vec[i].end(),
|
||||
[&](SectionFragment *a, SectionFragment *b) {
|
||||
if (a->data.size() != b->data.size())
|
||||
return a->data.size() < b->data.size();
|
||||
return a->data < b->data;
|
||||
});
|
||||
});
|
||||
|
||||
fragments = flatten(vec);
|
||||
|
||||
// Assign offsets.
|
||||
i64 offset = 0;
|
||||
for (SectionFragment *frag : fragments) {
|
||||
offset = align_to(offset, frag->alignment);
|
||||
frag->offset = offset;
|
||||
offset += frag->data.size();
|
||||
}
|
||||
shdr.sh_size = offset;
|
||||
|
||||
for (SectionFragment *frag : fragments)
|
||||
shdr.sh_addralign = std::max<i64>(shdr.sh_addralign, frag->alignment);
|
||||
}
|
||||
|
||||
void MergedSection::copy_buf() {
|
||||
u8 *base = out::buf + shdr.sh_offset;
|
||||
i64 n = 0;
|
||||
|
||||
for (SectionFragment *frag : fragments) {
|
||||
memset(base + n, 0, frag->offset - n);
|
||||
memcpy(base + frag->offset, frag->data.data(), frag->data.size());
|
||||
n = frag->offset + frag->data.size();
|
||||
}
|
||||
|
||||
static Counter merged_strings("merged_strings");
|
||||
merged_strings += map.size();
|
||||
merged_strings += fragments.size();
|
||||
}
|
||||
|
||||
void EhFrameSection::construct() {
|
||||
|
@ -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 '000000000000111c 0 NOTYPE GLOBAL DEFAULT 16 fn1' $t/log
|
||||
grep -q '000000000000111c 0 NOTYPE GLOBAL DEFAULT 17 fn1' $t/log
|
||||
|
||||
cat <<EOF | clang -fPIC -c -o $t/c.o -xc -
|
||||
#include <stdio.h>
|
||||
|
Loading…
Reference in New Issue
Block a user