From 1ee628a3e08ab5a150e45e79a778ac04e7f8b1e0 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 29 Jan 2024 19:58:00 +0100 Subject: [PATCH 1/2] macho: improve error msg when relaxing GOT fails --- src/link/MachO/Atom.zig | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 429a7993f185..14c25261086b 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -546,8 +546,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { relocs_log.debug("{x}: {s}", .{ self.value, name }); + var has_error = false; var stream = std.io.fixedBufferStream(buffer); - var i: usize = 0; while (i < relocs.len) : (i += 1) { const rel = relocs[i]; @@ -562,25 +562,34 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| { switch (err) { error.RelaxFail => { + const target = switch (rel.tag) { + .@"extern" => rel.getTargetSymbol(macho_file).getName(macho_file), + .local => rel.getTargetAtom(macho_file).getName(macho_file), + }; try macho_file.reportParseError2( file.getIndex(), - "{s}: 0x{x}: failed to relax relocation: in {s}", - .{ name, rel.offset, @tagName(rel.type) }, + "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {s}, target {s}", + .{ name, self.value, rel.offset, @tagName(rel.type), target }, ); - return error.ResolveFailed; + has_error = true; }, + error.RelaxFailUnexpectedInstruction => has_error = true, else => |e| return e, } }; } + + if (has_error) return error.ResolveFailed; } const ResolveError = error{ RelaxFail, + RelaxFailUnexpectedInstruction, NoSpaceLeft, DivisionByZero, UnexpectedRemainder, Overflow, + OutOfMemory, }; fn resolveRelocInner( @@ -704,7 +713,7 @@ fn resolveRelocInner( if (rel.getTargetSymbol(macho_file).flags.has_got) { try writer.writeInt(i32, @intCast(G + A - P), .little); } else { - try x86_64.relaxGotLoad(code[rel_offset - 3 ..]); + try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file); try writer.writeInt(i32, @intCast(S + A - P), .little); } }, @@ -898,7 +907,7 @@ fn resolveRelocInner( } const x86_64 = struct { - fn relaxGotLoad(code: []u8) error{RelaxFail}!void { + fn relaxGotLoad(self: Atom, code: []u8, rel: Relocation, macho_file: *MachO) ResolveError!void { const old_inst = disassemble(code) orelse return error.RelaxFail; switch (old_inst.encoding.mnemonic) { .mov => { @@ -906,7 +915,18 @@ const x86_64 = struct { relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding }); encode(&.{inst}, code) catch return error.RelaxFail; }, - else => return error.RelaxFail, + else => |x| { + var err = try macho_file.addErrorWithNotes(2); + try err.addMsg(macho_file, "{s}: 0x{x}: 0x{x}: failed to relax relocation of type {s}", .{ + self.getName(macho_file), + self.value, + rel.offset, + @tagName(rel.type), + }); + try err.addNote(macho_file, "expected .mov instruction but found .{s}", .{@tagName(x)}); + try err.addNote(macho_file, "while parsing {}", .{self.getFile(macho_file).fmtPath()}); + return error.RelaxFailUnexpectedInstruction; + }, } } From d4966517f6d7204bb4c23204025cbd5ff3e06a03 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 29 Jan 2024 21:12:56 +0100 Subject: [PATCH 2/2] x86_64+macho: emit .got instead of .got_load relocs --- src/arch/x86_64/Emit.zig | 8 +++++--- src/link/MachO/ZigObject.zig | 15 ++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 35d6935d771f..b78b56efed15 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -62,7 +62,7 @@ pub fn emitMir(emit: *Emit) Error!void { .pcrel = true, .has_subtractor = false, .length = 2, - .symbolnum = 0, + .symbolnum = @intCast(symbol.sym_index), }, }); } else if (emit.lower.bin_file.cast(link.File.Coff)) |coff_file| { @@ -165,7 +165,9 @@ pub fn emitMir(emit: *Emit) Error!void { const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib) .zig_got_load else if (sym.flags.needs_got) - .got_load + // TODO: it is possible to emit .got_load here that can potentially be relaxed + // however this requires always to use a MOVQ mnemonic + .got else if (sym.flags.tlv) .tlv else @@ -180,7 +182,7 @@ pub fn emitMir(emit: *Emit) Error!void { .pcrel = true, .has_subtractor = false, .length = 2, - .symbolnum = 0, + .symbolnum = @intCast(data.sym_index), }, }); } else unreachable, diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index c05a03e673d2..0634cb68f728 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -390,7 +390,7 @@ pub fn getDeclVAddr( .pcrel = false, .has_subtractor = false, .length = 3, - .symbolnum = 0, + .symbolnum = @intCast(sym.nlist_idx), }, }); return vaddr; @@ -416,7 +416,7 @@ pub fn getAnonDeclVAddr( .pcrel = false, .has_subtractor = false, .length = 3, - .symbolnum = 0, + .symbolnum = @intCast(sym.nlist_idx), }, }); return vaddr; @@ -856,21 +856,18 @@ fn createTlvDescriptor( atom.alignment = alignment; atom.size = size; - const tlv_bootstrap_index = blk: { - const index = try self.getGlobalSymbol(macho_file, "_tlv_bootstrap", null); - break :blk self.symbols.items[index]; - }; + const tlv_bootstrap_index = try self.getGlobalSymbol(macho_file, "_tlv_bootstrap", null); try atom.addReloc(macho_file, .{ .tag = .@"extern", .offset = 0, - .target = tlv_bootstrap_index, + .target = self.symbols.items[tlv_bootstrap_index], .addend = 0, .type = .unsigned, .meta = .{ .pcrel = false, .has_subtractor = false, .length = 3, - .symbolnum = 0, + .symbolnum = @intCast(tlv_bootstrap_index), }, }); try atom.addReloc(macho_file, .{ @@ -883,7 +880,7 @@ fn createTlvDescriptor( .pcrel = false, .has_subtractor = false, .length = 3, - .symbolnum = 0, + .symbolnum = @intCast(macho_file.getSymbol(init_sym_index).nlist_idx), }, });