aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/relocatable.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/link/MachO/relocatable.zig')
-rw-r--r--src/link/MachO/relocatable.zig73
1 files changed, 71 insertions, 2 deletions
diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig
index 474d039829..cbfd81f9d1 100644
--- a/src/link/MachO/relocatable.zig
+++ b/src/link/MachO/relocatable.zig
@@ -63,14 +63,15 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
allocateSegment(macho_file);
macho_file.allocateAtoms();
- state_log.debug("{}", .{macho_file.dumpState()});
-
var off = off: {
const seg = macho_file.segments.items[0];
const off = math.cast(u32, seg.fileoff + seg.filesize) orelse return error.Overflow;
break :off mem.alignForward(u32, off, @alignOf(macho.relocation_info));
};
off = allocateSectionsRelocs(macho_file, off);
+
+ state_log.debug("{}", .{macho_file.dumpState()});
+
try macho_file.calcSymtabSize();
try writeAtoms(macho_file);
try writeCompactUnwind(macho_file);
@@ -195,6 +196,16 @@ fn calcSectionSizes(macho_file: *MachO) !void {
sect.@"align" = 3;
sect.nreloc = eh_frame.calcNumRelocs(macho_file);
}
+
+ if (macho_file.getZigObject()) |zo| {
+ for (zo.atoms.items) |atom_index| {
+ const atom = macho_file.getAtom(atom_index) orelse continue;
+ if (!atom.flags.alive) continue;
+ const header = &macho_file.sections.items(.header)[atom.out_n_sect];
+ if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue;
+ header.nreloc += atom.calcNumRelocs(macho_file);
+ }
+ }
}
fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void {
@@ -303,6 +314,7 @@ fn writeAtoms(macho_file: *MachO) !void {
for (slice.items(.header), slice.items(.atoms)) |header, atoms| {
if (atoms.items.len == 0) continue;
if (header.isZerofill()) continue;
+ if (mem.indexOf(u8, header.segName(), "ZIG") != null) continue;
const size = math.cast(usize, header.size) orelse return error.Overflow;
const code = try gpa.alloc(u8, size);
@@ -330,6 +342,63 @@ fn writeAtoms(macho_file: *MachO) !void {
try macho_file.base.file.?.pwriteAll(code, header.offset);
try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
}
+
+ if (macho_file.getZigObject()) |zo| {
+ // TODO: this is ugly; perhaps we should aggregrate before?
+ var relocs = std.AutoArrayHashMap(u8, std.ArrayList(macho.relocation_info)).init(gpa);
+ defer {
+ for (relocs.values()) |*list| {
+ list.deinit();
+ }
+ relocs.deinit();
+ }
+
+ for (macho_file.sections.items(.header), 0..) |header, n_sect| {
+ if (header.isZerofill()) continue;
+ if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue;
+ const gop = try relocs.getOrPut(@intCast(n_sect));
+ if (gop.found_existing) continue;
+ gop.value_ptr.* = try std.ArrayList(macho.relocation_info).initCapacity(gpa, header.nreloc);
+ }
+
+ for (zo.atoms.items) |atom_index| {
+ const atom = macho_file.getAtom(atom_index) orelse continue;
+ if (!atom.flags.alive) continue;
+ const header = macho_file.sections.items(.header)[atom.out_n_sect];
+ if (header.isZerofill()) continue;
+ if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue;
+ if (atom.getRelocs(macho_file).len == 0) continue;
+ const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
+ const code = try gpa.alloc(u8, atom_size);
+ defer gpa.free(code);
+ atom.getData(macho_file, code) catch |err| switch (err) {
+ error.InputOutput => {
+ try macho_file.reportUnexpectedError("fetching code for '{s}' failed", .{
+ atom.getName(macho_file),
+ });
+ return error.FlushFailure;
+ },
+ else => |e| {
+ try macho_file.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{
+ atom.getName(macho_file),
+ @errorName(e),
+ });
+ return error.FlushFailure;
+ },
+ };
+ const file_offset = header.offset + atom.value - header.addr;
+ const rels = relocs.getPtr(atom.out_n_sect).?;
+ try atom.writeRelocs(macho_file, code, rels);
+ try macho_file.base.file.?.pwriteAll(code, file_offset);
+ }
+
+ for (relocs.keys(), relocs.values()) |sect_id, rels| {
+ const header = macho_file.sections.items(.header)[sect_id];
+ assert(rels.items.len == header.nreloc);
+ mem.sort(macho.relocation_info, rels.items, {}, sortReloc);
+ try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(rels.items), header.reloff);
+ }
+ }
}
fn writeCompactUnwind(macho_file: *MachO) !void {