authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-01 12:13:46+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-03 09:25:41+01:00
log352941b0308057b434f6db664e66a9ea793fac95
tree65838d3845e584b0ca65f42d85582b14a78e102b
parentf2e249e92020462ac29f34fc3d45cef3dc90a3b2

macho: emit incomplete object file


2 files changed, 63 insertions(+), 38 deletions(-)

src/link/MachO.zig+32-27
......@@ -285,8 +285,7 @@ pub fn createEmpty(
285285 };
286286 try self.d_sym.?.initMetadata(self);
287287 } else {
288 try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{});
289 return error.Unexpected;
288 @panic("TODO: implement generating and emitting __DWARF in .o file");
290289 },
291290 .code_view => unreachable,
292291 }
......@@ -2025,7 +2024,7 @@ pub fn sortSections(self: *MachO) !void {
20252024
20262025 for (zo.symtab.items(.nlist)) |*sym| {
20272026 if (sym.sect()) {
2028 sym.n_sect = backlinks[sym.n_sect];
2027 sym.n_sect = backlinks[sym.n_sect - 1] + 1;
20292028 }
20302029 }
20312030
......@@ -3391,8 +3390,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
33913390 .prot = macho.PROT.READ | macho.PROT.WRITE,
33923391 });
33933392 }
3394 } else {
3395 @panic("TODO initMetadata when relocatable");
33963393 }
33973394
33983395 const appendSect = struct {
......@@ -3415,7 +3412,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
34153412 },
34163413 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
34173414 });
3418 appendSect(self, self.zig_text_sect_index.?, self.zig_text_seg_index.?);
3415 if (!self.base.isRelocatable()) appendSect(self, self.zig_text_sect_index.?, self.zig_text_seg_index.?);
34193416 }
34203417
34213418 if (!self.base.isRelocatable()) {
......@@ -3427,33 +3424,35 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
34273424
34283425 {
34293426 self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{});
3430 appendSect(self, self.zig_const_sect_index.?, self.zig_const_seg_index.?);
3427 if (!self.base.isRelocatable()) appendSect(self, self.zig_const_sect_index.?, self.zig_const_seg_index.?);
34313428 }
34323429
34333430 {
34343431 self.zig_data_sect_index = try self.addSection("__DATA_ZIG", "__data_zig", .{});
3435 appendSect(self, self.zig_data_sect_index.?, self.zig_data_seg_index.?);
3432 if (!self.base.isRelocatable()) appendSect(self, self.zig_data_sect_index.?, self.zig_data_seg_index.?);
34363433 }
34373434
34383435 {
34393436 self.zig_bss_sect_index = try self.addSection("__BSS_ZIG", "__bss_zig", .{
34403437 .flags = macho.S_ZEROFILL,
34413438 });
3442 appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
3439 if (!self.base.isRelocatable()) appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
34433440 }
34443441}
34453442
34463443pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
34473444 const sect = &self.sections.items(.header)[sect_index];
3448 const seg_id = self.sections.items(.segment_id)[sect_index];
3449 const seg = &self.segments.items[seg_id];
34503445
34513446 if (needed_size > self.allocatedSize(sect.offset) and !sect.isZerofill()) {
34523447 const existing_size = sect.size;
34533448 sect.size = 0;
34543449
34553450 // Must move the entire section.
3456 const new_offset = self.findFreeSpace(needed_size, self.getPageSize());
3451 const alignment = if (self.base.isRelocatable())
3452 try math.powi(u32, 2, sect.@"align")
3453 else
3454 self.getPageSize();
3455 const new_offset = self.findFreeSpace(needed_size, alignment);
34573456
34583457 log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
34593458 sect.segName(),
......@@ -3465,26 +3464,32 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
34653464 try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
34663465
34673466 sect.offset = @intCast(new_offset);
3468 seg.fileoff = new_offset;
34693467 }
34703468
34713469 sect.size = needed_size;
3472 if (!sect.isZerofill()) {
3473 seg.filesize = needed_size;
3474 }
34753470
3476 const mem_capacity = self.allocatedVirtualSize(seg.vmaddr);
3477 if (needed_size > mem_capacity) {
3478 var err = try self.addErrorWithNotes(2);
3479 try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{
3480 seg_id,
3481 seg.segName(),
3482 });
3483 try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{});
3484 try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
3485 }
3471 if (!self.base.isRelocatable()) {
3472 const seg_id = self.sections.items(.segment_id)[sect_index];
3473 const seg = &self.segments.items[seg_id];
3474 seg.fileoff = sect.offset;
34863475
3487 seg.vmsize = needed_size;
3476 if (!sect.isZerofill()) {
3477 seg.filesize = needed_size;
3478 }
3479
3480 const mem_capacity = self.allocatedVirtualSize(seg.vmaddr);
3481 if (needed_size > mem_capacity) {
3482 var err = try self.addErrorWithNotes(2);
3483 try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{
3484 seg_id,
3485 seg.segName(),
3486 });
3487 try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{});
3488 try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
3489 }
3490
3491 seg.vmsize = needed_size;
3492 }
34883493}
34893494
34903495pub fn getTarget(self: MachO) std.Target {
src/link/MachO/relocatable.zig+31-11
......@@ -12,7 +12,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
1212
1313 if (module_obj_path) |path| try positionals.append(.{ .path = path });
1414
15 if (positionals.items.len == 1) {
15 if (macho_file.getZigObject() == null and positionals.items.len == 1) {
1616 // Instead of invoking a full-blown `-r` mode on the input which sadly will strip all
1717 // debug info segments/sections (this is apparently by design by Apple), we copy
1818 // the *only* input file over.
......@@ -26,6 +26,11 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
2626 return;
2727 }
2828
29 if (macho_file.getZigObject() != null and positionals.items.len > 0) {
30 try macho_file.reportUnexpectedError("TODO: build-obj for ZigObject and input object files", .{});
31 return error.FlushFailure;
32 }
33
2934 for (positionals.items) |obj| {
3035 macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
3136 error.MalformedObject,
......@@ -46,8 +51,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
4651
4752 try macho_file.addUndefinedGlobals();
4853 try macho_file.resolveSymbols();
49 markExports(macho_file);
50 claimUnresolved(macho_file);
54 try markExports(macho_file);
55 try claimUnresolved(macho_file);
5156 try initOutputSections(macho_file);
5257 try macho_file.sortSections();
5358 try macho_file.addAtomsToSections();
......@@ -109,8 +114,13 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
109114 try writeHeader(macho_file, ncmds, sizeofcmds);
110115}
111116
112fn markExports(macho_file: *MachO) void {
113 for (macho_file.objects.items) |index| {
117fn markExports(macho_file: *MachO) error{OutOfMemory}!void {
118 var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
119 defer objects.deinit();
120 if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
121 objects.appendSliceAssumeCapacity(macho_file.objects.items);
122
123 for (objects.items) |index| {
114124 for (macho_file.getFile(index).?.getSymbols()) |sym_index| {
115125 const sym = macho_file.getSymbol(sym_index);
116126 const file = sym.getFile(macho_file) orelse continue;
......@@ -122,13 +132,22 @@ fn markExports(macho_file: *MachO) void {
122132 }
123133}
124134
125fn claimUnresolved(macho_file: *MachO) void {
126 for (macho_file.objects.items) |index| {
127 const object = macho_file.getFile(index).?.object;
135fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void {
136 var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
137 defer objects.deinit();
138 if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
139 objects.appendSliceAssumeCapacity(macho_file.objects.items);
128140
129 for (object.symbols.items, 0..) |sym_index, i| {
141 for (objects.items) |index| {
142 const file = macho_file.getFile(index).?;
143
144 for (file.getSymbols(), 0..) |sym_index, i| {
130145 const nlist_idx = @as(Symbol.Index, @intCast(i));
131 const nlist = object.symtab.items(.nlist)[nlist_idx];
146 const nlist = switch (file) {
147 .object => |x| x.symtab.items(.nlist)[nlist_idx],
148 .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
149 else => unreachable,
150 };
132151 if (!nlist.ext()) continue;
133152 if (!nlist.undf()) continue;
134153
......@@ -290,7 +309,7 @@ fn writeAtoms(macho_file: *MachO) !void {
290309 assert(atom.flags.alive);
291310 const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow;
292311 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
293 try atom.getFile(macho_file).object.getAtomData(atom.*, code[off..][0..atom_size]);
312 try atom.getData(macho_file, code[off..][0..atom_size]);
294313 try atom.writeRelocs(macho_file, code[off..][0..atom_size], &relocs);
295314 }
296315
......@@ -501,5 +520,6 @@ const trace = @import("../../tracy.zig").trace;
501520
502521const Atom = @import("Atom.zig");
503522const Compilation = @import("../../Compilation.zig");
523const File = @import("file.zig").File;
504524const MachO = @import("../MachO.zig");
505525const Symbol = @import("Symbol.zig");