elf: emit .rela.eh_frame section contents
This commit is contained in:
@@ -4245,11 +4245,10 @@ fn updateSectionSizesObject(self: *Elf) !void {
|
||||
|
||||
if (self.eh_frame_section_index) |index| {
|
||||
self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
|
||||
|
||||
if (self.eh_frame_rela_section_index) |rela_index| {
|
||||
const shdr = &self.shdrs.items[rela_index];
|
||||
shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize;
|
||||
}
|
||||
}
|
||||
if (self.eh_frame_rela_section_index) |index| {
|
||||
const shdr = &self.shdrs.items[index];
|
||||
shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize;
|
||||
}
|
||||
|
||||
try self.updateSymtabSize();
|
||||
@@ -5013,6 +5012,14 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
|
||||
try eh_frame.writeEhFrame(self, buffer.writer());
|
||||
try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
|
||||
}
|
||||
if (self.eh_frame_rela_section_index) |shndx| {
|
||||
const shdr = self.shdrs.items[shndx];
|
||||
const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
|
||||
var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
|
||||
defer buffer.deinit();
|
||||
try eh_frame.writeEhFrameRelocs(self, buffer.writer());
|
||||
try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
|
||||
}
|
||||
|
||||
try self.writeSymtab();
|
||||
try self.writeShStrtab();
|
||||
|
||||
@@ -373,6 +373,62 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
|
||||
try writer.writeInt(u32, 0, .little);
|
||||
}
|
||||
|
||||
fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {
|
||||
const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset;
|
||||
const r_type = rel.r_type();
|
||||
var r_addend = rel.r_addend;
|
||||
var r_sym: u32 = 0;
|
||||
switch (sym.type(elf_file)) {
|
||||
elf.STT_SECTION => {
|
||||
r_addend += @intCast(sym.value);
|
||||
r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?);
|
||||
},
|
||||
else => {
|
||||
r_sym = sym.outputSymtabIndex(elf_file) orelse 0;
|
||||
},
|
||||
}
|
||||
|
||||
relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{
|
||||
Atom.fmtRelocType(r_type),
|
||||
r_offset,
|
||||
r_sym,
|
||||
sym.name(elf_file),
|
||||
r_addend,
|
||||
});
|
||||
|
||||
return .{
|
||||
.r_offset = r_offset,
|
||||
.r_addend = r_addend,
|
||||
.r_info = (@as(u64, @intCast(r_sym)) << 32) | r_type,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
|
||||
relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr});
|
||||
|
||||
for (elf_file.objects.items) |index| {
|
||||
const object = elf_file.file(index).?.object;
|
||||
|
||||
for (object.cies.items) |cie| {
|
||||
if (!cie.alive) continue;
|
||||
for (cie.relocs(elf_file)) |rel| {
|
||||
const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
|
||||
const out_rel = emitReloc(elf_file, cie, sym, rel);
|
||||
try writer.writeStruct(out_rel);
|
||||
}
|
||||
}
|
||||
|
||||
for (object.fdes.items) |fde| {
|
||||
if (!fde.alive) continue;
|
||||
for (fde.relocs(elf_file)) |rel| {
|
||||
const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
|
||||
const out_rel = emitReloc(elf_file, fde, sym, rel);
|
||||
try writer.writeStruct(out_rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
|
||||
try writer.writeByte(1); // version
|
||||
try writer.writeByte(EH_PE.pcrel | EH_PE.sdata4);
|
||||
|
||||
Reference in New Issue
Block a user