| ... | ... | @@ -63,14 +63,15 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 63 | 63 | allocateSegment(macho_file); |
| 64 | 64 | macho_file.allocateAtoms(); |
| 65 | 65 | |
| 66 | | state_log.debug("{}", .{macho_file.dumpState()}); |
| 67 | | |
| 68 | 66 | var off = off: { |
| 69 | 67 | const seg = macho_file.segments.items[0]; |
| 70 | 68 | const off = math.cast(u32, seg.fileoff + seg.filesize) orelse return error.Overflow; |
| 71 | 69 | break :off mem.alignForward(u32, off, @alignOf(macho.relocation_info)); |
| 72 | 70 | }; |
| 73 | 71 | off = allocateSectionsRelocs(macho_file, off); |
| 72 | |
| 73 | state_log.debug("{}", .{macho_file.dumpState()}); |
| 74 | |
| 74 | 75 | try macho_file.calcSymtabSize(); |
| 75 | 76 | try writeAtoms(macho_file); |
| 76 | 77 | try writeCompactUnwind(macho_file); |
| ... | ... | @@ -195,6 +196,16 @@ fn calcSectionSizes(macho_file: *MachO) !void { |
| 195 | 196 | sect.@"align" = 3; |
| 196 | 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 | 211 | fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void { |
| ... | ... | @@ -303,6 +314,7 @@ fn writeAtoms(macho_file: *MachO) !void { |
| 303 | 314 | for (slice.items(.header), slice.items(.atoms)) |header, atoms| { |
| 304 | 315 | if (atoms.items.len == 0) continue; |
| 305 | 316 | if (header.isZerofill()) continue; |
| 317 | if (mem.indexOf(u8, header.segName(), "ZIG") != null) continue; |
| 306 | 318 | |
| 307 | 319 | const size = math.cast(usize, header.size) orelse return error.Overflow; |
| 308 | 320 | const code = try gpa.alloc(u8, size); |
| ... | ... | @@ -330,6 +342,63 @@ fn writeAtoms(macho_file: *MachO) !void { |
| 330 | 342 | try macho_file.base.file.?.pwriteAll(code, header.offset); |
| 331 | 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 | 404 | fn writeCompactUnwind(macho_file: *MachO) !void { |