| ... | @@ -546,8 +546,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -546,8 +546,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 546 | | 546 | |
| 547 | relocs_log.debug("{x}: {s}", .{ self.value, name }); | 547 | relocs_log.debug("{x}: {s}", .{ self.value, name }); |
| 548 | | 548 | |
| | 549 | var has_error = false; |
| 549 | var stream = std.io.fixedBufferStream(buffer); | 550 | var stream = std.io.fixedBufferStream(buffer); |
| 550 | | | |
| 551 | var i: usize = 0; | 551 | var i: usize = 0; |
| 552 | while (i < relocs.len) : (i += 1) { | 552 | while (i < relocs.len) : (i += 1) { |
| 553 | const rel = relocs[i]; | 553 | const rel = relocs[i]; |
| ... | @@ -562,25 +562,34 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -562,25 +562,34 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 562 | self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| { | 562 | self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| { |
| 563 | switch (err) { | 563 | switch (err) { |
| 564 | error.RelaxFail => { | 564 | error.RelaxFail => { |
| | 565 | const target = switch (rel.tag) { |
| | 566 | .@"extern" => rel.getTargetSymbol(macho_file).getName(macho_file), |
| | 567 | .local => rel.getTargetAtom(macho_file).getName(macho_file), |
| | 568 | }; |
| 565 | try macho_file.reportParseError2( | 569 | try macho_file.reportParseError2( |
| 566 | file.getIndex(), | 570 | file.getIndex(), |
| 567 | "{s}: 0x{x}: failed to relax relocation: in {s}", | 571 | "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {s}, target {s}", |
| 568 | .{ name, rel.offset, @tagName(rel.type) }, | 572 | .{ name, self.value, rel.offset, @tagName(rel.type), target }, |
| 569 | ); | 573 | ); |
| 570 | return error.ResolveFailed; | 574 | has_error = true; |
| 571 | }, | 575 | }, |
| | 576 | error.RelaxFailUnexpectedInstruction => has_error = true, |
| 572 | else => |e| return e, | 577 | else => |e| return e, |
| 573 | } | 578 | } |
| 574 | }; | 579 | }; |
| 575 | } | 580 | } |
| | 581 | |
| | 582 | if (has_error) return error.ResolveFailed; |
| 576 | } | 583 | } |
| 577 | | 584 | |
| 578 | const ResolveError = error{ | 585 | const ResolveError = error{ |
| 579 | RelaxFail, | 586 | RelaxFail, |
| | 587 | RelaxFailUnexpectedInstruction, |
| 580 | NoSpaceLeft, | 588 | NoSpaceLeft, |
| 581 | DivisionByZero, | 589 | DivisionByZero, |
| 582 | UnexpectedRemainder, | 590 | UnexpectedRemainder, |
| 583 | Overflow, | 591 | Overflow, |
| | 592 | OutOfMemory, |
| 584 | }; | 593 | }; |
| 585 | | 594 | |
| 586 | fn resolveRelocInner( | 595 | fn resolveRelocInner( |
| ... | @@ -704,7 +713,7 @@ fn resolveRelocInner( | ... | @@ -704,7 +713,7 @@ fn resolveRelocInner( |
| 704 | if (rel.getTargetSymbol(macho_file).flags.has_got) { | 713 | if (rel.getTargetSymbol(macho_file).flags.has_got) { |
| 705 | try writer.writeInt(i32, @intCast(G + A - P), .little); | 714 | try writer.writeInt(i32, @intCast(G + A - P), .little); |
| 706 | } else { | 715 | } else { |
| 707 | try x86_64.relaxGotLoad(code[rel_offset - 3 ..]); | 716 | try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file); |
| 708 | try writer.writeInt(i32, @intCast(S + A - P), .little); | 717 | try writer.writeInt(i32, @intCast(S + A - P), .little); |
| 709 | } | 718 | } |
| 710 | }, | 719 | }, |
| ... | @@ -898,7 +907,7 @@ fn resolveRelocInner( | ... | @@ -898,7 +907,7 @@ fn resolveRelocInner( |
| 898 | } | 907 | } |
| 899 | | 908 | |
| 900 | const x86_64 = struct { | 909 | const x86_64 = struct { |
| 901 | fn relaxGotLoad(code: []u8) error{RelaxFail}!void { | 910 | fn relaxGotLoad(self: Atom, code: []u8, rel: Relocation, macho_file: *MachO) ResolveError!void { |
| 902 | const old_inst = disassemble(code) orelse return error.RelaxFail; | 911 | const old_inst = disassemble(code) orelse return error.RelaxFail; |
| 903 | switch (old_inst.encoding.mnemonic) { | 912 | switch (old_inst.encoding.mnemonic) { |
| 904 | .mov => { | 913 | .mov => { |
| ... | @@ -906,7 +915,18 @@ const x86_64 = struct { | ... | @@ -906,7 +915,18 @@ const x86_64 = struct { |
| 906 | relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding }); | 915 | relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding }); |
| 907 | encode(&.{inst}, code) catch return error.RelaxFail; | 916 | encode(&.{inst}, code) catch return error.RelaxFail; |
| 908 | }, | 917 | }, |
| 909 | else => return error.RelaxFail, | 918 | else => |x| { |
| | 919 | var err = try macho_file.addErrorWithNotes(2); |
| | 920 | try err.addMsg(macho_file, "{s}: 0x{x}: 0x{x}: failed to relax relocation of type {s}", .{ |
| | 921 | self.getName(macho_file), |
| | 922 | self.value, |
| | 923 | rel.offset, |
| | 924 | @tagName(rel.type), |
| | 925 | }); |
| | 926 | try err.addNote(macho_file, "expected .mov instruction but found .{s}", .{@tagName(x)}); |
| | 927 | try err.addNote(macho_file, "while parsing {}", .{self.getFile(macho_file).fmtPath()}); |
| | 928 | return error.RelaxFailUnexpectedInstruction; |
| | 929 | }, |
| 910 | } | 930 | } |
| 911 | } | 931 | } |
| 912 | | 932 | |