authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-13 17:54:57+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-13 21:51:43+02:00
log5eef7577d1a49006d69d5067af0dd87be272db52
tree381bf50deb989df2eac48f0e5a4c54235454258d
parent7a16a97671af5ca324150e4f2f9bdf12cb3cc2cd

elf: handle more relocs with GOT relaxation


1 files changed, 77 insertions(+), 0 deletions(-)

src/link/Elf/Atom.zig+77
......@@ -460,10 +460,35 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
460460
461461 elf.R_X86_64_64 => try cwriter.writeIntLittle(i64, S + A),
462462
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
463466 elf.R_X86_64_PLT32,
464467 elf.R_X86_64_PC32,
465468 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))),
466469
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
467492 else => {
468493 log.err("TODO: unhandled relocation type {}", .{fmtRelocType(rel.r_type())});
469494 @panic("TODO unhandled relocation type");
......@@ -591,6 +616,58 @@ fn format2(
591616// future.
592617pub const Index = u16;
593618
619const 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
594671const std = @import("std");
595672const assert = std.debug.assert;
596673const elf = std.elf;