authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-21 20:50:29+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-21 20:50:29+01:00
log775a161794c9486b7866b27d364acea1cb78b6cd
tree28cd19ca7c3cf985f1cf9cda618f6ffa5ea1c700
parent06c191a4ffdb977f9668d6cae90aa7e72065f362

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


2 files changed, 35 insertions(+), 14 deletions(-)

src/link/Elf.zig+9-9
...@@ -1371,14 +1371,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)...@@ -1371,14 +1371,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
1371 try self.writePhdrTable();1371 try self.writePhdrTable();
1372 try self.writeShdrTable();1372 try self.writeShdrTable();
1373 try self.writeAtoms();1373 try self.writeAtoms();
13741374 try self.writeSyntheticSections();
1375 self.writeSyntheticSections() catch |err| switch (err) {
1376 error.UnsupportedCpuArch => {
1377 try self.reportUnsupportedCpuArch();
1378 return error.FlushFailure;
1379 },
1380 else => |e| return e,
1381 };
13821375
1383 if (self.entry_index == null and self.base.isExe()) {1376 if (self.entry_index == null and self.base.isExe()) {
1384 log.debug("flushing. no_entry_point_found = true", .{});1377 log.debug("flushing. no_entry_point_found = true", .{});
...@@ -4689,7 +4682,14 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4689,7 +4682,14 @@ fn writeSyntheticSections(self: *Elf) !void {
4689 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;4682 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
4690 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);4683 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
4691 defer buffer.deinit();4684 defer buffer.deinit();
4692 try eh_frame.writeEhFrame(self, buffer.writer());4685 eh_frame.writeEhFrame(self, buffer.writer()) catch |err| switch (err) {
4686 error.RelocFailure => return error.FlushFailure,
4687 error.UnsupportedCpuArch => {
4688 try self.reportUnsupportedCpuArch();
4689 return error.FlushFailure;
4690 },
4691 else => |e| return e,
4692 };
4693 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4693 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4694 }4694 }
46954695
src/link/Elf/eh_frame.zig+26-5
...@@ -317,7 +317,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -317,7 +317,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
317 });317 });
318318
319 switch (cpu_arch) {319 switch (cpu_arch) {
320 .x86_64 => x86_64.resolveReloc(rel, P, S + A, contents[offset..]),320 .x86_64 => try x86_64.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]),
321 else => return error.UnsupportedCpuArch,321 else => return error.UnsupportedCpuArch,
322 }322 }
323}323}
...@@ -325,6 +325,8 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -325,6 +325,8 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
325pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {325pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
326 relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr});326 relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr});
327327
328 var has_reloc_errors = false;
329
328 for (elf_file.objects.items) |index| {330 for (elf_file.objects.items) |index| {
329 const object = elf_file.file(index).?.object;331 const object = elf_file.file(index).?.object;
330332
...@@ -335,7 +337,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {...@@ -335,7 +337,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
335337
336 for (cie.relocs(elf_file)) |rel| {338 for (cie.relocs(elf_file)) |rel| {
337 const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);339 const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
338 try resolveReloc(cie, sym, rel, elf_file, contents);340 resolveReloc(cie, sym, rel, elf_file, contents) catch |err| switch (err) {
341 error.RelocFailure => has_reloc_errors = true,
342 else => |e| return e,
343 };
339 }344 }
340345
341 try writer.writeAll(contents);346 try writer.writeAll(contents);
...@@ -359,7 +364,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {...@@ -359,7 +364,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
359364
360 for (fde.relocs(elf_file)) |rel| {365 for (fde.relocs(elf_file)) |rel| {
361 const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);366 const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
362 try resolveReloc(fde, sym, rel, elf_file, contents);367 resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) {
368 error.RelocFailure => has_reloc_errors = true,
369 else => |e| return e,
370 };
363 }371 }
364372
365 try writer.writeAll(contents);373 try writer.writeAll(contents);
...@@ -367,6 +375,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {...@@ -367,6 +375,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
367 }375 }
368376
369 try writer.writeInt(u32, 0, .little);377 try writer.writeInt(u32, 0, .little);
378
379 if (has_reloc_errors) return error.RelocFailure;
370}380}
371381
372pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void {382pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void {
...@@ -540,18 +550,29 @@ const EH_PE = struct {...@@ -540,18 +550,29 @@ const EH_PE = struct {
540};550};
541551
542const x86_64 = struct {552const x86_64 = struct {
543 fn resolveReloc(rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) void {553 fn resolveReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) !void {
544 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());554 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
545 switch (r_type) {555 switch (r_type) {
556 .NONE => {},
546 .@"32" => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little),557 .@"32" => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little),
547 .@"64" => std.mem.writeInt(i64, data[0..8], target, .little),558 .@"64" => std.mem.writeInt(i64, data[0..8], target, .little),
548 .PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little),559 .PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little),
549 .PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little),560 .PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little),
550 else => unreachable,561 else => try reportInvalidReloc(rec, elf_file, rel),
551 }562 }
552 }563 }
553};564};
554565
566fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {
567 var err = try elf_file.addErrorWithNotes(1);
568 try err.addMsg(elf_file, "invalid relocation type {} at offset 0x{x}", .{
569 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
570 rel.r_offset,
571 });
572 try err.addNote(elf_file, "in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});
573 return error.RelocFailure;
574}
575
555const std = @import("std");576const std = @import("std");
556const assert = std.debug.assert;577const assert = std.debug.assert;
557const elf = std.elf;578const elf = std.elf;