1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-21 09:57:18 +03:00
This commit is contained in:
Rui Ueyama 2021-04-16 22:39:53 +09:00
parent 3a97d2f75a
commit 1f1e442265
5 changed files with 48 additions and 43 deletions

View File

@ -42,7 +42,7 @@ static void visit(Context<E> &ctx, InputSection<E> *isec,
// describing how to handle exceptions for that function.
// We want to keep associated .eh_frame records.
for (FdeRecord<E> &fde : isec->get_fdes())
for (ElfRel<E> &rel : fde.get_rels(isec->file).subspan(1))
for (ElfRel<E> &rel : fde.get_rels().subspan(1))
if (Symbol<E> *sym = isec->file.symbols[rel.r_sym])
if (mark_section(sym->input_section))
feeder.add(sym->input_section);

17
icf.cc
View File

@ -128,7 +128,7 @@ static bool is_leaf(Context<E> &ctx, InputSection<E> &isec) {
return false;
for (FdeRecord<E> &fde : isec.get_fdes())
if (fde.get_rels(isec.file).size() > 1)
if (fde.get_rels().size() > 1)
return false;
return true;
@ -143,7 +143,7 @@ struct LeafHasher {
size_t operator()(const InputSection<E> *isec) const {
size_t h = hash_string(isec->contents);
for (FdeRecord<E> &fde : isec->get_fdes()) {
size_t h2 = hash_string(fde.get_contents(isec->file).substr(8));
size_t h2 = hash_string(fde.get_contents().substr(8));
h = combine_hash(h, h2);
}
return h;
@ -163,8 +163,7 @@ struct LeafEq {
return false;
for (i64 i = 0; i < x.size(); i++)
if (x[i].get_contents(a->file).substr(8) !=
y[i].get_contents(b->file).substr(8))
if (x[i].get_contents().substr(8) != y[i].get_contents().substr(8))
return false;
return true;
}
@ -260,19 +259,19 @@ static Digest compute_digest(Context<E> &ctx, InputSection<E> &isec) {
hash(isec.get_rels(ctx).size());
for (FdeRecord<E> &fde : isec.get_fdes()) {
hash(isec.file.cies[fde.cie_idx].icf_idx);
hash(fde.cie->icf_idx);
// Bytes 0 to 4 contain the length of this record, and
// bytes 4 to 8 contain an offset to CIE.
hash_string(fde.get_contents(isec.file).substr(8));
hash_string(fde.get_contents().substr(8));
hash(fde.get_rels(isec.file).size());
hash(fde.get_rels().size());
for (ElfRel<E> &rel : fde.get_rels(isec.file).subspan(1)) {
for (ElfRel<E> &rel : fde.get_rels().subspan(1)) {
hash_symbol(*isec.file.symbols[rel.r_sym]);
hash(rel.r_type);
hash(rel.r_offset - fde.input_offset);
hash(isec.file.cies[fde.cie_idx].input_section.get_addend(rel));
hash(fde.cie->input_section.get_addend(rel));
}
}

19
mold.h
View File

@ -51,6 +51,8 @@ template <typename E> class OutputSection;
template <typename E> class SharedFile;
template <typename E> class Symbol;
template <typename E> struct Context;
template <typename E> struct FdeRecord;
template <typename E> struct CieRecord;
template <typename E> void cleanup();
@ -149,31 +151,30 @@ enum {
template <typename E>
struct FdeRecord {
FdeRecord(u32 input_offset, u32 rel_idx, u16 cie_idx)
: input_offset(input_offset), rel_idx(rel_idx), cie_idx(cie_idx) {}
FdeRecord(u32 input_offset, u32 rel_idx)
: input_offset(input_offset), rel_idx(rel_idx) {}
FdeRecord(const FdeRecord &other)
: input_offset(other.input_offset),
output_offset(other.output_offset),
rel_idx(other.rel_idx), cie_idx(other.cie_idx),
: cie(other.cie), input_offset(other.input_offset),
output_offset(other.output_offset), rel_idx(other.rel_idx),
is_alive(other.is_alive.load()) {}
FdeRecord &operator=(const FdeRecord<E> &other) {
cie = other.cie;
input_offset = other.input_offset;
output_offset = other.output_offset;
rel_idx = other.rel_idx;
cie_idx = other.cie_idx;
is_alive = other.is_alive.load();
return *this;
}
std::string_view get_contents(ObjectFile<E> &file) const;
std::span<ElfRel<E>> get_rels(ObjectFile<E> &file) const;
std::string_view get_contents() const;
std::span<ElfRel<E>> get_rels() const;
CieRecord<E> *cie = nullptr;
u32 input_offset = -1;
u32 output_offset = -1;
u32 rel_idx = -1;
u16 cie_idx = -1;
std::atomic_bool is_alive = true;
};

View File

@ -306,13 +306,6 @@ void ObjectFile<E>::read_ehframe(Context<E> &ctx, InputSection<E> &isec) {
std::string_view contents = this->get_string(ctx, isec.shdr);
i64 rel_idx = 0;
auto find_cie = [&](i64 offset) -> u16{
for (i64 i = cies.size() - 1; i >= 0; i--)
if (cies[i].input_offset == offset)
return i;
Fatal(ctx) << isec << ": bad FDE pointer";
};
for (std::string_view data = contents; !data.empty();) {
i64 size = *(u32 *)data.data();
if (size == 0) {
@ -339,11 +332,25 @@ void ObjectFile<E>::read_ehframe(Context<E> &ctx, InputSection<E> &isec) {
if (rels[rel_begin].r_offset - begin_offset != 8)
Fatal(ctx) << isec << ": FDE's first relocation should have offset 8";
i64 cie_idx = find_cie(begin_offset + 4 - id);
fdes.push_back(FdeRecord<E>(begin_offset, rel_begin, cie_idx));
fdes.push_back(FdeRecord<E>(begin_offset, rel_begin));
}
}
// Associate CIEs to FDEs.
auto find_cie = [&](i64 offset) -> CieRecord<E> * {
for (i64 i = cies.size() - 1; i >= 0; i--)
if (cies[i].input_offset == offset)
return &cies[i];
Fatal(ctx) << isec << ": bad FDE pointer";
};
for (FdeRecord<E> &fde : fdes) {
i64 cie_offset = *(i32 *)(contents.data() + fde.input_offset + 4);
fde.cie = find_cie(fde.input_offset + 4 - cie_offset);
}
// We assume that FDEs for the same input sections are contiguous
// in `fdes` vector.
sort(fdes, [&](const FdeRecord<E> &a, const FdeRecord<E> &b) {
InputSection<E> *x = this->symbols[rels[a.rel_idx].r_sym]->input_section;
InputSection<E> *y = this->symbols[rels[b.rel_idx].r_sym]->input_section;
@ -1293,16 +1300,15 @@ bool SharedFile<E>::is_readonly(Context<E> &ctx, Symbol<E> *sym) {
}
template <typename E>
std::string_view FdeRecord<E>::get_contents(ObjectFile<E> &file) const {
std::string_view data = file.cies[cie_idx].contents;
i64 size = *(u32 *)(data.data() + input_offset) + 4;
return data.substr(input_offset, size);
std::string_view FdeRecord<E>::get_contents() const {
i64 size = *(u32 *)(cie->contents.data() + input_offset) + 4;
return cie->contents.substr(input_offset, size);
}
template <typename E>
std::span<ElfRel<E>> FdeRecord<E>::get_rels(ObjectFile<E> &file) const {
std::span<ElfRel<E>> rels = file.cies[cie_idx].rels;
i64 size = get_contents(file).size();
std::span<ElfRel<E>> FdeRecord<E>::get_rels() const {
std::span<ElfRel<E>> rels = cie->rels;
i64 size = get_contents().size();
i64 end = rel_idx;
while (end < rels.size() && rels[end].r_offset < input_offset + size)
end++;

View File

@ -1154,7 +1154,7 @@ void EhFrameSection<E>::construct(Context<E> &ctx) {
i64 offset = 0;
for (FdeRecord<E> &fde : file->fdes) {
fde.output_offset = offset;
offset += fde.get_contents(*file).size();
offset += fde.get_contents().size();
}
file->fde_size = offset;
});
@ -1223,17 +1223,16 @@ void EhFrameSection<E>::copy_buf(Context<E> &ctx) {
for (FdeRecord<E> &fde : file->fdes) {
i64 offset = file->fde_offset + fde.output_offset;
std::string_view contents = fde.get_contents(*file);
std::string_view contents = fde.get_contents();
memcpy(base + offset, contents.data(), contents.size());
CieRecord<E> &cie = file->cies[fde.cie_idx];
*(u32 *)(base + offset + 4) = offset + 4 - cie.output_offset;
*(u32 *)(base + offset + 4) = offset + 4 - fde.cie->output_offset;
for (ElfRel<E> &rel : fde.get_rels(*file)) {
for (ElfRel<E> &rel : fde.get_rels()) {
assert(rel.r_offset - fde.input_offset < contents.size());
u64 loc = offset + rel.r_offset - fde.input_offset;
u64 val = file->symbols[rel.r_sym]->get_addr(ctx);
u64 addend = cie.input_section.get_addend(rel);
u64 addend = fde.cie->input_section.get_addend(rel);
apply_reloc(ctx, rel, loc, val + addend);
}
}
@ -1266,9 +1265,9 @@ void EhFrameHdrSection<E>::copy_buf(Context<E> &ctx) {
Entry *entry = (Entry *)(base + HEADER_SIZE) + file->fde_idx;
for (FdeRecord<E> &fde : file->fdes) {
ElfRel<E> rel = fde.get_rels(*file)[0];
ElfRel<E> rel = fde.get_rels()[0];
u64 val = file->symbols[rel.r_sym]->get_addr(ctx);
u64 addend = file->cies[fde.cie_idx].input_section.get_addend(rel);
u64 addend = fde.cie->input_section.get_addend(rel);
*entry++ = {(i32)(val + addend - this->shdr.sh_addr),
(i32)(eh_frame_addr + file->fde_offset +