| ... | ... | @@ -460,10 +460,35 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { |
| 460 | 460 | |
| 461 | 461 | elf.R_X86_64_64 => try cwriter.writeIntLittle(i64, S + A), |
| 462 | 462 | |
| 463 | elf.R_X86_64_32 => try cwriter.writeIntLittle(u32, @as(u32, @truncate(@as(u64, @intCast(S + A))))), |
| 464 | elf.R_X86_64_32S => try cwriter.writeIntLittle(i32, @as(i32, @truncate(S + A))), |
| 465 | |
| 463 | 466 | elf.R_X86_64_PLT32, |
| 464 | 467 | elf.R_X86_64_PC32, |
| 465 | 468 | => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))), |
| 466 | 469 | |
| 470 | elf.R_X86_64_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A - P))), |
| 471 | elf.R_X86_64_GOTPC32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(GOT + A - P))), |
| 472 | elf.R_X86_64_GOTPC64 => try cwriter.writeIntLittle(i64, GOT + A - P), |
| 473 | |
| 474 | elf.R_X86_64_GOTPCRELX => { |
| 475 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { |
| 476 | x86_64.relaxGotpcrelx(code[rel.r_offset - 2 ..]) catch break :blk; |
| 477 | try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))); |
| 478 | continue; |
| 479 | } |
| 480 | try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A - P))); |
| 481 | }, |
| 482 | |
| 483 | elf.R_X86_64_REX_GOTPCRELX => { |
| 484 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { |
| 485 | x86_64.relaxRexGotpcrelx(code[rel.r_offset - 3 ..]) catch break :blk; |
| 486 | try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))); |
| 487 | continue; |
| 488 | } |
| 489 | try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A - P))); |
| 490 | }, |
| 491 | |
| 467 | 492 | else => { |
| 468 | 493 | log.err("TODO: unhandled relocation type {}", .{fmtRelocType(rel.r_type())}); |
| 469 | 494 | @panic("TODO unhandled relocation type"); |
| ... | ... | @@ -591,6 +616,58 @@ fn format2( |
| 591 | 616 | // future. |
| 592 | 617 | pub const Index = u16; |
| 593 | 618 | |
| 619 | const x86_64 = struct { |
| 620 | pub fn relaxGotpcrelx(code: []u8) !void { |
| 621 | const old_inst = disassemble(code) orelse return error.RelaxFail; |
| 622 | const inst = switch (old_inst.encoding.mnemonic) { |
| 623 | .call => try Instruction.new(old_inst.prefix, .call, &.{ |
| 624 | // TODO: hack to force imm32s in the assembler |
| 625 | .{ .imm = Immediate.s(-129) }, |
| 626 | }), |
| 627 | .jmp => try Instruction.new(old_inst.prefix, .jmp, &.{ |
| 628 | // TODO: hack to force imm32s in the assembler |
| 629 | .{ .imm = Immediate.s(-129) }, |
| 630 | }), |
| 631 | else => return error.RelaxFail, |
| 632 | }; |
| 633 | relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding }); |
| 634 | const nop = try Instruction.new(.none, .nop, &.{}); |
| 635 | encode(&.{ nop, inst }, code) catch return error.RelaxFail; |
| 636 | } |
| 637 | |
| 638 | pub fn relaxRexGotpcrelx(code: []u8) !void { |
| 639 | const old_inst = disassemble(code) orelse return error.RelaxFail; |
| 640 | switch (old_inst.encoding.mnemonic) { |
| 641 | .mov => { |
| 642 | const inst = try Instruction.new(old_inst.prefix, .lea, &old_inst.ops); |
| 643 | relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding }); |
| 644 | encode(&.{inst}, code) catch return error.RelaxFail; |
| 645 | }, |
| 646 | else => return error.RelaxFail, |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | fn disassemble(code: []const u8) ?Instruction { |
| 651 | var disas = Disassembler.init(code); |
| 652 | const inst = disas.next() catch return null; |
| 653 | return inst; |
| 654 | } |
| 655 | |
| 656 | fn encode(insts: []const Instruction, code: []u8) !void { |
| 657 | var stream = std.io.fixedBufferStream(code); |
| 658 | const writer = stream.writer(); |
| 659 | for (insts) |inst| { |
| 660 | try inst.encode(writer, .{}); |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | const bits = @import("../../arch/x86_64/bits.zig"); |
| 665 | const encoder = @import("../../arch/x86_64/encoder.zig"); |
| 666 | const Disassembler = @import("../../arch/x86_64/Disassembler.zig"); |
| 667 | const Immediate = bits.Immediate; |
| 668 | const Instruction = encoder.Instruction; |
| 669 | }; |
| 670 | |
| 594 | 671 | const std = @import("std"); |
| 595 | 672 | const assert = std.debug.assert; |
| 596 | 673 | const elf = std.elf; |