authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-12 10:46:56+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:39+01:00
log10a5536a7c9f9545c292f8e863a7cecd89e9ee54
tree5b8e398a33144ecae930d7f05162d20b118e90f3
parentc2a0a882842d8cc9d0ad29781fe1e13c1a5880cd

macho: re-instate build-obj codepath


4 files changed, 81 insertions(+), 56 deletions(-)

src/link/MachO.zig+6-14
......@@ -369,7 +369,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
369369 if (comp.verbose_link) try self.dumpArgv(comp);
370370
371371 if (self.base.isStaticLib()) return self.flushStaticLib(comp, module_obj_path);
372 if (self.base.isObject()) return self.flushObject(comp, module_obj_path);
372 if (self.base.isObject()) return relocatable.flush(self, comp, module_obj_path);
373373
374374 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
375375 defer positionals.deinit();
......@@ -483,7 +483,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
483483 self.getFile(index).?.dylib.umbrella = index;
484484 }
485485
486 // try self.parseDependentDylibs();
486 // TODO: try self.parseDependentDylibs();
487487
488488 for (self.dylibs.items) |index| {
489489 const dylib = self.getFile(index).?.dylib;
......@@ -783,16 +783,6 @@ fn flushStaticLib(self: *MachO, comp: *Compilation, module_obj_path: ?[]const u8
783783 return error.FlushFailure;
784784}
785785
786fn flushObject(self: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
787 _ = comp;
788 _ = module_obj_path;
789
790 var err = try self.addErrorWithNotes(0);
791 try err.addMsg(self, "TODO implement flushObject", .{});
792
793 return error.FlushFailure;
794}
795
796786pub fn resolveLibSystem(
797787 self: *MachO,
798788 arena: Allocator,
......@@ -890,7 +880,7 @@ const ParseError = error{
890880 UnknownFileType,
891881} || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError || tapi.TapiError;
892882
893fn parsePositional(self: *MachO, path: []const u8, must_link: bool) ParseError!void {
883pub fn parsePositional(self: *MachO, path: []const u8, must_link: bool) ParseError!void {
894884 const tracy = trace(@src());
895885 defer tracy.end();
896886 if (try Object.isObject(path)) {
......@@ -1083,6 +1073,7 @@ fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!File.Index
10831073// return false;
10841074// }
10851075
1076// TODO:
10861077// fn parseDependentDylibs(
10871078// self: *MachO
10881079// ) !void {
......@@ -1212,7 +1203,7 @@ fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!File.Index
12121203// }
12131204// }
12141205
1215fn addUndefinedGlobals(self: *MachO) !void {
1206pub fn addUndefinedGlobals(self: *MachO) !void {
12161207 const gpa = self.base.comp.gpa;
12171208
12181209 try self.undefined_symbols.ensureUnusedCapacity(gpa, self.base.comp.force_undefined_symbols.keys().len);
......@@ -4033,6 +4024,7 @@ const fat = @import("MachO/fat.zig");
40334024const link = @import("../link.zig");
40344025const llvm_backend = @import("../codegen/llvm.zig");
40354026const load_commands = @import("MachO/load_commands.zig");
4027const relocatable = @import("MachO/relocatable.zig");
40364028const tapi = @import("tapi.zig");
40374029const target_util = @import("../target.zig");
40384030const thunks = @import("MachO/thunks.zig");
src/link/MachO/Atom.zig+2-2
......@@ -682,7 +682,7 @@ const x86_64 = struct {
682682};
683683
684684pub fn calcNumRelocs(self: Atom, macho_file: *MachO) u32 {
685 switch (macho_file.options.cpu_arch.?) {
685 switch (macho_file.getTarget().cpu.arch) {
686686 .aarch64 => {
687687 var nreloc: u32 = 0;
688688 for (self.getRelocs(macho_file)) |rel| {
......@@ -705,7 +705,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: *std.Arra
705705 const tracy = trace(@src());
706706 defer tracy.end();
707707
708 const cpu_arch = macho_file.options.cpu_arch.?;
708 const cpu_arch = macho_file.getTarget().cpu.arch;
709709 const relocs = self.getRelocs(macho_file);
710710 const sect = macho_file.sections.items(.header)[self.out_n_sect];
711711 var stream = std.io.fixedBufferStream(code);
src/link/MachO/load_commands.zig+6-9
......@@ -98,7 +98,6 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 {
9898}
9999
100100pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
101 const options = &macho_file.options;
102101 var sizeofcmds: u64 = 0;
103102
104103 // LC_SEGMENT_64
......@@ -116,14 +115,12 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
116115 // LC_DYSYMTAB
117116 sizeofcmds += @sizeOf(macho.dysymtab_command);
118117
119 if (options.platform) |platform| {
120 if (platform.isBuildVersionCompatible()) {
121 // LC_BUILD_VERSION
122 sizeofcmds += @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
123 } else {
124 // LC_VERSION_MIN_*
125 sizeofcmds += @sizeOf(macho.version_min_command);
126 }
118 if (macho_file.platform.isBuildVersionCompatible()) {
119 // LC_BUILD_VERSION
120 sizeofcmds += @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
121 } else {
122 // LC_VERSION_MIN_*
123 sizeofcmds += @sizeOf(macho.version_min_command);
127124 }
128125
129126 return @as(u32, @intCast(sizeofcmds));
src/link/MachO/relocatable.zig+67-31
......@@ -1,4 +1,37 @@
1pub fn flush(macho_file: *MachO) !void {
1pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
2 const gpa = macho_file.base.comp.gpa;
3
4 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
5 defer positionals.deinit();
6 try positionals.ensureUnusedCapacity(comp.objects.len);
7 positionals.appendSliceAssumeCapacity(comp.objects);
8
9 for (comp.c_object_table.keys()) |key| {
10 try positionals.append(.{ .path = key.status.success.object_path });
11 }
12
13 if (module_obj_path) |path| try positionals.append(.{ .path = path });
14
15 for (positionals.items) |obj| {
16 macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
17 error.MalformedObject,
18 error.MalformedArchive,
19 error.InvalidCpuArch,
20 error.InvalidTarget,
21 => continue, // already reported
22 error.UnknownFileType => try macho_file.reportParseError(obj.path, "unknown file type for an object file", .{}),
23 else => |e| try macho_file.reportParseError(
24 obj.path,
25 "unexpected error: parsing input file failed with error {s}",
26 .{@errorName(e)},
27 ),
28 };
29 }
30
31 if (comp.link_errors.items.len > 0) return error.FlushFailure;
32
33 try macho_file.addUndefinedGlobals();
34 try macho_file.resolveSymbols();
235 markExports(macho_file);
336 claimUnresolved(macho_file);
437 try initOutputSections(macho_file);
......@@ -9,7 +42,7 @@ pub fn flush(macho_file: *MachO) !void {
942 {
1043 // For relocatable, we only ever need a single segment so create it now.
1144 const prot: macho.vm_prot_t = macho.PROT.READ | macho.PROT.WRITE | macho.PROT.EXEC;
12 try macho_file.segments.append(macho_file.base.allocator, .{
45 try macho_file.segments.append(gpa, .{
1346 .cmdsize = @sizeOf(macho.segment_command_64),
1447 .segname = MachO.makeStaticString(""),
1548 .maxprot = prot,
......@@ -128,17 +161,20 @@ fn initOutputSections(macho_file: *MachO) !void {
128161}
129162
130163fn calcSectionSizes(macho_file: *MachO) !void {
164 const tracy = trace(@src());
165 defer tracy.end();
166
131167 const slice = macho_file.sections.slice();
132168 for (slice.items(.header), slice.items(.atoms)) |*header, atoms| {
133169 if (atoms.items.len == 0) continue;
134170 for (atoms.items) |atom_index| {
135171 const atom = macho_file.getAtom(atom_index).?;
136 const atom_alignment = try math.powi(u32, 2, atom.alignment);
172 const atom_alignment = atom.alignment.toByteUnits(1);
137173 const offset = mem.alignForward(u64, header.size, atom_alignment);
138174 const padding = offset - header.size;
139175 atom.value = offset;
140176 header.size += padding + atom.size;
141 header.@"align" = @max(header.@"align", atom.alignment);
177 header.@"align" = @max(header.@"align", atom.alignment.toLog2Units());
142178 header.nreloc += atom.calcNumRelocs(macho_file);
143179 }
144180 }
......@@ -218,8 +254,8 @@ fn writeAtoms(macho_file: *MachO) !void {
218254 const tracy = trace(@src());
219255 defer tracy.end();
220256
221 const gpa = macho_file.base.allocator;
222 const cpu_arch = macho_file.options.cpu_arch.?;
257 const gpa = macho_file.base.comp.gpa;
258 const cpu_arch = macho_file.getTarget().cpu.arch;
223259 const slice = macho_file.sections.slice();
224260
225261 for (slice.items(.header), slice.items(.atoms)) |header, atoms| {
......@@ -247,14 +283,14 @@ fn writeAtoms(macho_file: *MachO) !void {
247283 mem.sort(macho.relocation_info, relocs.items, {}, sortReloc);
248284
249285 // TODO scattered writes?
250 try macho_file.base.file.pwriteAll(code, header.offset);
251 try macho_file.base.file.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
286 try macho_file.base.file.?.pwriteAll(code, header.offset);
287 try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
252288 }
253289}
254290
255291fn writeCompactUnwind(macho_file: *MachO) !void {
256292 const sect_index = macho_file.unwind_info_sect_index orelse return;
257 const gpa = macho_file.base.allocator;
293 const gpa = macho_file.base.comp.gpa;
258294 const header = macho_file.sections.items(.header)[sect_index];
259295
260296 const nrecs = @divExact(header.size, @sizeOf(macho.compact_unwind_entry));
......@@ -301,7 +337,7 @@ fn writeCompactUnwind(macho_file: *MachO) !void {
301337 const atom = rec.getAtom(macho_file);
302338 const addr = rec.getAtomAddress(macho_file);
303339 out.rangeStart = addr;
304 var reloc = addReloc(offset, macho_file.options.cpu_arch.?);
340 var reloc = addReloc(offset, macho_file.getTarget().cpu.arch);
305341 reloc.r_symbolnum = atom.out_n_sect + 1;
306342 relocs.appendAssumeCapacity(reloc);
307343 }
......@@ -309,7 +345,7 @@ fn writeCompactUnwind(macho_file: *MachO) !void {
309345 // Personality function
310346 if (rec.getPersonality(macho_file)) |sym| {
311347 const r_symbolnum = math.cast(u24, sym.getOutputSymtabIndex(macho_file).?) orelse return error.Overflow;
312 var reloc = addReloc(offset + 16, macho_file.options.cpu_arch.?);
348 var reloc = addReloc(offset + 16, macho_file.getTarget().cpu.arch);
313349 reloc.r_symbolnum = r_symbolnum;
314350 reloc.r_extern = 1;
315351 relocs.appendAssumeCapacity(reloc);
......@@ -319,7 +355,7 @@ fn writeCompactUnwind(macho_file: *MachO) !void {
319355 if (rec.getLsdaAtom(macho_file)) |atom| {
320356 const addr = rec.getLsdaAddress(macho_file);
321357 out.lsda = addr;
322 var reloc = addReloc(offset + 24, macho_file.options.cpu_arch.?);
358 var reloc = addReloc(offset + 24, macho_file.getTarget().cpu.arch);
323359 reloc.r_symbolnum = atom.out_n_sect + 1;
324360 relocs.appendAssumeCapacity(reloc);
325361 }
......@@ -335,13 +371,13 @@ fn writeCompactUnwind(macho_file: *MachO) !void {
335371 mem.sort(macho.relocation_info, relocs.items, {}, sortReloc);
336372
337373 // TODO scattered writes?
338 try macho_file.base.file.pwriteAll(mem.sliceAsBytes(entries.items), header.offset);
339 try macho_file.base.file.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
374 try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(entries.items), header.offset);
375 try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
340376}
341377
342378fn writeEhFrame(macho_file: *MachO) !void {
343379 const sect_index = macho_file.eh_frame_sect_index orelse return;
344 const gpa = macho_file.base.allocator;
380 const gpa = macho_file.base.comp.gpa;
345381 const header = macho_file.sections.items(.header)[sect_index];
346382
347383 const code = try gpa.alloc(u8, header.size);
......@@ -356,12 +392,12 @@ fn writeEhFrame(macho_file: *MachO) !void {
356392 mem.sort(macho.relocation_info, relocs.items, {}, sortReloc);
357393
358394 // TODO scattered writes?
359 try macho_file.base.file.pwriteAll(code, header.offset);
360 try macho_file.base.file.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
395 try macho_file.base.file.?.pwriteAll(code, header.offset);
396 try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
361397}
362398
363399fn writeLoadCommands(macho_file: *MachO) !struct { usize, usize } {
364 const gpa = macho_file.base.allocator;
400 const gpa = macho_file.base.comp.gpa;
365401 const needed_size = load_commands.calcLoadCommandsSizeObject(macho_file);
366402 const buffer = try gpa.alloc(u8, needed_size);
367403 defer gpa.free(buffer);
......@@ -390,19 +426,17 @@ fn writeLoadCommands(macho_file: *MachO) !struct { usize, usize } {
390426 try writer.writeStruct(macho_file.dysymtab_cmd);
391427 ncmds += 1;
392428
393 if (macho_file.options.platform) |platform| {
394 if (platform.isBuildVersionCompatible()) {
395 try load_commands.writeBuildVersionLC(platform, macho_file.options.sdk_version, writer);
396 ncmds += 1;
397 } else {
398 try load_commands.writeVersionMinLC(platform, macho_file.options.sdk_version, writer);
399 ncmds += 1;
400 }
429 if (macho_file.platform.isBuildVersionCompatible()) {
430 try load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, writer);
431 ncmds += 1;
432 } else {
433 try load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, writer);
434 ncmds += 1;
401435 }
402436
403437 assert(cwriter.bytes_written == needed_size);
404438
405 try macho_file.base.file.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
439 try macho_file.base.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
406440
407441 return .{ ncmds, buffer.len };
408442}
......@@ -419,7 +453,7 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
419453 header.flags |= macho.MH_SUBSECTIONS_VIA_SYMBOLS;
420454 }
421455
422 switch (macho_file.options.cpu_arch.?) {
456 switch (macho_file.getTarget().cpu.arch) {
423457 .aarch64 => {
424458 header.cputype = macho.CPU_TYPE_ARM64;
425459 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
......@@ -434,19 +468,21 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
434468 header.ncmds = @intCast(ncmds);
435469 header.sizeofcmds = @intCast(sizeofcmds);
436470
437 try macho_file.base.file.pwriteAll(mem.asBytes(&header), 0);
471 try macho_file.base.file.?.pwriteAll(mem.asBytes(&header), 0);
438472}
439473
440474const assert = std.debug.assert;
441475const eh_frame = @import("eh_frame.zig");
476const link = @import("../../link.zig");
442477const load_commands = @import("load_commands.zig");
443478const macho = std.macho;
444479const math = std.math;
445480const mem = std.mem;
446const state_log = std.log.scoped(.state);
481const state_log = std.log.scoped(.link_state);
447482const std = @import("std");
448const trace = @import("../tracy.zig").trace;
483const trace = @import("../../tracy.zig").trace;
449484
450485const Atom = @import("Atom.zig");
486const Compilation = @import("../../Compilation.zig");
451487const MachO = @import("../MachO.zig");
452488const Symbol = @import("Symbol.zig");