authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-12 06:50:57+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
log4aff0ec394cb6ef42db982df86caf8976b558d43
tree31b9adeae926a2f2a451196f0286b9e3094d3969
parentb62281a9c87caab22ff22fb783751a1cd784bcaa

macho: move relocs re-resolution logic to ZigObject


2 files changed, 53 insertions(+), 41 deletions(-)

src/link/MachO.zig+4-41
...@@ -567,47 +567,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -567,47 +567,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
567 try self.resizeSections();567 try self.resizeSections();
568568
569 if (self.getZigObject()) |zo| {569 if (self.getZigObject()) |zo| {
570 var has_resolve_error = false;570 zo.resolveRelocs(self) catch |err| switch (err) {
571571 error.ResolveFailed => return error.FlushFailure,
572 for (zo.getAtoms()) |atom_index| {572 else => |e| return e,
573 const atom = zo.getAtom(atom_index) orelse continue;573 };
574 if (!atom.flags.alive) continue;
575 const sect = &self.sections.items(.header)[atom.out_n_sect];
576 if (sect.isZerofill()) continue;
577 if (!self.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately
578 if (atom.getRelocs(self).len == 0) continue;
579 // TODO: we will resolve and write ZigObject's TLS data twice:
580 // once here, and once in writeAtoms
581 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
582 const code = try gpa.alloc(u8, atom_size);
583 defer gpa.free(code);
584 zo.getAtomData(self, atom.*, code) catch |err| switch (err) {
585 error.InputOutput => {
586 try self.reportUnexpectedError("fetching code for '{s}' failed", .{
587 atom.getName(self),
588 });
589 return error.FlushFailure;
590 },
591 else => |e| {
592 try self.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{
593 atom.getName(self),
594 @errorName(e),
595 });
596 return error.FlushFailure;
597 },
598 };
599 const file_offset = sect.offset + atom.value;
600 atom.resolveRelocs(self, code) catch |err| switch (err) {
601 error.ResolveFailed => has_resolve_error = true,
602 else => |e| {
603 try self.reportUnexpectedError("unexpected error while resolving relocations", .{});
604 return e;
605 },
606 };
607 try self.base.file.?.pwriteAll(code, file_offset);
608 }
609
610 if (has_resolve_error) return error.FlushFailure;
611 }574 }
612 self.writeSectionsAndUpdateLinkeditSizes() catch |err| {575 self.writeSectionsAndUpdateLinkeditSizes() catch |err| {
613 switch (err) {576 switch (err) {
src/link/MachO/ZigObject.zig+49
...@@ -383,6 +383,55 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {...@@ -383,6 +383,55 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
383 }383 }
384}384}
385385
386pub fn resolveRelocs(self: *ZigObject, macho_file: *MachO) !void {
387 const gpa = macho_file.base.comp.gpa;
388 var has_error = false;
389 for (self.getAtoms()) |atom_index| {
390 const atom = self.getAtom(atom_index) orelse continue;
391 if (!atom.flags.alive) continue;
392 const sect = &macho_file.sections.items(.header)[atom.out_n_sect];
393 if (sect.isZerofill()) continue;
394 if (!macho_file.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately
395 if (atom.getRelocs(macho_file).len == 0) continue;
396 // TODO: we will resolve and write ZigObject's TLS data twice:
397 // once here, and once in writeAtoms
398 const atom_size = std.math.cast(usize, atom.size) orelse return error.Overflow;
399 const code = try gpa.alloc(u8, atom_size);
400 defer gpa.free(code);
401 self.getAtomData(macho_file, atom.*, code) catch |err| {
402 switch (err) {
403 error.InputOutput => {
404 try macho_file.reportUnexpectedError("fetching code for '{s}' failed", .{
405 atom.getName(macho_file),
406 });
407 },
408 else => |e| {
409 try macho_file.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{
410 atom.getName(macho_file),
411 @errorName(e),
412 });
413 },
414 }
415 has_error = true;
416 continue;
417 };
418 const file_offset = sect.offset + atom.value;
419 atom.resolveRelocs(macho_file, code) catch |err| {
420 switch (err) {
421 error.ResolveFailed => {},
422 else => |e| {
423 try macho_file.reportUnexpectedError("unexpected error while resolving relocations: {s}", .{@errorName(e)});
424 },
425 }
426 has_error = true;
427 continue;
428 };
429 try macho_file.base.file.?.pwriteAll(code, file_offset);
430 }
431
432 if (has_error) return error.ResolveFailed;
433}
434
386pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {435pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
387 const tracy = trace(@src());436 const tracy = trace(@src());
388 defer tracy.end();437 defer tracy.end();