elf: simplify logic for resolving .eh_frame relocs on different arches

This commit is contained in:
Jakub Konka
2024-02-21 20:50:29 +01:00
parent 06c191a4ff
commit 775a161794
2 changed files with 35 additions and 14 deletions

View File

@@ -1371,14 +1371,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
try self.writePhdrTable();
try self.writeShdrTable();
try self.writeAtoms();
self.writeSyntheticSections() catch |err| switch (err) {
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
return error.FlushFailure;
},
else => |e| return e,
};
try self.writeSyntheticSections();
if (self.entry_index == null and self.base.isExe()) {
log.debug("flushing. no_entry_point_found = true", .{});
@@ -4689,7 +4682,14 @@ fn writeSyntheticSections(self: *Elf) !void {
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.writeEhFrame(self, buffer.writer());
eh_frame.writeEhFrame(self, buffer.writer()) catch |err| switch (err) {
error.RelocFailure => return error.FlushFailure,
error.UnsupportedCpuArch => {
try self.reportUnsupportedCpuArch();
return error.FlushFailure;
},
else => |e| return e,
};
try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
}

View File

@@ -317,7 +317,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
});
switch (cpu_arch) {
.x86_64 => x86_64.resolveReloc(rel, P, S + A, contents[offset..]),
.x86_64 => try x86_64.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]),
else => return error.UnsupportedCpuArch,
}
}
@@ -325,6 +325,8 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr});
var has_reloc_errors = false;
for (elf_file.objects.items) |index| {
const object = elf_file.file(index).?.object;
@@ -335,7 +337,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
for (cie.relocs(elf_file)) |rel| {
const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
try resolveReloc(cie, sym, rel, elf_file, contents);
resolveReloc(cie, sym, rel, elf_file, contents) catch |err| switch (err) {
error.RelocFailure => has_reloc_errors = true,
else => |e| return e,
};
}
try writer.writeAll(contents);
@@ -359,7 +364,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
for (fde.relocs(elf_file)) |rel| {
const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
try resolveReloc(fde, sym, rel, elf_file, contents);
resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) {
error.RelocFailure => has_reloc_errors = true,
else => |e| return e,
};
}
try writer.writeAll(contents);
@@ -367,6 +375,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
}
try writer.writeInt(u32, 0, .little);
if (has_reloc_errors) return error.RelocFailure;
}
pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void {
@@ -540,18 +550,29 @@ const EH_PE = struct {
};
const x86_64 = struct {
fn resolveReloc(rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) void {
fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void {
const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
switch (r_type) {
.NONE => {},
.@"32" => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little),
.@"64" => std.mem.writeInt(i64, data[0..8], target, .little),
.PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little),
.PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little),
else => unreachable,
else => try reportInvalidReloc(rec, elf_file, rel),
}
}
};
fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {
var err = try elf_file.addErrorWithNotes(1);
try err.addMsg(elf_file, "invalid relocation type {} at offset 0x{x}", .{
relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
rel.r_offset,
});
try err.addNote(elf_file, "in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});
return error.RelocFailure;
}
const std = @import("std");
const assert = std.debug.assert;
const elf = std.elf;