| ... | @@ -63,14 +63,15 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u | ... | @@ -63,14 +63,15 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 63 | allocateSegment(macho_file); | 63 | allocateSegment(macho_file); |
| 64 | macho_file.allocateAtoms(); | 64 | macho_file.allocateAtoms(); |
| 65 | | 65 | |
| 66 | state_log.debug("{}", .{macho_file.dumpState()}); | | |
| 67 | | | |
| 68 | var off = off: { | 66 | var off = off: { |
| 69 | const seg = macho_file.segments.items[0]; | 67 | const seg = macho_file.segments.items[0]; |
| 70 | const off = math.cast(u32, seg.fileoff + seg.filesize) orelse return error.Overflow; | 68 | const off = math.cast(u32, seg.fileoff + seg.filesize) orelse return error.Overflow; |
| 71 | break :off mem.alignForward(u32, off, @alignOf(macho.relocation_info)); | 69 | break :off mem.alignForward(u32, off, @alignOf(macho.relocation_info)); |
| 72 | }; | 70 | }; |
| 73 | off = allocateSectionsRelocs(macho_file, off); | 71 | off = allocateSectionsRelocs(macho_file, off); |
| | 72 | |
| | 73 | state_log.debug("{}", .{macho_file.dumpState()}); |
| | 74 | |
| 74 | try macho_file.calcSymtabSize(); | 75 | try macho_file.calcSymtabSize(); |
| 75 | try writeAtoms(macho_file); | 76 | try writeAtoms(macho_file); |
| 76 | try writeCompactUnwind(macho_file); | 77 | try writeCompactUnwind(macho_file); |
| ... | @@ -195,6 +196,16 @@ fn calcSectionSizes(macho_file: *MachO) !void { | ... | @@ -195,6 +196,16 @@ fn calcSectionSizes(macho_file: *MachO) !void { |
| 195 | sect.@"align" = 3; | 196 | sect.@"align" = 3; |
| 196 | sect.nreloc = eh_frame.calcNumRelocs(macho_file); | 197 | sect.nreloc = eh_frame.calcNumRelocs(macho_file); |
| 197 | } | 198 | } |
| | 199 | |
| | 200 | if (macho_file.getZigObject()) |zo| { |
| | 201 | for (zo.atoms.items) |atom_index| { |
| | 202 | const atom = macho_file.getAtom(atom_index) orelse continue; |
| | 203 | if (!atom.flags.alive) continue; |
| | 204 | const header = &macho_file.sections.items(.header)[atom.out_n_sect]; |
| | 205 | if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue; |
| | 206 | header.nreloc += atom.calcNumRelocs(macho_file); |
| | 207 | } |
| | 208 | } |
| 198 | } | 209 | } |
| 199 | | 210 | |
| 200 | fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void { | 211 | fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void { |
| ... | @@ -303,6 +314,7 @@ fn writeAtoms(macho_file: *MachO) !void { | ... | @@ -303,6 +314,7 @@ fn writeAtoms(macho_file: *MachO) !void { |
| 303 | for (slice.items(.header), slice.items(.atoms)) |header, atoms| { | 314 | for (slice.items(.header), slice.items(.atoms)) |header, atoms| { |
| 304 | if (atoms.items.len == 0) continue; | 315 | if (atoms.items.len == 0) continue; |
| 305 | if (header.isZerofill()) continue; | 316 | if (header.isZerofill()) continue; |
| | 317 | if (mem.indexOf(u8, header.segName(), "ZIG") != null) continue; |
| 306 | | 318 | |
| 307 | const size = math.cast(usize, header.size) orelse return error.Overflow; | 319 | const size = math.cast(usize, header.size) orelse return error.Overflow; |
| 308 | const code = try gpa.alloc(u8, size); | 320 | const code = try gpa.alloc(u8, size); |
| ... | @@ -330,6 +342,63 @@ fn writeAtoms(macho_file: *MachO) !void { | ... | @@ -330,6 +342,63 @@ fn writeAtoms(macho_file: *MachO) !void { |
| 330 | try macho_file.base.file.?.pwriteAll(code, header.offset); | 342 | try macho_file.base.file.?.pwriteAll(code, header.offset); |
| 331 | try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff); | 343 | try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff); |
| 332 | } | 344 | } |
| | 345 | |
| | 346 | if (macho_file.getZigObject()) |zo| { |
| | 347 | // TODO: this is ugly; perhaps we should aggregrate before? |
| | 348 | var relocs = std.AutoArrayHashMap(u8, std.ArrayList(macho.relocation_info)).init(gpa); |
| | 349 | defer { |
| | 350 | for (relocs.values()) |*list| { |
| | 351 | list.deinit(); |
| | 352 | } |
| | 353 | relocs.deinit(); |
| | 354 | } |
| | 355 | |
| | 356 | for (macho_file.sections.items(.header), 0..) |header, n_sect| { |
| | 357 | if (header.isZerofill()) continue; |
| | 358 | if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue; |
| | 359 | const gop = try relocs.getOrPut(@intCast(n_sect)); |
| | 360 | if (gop.found_existing) continue; |
| | 361 | gop.value_ptr.* = try std.ArrayList(macho.relocation_info).initCapacity(gpa, header.nreloc); |
| | 362 | } |
| | 363 | |
| | 364 | for (zo.atoms.items) |atom_index| { |
| | 365 | const atom = macho_file.getAtom(atom_index) orelse continue; |
| | 366 | if (!atom.flags.alive) continue; |
| | 367 | const header = macho_file.sections.items(.header)[atom.out_n_sect]; |
| | 368 | if (header.isZerofill()) continue; |
| | 369 | if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue; |
| | 370 | if (atom.getRelocs(macho_file).len == 0) continue; |
| | 371 | const atom_size = math.cast(usize, atom.size) orelse return error.Overflow; |
| | 372 | const code = try gpa.alloc(u8, atom_size); |
| | 373 | defer gpa.free(code); |
| | 374 | atom.getData(macho_file, code) catch |err| switch (err) { |
| | 375 | error.InputOutput => { |
| | 376 | try macho_file.reportUnexpectedError("fetching code for '{s}' failed", .{ |
| | 377 | atom.getName(macho_file), |
| | 378 | }); |
| | 379 | return error.FlushFailure; |
| | 380 | }, |
| | 381 | else => |e| { |
| | 382 | try macho_file.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{ |
| | 383 | atom.getName(macho_file), |
| | 384 | @errorName(e), |
| | 385 | }); |
| | 386 | return error.FlushFailure; |
| | 387 | }, |
| | 388 | }; |
| | 389 | const file_offset = header.offset + atom.value - header.addr; |
| | 390 | const rels = relocs.getPtr(atom.out_n_sect).?; |
| | 391 | try atom.writeRelocs(macho_file, code, rels); |
| | 392 | try macho_file.base.file.?.pwriteAll(code, file_offset); |
| | 393 | } |
| | 394 | |
| | 395 | for (relocs.keys(), relocs.values()) |sect_id, rels| { |
| | 396 | const header = macho_file.sections.items(.header)[sect_id]; |
| | 397 | assert(rels.items.len == header.nreloc); |
| | 398 | mem.sort(macho.relocation_info, rels.items, {}, sortReloc); |
| | 399 | try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(rels.items), header.reloff); |
| | 400 | } |
| | 401 | } |
| 333 | } | 402 | } |
| 334 | | 403 | |
| 335 | fn writeCompactUnwind(macho_file: *MachO) !void { | 404 | fn writeCompactUnwind(macho_file: *MachO) !void { |