elf: simplify logic for resolving .eh_frame relocs on different arches
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user