diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 59 | ||||
| -rw-r--r-- | src/link/MachO/relocatable.zig | 42 |
2 files changed, 63 insertions, 38 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index e7603e2bde..5baccb51fa 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -285,8 +285,7 @@ pub fn createEmpty( }; try self.d_sym.?.initMetadata(self); } else { - try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{}); - return error.Unexpected; + @panic("TODO: implement generating and emitting __DWARF in .o file"); }, .code_view => unreachable, } @@ -2025,7 +2024,7 @@ pub fn sortSections(self: *MachO) !void { for (zo.symtab.items(.nlist)) |*sym| { if (sym.sect()) { - sym.n_sect = backlinks[sym.n_sect]; + sym.n_sect = backlinks[sym.n_sect - 1] + 1; } } @@ -3391,8 +3390,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { .prot = macho.PROT.READ | macho.PROT.WRITE, }); } - } else { - @panic("TODO initMetadata when relocatable"); } const appendSect = struct { @@ -3415,7 +3412,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { }, .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, }); - appendSect(self, self.zig_text_sect_index.?, self.zig_text_seg_index.?); + if (!self.base.isRelocatable()) appendSect(self, self.zig_text_sect_index.?, self.zig_text_seg_index.?); } if (!self.base.isRelocatable()) { @@ -3427,33 +3424,35 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { { self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{}); - appendSect(self, self.zig_const_sect_index.?, self.zig_const_seg_index.?); + if (!self.base.isRelocatable()) appendSect(self, self.zig_const_sect_index.?, self.zig_const_seg_index.?); } { self.zig_data_sect_index = try self.addSection("__DATA_ZIG", "__data_zig", .{}); - appendSect(self, self.zig_data_sect_index.?, self.zig_data_seg_index.?); + if (!self.base.isRelocatable()) appendSect(self, self.zig_data_sect_index.?, self.zig_data_seg_index.?); } { self.zig_bss_sect_index = try self.addSection("__BSS_ZIG", "__bss_zig", .{ .flags = macho.S_ZEROFILL, }); - appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?); + if (!self.base.isRelocatable()) appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?); } } pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void { const sect = &self.sections.items(.header)[sect_index]; - const seg_id = self.sections.items(.segment_id)[sect_index]; - const seg = &self.segments.items[seg_id]; if (needed_size > self.allocatedSize(sect.offset) and !sect.isZerofill()) { const existing_size = sect.size; sect.size = 0; // Must move the entire section. - const new_offset = self.findFreeSpace(needed_size, self.getPageSize()); + const alignment = if (self.base.isRelocatable()) + try math.powi(u32, 2, sect.@"align") + else + self.getPageSize(); + const new_offset = self.findFreeSpace(needed_size, alignment); log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{ sect.segName(), @@ -3465,26 +3464,32 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void { try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size); sect.offset = @intCast(new_offset); - seg.fileoff = new_offset; } sect.size = needed_size; - if (!sect.isZerofill()) { - seg.filesize = needed_size; - } - const mem_capacity = self.allocatedVirtualSize(seg.vmaddr); - if (needed_size > mem_capacity) { - var err = try self.addErrorWithNotes(2); - try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{ - seg_id, - seg.segName(), - }); - try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); - try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); - } + if (!self.base.isRelocatable()) { + const seg_id = self.sections.items(.segment_id)[sect_index]; + const seg = &self.segments.items[seg_id]; + seg.fileoff = sect.offset; - seg.vmsize = needed_size; + if (!sect.isZerofill()) { + seg.filesize = needed_size; + } + + const mem_capacity = self.allocatedVirtualSize(seg.vmaddr); + if (needed_size > mem_capacity) { + var err = try self.addErrorWithNotes(2); + try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{ + seg_id, + seg.segName(), + }); + try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); + try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); + } + + seg.vmsize = needed_size; + } } pub fn getTarget(self: MachO) std.Target { diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index 0b3df180a5..ec8b1b75e6 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -12,7 +12,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u if (module_obj_path) |path| try positionals.append(.{ .path = path }); - if (positionals.items.len == 1) { + if (macho_file.getZigObject() == null and positionals.items.len == 1) { // Instead of invoking a full-blown `-r` mode on the input which sadly will strip all // debug info segments/sections (this is apparently by design by Apple), we copy // the *only* input file over. @@ -26,6 +26,11 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u return; } + if (macho_file.getZigObject() != null and positionals.items.len > 0) { + try macho_file.reportUnexpectedError("TODO: build-obj for ZigObject and input object files", .{}); + return error.FlushFailure; + } + for (positionals.items) |obj| { macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { error.MalformedObject, @@ -46,8 +51,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u try macho_file.addUndefinedGlobals(); try macho_file.resolveSymbols(); - markExports(macho_file); - claimUnresolved(macho_file); + try markExports(macho_file); + try claimUnresolved(macho_file); try initOutputSections(macho_file); try macho_file.sortSections(); try macho_file.addAtomsToSections(); @@ -109,8 +114,13 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u try writeHeader(macho_file, ncmds, sizeofcmds); } -fn markExports(macho_file: *MachO) void { - for (macho_file.objects.items) |index| { +fn markExports(macho_file: *MachO) error{OutOfMemory}!void { + var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); + defer objects.deinit(); + if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); + objects.appendSliceAssumeCapacity(macho_file.objects.items); + + for (objects.items) |index| { for (macho_file.getFile(index).?.getSymbols()) |sym_index| { const sym = macho_file.getSymbol(sym_index); const file = sym.getFile(macho_file) orelse continue; @@ -122,13 +132,22 @@ fn markExports(macho_file: *MachO) void { } } -fn claimUnresolved(macho_file: *MachO) void { - for (macho_file.objects.items) |index| { - const object = macho_file.getFile(index).?.object; +fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void { + var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); + defer objects.deinit(); + if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); + objects.appendSliceAssumeCapacity(macho_file.objects.items); - for (object.symbols.items, 0..) |sym_index, i| { + for (objects.items) |index| { + const file = macho_file.getFile(index).?; + + for (file.getSymbols(), 0..) |sym_index, i| { const nlist_idx = @as(Symbol.Index, @intCast(i)); - const nlist = object.symtab.items(.nlist)[nlist_idx]; + const nlist = switch (file) { + .object => |x| x.symtab.items(.nlist)[nlist_idx], + .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], + else => unreachable, + }; if (!nlist.ext()) continue; if (!nlist.undf()) continue; @@ -290,7 +309,7 @@ fn writeAtoms(macho_file: *MachO) !void { assert(atom.flags.alive); const off = math.cast(usize, atom.value - header.addr) orelse return error.Overflow; const atom_size = math.cast(usize, atom.size) orelse return error.Overflow; - try atom.getFile(macho_file).object.getAtomData(atom.*, code[off..][0..atom_size]); + try atom.getData(macho_file, code[off..][0..atom_size]); try atom.writeRelocs(macho_file, code[off..][0..atom_size], &relocs); } @@ -501,5 +520,6 @@ const trace = @import("../../tracy.zig").trace; const Atom = @import("Atom.zig"); const Compilation = @import("../../Compilation.zig"); +const File = @import("file.zig").File; const MachO = @import("../MachO.zig"); const Symbol = @import("Symbol.zig"); |
