Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/arch/x86_64/Emit.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
34 changes: 27 additions & 7 deletions src/link/MachO/Atom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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(
Expand Down Expand Up @@ -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);
}
},
Expand Down Expand Up @@ -898,15 +907,26 @@ 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 => {
const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops) catch return error.RelaxFail;
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;
},
}
}

Expand Down
15 changes: 6 additions & 9 deletions src/link/MachO/ZigObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ pub fn getDeclVAddr(
.pcrel = false,
.has_subtractor = false,
.length = 3,
.symbolnum = 0,
.symbolnum = @intCast(sym.nlist_idx),
},
});
return vaddr;
Expand All @@ -416,7 +416,7 @@ pub fn getAnonDeclVAddr(
.pcrel = false,
.has_subtractor = false,
.length = 3,
.symbolnum = 0,
.symbolnum = @intCast(sym.nlist_idx),
},
});
return vaddr;
Expand Down Expand Up @@ -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, .{
Expand All @@ -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),
},
});

Expand Down