diff --git a/gc_sections.cc b/gc_sections.cc index ee57d777..b93072f9 100644 --- a/gc_sections.cc +++ b/gc_sections.cc @@ -42,7 +42,7 @@ static void visit(Context &ctx, InputSection *isec, // describing how to handle exceptions for that function. // We want to keep associated .eh_frame records. for (FdeRecord &fde : isec->get_fdes()) - for (ElfRel &rel : fde.get_rels(isec->file).subspan(1)) + for (ElfRel &rel : fde.get_rels().subspan(1)) if (Symbol *sym = isec->file.symbols[rel.r_sym]) if (mark_section(sym->input_section)) feeder.add(sym->input_section); diff --git a/icf.cc b/icf.cc index 8c4772d2..8a8b64df 100644 --- a/icf.cc +++ b/icf.cc @@ -128,7 +128,7 @@ static bool is_leaf(Context &ctx, InputSection &isec) { return false; for (FdeRecord &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 *isec) const { size_t h = hash_string(isec->contents); for (FdeRecord &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 &ctx, InputSection &isec) { hash(isec.get_rels(ctx).size()); for (FdeRecord &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 &rel : fde.get_rels(isec.file).subspan(1)) { + for (ElfRel &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)); } } diff --git a/mold.h b/mold.h index 3a6f5b40..db609a56 100644 --- a/mold.h +++ b/mold.h @@ -51,6 +51,8 @@ template class OutputSection; template class SharedFile; template class Symbol; template struct Context; +template struct FdeRecord; +template struct CieRecord; template void cleanup(); @@ -149,31 +151,30 @@ enum { template 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 &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 &file) const; - std::span> get_rels(ObjectFile &file) const; + std::string_view get_contents() const; + std::span> get_rels() const; + CieRecord *cie = nullptr; u32 input_offset = -1; u32 output_offset = -1; u32 rel_idx = -1; - u16 cie_idx = -1; std::atomic_bool is_alive = true; }; diff --git a/object_file.cc b/object_file.cc index e763eafb..02635108 100644 --- a/object_file.cc +++ b/object_file.cc @@ -306,13 +306,6 @@ void ObjectFile::read_ehframe(Context &ctx, InputSection &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::read_ehframe(Context &ctx, InputSection &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(begin_offset, rel_begin, cie_idx)); + fdes.push_back(FdeRecord(begin_offset, rel_begin)); } } + // Associate CIEs to FDEs. + auto find_cie = [&](i64 offset) -> CieRecord * { + 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 &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 &a, const FdeRecord &b) { InputSection *x = this->symbols[rels[a.rel_idx].r_sym]->input_section; InputSection *y = this->symbols[rels[b.rel_idx].r_sym]->input_section; @@ -1293,16 +1300,15 @@ bool SharedFile::is_readonly(Context &ctx, Symbol *sym) { } template -std::string_view FdeRecord::get_contents(ObjectFile &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::get_contents() const { + i64 size = *(u32 *)(cie->contents.data() + input_offset) + 4; + return cie->contents.substr(input_offset, size); } template -std::span> FdeRecord::get_rels(ObjectFile &file) const { - std::span> rels = file.cies[cie_idx].rels; - i64 size = get_contents(file).size(); +std::span> FdeRecord::get_rels() const { + std::span> rels = cie->rels; + i64 size = get_contents().size(); i64 end = rel_idx; while (end < rels.size() && rels[end].r_offset < input_offset + size) end++; diff --git a/output_chunks.cc b/output_chunks.cc index 353d3306..86613af6 100644 --- a/output_chunks.cc +++ b/output_chunks.cc @@ -1154,7 +1154,7 @@ void EhFrameSection::construct(Context &ctx) { i64 offset = 0; for (FdeRecord &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::copy_buf(Context &ctx) { for (FdeRecord &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 &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 &rel : fde.get_rels(*file)) { + for (ElfRel &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::copy_buf(Context &ctx) { Entry *entry = (Entry *)(base + HEADER_SIZE) + file->fde_idx; for (FdeRecord &fde : file->fdes) { - ElfRel rel = fde.get_rels(*file)[0]; + ElfRel 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 +