mirror of
https://github.com/rui314/mold.git
synced 2024-12-28 19:04:27 +03:00
wip
This commit is contained in:
parent
c8e2c183b2
commit
f82811562a
@ -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
|
||||
|
@ -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++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user