| ... | @@ -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 | }); |
| 318 | | 318 | |
| 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: |
| 325 | pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { | 325 | pub 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}); |
| 327 | | 327 | |
| | 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; |
| 330 | | 332 | |
| ... | @@ -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 { |
| 335 | | 337 | |
| 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 | } |
| 340 | | 345 | |
| 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 { |
| 359 | | 364 | |
| 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 | } |
| 364 | | 372 | |
| 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 | } |
| 368 | | 376 | |
| 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 | } |
| 371 | | 381 | |
| 372 | pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void { | 382 | pub 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 | }; |
| 541 | | 551 | |
| 542 | const x86_64 = struct { | 552 | const 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 | }; |
| 554 | | 565 | |
| | 566 | fn 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 | |
| 555 | const std = @import("std"); | 576 | const std = @import("std"); |
| 556 | const assert = std.debug.assert; | 577 | const assert = std.debug.assert; |
| 557 | const elf = std.elf; | 578 | const elf = std.elf; |