1
1
mirror of https://github.com/rui314/mold.git synced 2024-12-28 19:04:27 +03:00
This commit is contained in:
Rui Ueyama 2021-01-24 09:38:23 +09:00
parent c8e2c183b2
commit f82811562a
2 changed files with 20 additions and 22 deletions

View File

@ -198,25 +198,25 @@ void ObjectFile::initialize_ehframe_sections() {
// .eh_frame contains data records explaining how to handle exceptions.
// When an exception is thrown, the runtime searches a record from
// .eh_frame with the current program counter as a key. A record that
// covers the current PC explains how to find a handler and transfer the
// control ot it.
// covers the current PC explains how to find a handler and how to
// transfer the control ot it.
//
// Unlike most other sections, linker has to parse .eh_frame contents
// Unlike the most other sections, linker has to parse .eh_frame contents
// because of the following reasons:
//
// - There's usually only one .eh_frame section for each object file,
// which explains how to handle exceptions for all functions in the same
// object. If we just copy them, the resulting .eh_frame section will
// contain lots of records for dead sections (i.e. de-duplicated inline
// functions). We want to only copy records for live functions.
// functions). We want to copy only records for live functions.
//
// - .eh_frame contains two types of records: CIE and FDE. There's usually
// only one CIE at beginning of .eh_frame section followed by FDEs.
// Compiler usually emits the identical CIE record for all object files.
// We want to merge them in an output .eh_frame section to reduce the
// section size.
// We want to merge identical CIEs in an output .eh_frame section to
// reduce the section size.
//
// - Scanning a .eh_frame section to find a record is a O(n) operation
// - Scanning a .eh_frame section to find a record is an O(n) operation
// where n is the number of records in the section. To reduce it to
// O(log n), linker creates a .eh_frame_hdr section. The section
// contains a sorted list of [an address in .text, an FDE address whose

View File

@ -36,13 +36,13 @@ void OutputShdr::update_shdr() {
}
void OutputShdr::copy_buf() {
ElfShdr *ent = (ElfShdr *)(out::buf + shdr.sh_offset);
ent[0] = {};
ElfShdr *hdr = (ElfShdr *)(out::buf + shdr.sh_offset);
hdr[0] = {};
int i = 1;
for (OutputChunk *chunk : out::chunks)
if (chunk->kind != OutputChunk::HEADER)
ent[i++] = chunk->shdr;
hdr[i++] = chunk->shdr;
}
static u32 to_phdr_flags(OutputChunk *chunk) {
@ -890,11 +890,11 @@ void EhFrameSection::copy_buf() {
if (out::eh_frame_hdr)
hdr_base = out::buf + out::eh_frame_hdr->shdr.sh_offset;
auto apply_reloc = [](EhReloc &rel, u8 *loc, u32 S, u32 P, i64 A) {
auto apply_reloc = [&](EhReloc &rel, u64 loc, u64 val) {
if (rel.r_type == R_X86_64_32)
*(u32 *)loc = S + A;
*(u32 *)(base + loc) = val;
else if (rel.r_type == R_X86_64_PC32)
*(u32 *)loc = S + A - P;
*(u32 *)(base + loc) = val - shdr.sh_addr - loc;
else
unreachable();
};
@ -918,10 +918,9 @@ void EhFrameSection::copy_buf() {
cie_size = cie->contents.size();
for (EhReloc &rel : cie->rels) {
u32 S = rel.sym->get_addr();
u32 P = shdr.sh_addr + cie->offset + rel.offset;
u8 *loc = base + cie->offset + rel.offset;
apply_reloc(rel, loc, S, P, rel.r_addend);
u64 loc = cie->offset + rel.offset;
u64 val = rel.sym->get_addr() + rel.r_addend;
apply_reloc(rel, loc, val);
}
}
@ -936,15 +935,14 @@ void EhFrameSection::copy_buf() {
for (int i = 0; i < fde.rels.size(); i++) {
EhReloc &rel = fde.rels[i];
u32 S = rel.sym->get_addr();
u32 P = shdr.sh_addr + fde_off + rel.offset;
u8 *loc = base + fde_off + rel.offset;
apply_reloc(rel, loc, S, P, rel.r_addend);
u64 loc = fde_off + rel.offset;
u64 val = rel.sym->get_addr() + rel.r_addend;
apply_reloc(rel, loc, val);
// Write to .eh_frame_hdr
if (out::eh_frame_hdr && i == 0) {
assert(rel.offset == 8);
entry->init_addr = S + rel.r_addend - out::eh_frame_hdr->shdr.sh_addr;
entry->init_addr = val - out::eh_frame_hdr->shdr.sh_addr;
entry->fde_addr = shdr.sh_addr + fde_off - out::eh_frame_hdr->shdr.sh_addr;
entry++;
}