authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-10 19:39:40+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:38+01:00
log0c171afab003f7d7dfde8491141e00cac7e99c21
tree4873f24bd6468489045beada751540f82c5d956f
parent7588eeccea02b155f934a453cc47d8641686ab22

macho: parse an input object file!


8 files changed, 797 insertions(+), 431 deletions(-)

src/link/MachO.zig+630-305
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1base: File,1base: link.File,
22
3/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.3/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
4llvm_object: ?*LlvmObject = null,4llvm_object: ?*LlvmObject = null,
...@@ -6,6 +6,27 @@ llvm_object: ?*LlvmObject = null,...@@ -6,6 +6,27 @@ llvm_object: ?*LlvmObject = null,
6/// Debug symbols bundle (or dSym).6/// Debug symbols bundle (or dSym).
7d_sym: ?DebugSymbols = null,7d_sym: ?DebugSymbols = null,
88
9/// A list of all input files.
10/// Index of each input file also encodes the priority or precedence of one input file
11/// over another.
12files: std.MultiArrayList(File.Entry) = .{},
13internal_object: ?File.Index = null,
14objects: std.ArrayListUnmanaged(File.Index) = .{},
15dylibs: std.ArrayListUnmanaged(File.Index) = .{},
16
17segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},
18sections: std.MultiArrayList(Section) = .{},
19
20symbols: std.ArrayListUnmanaged(Symbol) = .{},
21symbols_extra: std.ArrayListUnmanaged(u32) = .{},
22globals: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
23/// This table will be populated after `scanRelocs` has run.
24/// Key is symbol index.
25undefs: std.AutoHashMapUnmanaged(Symbol.Index, std.ArrayListUnmanaged(Atom.Index)) = .{},
26/// Global symbols we need to resolve for the link to succeed.
27undefined_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
28boundary_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
29
9dyld_info_cmd: macho.dyld_info_command = .{},30dyld_info_cmd: macho.dyld_info_command = .{},
10symtab_cmd: macho.symtab_command = .{},31symtab_cmd: macho.symtab_command = .{},
11dysymtab_cmd: macho.dysymtab_command = .{},32dysymtab_cmd: macho.dysymtab_command = .{},
...@@ -14,36 +35,46 @@ data_in_code_cmd: macho.linkedit_data_command = .{ .cmd = .DATA_IN_CODE },...@@ -14,36 +35,46 @@ data_in_code_cmd: macho.linkedit_data_command = .{ .cmd = .DATA_IN_CODE },
14uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },35uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },
15codesig_cmd: macho.linkedit_data_command = .{ .cmd = .CODE_SIGNATURE },36codesig_cmd: macho.linkedit_data_command = .{ .cmd = .CODE_SIGNATURE },
1637
17segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},38pagezero_seg_index: ?u8 = null,
18sections: std.MultiArrayList(Section) = .{},39text_seg_index: ?u8 = null,
1940linkedit_seg_index: ?u8 = null,
20pagezero_segment_cmd_index: ?u8 = null,41data_sect_index: ?u8 = null,
21header_segment_cmd_index: ?u8 = null,42got_sect_index: ?u8 = null,
22text_segment_cmd_index: ?u8 = null,43stubs_sect_index: ?u8 = null,
23data_const_segment_cmd_index: ?u8 = null,44stubs_helper_sect_index: ?u8 = null,
24data_segment_cmd_index: ?u8 = null,45la_symbol_ptr_sect_index: ?u8 = null,
25linkedit_segment_cmd_index: ?u8 = null,46tlv_ptr_sect_index: ?u8 = null,
2647eh_frame_sect_index: ?u8 = null,
27text_section_index: ?u8 = null,48unwind_info_sect_index: ?u8 = null,
28data_const_section_index: ?u8 = null,49objc_stubs_sect_index: ?u8 = null,
29data_section_index: ?u8 = null,
30bss_section_index: ?u8 = null,
31thread_vars_section_index: ?u8 = null,
32thread_data_section_index: ?u8 = null,
33thread_bss_section_index: ?u8 = null,
34eh_frame_section_index: ?u8 = null,
35unwind_info_section_index: ?u8 = null,
36stubs_section_index: ?u8 = null,
37stub_helper_section_index: ?u8 = null,
38got_section_index: ?u8 = null,
39la_symbol_ptr_section_index: ?u8 = null,
40tlv_ptr_section_index: ?u8 = null,
41
42strtab: StringTable = .{},
4350
44/// List of atoms that are either synthetic or map directly to the Zig source program.51/// List of atoms that are either synthetic or map directly to the Zig source program.
45atoms: std.ArrayListUnmanaged(Atom) = .{},52atoms: std.ArrayListUnmanaged(Atom) = .{},
4653thunks: std.ArrayListUnmanaged(Thunk) = .{},
54unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record) = .{},
55
56/// String interning table
57strings: StringTable = .{},
58
59/// Output synthetic sections
60symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
61strtab: std.ArrayListUnmanaged(u8) = .{},
62indsymtab: Indsymtab = .{},
63got: GotSection = .{},
64stubs: StubsSection = .{},
65stubs_helper: StubsHelperSection = .{},
66objc_stubs: ObjcStubsSection = .{},
67la_symbol_ptr: LaSymbolPtrSection = .{},
68tlv_ptr: TlvPtrSection = .{},
69rebase: RebaseSection = .{},
70bind: BindSection = .{},
71weak_bind: WeakBindSection = .{},
72lazy_bind: LazyBindSection = .{},
73export_trie: ExportTrieSection = .{},
74unwind_info: UnwindInfo = .{},
75
76/// Options
77/// SDK layout
47sdk_layout: ?SdkLayout,78sdk_layout: ?SdkLayout,
48/// Size of the __PAGEZERO segment.79/// Size of the __PAGEZERO segment.
49pagezero_vmsize: ?u64,80pagezero_vmsize: ?u64,
...@@ -62,6 +93,8 @@ entitlements: ?[]const u8,...@@ -62,6 +93,8 @@ entitlements: ?[]const u8,
62compatibility_version: ?std.SemanticVersion,93compatibility_version: ?std.SemanticVersion,
63/// Entry name94/// Entry name
64entry_name: ?[]const u8,95entry_name: ?[]const u8,
96platform: Platform,
97sdk_version: ?std.SemanticVersion,
6598
66/// Hot-code swapping state.99/// Hot-code swapping state.
67hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},100hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},
...@@ -144,6 +177,8 @@ pub fn createEmpty(...@@ -144,6 +177,8 @@ pub fn createEmpty(
144 .enabled => default_entry_symbol_name,177 .enabled => default_entry_symbol_name,
145 .named => |name| name,178 .named => |name| name,
146 },179 },
180 .platform = Platform.fromTarget(target),
181 .sdk_version = if (options.darwin_sdk_layout) |layout| inferSdkVersion(comp, layout) else null,
147 };182 };
148 if (use_llvm and comp.config.have_zcu) {183 if (use_llvm and comp.config.have_zcu) {
149 self.llvm_object = try LlvmObject.create(arena, comp);184 self.llvm_object = try LlvmObject.create(arena, comp);
...@@ -156,9 +191,16 @@ pub fn createEmpty(...@@ -156,9 +191,16 @@ pub fn createEmpty(
156 .mode = link.File.determineMode(false, output_mode, link_mode),191 .mode = link.File.determineMode(false, output_mode, link_mode),
157 });192 });
158193
159 // Index 0 is always a null symbol.194 // Append null file
160 // try self.locals.append(gpa, null_sym);195 try self.files.append(gpa, .null);
161 try self.strtab.buffer.append(gpa, 0);196 // Atom at index 0 is reserved as null atom
197 try self.atoms.append(gpa, .{});
198 // Append empty string to string tables
199 try self.strings.buffer.append(gpa, 0);
200 try self.strtab.append(gpa, 0);
201 // Append null symbols
202 try self.symbols.append(gpa, .{});
203 try self.symbols_extra.append(gpa, 0);
162204
163 // TODO: init205 // TODO: init
164206
...@@ -208,8 +250,71 @@ pub fn open(...@@ -208,8 +250,71 @@ pub fn open(
208 return createEmpty(arena, comp, emit, options);250 return createEmpty(arena, comp, emit, options);
209}251}
210252
253pub fn deinit(self: *MachO) void {
254 const gpa = self.base.comp.gpa;
255
256 if (self.llvm_object) |llvm_object| llvm_object.deinit();
257
258 if (self.d_sym) |*d_sym| {
259 d_sym.deinit();
260 }
261
262 for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) {
263 .null => {},
264 .internal => data.internal.deinit(gpa),
265 .object => data.object.deinit(gpa),
266 .dylib => data.dylib.deinit(gpa),
267 };
268 self.files.deinit(gpa);
269 self.objects.deinit(gpa);
270 self.dylibs.deinit(gpa);
271
272 self.segments.deinit(gpa);
273 for (self.sections.items(.atoms)) |*list| {
274 list.deinit(gpa);
275 }
276 self.sections.deinit(gpa);
277
278 self.symbols.deinit(gpa);
279 self.symbols_extra.deinit(gpa);
280 self.globals.deinit(gpa);
281 {
282 var it = self.undefs.iterator();
283 while (it.next()) |entry| {
284 entry.value_ptr.deinit(gpa);
285 }
286 self.undefs.deinit(gpa);
287 }
288 self.undefined_symbols.deinit(gpa);
289 self.boundary_symbols.deinit(gpa);
290
291 self.strings.deinit(gpa);
292 self.symtab.deinit(gpa);
293 self.strtab.deinit(gpa);
294 self.got.deinit(gpa);
295 self.stubs.deinit(gpa);
296 self.objc_stubs.deinit(gpa);
297 self.tlv_ptr.deinit(gpa);
298 self.rebase.deinit(gpa);
299 self.bind.deinit(gpa);
300 self.weak_bind.deinit(gpa);
301 self.lazy_bind.deinit(gpa);
302 self.export_trie.deinit(gpa);
303 self.unwind_info.deinit(gpa);
304
305 self.atoms.deinit(gpa);
306 for (self.thunks.items) |*thunk| {
307 thunk.deinit(gpa);
308 }
309 self.thunks.deinit(gpa);
310 self.unwind_records.deinit(gpa);
311}
312
211pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {313pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
212 // TODO: what else should we do in flush? Is it actually needed at all?314 // TODO: I think this is just a temp and can be removed once we can emit static archives
315 if (self.base.isStaticLib() and build_options.have_llvm) {
316 return self.base.linkAsArchive(arena, prog_node);
317 }
213 try self.flushModule(arena, prog_node);318 try self.flushModule(arena, prog_node);
214}319}
215320
...@@ -219,10 +324,11 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -219,10 +324,11 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
219324
220 const comp = self.base.comp;325 const comp = self.base.comp;
221 const gpa = comp.gpa;326 const gpa = comp.gpa;
222 _ = gpa;
223327
224 if (self.llvm_object) |llvm_object| {328 if (self.llvm_object) |llvm_object| {
225 try self.base.emitLlvmObject(arena, llvm_object, prog_node);329 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
330 // TODO: I think this is just a temp and can be removed once we can emit static archives
331 if (self.base.isStaticLib() and build_options.have_llvm) return;
226 }332 }
227333
228 var sub_prog_node = prog_node.start("MachO Flush", 0);334 var sub_prog_node = prog_node.start("MachO Flush", 0);
...@@ -240,11 +346,55 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -240,11 +346,55 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
240 break :blk path;346 break :blk path;
241 }347 }
242 } else null;348 } else null;
243 _ = module_obj_path;
244349
245 // --verbose-link350 // --verbose-link
246 if (comp.verbose_link) try self.dumpArgv(comp);351 if (comp.verbose_link) try self.dumpArgv(comp);
247352
353 if (self.base.isStaticLib()) return self.flushStaticLib(comp, module_obj_path);
354 if (self.base.isObject()) return self.flushObject(comp, module_obj_path);
355
356 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
357 defer positionals.deinit();
358
359 try positionals.ensureUnusedCapacity(comp.objects.len);
360 positionals.appendSliceAssumeCapacity(comp.objects);
361
362 // This is a set of object files emitted by clang in a single `build-exe` invocation.
363 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
364 // in this set.
365 try positionals.ensureUnusedCapacity(comp.c_object_table.keys().len);
366 for (comp.c_object_table.keys()) |key| {
367 positionals.appendAssumeCapacity(.{ .path = key.status.success.object_path });
368 }
369
370 if (module_obj_path) |path| try positionals.append(.{ .path = path });
371
372 // rpaths
373 var rpath_table = std.StringArrayHashMap(void).init(gpa);
374 defer rpath_table.deinit();
375 try rpath_table.ensureUnusedCapacity(self.base.rpath_list.len);
376
377 for (self.base.rpath_list) |rpath| {
378 _ = rpath_table.putAssumeCapacity(rpath, {});
379 }
380
381 for (positionals.items) |obj| {
382 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
383 error.MalformedObject,
384 error.MalformedArchive,
385 error.InvalidCpuArch,
386 error.InvalidTarget,
387 => continue, // already reported
388 else => |e| try self.reportParseError(
389 obj.path,
390 "unexpected error: parsing input file failed with error {s}",
391 .{@errorName(e)},
392 ),
393 };
394 }
395
396 state_log.debug("{}", .{self.dumpState()});
397
248 @panic("TODO");398 @panic("TODO");
249}399}
250400
...@@ -255,7 +405,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {...@@ -255,7 +405,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
255 defer arena_allocator.deinit();405 defer arena_allocator.deinit();
256 const arena = arena_allocator.allocator();406 const arena = arena_allocator.allocator();
257407
258 const target = self.base.comp.root_mod.resolved_target.result;
259 const directory = self.base.emit.directory;408 const directory = self.base.emit.directory;
260 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});409 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
261 const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {410 const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
...@@ -309,18 +458,14 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {...@@ -309,18 +458,14 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
309 }458 }
310 }459 }
311460
312 {461 try argv.append("-platform_version");
313 const platform = Platform.fromTarget(target);462 try argv.append(@tagName(self.platform.os_tag));
314 try argv.append("-platform_version");463 try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version}));
315 try argv.append(@tagName(platform.os_tag));464
316 try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version}));465 if (self.sdk_version) |ver| {
317466 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));
318 const sdk_version: ?std.SemanticVersion = self.inferSdkVersion();467 } else {
319 if (sdk_version) |ver| {468 try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version}));
320 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));
321 } else {
322 try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version}));
323 }
324 }469 }
325470
326 if (comp.sysroot) |syslibroot| {471 if (comp.sysroot) |syslibroot| {
...@@ -419,6 +564,26 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {...@@ -419,6 +564,26 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
419 Compilation.dump_argv(argv.items);564 Compilation.dump_argv(argv.items);
420}565}
421566
567fn flushStaticLib(self: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
568 _ = comp;
569 _ = module_obj_path;
570
571 var err = try self.addErrorWithNotes(0);
572 try err.addMsg(self, "TODO implement flushStaticLib", .{});
573
574 return error.FlushFailure;
575}
576
577fn flushObject(self: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
578 _ = comp;
579 _ = module_obj_path;
580
581 var err = try self.addErrorWithNotes(0);
582 try err.addMsg(self, "TODO implement flushObject", .{});
583
584 return error.FlushFailure;
585}
586
422/// XNU starting with Big Sur running on arm64 is caching inodes of running binaries.587/// XNU starting with Big Sur running on arm64 is caching inodes of running binaries.
423/// Any change to the binary will effectively invalidate the kernel's cache588/// Any change to the binary will effectively invalidate the kernel's cache
424/// resulting in a SIGKILL on each subsequent run. Since when doing incremental589/// resulting in a SIGKILL on each subsequent run. Since when doing incremental
...@@ -518,132 +683,60 @@ fn accessLibPath(...@@ -518,132 +683,60 @@ fn accessLibPath(
518}683}
519684
520const ParseError = error{685const ParseError = error{
521 UnknownFileType,686 MalformedObject,
687 MalformedArchive,
688 NotLibStub,
689 InvalidCpuArch,
522 InvalidTarget,690 InvalidTarget,
523 InvalidTargetFatLibrary,691 InvalidTargetFatLibrary,
524 DylibAlreadyExists,
525 IncompatibleDylibVersion,692 IncompatibleDylibVersion,
526 OutOfMemory,693 OutOfMemory,
527 Overflow,694 Overflow,
528 InputOutput,695 InputOutput,
529 MalformedArchive,
530 NotLibStub,
531 EndOfStream,696 EndOfStream,
532 FileSystem,697 FileSystem,
533 NotSupported,698 NotSupported,
534} || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError || tapi.TapiError;699} || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError || tapi.TapiError;
535700
536pub fn parsePositional(701fn parsePositional(self: *MachO, path: []const u8, must_link: bool) ParseError!void {
537 self: *MachO,
538 file: std.fs.File,
539 path: []const u8,
540 must_link: bool,
541 dependent_libs: anytype,
542 ctx: *ParseErrorCtx,
543) ParseError!void {
544 const tracy = trace(@src());702 const tracy = trace(@src());
545 defer tracy.end();703 defer tracy.end();
704 if (try Object.isObject(path)) {
705 try self.parseObject(path);
706 } else {
707 try self.parseLibrary(.{ .path = path }, must_link);
708 }
709}
546710
711fn parseLibrary(self: *MachO, lib: SystemLib, must_link: bool) ParseError!void {
547 _ = self;712 _ = self;
548 _ = file;713 _ = lib;
549 _ = path;
550 _ = must_link;714 _ = must_link;
551 _ = dependent_libs;
552 _ = ctx;
553}715}
554716
555pub fn deinit(self: *MachO) void {717fn parseObject(self: *MachO, path: []const u8) ParseError!void {
556 const gpa = self.base.comp.gpa;718 const tracy = trace(@src());
557719 defer tracy.end();
558 if (self.llvm_object) |llvm_object| llvm_object.deinit();
559
560 if (self.d_sym) |*d_sym| {
561 d_sym.deinit();
562 }
563
564 self.strtab.deinit(gpa);
565
566 self.segments.deinit(gpa);
567
568 for (self.sections.items(.free_list)) |*list| {
569 list.deinit(gpa);
570 }
571 self.sections.deinit(gpa);
572}
573720
574fn freeAtom(self: *MachO, atom_index: Atom.Index) void {
575 const gpa = self.base.comp.gpa;721 const gpa = self.base.comp.gpa;
576 log.debug("freeAtom {d}", .{atom_index});722 const file = try std.fs.cwd().openFile(path, .{});
577723 defer file.close();
578 // Remove any relocs and base relocs associated with this Atom724 const mtime: u64 = mtime: {
579 Atom.freeRelocations(self, atom_index);725 const stat = file.stat() catch break :mtime 0;
580726 break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000)));
581 const atom = self.getAtom(atom_index);727 };
582 const sect_id = atom.getSymbol(self).n_sect - 1;728 const data = try file.readToEndAlloc(gpa, std.math.maxInt(u32));
583 const free_list = &self.sections.items(.free_list)[sect_id];729 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
584 var already_have_free_list_node = false;730 self.files.set(index, .{ .object = .{
585 {731 .path = try gpa.dupe(u8, path),
586 var i: usize = 0;732 .mtime = mtime,
587 // TODO turn free_list into a hash map733 .data = data,
588 while (i < free_list.items.len) {734 .index = index,
589 if (free_list.items[i] == atom_index) {735 } });
590 _ = free_list.swapRemove(i);736 try self.objects.append(gpa, index);
591 continue;737
592 }738 const object = self.getFile(index).?.object;
593 if (free_list.items[i] == atom.prev_index) {739 try object.parse(self);
594 already_have_free_list_node = true;
595 }
596 i += 1;
597 }
598 }
599
600 const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id];
601 if (maybe_last_atom_index.*) |last_atom_index| {
602 if (last_atom_index == atom_index) {
603 if (atom.prev_index) |prev_index| {
604 // TODO shrink the section size here
605 maybe_last_atom_index.* = prev_index;
606 } else {
607 maybe_last_atom_index.* = null;
608 }
609 }
610 }
611
612 if (atom.prev_index) |prev_index| {
613 const prev = self.getAtomPtr(prev_index);
614 prev.next_index = atom.next_index;
615
616 if (!already_have_free_list_node and prev.*.freeListEligible(self)) {
617 // The free list is heuristics, it doesn't have to be perfect, so we can ignore
618 // the OOM here.
619 free_list.append(gpa, prev_index) catch {};
620 }
621 } else {
622 self.getAtomPtr(atom_index).prev_index = null;
623 }
624
625 if (atom.next_index) |next_index| {
626 self.getAtomPtr(next_index).prev_index = atom.prev_index;
627 } else {
628 self.getAtomPtr(atom_index).next_index = null;
629 }
630
631 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
632 const sym_index = atom.getSymbolIndex().?;
633
634 self.locals_free_list.append(gpa, sym_index) catch {};
635
636 // Try freeing GOT atom if this decl had one
637 self.got_table.freeEntry(gpa, .{ .sym_index = sym_index });
638
639 if (self.d_sym) |*d_sym| {
640 d_sym.swapRemoveRelocs(sym_index);
641 }
642
643 self.locals.items[sym_index].n_type = 0;
644 _ = self.atom_by_index_table.remove(sym_index);
645 log.debug(" adding local symbol index {d} to free list", .{sym_index});
646 self.getAtomPtr(atom_index).sym_index = 0;
647}740}
648741
649fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void {742fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void {
...@@ -716,7 +809,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)...@@ -716,7 +809,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex)
716809
717fn updateLazySymbolAtom(810fn updateLazySymbolAtom(
718 self: *MachO,811 self: *MachO,
719 sym: File.LazySymbol,812 sym: link.File.LazySymbol,
720 atom_index: Atom.Index,813 atom_index: Atom.Index,
721 section_index: u8,814 section_index: u8,
722) !void {815) !void {
...@@ -727,7 +820,7 @@ fn updateLazySymbolAtom(...@@ -727,7 +820,7 @@ fn updateLazySymbolAtom(
727 @panic("TODO updateLazySymbolAtom");820 @panic("TODO updateLazySymbolAtom");
728}821}
729822
730pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index {823pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: link.File.LazySymbol) !Atom.Index {
731 _ = self;824 _ = self;
732 _ = sym;825 _ = sym;
733 @panic("TODO getOrCreateAtomForLazySymbol");826 @panic("TODO getOrCreateAtomForLazySymbol");
...@@ -763,7 +856,7 @@ pub fn updateExports(...@@ -763,7 +856,7 @@ pub fn updateExports(
763 mod: *Module,856 mod: *Module,
764 exported: Module.Exported,857 exported: Module.Exported,
765 exports: []const *Module.Export,858 exports: []const *Module.Export,
766) File.UpdateExportsError!void {859) link.File.UpdateExportsError!void {
767 if (build_options.skip_non_native and builtin.object_format != .macho) {860 if (build_options.skip_non_native and builtin.object_format != .macho) {
768 @panic("Attempted to compile for object format that was disabled by build configuration");861 @panic("Attempted to compile for object format that was disabled by build configuration");
769 }862 }
...@@ -795,7 +888,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {...@@ -795,7 +888,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {
795 @panic("TODO freeDecl");888 @panic("TODO freeDecl");
796}889}
797890
798pub fn getDeclVAddr(self: *MachO, decl_index: InternPool.DeclIndex, reloc_info: File.RelocInfo) !u64 {891pub fn getDeclVAddr(self: *MachO, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
799 assert(self.llvm_object == null);892 assert(self.llvm_object == null);
800 _ = decl_index;893 _ = decl_index;
801 _ = reloc_info;894 _ = reloc_info;
...@@ -872,94 +965,224 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 {...@@ -872,94 +965,224 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 {
872 return start;965 return start;
873}966}
874967
968pub fn getTarget(self: MachO) std.Target {
969 return self.base.comp.root_mod.resolved_target.result;
970}
971
875pub fn makeStaticString(bytes: []const u8) [16]u8 {972pub fn makeStaticString(bytes: []const u8) [16]u8 {
876 var buf = [_]u8{0} ** 16;973 var buf = [_]u8{0} ** 16;
877 @memcpy(buf[0..bytes.len], bytes);974 @memcpy(buf[0..bytes.len], bytes);
878 return buf;975 return buf;
879}976}
880977
881pub const ParseErrorCtx = struct {978pub fn getFile(self: *MachO, index: File.Index) ?File {
882 arena_allocator: std.heap.ArenaAllocator,979 const tag = self.files.items(.tags)[index];
883 detected_dylib_id: struct {980 return switch (tag) {
884 parent: u16,981 .null => null,
885 required_version: u32,982 .internal => .{ .internal = &self.files.items(.data)[index].internal },
886 found_version: u32,983 .object => .{ .object = &self.files.items(.data)[index].object },
887 },984 .dylib => .{ .dylib = &self.files.items(.data)[index].dylib },
888 detected_targets: std.ArrayList([]const u8),985 };
986}
889987
890 pub fn init(gpa: Allocator) ParseErrorCtx {988pub fn getInternalObject(self: *MachO) ?*InternalObject {
891 return .{989 const index = self.internal_object orelse return null;
892 .arena_allocator = std.heap.ArenaAllocator.init(gpa),990 return self.getFile(index).?.internal;
893 .detected_dylib_id = undefined,991}
894 .detected_targets = std.ArrayList([]const u8).init(gpa),992
993pub fn addAtom(self: *MachO) error{OutOfMemory}!Atom.Index {
994 const index = @as(Atom.Index, @intCast(self.atoms.items.len));
995 const atom = try self.atoms.addOne(self.base.comp.gpa);
996 atom.* = .{};
997 return index;
998}
999
1000pub fn getAtom(self: *MachO, index: Atom.Index) ?*Atom {
1001 if (index == 0) return null;
1002 assert(index < self.atoms.items.len);
1003 return &self.atoms.items[index];
1004}
1005
1006pub fn addSymbol(self: *MachO) !Symbol.Index {
1007 const index = @as(Symbol.Index, @intCast(self.symbols.items.len));
1008 const symbol = try self.symbols.addOne(self.base.comp.gpa);
1009 symbol.* = .{};
1010 return index;
1011}
1012
1013pub fn getSymbol(self: *MachO, index: Symbol.Index) *Symbol {
1014 assert(index < self.symbols.items.len);
1015 return &self.symbols.items[index];
1016}
1017
1018pub fn addSymbolExtra(self: *MachO, extra: Symbol.Extra) !u32 {
1019 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1020 try self.symbols_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len);
1021 return self.addSymbolExtraAssumeCapacity(extra);
1022}
1023
1024pub fn addSymbolExtraAssumeCapacity(self: *MachO, extra: Symbol.Extra) u32 {
1025 const index = @as(u32, @intCast(self.symbols_extra.items.len));
1026 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1027 inline for (fields) |field| {
1028 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
1029 u32 => @field(extra, field.name),
1030 else => @compileError("bad field type"),
1031 });
1032 }
1033 return index;
1034}
1035
1036pub fn getSymbolExtra(self: MachO, index: u32) ?Symbol.Extra {
1037 if (index == 0) return null;
1038 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1039 var i: usize = index;
1040 var result: Symbol.Extra = undefined;
1041 inline for (fields) |field| {
1042 @field(result, field.name) = switch (field.type) {
1043 u32 => self.symbols_extra.items[i],
1044 else => @compileError("bad field type"),
895 };1045 };
1046 i += 1;
896 }1047 }
1048 return result;
1049}
8971050
898 pub fn deinit(ctx: *ParseErrorCtx) void {1051pub fn setSymbolExtra(self: *MachO, index: u32, extra: Symbol.Extra) void {
899 ctx.arena_allocator.deinit();1052 assert(index > 0);
900 ctx.detected_targets.deinit();1053 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1054 inline for (fields, 0..) |field, i| {
1055 self.symbols_extra.items[index + i] = switch (field.type) {
1056 u32 => @field(extra, field.name),
1057 else => @compileError("bad field type"),
1058 };
901 }1059 }
1060}
1061
1062const GetOrCreateGlobalResult = struct {
1063 found_existing: bool,
1064 index: Symbol.Index,
1065};
9021066
903 pub fn arena(ctx: *ParseErrorCtx) Allocator {1067pub fn getOrCreateGlobal(self: *MachO, off: u32) !GetOrCreateGlobalResult {
904 return ctx.arena_allocator.allocator();1068 const gpa = self.base.comp.gpa;
1069 const gop = try self.globals.getOrPut(gpa, off);
1070 if (!gop.found_existing) {
1071 const index = try self.addSymbol();
1072 const global = self.getSymbol(index);
1073 global.name = off;
1074 gop.value_ptr.* = index;
1075 }
1076 return .{
1077 .found_existing = gop.found_existing,
1078 .index = gop.value_ptr.*,
1079 };
1080}
1081
1082pub fn getGlobalByName(self: *MachO, name: []const u8) ?Symbol.Index {
1083 const off = self.strings.getOffset(name) orelse return null;
1084 return self.globals.get(off);
1085}
1086
1087pub fn addUnwindRecord(self: *MachO) !UnwindInfo.Record.Index {
1088 const index = @as(UnwindInfo.Record.Index, @intCast(self.unwind_records.items.len));
1089 const rec = try self.unwind_records.addOne(self.base.comp.gpa);
1090 rec.* = .{};
1091 return index;
1092}
1093
1094pub fn getUnwindRecord(self: *MachO, index: UnwindInfo.Record.Index) *UnwindInfo.Record {
1095 assert(index < self.unwind_records.items.len);
1096 return &self.unwind_records.items[index];
1097}
1098
1099pub fn addThunk(self: *MachO) !Thunk.Index {
1100 const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
1101 const thunk = try self.thunks.addOne(self.base.comp.gpa);
1102 thunk.* = .{};
1103 return index;
1104}
1105
1106pub fn getThunk(self: *MachO, index: Thunk.Index) *Thunk {
1107 assert(index < self.thunks.items.len);
1108 return &self.thunks.items[index];
1109}
1110
1111pub fn eatPrefix(path: []const u8, prefix: []const u8) ?[]const u8 {
1112 if (mem.startsWith(u8, path, prefix)) return path[prefix.len..];
1113 return null;
1114}
1115
1116const ErrorWithNotes = struct {
1117 /// Allocated index in comp.link_errors array.
1118 index: usize,
1119
1120 /// Next available note slot.
1121 note_slot: usize = 0,
1122
1123 pub fn addMsg(
1124 err: ErrorWithNotes,
1125 macho_file: *MachO,
1126 comptime format: []const u8,
1127 args: anytype,
1128 ) error{OutOfMemory}!void {
1129 const comp = macho_file.base.comp;
1130 const gpa = comp.gpa;
1131 const err_msg = &comp.link_errors.items[err.index];
1132 err_msg.msg = try std.fmt.allocPrint(gpa, format, args);
1133 }
1134
1135 pub fn addNote(
1136 err: *ErrorWithNotes,
1137 macho_file: *MachO,
1138 comptime format: []const u8,
1139 args: anytype,
1140 ) error{OutOfMemory}!void {
1141 const comp = macho_file.base.comp;
1142 const gpa = comp.gpa;
1143 const err_msg = &comp.link_errors.items[err.index];
1144 assert(err.note_slot < err_msg.notes.len);
1145 err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) };
1146 err.note_slot += 1;
905 }1147 }
906};1148};
9071149
908pub fn handleAndReportParseError(1150pub fn addErrorWithNotes(self: *MachO, note_count: usize) error{OutOfMemory}!ErrorWithNotes {
1151 const comp = self.base.comp;
1152 const gpa = comp.gpa;
1153 try comp.link_errors.ensureUnusedCapacity(gpa, 1);
1154 return self.addErrorWithNotesAssumeCapacity(note_count);
1155}
1156
1157fn addErrorWithNotesAssumeCapacity(self: *MachO, note_count: usize) error{OutOfMemory}!ErrorWithNotes {
1158 const comp = self.base.comp;
1159 const gpa = comp.gpa;
1160 const index = comp.link_errors.items.len;
1161 const err = comp.link_errors.addOneAssumeCapacity();
1162 err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) };
1163 return .{ .index = index };
1164}
1165
1166pub fn reportParseError(
909 self: *MachO,1167 self: *MachO,
910 path: []const u8,1168 path: []const u8,
911 err: ParseError,1169 comptime format: []const u8,
912 ctx: *const ParseErrorCtx,1170 args: anytype,
913) error{OutOfMemory}!void {1171) error{OutOfMemory}!void {
914 const target = self.base.comp.root_mod.resolved_target.result;1172 var err = try self.addErrorWithNotes(1);
915 const gpa = self.base.comp.gpa;1173 try err.addMsg(self, format, args);
916 const cpu_arch = target.cpu.arch;1174 try err.addNote(self, "while parsing {s}", .{path});
917 switch (err) {1175}
918 error.DylibAlreadyExists => {},
919 error.IncompatibleDylibVersion => {
920 const parent = &self.dylibs.items[ctx.detected_dylib_id.parent];
921 try self.reportDependencyError(
922 if (parent.id) |id| id.name else parent.path,
923 path,
924 "incompatible dylib version: expected at least '{}', but found '{}'",
925 .{
926 load_commands.appleVersionToSemanticVersion(ctx.detected_dylib_id.required_version),
927 load_commands.appleVersionToSemanticVersion(ctx.detected_dylib_id.found_version),
928 },
929 );
930 },
931 error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}),
932 error.InvalidTarget, error.InvalidTargetFatLibrary => {
933 var targets_string = std.ArrayList(u8).init(gpa);
934 defer targets_string.deinit();
935
936 if (ctx.detected_targets.items.len > 1) {
937 try targets_string.writer().writeAll("(");
938 for (ctx.detected_targets.items) |t| {
939 try targets_string.writer().print("{s}, ", .{t});
940 }
941 try targets_string.resize(targets_string.items.len - 2);
942 try targets_string.writer().writeAll(")");
943 } else {
944 try targets_string.writer().writeAll(ctx.detected_targets.items[0]);
945 }
9461176
947 switch (err) {1177pub fn reportParseError2(
948 error.InvalidTarget => try self.reportParseError(1178 self: *MachO,
949 path,1179 file_index: File.Index,
950 "invalid target: expected '{}', but found '{s}'",1180 comptime format: []const u8,
951 .{ Platform.fromTarget(target).fmtTarget(cpu_arch), targets_string.items },1181 args: anytype,
952 ),1182) error{OutOfMemory}!void {
953 error.InvalidTargetFatLibrary => try self.reportParseError(1183 var err = try self.addErrorWithNotes(1);
954 path,1184 try err.addMsg(self, format, args);
955 "invalid architecture in universal library: expected '{s}', but found '{s}'",1185 try err.addNote(self, "while parsing {}", .{self.getFile(file_index).?.fmtPath()});
956 .{ @tagName(cpu_arch), targets_string.items },
957 ),
958 else => unreachable,
959 }
960 },
961 else => |e| try self.reportParseError(path, "{s}: parsing object failed", .{@errorName(e)}),
962 }
963}1186}
9641187
965fn reportMissingLibraryError(1188fn reportMissingLibraryError(
...@@ -968,18 +1191,11 @@ fn reportMissingLibraryError(...@@ -968,18 +1191,11 @@ fn reportMissingLibraryError(
968 comptime format: []const u8,1191 comptime format: []const u8,
969 args: anytype,1192 args: anytype,
970) error{OutOfMemory}!void {1193) error{OutOfMemory}!void {
971 const comp = self.base.comp;1194 var err = try self.addErrorWithNotes(checked_paths.len);
972 const gpa = comp.gpa;1195 try err.addMsg(self, format, args);
973 try comp.link_errors.ensureUnusedCapacity(gpa, 1);1196 for (checked_paths) |path| {
974 const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len);1197 try err.addNote(self, "tried {s}", .{path});
975 errdefer gpa.free(notes);
976 for (checked_paths, notes) |path, *note| {
977 note.* = .{ .msg = try std.fmt.allocPrint(gpa, "tried {s}", .{path}) };
978 }1198 }
979 comp.link_errors.appendAssumeCapacity(.{
980 .msg = try std.fmt.allocPrint(gpa, format, args),
981 .notes = notes,
982 });
983}1199}
9841200
985fn reportDependencyError(1201fn reportDependencyError(
...@@ -992,7 +1208,7 @@ fn reportDependencyError(...@@ -992,7 +1208,7 @@ fn reportDependencyError(
992 const comp = self.base.comp;1208 const comp = self.base.comp;
993 const gpa = comp.gpa;1209 const gpa = comp.gpa;
994 try comp.link_errors.ensureUnusedCapacity(gpa, 1);1210 try comp.link_errors.ensureUnusedCapacity(gpa, 1);
995 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);1211 var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, 2);
996 defer notes.deinit();1212 defer notes.deinit();
997 if (path) |p| {1213 if (path) |p| {
998 notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{p}) });1214 notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{p}) });
...@@ -1004,42 +1220,6 @@ fn reportDependencyError(...@@ -1004,42 +1220,6 @@ fn reportDependencyError(
1004 });1220 });
1005}1221}
10061222
1007pub fn reportParseError(
1008 self: *MachO,
1009 path: []const u8,
1010 comptime format: []const u8,
1011 args: anytype,
1012) error{OutOfMemory}!void {
1013 const comp = self.base.comp;
1014 const gpa = comp.gpa;
1015 try comp.link_errors.ensureUnusedCapacity(gpa, 1);
1016 var notes = try gpa.alloc(File.ErrorMsg, 1);
1017 errdefer gpa.free(notes);
1018 notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{path}) };
1019 comp.link_errors.appendAssumeCapacity(.{
1020 .msg = try std.fmt.allocPrint(gpa, format, args),
1021 .notes = notes,
1022 });
1023}
1024
1025pub fn reportUnresolvedBoundarySymbol(
1026 self: *MachO,
1027 sym_name: []const u8,
1028 comptime format: []const u8,
1029 args: anytype,
1030) error{OutOfMemory}!void {
1031 const comp = self.base.comp;
1032 const gpa = comp.gpa;
1033 try comp.link_errors.ensureUnusedCapacity(gpa, 1);
1034 var notes = try gpa.alloc(File.ErrorMsg, 1);
1035 errdefer gpa.free(notes);
1036 notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while resolving {s}", .{sym_name}) };
1037 comp.link_errors.appendAssumeCapacity(.{
1038 .msg = try std.fmt.allocPrint(gpa, format, args),
1039 .notes = notes,
1040 });
1041}
1042
1043pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {1223pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {
1044 const comp = self.base.comp;1224 const comp = self.base.comp;
1045 const gpa = comp.gpa;1225 const gpa = comp.gpa;
...@@ -1050,7 +1230,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {...@@ -1050,7 +1230,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {
1050 const global = self.globals.items[global_index];1230 const global = self.globals.items[global_index];
1051 const sym_name = self.getSymbolName(global);1231 const sym_name = self.getSymbolName(global);
10521232
1053 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 1);1233 var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, 1);
1054 defer notes.deinit();1234 defer notes.deinit();
10551235
1056 if (global.getFile()) |file| {1236 if (global.getFile()) |file| {
...@@ -1060,7 +1240,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {...@@ -1060,7 +1240,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {
1060 notes.appendAssumeCapacity(.{ .msg = note });1240 notes.appendAssumeCapacity(.{ .msg = note });
1061 }1241 }
10621242
1063 var err_msg = File.ErrorMsg{1243 var err_msg = link.File.ErrorMsg{
1064 .msg = try std.fmt.allocPrint(gpa, "undefined reference to symbol {s}", .{sym_name}),1244 .msg = try std.fmt.allocPrint(gpa, "undefined reference to symbol {s}", .{sym_name}),
1065 };1245 };
1066 err_msg.notes = try notes.toOwnedSlice();1246 err_msg.notes = try notes.toOwnedSlice();
...@@ -1164,6 +1344,145 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void {...@@ -1164,6 +1344,145 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void {
1164 self.hot_state.mach_task = null;1344 self.hot_state.mach_task = null;
1165}1345}
11661346
1347pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) {
1348 return .{ .data = self };
1349}
1350
1351fn fmtDumpState(
1352 self: *MachO,
1353 comptime unused_fmt_string: []const u8,
1354 options: std.fmt.FormatOptions,
1355 writer: anytype,
1356) !void {
1357 _ = options;
1358 _ = unused_fmt_string;
1359 for (self.objects.items) |index| {
1360 const object = self.getFile(index).?.object;
1361 try writer.print("object({d}) : {} : has_debug({})", .{
1362 index,
1363 object.fmtPath(),
1364 object.hasDebugInfo(),
1365 });
1366 if (!object.alive) try writer.writeAll(" : ([*])");
1367 try writer.writeByte('\n');
1368 try writer.print("{}{}{}{}{}\n", .{
1369 object.fmtAtoms(self),
1370 object.fmtCies(self),
1371 object.fmtFdes(self),
1372 object.fmtUnwindRecords(self),
1373 object.fmtSymtab(self),
1374 });
1375 }
1376 // for (self.dylibs.items) |index| {
1377 // const dylib = self.getFile(index).?.dylib;
1378 // try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{
1379 // index,
1380 // dylib.path,
1381 // dylib.needed,
1382 // dylib.weak,
1383 // });
1384 // if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])");
1385 // try writer.writeByte('\n');
1386 // try writer.print("{}\n", .{dylib.fmtSymtab(self)});
1387 // }
1388 if (self.getInternalObject()) |internal| {
1389 try writer.print("internal({d}) : internal\n", .{internal.index});
1390 try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) });
1391 }
1392 try writer.writeAll("thunks\n");
1393 for (self.thunks.items, 0..) |thunk, index| {
1394 try writer.print("thunk({d}) : {}\n", .{ index, thunk.fmt(self) });
1395 }
1396 try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)});
1397 try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)});
1398 try writer.print("got\n{}\n", .{self.got.fmt(self)});
1399 try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)});
1400 try writer.writeByte('\n');
1401 try writer.print("sections\n{}\n", .{self.fmtSections()});
1402 try writer.print("segments\n{}\n", .{self.fmtSegments()});
1403}
1404
1405fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) {
1406 return .{ .data = self };
1407}
1408
1409fn formatSections(
1410 self: *MachO,
1411 comptime unused_fmt_string: []const u8,
1412 options: std.fmt.FormatOptions,
1413 writer: anytype,
1414) !void {
1415 _ = options;
1416 _ = unused_fmt_string;
1417 const slice = self.sections.slice();
1418 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {
1419 try writer.print("sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x})\n", .{
1420 i, seg_id, header.segName(), header.sectName(), header.offset, header.addr,
1421 header.@"align", header.size,
1422 });
1423 }
1424}
1425
1426fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) {
1427 return .{ .data = self };
1428}
1429
1430fn formatSegments(
1431 self: *MachO,
1432 comptime unused_fmt_string: []const u8,
1433 options: std.fmt.FormatOptions,
1434 writer: anytype,
1435) !void {
1436 _ = options;
1437 _ = unused_fmt_string;
1438 for (self.segments.items, 0..) |seg, i| {
1439 try writer.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{
1440 i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize,
1441 seg.fileoff, seg.fileoff + seg.filesize,
1442 });
1443 }
1444}
1445
1446pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) {
1447 return .{ .data = tt };
1448}
1449
1450fn formatSectType(
1451 tt: u8,
1452 comptime unused_fmt_string: []const u8,
1453 options: std.fmt.FormatOptions,
1454 writer: anytype,
1455) !void {
1456 _ = options;
1457 _ = unused_fmt_string;
1458 const name = switch (tt) {
1459 macho.S_REGULAR => "REGULAR",
1460 macho.S_ZEROFILL => "ZEROFILL",
1461 macho.S_CSTRING_LITERALS => "CSTRING_LITERALS",
1462 macho.S_4BYTE_LITERALS => "4BYTE_LITERALS",
1463 macho.S_8BYTE_LITERALS => "8BYTE_LITERALS",
1464 macho.S_16BYTE_LITERALS => "16BYTE_LITERALS",
1465 macho.S_LITERAL_POINTERS => "LITERAL_POINTERS",
1466 macho.S_NON_LAZY_SYMBOL_POINTERS => "NON_LAZY_SYMBOL_POINTERS",
1467 macho.S_LAZY_SYMBOL_POINTERS => "LAZY_SYMBOL_POINTERS",
1468 macho.S_SYMBOL_STUBS => "SYMBOL_STUBS",
1469 macho.S_MOD_INIT_FUNC_POINTERS => "MOD_INIT_FUNC_POINTERS",
1470 macho.S_MOD_TERM_FUNC_POINTERS => "MOD_TERM_FUNC_POINTERS",
1471 macho.S_COALESCED => "COALESCED",
1472 macho.S_GB_ZEROFILL => "GB_ZEROFILL",
1473 macho.S_INTERPOSING => "INTERPOSING",
1474 macho.S_DTRACE_DOF => "DTRACE_DOF",
1475 macho.S_THREAD_LOCAL_REGULAR => "THREAD_LOCAL_REGULAR",
1476 macho.S_THREAD_LOCAL_ZEROFILL => "THREAD_LOCAL_ZEROFILL",
1477 macho.S_THREAD_LOCAL_VARIABLES => "THREAD_LOCAL_VARIABLES",
1478 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS",
1479 macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS",
1480 macho.S_INIT_FUNC_OFFSETS => "INIT_FUNC_OFFSETS",
1481 else => |x| return writer.print("UNKNOWN({x})", .{x}),
1482 };
1483 try writer.print("{s}", .{name});
1484}
1485
1167const is_hot_update_compatible = switch (builtin.target.os.tag) {1486const is_hot_update_compatible = switch (builtin.target.os.tag) {
1168 .macos => true,1487 .macos => true,
1169 else => false,1488 else => false,
...@@ -1171,32 +1490,14 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) {...@@ -1171,32 +1490,14 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) {
11711490
1172const default_entry_symbol_name = "_main";1491const default_entry_symbol_name = "_main";
11731492
1174pub const base_tag: File.Tag = File.Tag.macho;1493pub const base_tag: link.File.Tag = link.File.Tag.macho;
1175pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1)));1494pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1)));
1176pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2)));1495pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2)));
11771496
1178pub const Section = struct {1497const Section = struct {
1179 header: macho.section_64,1498 header: macho.section_64,
1180 segment_index: u8,1499 segment_id: u8,
1181 first_atom_index: ?Atom.Index = null,1500 atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
1182 last_atom_index: ?Atom.Index = null,
1183
1184 /// A list of atoms that have surplus capacity. This list can have false
1185 /// positives, as functions grow and shrink over time, only sometimes being added
1186 /// or removed from the freelist.
1187 ///
1188 /// An atom has surplus capacity when its overcapacity value is greater than
1189 /// padToIdeal(minimum_atom_size). That is, when it has so
1190 /// much extra capacity, that we could fit a small new symbol in it, itself with
1191 /// ideal_capacity or more.
1192 ///
1193 /// Ideal capacity is defined by size + (size / ideal_factor).
1194 ///
1195 /// Overcapacity is measured by actual_capacity - ideal_capacity. Note that
1196 /// overcapacity can be negative. A simple way to have negative overcapacity is to
1197 /// allocate a fresh atom, which will have ideal capacity, and then grow it
1198 /// by 1 byte. It will then have -1 overcapacity.
1199 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
1200};1501};
12011502
1202const HotUpdateState = struct {1503const HotUpdateState = struct {
...@@ -1385,15 +1686,13 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion {...@@ -1385,15 +1686,13 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion {
1385 };1686 };
1386}1687}
13871688
1388fn inferSdkVersion(self: *MachO) ?std.SemanticVersion {1689fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersion {
1389 const comp = self.base.comp;
1390 const gpa = comp.gpa;1690 const gpa = comp.gpa;
13911691
1392 var arena_allocator = std.heap.ArenaAllocator.init(gpa);1692 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1393 defer arena_allocator.deinit();1693 defer arena_allocator.deinit();
1394 const arena = arena_allocator.allocator();1694 const arena = arena_allocator.allocator();
13951695
1396 const sdk_layout = self.sdk_layout orelse return null;
1397 const sdk_dir = switch (sdk_layout) {1696 const sdk_dir = switch (sdk_layout) {
1398 .sdk => comp.sysroot.?,1697 .sdk => comp.sysroot.?,
1399 .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null,1698 .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null,
...@@ -1402,6 +1701,7 @@ fn inferSdkVersion(self: *MachO) ?std.SemanticVersion {...@@ -1402,6 +1701,7 @@ fn inferSdkVersion(self: *MachO) ?std.SemanticVersion {
1402 return parseSdkVersion(ver);1701 return parseSdkVersion(ver);
1403 } else |_| {1702 } else |_| {
1404 // Read from settings should always succeed when vendored.1703 // Read from settings should always succeed when vendored.
1704 // TODO: convert to fatal linker error
1405 if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version");1705 if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version");
1406 }1706 }
14071707
...@@ -1470,6 +1770,15 @@ pub const default_pagezero_vmsize: u64 = 0x100000000;...@@ -1470,6 +1770,15 @@ pub const default_pagezero_vmsize: u64 = 0x100000000;
1470/// potential future extensions.1770/// potential future extensions.
1471pub const default_headerpad_size: u32 = 0x1000;1771pub const default_headerpad_size: u32 = 0x1000;
14721772
1773const SystemLib = struct {
1774 path: []const u8,
1775 needed: bool = false,
1776 weak: bool = false,
1777 hidden: bool = false,
1778 reexport: bool = false,
1779 must_link: bool = false,
1780};
1781
1473const MachO = @This();1782const MachO = @This();
14741783
1475const std = @import("std");1784const std = @import("std");
...@@ -1479,6 +1788,7 @@ const assert = std.debug.assert;...@@ -1479,6 +1788,7 @@ const assert = std.debug.assert;
1479const dwarf = std.dwarf;1788const dwarf = std.dwarf;
1480const fs = std.fs;1789const fs = std.fs;
1481const log = std.log.scoped(.link);1790const log = std.log.scoped(.link);
1791const state_log = std.log.scoped(.link_state);
1482const macho = std.macho;1792const macho = std.macho;
1483const math = std.math;1793const math = std.math;
1484const mem = std.mem;1794const mem = std.mem;
...@@ -1488,6 +1798,7 @@ const aarch64 = @import("../arch/aarch64/bits.zig");...@@ -1488,6 +1798,7 @@ const aarch64 = @import("../arch/aarch64/bits.zig");
1488const calcUuid = @import("MachO/uuid.zig").calcUuid;1798const calcUuid = @import("MachO/uuid.zig").calcUuid;
1489const codegen = @import("../codegen.zig");1799const codegen = @import("../codegen.zig");
1490const dead_strip = @import("MachO/dead_strip.zig");1800const dead_strip = @import("MachO/dead_strip.zig");
1801const eh_frame = @import("MachO/eh_frame.zig");
1491const fat = @import("MachO/fat.zig");1802const fat = @import("MachO/fat.zig");
1492const link = @import("../link.zig");1803const link = @import("../link.zig");
1493const llvm_backend = @import("../codegen/llvm.zig");1804const llvm_backend = @import("../codegen/llvm.zig");
...@@ -1496,12 +1807,14 @@ const tapi = @import("tapi.zig");...@@ -1496,12 +1807,14 @@ const tapi = @import("tapi.zig");
1496const target_util = @import("../target.zig");1807const target_util = @import("../target.zig");
1497const thunks = @import("MachO/thunks.zig");1808const thunks = @import("MachO/thunks.zig");
1498const trace = @import("../tracy.zig").trace;1809const trace = @import("../tracy.zig").trace;
1810const synthetic = @import("MachO/synthetic.zig");
14991811
1500const Air = @import("../Air.zig");1812const Air = @import("../Air.zig");
1501const Alignment = Atom.Alignment;1813const Alignment = Atom.Alignment;
1502const Allocator = mem.Allocator;1814const Allocator = mem.Allocator;
1503const Archive = @import("MachO/Archive.zig");1815const Archive = @import("MachO/Archive.zig");
1504pub const Atom = @import("MachO/Atom.zig");1816pub const Atom = @import("MachO/Atom.zig");
1817const BindSection = synthetic.BindSection;
1505const Cache = std.Build.Cache;1818const Cache = std.Build.Cache;
1506const CodeSignature = @import("MachO/CodeSignature.zig");1819const CodeSignature = @import("MachO/CodeSignature.zig");
1507const Compilation = @import("../Compilation.zig");1820const Compilation = @import("../Compilation.zig");
...@@ -1509,17 +1822,29 @@ pub const DebugSymbols = @import("MachO/DebugSymbols.zig");...@@ -1509,17 +1822,29 @@ pub const DebugSymbols = @import("MachO/DebugSymbols.zig");
1509const Dwarf = File.Dwarf;1822const Dwarf = File.Dwarf;
1510const DwarfInfo = @import("MachO/DwarfInfo.zig");1823const DwarfInfo = @import("MachO/DwarfInfo.zig");
1511const Dylib = @import("MachO/Dylib.zig");1824const Dylib = @import("MachO/Dylib.zig");
1512const File = link.File;1825const ExportTrieSection = synthetic.ExportTrieSection;
1826const File = @import("MachO/file.zig").File;
1827const GotSection = synthetic.GotSection;
1828const Indsymtab = synthetic.Indsymtab;
1829const InternalObject = @import("MachO/InternalObject.zig");
1830const ObjcStubsSection = synthetic.ObjcStubsSection;
1513const Object = @import("MachO/Object.zig");1831const Object = @import("MachO/Object.zig");
1832const LazyBindSection = synthetic.LazyBindSection;
1833const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;
1514const LibStub = tapi.LibStub;1834const LibStub = tapi.LibStub;
1515const Liveness = @import("../Liveness.zig");1835const Liveness = @import("../Liveness.zig");
1516const LlvmObject = @import("../codegen/llvm.zig").Object;1836const LlvmObject = @import("../codegen/llvm.zig").Object;
1517const Md5 = std.crypto.hash.Md5;1837const Md5 = std.crypto.hash.Md5;
1518const Module = @import("../Module.zig");1838const Module = @import("../Module.zig");
1519const InternPool = @import("../InternPool.zig");1839const InternPool = @import("../InternPool.zig");
1840const RebaseSection = synthetic.RebaseSection;
1520const Relocation = @import("MachO/Relocation.zig");1841const Relocation = @import("MachO/Relocation.zig");
1521const StringTable = @import("StringTable.zig");1842const StringTable = @import("StringTable.zig");
1522const TableSection = @import("table_section.zig").TableSection;1843const StubsSection = synthetic.StubsSection;
1523const Type = @import("../type.zig").Type;1844const StubsHelperSection = synthetic.StubsHelperSection;
1845const Symbol = @import("MachO/Symbol.zig");
1846const Thunk = thunks.Thunk;
1847const TlvPtrSection = synthetic.TlvPtrSection;
1524const TypedValue = @import("../TypedValue.zig");1848const TypedValue = @import("../TypedValue.zig");
1525const Value = @import("../value.zig").Value;1849const UnwindInfo = @import("MachO/UnwindInfo.zig");
1850const WeakBindSection = synthetic.WeakBindSection;
src/link/MachO/Atom.zig+1-1
...@@ -38,7 +38,7 @@ unwind_records: Loc = .{},...@@ -38,7 +38,7 @@ unwind_records: Loc = .{},
38flags: Flags = .{},38flags: Flags = .{},
3939
40pub fn getName(self: Atom, macho_file: *MachO) [:0]const u8 {40pub fn getName(self: Atom, macho_file: *MachO) [:0]const u8 {
41 return macho_file.string_intern.getAssumeExists(self.name);41 return macho_file.strings.getAssumeExists(self.name);
42}42}
4343
44pub fn getFile(self: Atom, macho_file: *MachO) File {44pub fn getFile(self: Atom, macho_file: *MachO) File {
src/link/MachO/Dylib.zig+1-1
...@@ -431,7 +431,7 @@ pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void {...@@ -431,7 +431,7 @@ pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void {
431431
432 for (self.exports.items(.name)) |noff| {432 for (self.exports.items(.name)) |noff| {
433 const name = self.getString(noff);433 const name = self.getString(noff);
434 const off = try macho_file.string_intern.insert(gpa, name);434 const off = try macho_file.strings.insert(gpa, name);
435 const gop = try macho_file.getOrCreateGlobal(off);435 const gop = try macho_file.getOrCreateGlobal(off);
436 self.symbols.addOneAssumeCapacity().* = gop.index;436 self.symbols.addOneAssumeCapacity().* = gop.index;
437 }437 }
src/link/MachO/Object.zig+138-96
...@@ -31,6 +31,14 @@ num_weak_bind_relocs: u32 = 0,...@@ -31,6 +31,14 @@ num_weak_bind_relocs: u32 = 0,
3131
32output_symtab_ctx: MachO.SymtabCtx = .{},32output_symtab_ctx: MachO.SymtabCtx = .{},
3333
34pub fn isObject(path: []const u8) !bool {
35 const file = try std.fs.cwd().openFile(path, .{});
36 defer file.close();
37 const reader = file.reader();
38 const header = reader.readStruct(macho.mach_header_64) catch return false;
39 return header.filetype == macho.MH_OBJECT;
40}
41
34pub fn deinit(self: *Object, allocator: Allocator) void {42pub fn deinit(self: *Object, allocator: Allocator) void {
35 for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| {43 for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| {
36 relocs.deinit(allocator);44 relocs.deinit(allocator);
...@@ -55,12 +63,25 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -55,12 +63,25 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
55 const tracy = trace(@src());63 const tracy = trace(@src());
56 defer tracy.end();64 defer tracy.end();
5765
58 const gpa = macho_file.base.allocator;66 const gpa = macho_file.base.comp.gpa;
59 var stream = std.io.fixedBufferStream(self.data);67 var stream = std.io.fixedBufferStream(self.data);
60 const reader = stream.reader();68 const reader = stream.reader();
6169
62 self.header = try reader.readStruct(macho.mach_header_64);70 self.header = try reader.readStruct(macho.mach_header_64);
6371
72 const this_cpu_arch: std.Target.Cpu.Arch = switch (self.header.?.cputype) {
73 macho.CPU_TYPE_ARM64 => .aarch64,
74 macho.CPU_TYPE_X86_64 => .x86_64,
75 else => |x| {
76 try macho_file.reportParseError2(self.index, "unknown cpu architecture: {d}", .{x});
77 return error.InvalidCpuArch;
78 },
79 };
80 if (macho_file.getTarget().cpu.arch != this_cpu_arch) {
81 try macho_file.reportParseError2(self.index, "invalid cpu architecture: {s}", .{@tagName(this_cpu_arch)});
82 return error.InvalidCpuArch;
83 }
84
64 if (self.getLoadCommand(.SEGMENT_64)) |lc| {85 if (self.getLoadCommand(.SEGMENT_64)) |lc| {
65 const sections = lc.getSections();86 const sections = lc.getSections();
66 try self.sections.ensureUnusedCapacity(gpa, sections.len);87 try self.sections.ensureUnusedCapacity(gpa, sections.len);
...@@ -146,6 +167,20 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -146,6 +167,20 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
146 }167 }
147168
148 self.initPlatform();169 self.initPlatform();
170
171 if (self.platform) |platform| {
172 if (!macho_file.platform.eqlTarget(platform)) {
173 try macho_file.reportParseError2(self.index, "invalid platform: {}", .{
174 platform.fmtTarget(macho_file.getTarget().cpu.arch),
175 });
176 return error.InvalidTarget;
177 }
178 if (macho_file.platform.version.order(platform.version) != .lt) {
179 try macho_file.reportParseError2(self.index, "object file built for newer platform: {}", .{platform});
180 return error.InvalidTarget;
181 }
182 }
183
149 try self.initDwarfInfo(macho_file);184 try self.initDwarfInfo(macho_file);
150185
151 for (self.atoms.items) |atom_index| {186 for (self.atoms.items) |atom_index| {
...@@ -175,7 +210,7 @@ inline fn isLiteral(sect: macho.section_64) bool {...@@ -175,7 +210,7 @@ inline fn isLiteral(sect: macho.section_64) bool {
175fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void {210fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void {
176 const tracy = trace(@src());211 const tracy = trace(@src());
177 defer tracy.end();212 defer tracy.end();
178 const gpa = macho_file.base.allocator;213 const gpa = macho_file.base.comp.gpa;
179 const slice = self.sections.slice();214 const slice = self.sections.slice();
180 for (slice.items(.header), slice.items(.subsections), 0..) |sect, *subsections, n_sect| {215 for (slice.items(.header), slice.items(.subsections), 0..) |sect, *subsections, n_sect| {
181 if (isLiteral(sect)) continue;216 if (isLiteral(sect)) continue;
...@@ -243,7 +278,7 @@ fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void {...@@ -243,7 +278,7 @@ fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void {
243fn initSections(self: *Object, nlists: anytype, macho_file: *MachO) !void {278fn initSections(self: *Object, nlists: anytype, macho_file: *MachO) !void {
244 const tracy = trace(@src());279 const tracy = trace(@src());
245 defer tracy.end();280 defer tracy.end();
246 const gpa = macho_file.base.allocator;281 const gpa = macho_file.base.comp.gpa;
247 const slice = self.sections.slice();282 const slice = self.sections.slice();
248283
249 try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len);284 try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len);
...@@ -299,12 +334,12 @@ const AddAtomArgs = struct {...@@ -299,12 +334,12 @@ const AddAtomArgs = struct {
299};334};
300335
301fn addAtom(self: *Object, args: AddAtomArgs, macho_file: *MachO) !Atom.Index {336fn addAtom(self: *Object, args: AddAtomArgs, macho_file: *MachO) !Atom.Index {
302 const gpa = macho_file.base.allocator;337 const gpa = macho_file.base.comp.gpa;
303 const atom_index = try macho_file.addAtom();338 const atom_index = try macho_file.addAtom();
304 const atom = macho_file.getAtom(atom_index).?;339 const atom = macho_file.getAtom(atom_index).?;
305 atom.file = self.index;340 atom.file = self.index;
306 atom.atom_index = atom_index;341 atom.atom_index = atom_index;
307 atom.name = try macho_file.string_intern.insert(gpa, args.name);342 atom.name = try macho_file.strings.insert(gpa, args.name);
308 atom.n_sect = args.n_sect;343 atom.n_sect = args.n_sect;
309 atom.size = args.size;344 atom.size = args.size;
310 atom.alignment = args.alignment;345 atom.alignment = args.alignment;
...@@ -319,7 +354,7 @@ fn initLiteralSections(self: *Object, macho_file: *MachO) !void {...@@ -319,7 +354,7 @@ fn initLiteralSections(self: *Object, macho_file: *MachO) !void {
319 // TODO here we should split into equal-sized records, hash the contents, and then354 // TODO here we should split into equal-sized records, hash the contents, and then
320 // deduplicate - ICF.355 // deduplicate - ICF.
321 // For now, we simply cover each literal section with one large atom.356 // For now, we simply cover each literal section with one large atom.
322 const gpa = macho_file.base.allocator;357 const gpa = macho_file.base.comp.gpa;
323 const slice = self.sections.slice();358 const slice = self.sections.slice();
324359
325 try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len);360 try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len);
...@@ -401,10 +436,10 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void {...@@ -401,10 +436,10 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void {
401 if (self.findAtomInSection(nlist.n_value, nlist.n_sect - 1)) |atom_index| {436 if (self.findAtomInSection(nlist.n_value, nlist.n_sect - 1)) |atom_index| {
402 atom.* = atom_index;437 atom.* = atom_index;
403 } else {438 } else {
404 macho_file.base.fatal("{}: symbol {s} not attached to any (sub)section", .{439 try macho_file.reportParseError2(self.index, "symbol {s} not attached to any (sub)section", .{
405 self.fmtPath(), self.getString(nlist.n_strx),440 self.getString(nlist.n_strx),
406 });441 });
407 return error.ParseFailed;442 return error.MalformedObject;
408 }443 }
409 }444 }
410 }445 }
...@@ -413,7 +448,7 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void {...@@ -413,7 +448,7 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void {
413fn initSymbols(self: *Object, macho_file: *MachO) !void {448fn initSymbols(self: *Object, macho_file: *MachO) !void {
414 const tracy = trace(@src());449 const tracy = trace(@src());
415 defer tracy.end();450 defer tracy.end();
416 const gpa = macho_file.base.allocator;451 const gpa = macho_file.base.comp.gpa;
417 const slice = self.symtab.slice();452 const slice = self.symtab.slice();
418453
419 try self.symbols.ensureUnusedCapacity(gpa, slice.items(.nlist).len);454 try self.symbols.ensureUnusedCapacity(gpa, slice.items(.nlist).len);
...@@ -421,7 +456,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void {...@@ -421,7 +456,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void {
421 for (slice.items(.nlist), slice.items(.atom), 0..) |nlist, atom_index, i| {456 for (slice.items(.nlist), slice.items(.atom), 0..) |nlist, atom_index, i| {
422 if (nlist.ext()) {457 if (nlist.ext()) {
423 const name = self.getString(nlist.n_strx);458 const name = self.getString(nlist.n_strx);
424 const off = try macho_file.string_intern.insert(gpa, name);459 const off = try macho_file.strings.insert(gpa, name);
425 const gop = try macho_file.getOrCreateGlobal(off);460 const gop = try macho_file.getOrCreateGlobal(off);
426 self.symbols.addOneAssumeCapacity().* = gop.index;461 self.symbols.addOneAssumeCapacity().* = gop.index;
427 continue;462 continue;
...@@ -433,7 +468,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void {...@@ -433,7 +468,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void {
433 const name = self.getString(nlist.n_strx);468 const name = self.getString(nlist.n_strx);
434 symbol.* = .{469 symbol.* = .{
435 .value = nlist.n_value,470 .value = nlist.n_value,
436 .name = try macho_file.string_intern.insert(gpa, name),471 .name = try macho_file.strings.insert(gpa, name),
437 .nlist_idx = @intCast(i),472 .nlist_idx = @intCast(i),
438 .atom = 0,473 .atom = 0,
439 .file = self.index,474 .file = self.index,
...@@ -482,7 +517,7 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void {...@@ -482,7 +517,7 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void {
482517
483 if (start == end) return;518 if (start == end) return;
484519
485 const gpa = macho_file.base.allocator;520 const gpa = macho_file.base.comp.gpa;
486 const syms = self.symtab.items(.nlist);521 const syms = self.symtab.items(.nlist);
487 const sym_lookup = SymbolLookup{ .ctx = self, .entries = nlists };522 const sym_lookup = SymbolLookup{ .ctx = self, .entries = nlists };
488523
...@@ -490,11 +525,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void {...@@ -490,11 +525,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void {
490 while (i < end) : (i += 1) {525 while (i < end) : (i += 1) {
491 const open = syms[i];526 const open = syms[i];
492 if (open.n_type != macho.N_SO) {527 if (open.n_type != macho.N_SO) {
493 macho_file.base.fatal("{}: unexpected symbol stab type 0x{x} as the first entry", .{528 try macho_file.reportParseError2(self.index, "unexpected symbol stab type 0x{x} as the first entry", .{
494 self.fmtPath(),
495 open.n_type,529 open.n_type,
496 });530 });
497 return error.ParseFailed;531 return error.MalformedObject;
498 }532 }
499533
500 while (i < end and syms[i].n_type == macho.N_SO and syms[i].n_sect != 0) : (i += 1) {}534 while (i < end and syms[i].n_type == macho.N_SO and syms[i].n_sect != 0) : (i += 1) {}
...@@ -522,11 +556,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void {...@@ -522,11 +556,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void {
522 stab.symbol = sym_lookup.find(nlist.n_value);556 stab.symbol = sym_lookup.find(nlist.n_value);
523 },557 },
524 else => {558 else => {
525 macho_file.base.fatal("{}: unhandled symbol stab type 0x{x}", .{559 try macho_file.reportParseError2(self.index, "unhandled symbol stab type 0x{x}", .{
526 self.fmtPath(),
527 nlist.n_type,560 nlist.n_type,
528 });561 });
529 return error.ParseFailed;562 return error.MalformedObject;
530 },563 },
531 }564 }
532 try sf.stabs.append(gpa, stab);565 try sf.stabs.append(gpa, stab);
...@@ -548,7 +581,7 @@ fn sortAtoms(self: *Object, macho_file: *MachO) !void {...@@ -548,7 +581,7 @@ fn sortAtoms(self: *Object, macho_file: *MachO) !void {
548fn initRelocs(self: *Object, macho_file: *MachO) !void {581fn initRelocs(self: *Object, macho_file: *MachO) !void {
549 const tracy = trace(@src());582 const tracy = trace(@src());
550 defer tracy.end();583 defer tracy.end();
551 const cpu_arch = macho_file.options.cpu_arch.?;584 const cpu_arch = macho_file.getTarget().cpu.arch;
552 const slice = self.sections.slice();585 const slice = self.sections.slice();
553586
554 for (slice.items(.header), slice.items(.relocs), 0..) |sect, *out, n_sect| {587 for (slice.items(.header), slice.items(.relocs), 0..) |sect, *out, n_sect| {
...@@ -589,7 +622,7 @@ fn initRelocs(self: *Object, macho_file: *MachO) !void {...@@ -589,7 +622,7 @@ fn initRelocs(self: *Object, macho_file: *MachO) !void {
589fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {622fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
590 const tracy = trace(@src());623 const tracy = trace(@src());
591 defer tracy.end();624 defer tracy.end();
592 const gpa = macho_file.base.allocator;625 const gpa = macho_file.base.comp.gpa;
593 const nlists = self.symtab.items(.nlist);626 const nlists = self.symtab.items(.nlist);
594 const slice = self.sections.slice();627 const slice = self.sections.slice();
595 const sect = slice.items(.header)[sect_id];628 const sect = slice.items(.header)[sect_id];
...@@ -667,10 +700,10 @@ fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -667,10 +700,10 @@ fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
667 const cie = for (self.cies.items) |*cie| {700 const cie = for (self.cies.items) |*cie| {
668 if (cie.offset <= rel.offset and rel.offset < cie.offset + cie.getSize()) break cie;701 if (cie.offset <= rel.offset and rel.offset < cie.offset + cie.getSize()) break cie;
669 } else {702 } else {
670 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{703 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
671 self.fmtPath(), sect.segName(), sect.sectName(), rel.offset,704 sect.segName(), sect.sectName(), rel.offset,
672 });705 });
673 return error.ParseFailed;706 return error.MalformedObject;
674 };707 };
675 cie.personality = .{ .index = @intCast(rel.target), .offset = rel.offset - cie.offset };708 cie.personality = .{ .index = @intCast(rel.target), .offset = rel.offset - cie.offset };
676 },709 },
...@@ -695,7 +728,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -695,7 +728,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
695 }728 }
696 };729 };
697730
698 const gpa = macho_file.base.allocator;731 const gpa = macho_file.base.comp.gpa;
699 const data = self.getSectionData(sect_id);732 const data = self.getSectionData(sect_id);
700 const nrecs = @divExact(data.len, @sizeOf(macho.compact_unwind_entry));733 const nrecs = @divExact(data.len, @sizeOf(macho.compact_unwind_entry));
701 const recs = @as([*]align(1) const macho.compact_unwind_entry, @ptrCast(data.ptr))[0..nrecs];734 const recs = @as([*]align(1) const macho.compact_unwind_entry, @ptrCast(data.ptr))[0..nrecs];
...@@ -722,10 +755,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -722,10 +755,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
722755
723 for (relocs[reloc_start..reloc_idx]) |rel| {756 for (relocs[reloc_start..reloc_idx]) |rel| {
724 if (rel.type != .unsigned or rel.meta.length != 3) {757 if (rel.type != .unsigned or rel.meta.length != 3) {
725 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{758 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
726 self.fmtPath(), header.segName(), header.sectName(), rel.offset,759 header.segName(), header.sectName(), rel.offset,
727 });760 });
728 return error.ParseFailed;761 return error.MalformedObject;
729 }762 }
730 assert(rel.type == .unsigned and rel.meta.length == 3); // TODO error763 assert(rel.type == .unsigned and rel.meta.length == 3); // TODO error
731 const offset = rel.offset - rec_start;764 const offset = rel.offset - rec_start;
...@@ -740,10 +773,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -740,10 +773,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
740 const atom = out.getAtom(macho_file);773 const atom = out.getAtom(macho_file);
741 out.atom_offset = @intCast(rec.rangeStart - atom.getInputAddress(macho_file));774 out.atom_offset = @intCast(rec.rangeStart - atom.getInputAddress(macho_file));
742 } else {775 } else {
743 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{776 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
744 self.fmtPath(), header.segName(), header.sectName(), rel.offset,777 header.segName(), header.sectName(), rel.offset,
745 });778 });
746 return error.ParseFailed;779 return error.MalformedObject;
747 },780 },
748 },781 },
749 16 => switch (rel.tag) { // personality function782 16 => switch (rel.tag) { // personality function
...@@ -753,10 +786,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -753,10 +786,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
753 .local => if (sym_lookup.find(rec.personalityFunction)) |sym_index| {786 .local => if (sym_lookup.find(rec.personalityFunction)) |sym_index| {
754 out.personality = sym_index;787 out.personality = sym_index;
755 } else {788 } else {
756 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{789 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
757 self.fmtPath(), header.segName(), header.sectName(), rel.offset,790 header.segName(), header.sectName(), rel.offset,
758 });791 });
759 return error.ParseFailed;792 return error.MalformedObject;
760 },793 },
761 },794 },
762 24 => switch (rel.tag) { // lsda795 24 => switch (rel.tag) { // lsda
...@@ -769,10 +802,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -769,10 +802,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
769 const atom = out.getLsdaAtom(macho_file).?;802 const atom = out.getLsdaAtom(macho_file).?;
770 out.lsda_offset = @intCast(rec.lsda - atom.getInputAddress(macho_file));803 out.lsda_offset = @intCast(rec.lsda - atom.getInputAddress(macho_file));
771 } else {804 } else {
772 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{805 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
773 self.fmtPath(), header.segName(), header.sectName(), rel.offset,806 header.segName(), header.sectName(), rel.offset,
774 });807 });
775 return error.ParseFailed;808 return error.MalformedObject;
776 },809 },
777 },810 },
778 else => {},811 else => {},
...@@ -780,7 +813,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {...@@ -780,7 +813,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
780 }813 }
781 }814 }
782815
783 if (!macho_file.options.relocatable) try self.synthesiseNullUnwindRecords(macho_file);816 if (!macho_file.base.isObject()) try self.synthesiseNullUnwindRecords(macho_file);
784817
785 const sortFn = struct {818 const sortFn = struct {
786 fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool {819 fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool {
...@@ -818,7 +851,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void {...@@ -818,7 +851,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void {
818851
819 const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null };852 const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null };
820853
821 const gpa = macho_file.base.allocator;854 const gpa = macho_file.base.comp.gpa;
822 var superposition = std.AutoArrayHashMap(u64, Superposition).init(gpa);855 var superposition = std.AutoArrayHashMap(u64, Superposition).init(gpa);
823 defer superposition.deinit();856 defer superposition.deinit();
824857
...@@ -875,7 +908,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void {...@@ -875,7 +908,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void {
875 rec.atom_offset = fde.atom_offset;908 rec.atom_offset = fde.atom_offset;
876 rec.fde = fde_index;909 rec.fde = fde_index;
877 rec.file = fde.file;910 rec.file = fde.file;
878 switch (macho_file.options.cpu_arch.?) {911 switch (macho_file.getTarget().cpu.arch) {
879 .x86_64 => rec.enc.setMode(macho.UNWIND_X86_64_MODE.DWARF),912 .x86_64 => rec.enc.setMode(macho.UNWIND_X86_64_MODE.DWARF),
880 .aarch64 => rec.enc.setMode(macho.UNWIND_ARM64_MODE.DWARF),913 .aarch64 => rec.enc.setMode(macho.UNWIND_ARM64_MODE.DWARF),
881 else => unreachable,914 else => unreachable,
...@@ -907,7 +940,7 @@ fn initPlatform(self: *Object) void {...@@ -907,7 +940,7 @@ fn initPlatform(self: *Object) void {
907 .VERSION_MIN_IPHONEOS,940 .VERSION_MIN_IPHONEOS,
908 .VERSION_MIN_TVOS,941 .VERSION_MIN_TVOS,
909 .VERSION_MIN_WATCHOS,942 .VERSION_MIN_WATCHOS,
910 => break MachO.Options.Platform.fromLoadCommand(cmd),943 => break MachO.Platform.fromLoadCommand(cmd),
911 else => {},944 else => {},
912 }945 }
913 } else null;946 } else null;
...@@ -921,7 +954,7 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void {...@@ -921,7 +954,7 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void {
921 const tracy = trace(@src());954 const tracy = trace(@src());
922 defer tracy.end();955 defer tracy.end();
923956
924 const gpa = macho_file.base.allocator;957 const gpa = macho_file.base.comp.gpa;
925958
926 var debug_info_index: ?usize = null;959 var debug_info_index: ?usize = null;
927 var debug_abbrev_index: ?usize = null;960 var debug_abbrev_index: ?usize = null;
...@@ -942,8 +975,8 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void {...@@ -942,8 +975,8 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void {
942 .debug_str = if (debug_str_index) |index| self.getSectionData(@intCast(index)) else "",975 .debug_str = if (debug_str_index) |index| self.getSectionData(@intCast(index)) else "",
943 };976 };
944 dwarf_info.init(gpa) catch {977 dwarf_info.init(gpa) catch {
945 macho_file.base.fatal("{}: invalid __DWARF info found", .{self.fmtPath()});978 try macho_file.reportParseError2(self.index, "invalid __DWARF info found", .{});
946 return error.ParseFailed;979 return error.MalformedObject;
947 };980 };
948 self.dwarf_info = dwarf_info;981 self.dwarf_info = dwarf_info;
949}982}
...@@ -1060,7 +1093,7 @@ pub fn scanRelocs(self: Object, macho_file: *MachO) !void {...@@ -1060,7 +1093,7 @@ pub fn scanRelocs(self: Object, macho_file: *MachO) !void {
1060pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {1093pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {
1061 const tracy = trace(@src());1094 const tracy = trace(@src());
1062 defer tracy.end();1095 defer tracy.end();
1063 const gpa = macho_file.base.allocator;1096 const gpa = macho_file.base.comp.gpa;
10641097
1065 for (self.symbols.items, 0..) |index, i| {1098 for (self.symbols.items, 0..) |index, i| {
1066 const sym = macho_file.getSymbol(index);1099 const sym = macho_file.getSymbol(index);
...@@ -1079,7 +1112,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {...@@ -1079,7 +1112,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void {
1079 defer gpa.free(name);1112 defer gpa.free(name);
1080 const atom = macho_file.getAtom(atom_index).?;1113 const atom = macho_file.getAtom(atom_index).?;
1081 atom.atom_index = atom_index;1114 atom.atom_index = atom_index;
1082 atom.name = try macho_file.string_intern.insert(gpa, name);1115 atom.name = try macho_file.strings.insert(gpa, name);
1083 atom.file = self.index;1116 atom.file = self.index;
1084 atom.size = nlist.n_value;1117 atom.size = nlist.n_value;
1085 atom.alignment = (nlist.n_desc >> 8) & 0x0f;1118 atom.alignment = (nlist.n_desc >> 8) & 0x0f;
...@@ -1130,7 +1163,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void {...@@ -1130,7 +1163,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void {
1130 const name = sym.getName(macho_file);1163 const name = sym.getName(macho_file);
1131 // TODO in -r mode, we actually want to merge symbol names and emit only one1164 // TODO in -r mode, we actually want to merge symbol names and emit only one
1132 // work it out when emitting relocs1165 // work it out when emitting relocs
1133 if (name.len > 0 and (name[0] == 'L' or name[0] == 'l') and !macho_file.options.relocatable) continue;1166 if (name.len > 0 and (name[0] == 'L' or name[0] == 'l') and !macho_file.base.isObject()) continue;
1134 sym.flags.output_symtab = true;1167 sym.flags.output_symtab = true;
1135 if (sym.isLocal()) {1168 if (sym.isLocal()) {
1136 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);1169 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
...@@ -1171,7 +1204,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void {...@@ -1171,7 +1204,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void {
1171 const file = sym.getFile(macho_file) orelse continue;1204 const file = sym.getFile(macho_file) orelse continue;
1172 if (file.getIndex() != self.index) continue;1205 if (file.getIndex() != self.index) continue;
1173 if (!sym.flags.output_symtab) continue;1206 if (!sym.flags.output_symtab) continue;
1174 if (macho_file.options.relocatable) {1207 if (macho_file.base.isObject()) {
1175 const name = sym.getName(macho_file);1208 const name = sym.getName(macho_file);
1176 if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue;1209 if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue;
1177 }1210 }
...@@ -1329,7 +1362,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) void {...@@ -1329,7 +1362,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) void {
1329 const file = sym.getFile(macho_file) orelse continue;1362 const file = sym.getFile(macho_file) orelse continue;
1330 if (file.getIndex() != self.index) continue;1363 if (file.getIndex() != self.index) continue;
1331 if (!sym.flags.output_symtab) continue;1364 if (!sym.flags.output_symtab) continue;
1332 if (macho_file.options.relocatable) {1365 if (macho_file.base.isObject()) {
1333 const name = sym.getName(macho_file);1366 const name = sym.getName(macho_file);
1334 if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue;1367 if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue;
1335 }1368 }
...@@ -1747,7 +1780,7 @@ const x86_64 = struct {...@@ -1747,7 +1780,7 @@ const x86_64 = struct {
1747 out: *std.ArrayListUnmanaged(Relocation),1780 out: *std.ArrayListUnmanaged(Relocation),
1748 macho_file: *MachO,1781 macho_file: *MachO,
1749 ) !void {1782 ) !void {
1750 const gpa = macho_file.base.allocator;1783 const gpa = macho_file.base.comp.gpa;
17511784
1752 const relocs = @as(1785 const relocs = @as(
1753 [*]align(1) const macho.relocation_info,1786 [*]align(1) const macho.relocation_info,
...@@ -1783,10 +1816,10 @@ const x86_64 = struct {...@@ -1783,10 +1816,10 @@ const x86_64 = struct {
1783 else1816 else
1784 addend;1817 addend;
1785 const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse {1818 const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse {
1786 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{1819 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
1787 self.fmtPath(), sect.segName(), sect.sectName(), rel.r_address,1820 sect.segName(), sect.sectName(), rel.r_address,
1788 });1821 });
1789 return error.ParseFailed;1822 return error.MalformedObject;
1790 };1823 };
1791 addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file)));1824 addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file)));
1792 break :blk target;1825 break :blk target;
...@@ -1796,34 +1829,38 @@ const x86_64 = struct {...@@ -1796,34 +1829,38 @@ const x86_64 = struct {
1796 @as(macho.reloc_type_x86_64, @enumFromInt(relocs[i - 1].r_type)) == .X86_64_RELOC_SUBTRACTOR)1829 @as(macho.reloc_type_x86_64, @enumFromInt(relocs[i - 1].r_type)) == .X86_64_RELOC_SUBTRACTOR)
1797 blk: {1830 blk: {
1798 if (rel_type != .X86_64_RELOC_UNSIGNED) {1831 if (rel_type != .X86_64_RELOC_UNSIGNED) {
1799 macho_file.base.fatal("{}: {s},{s}: 0x{x}: X86_64_RELOC_SUBTRACTOR followed by {s}", .{1832 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: X86_64_RELOC_SUBTRACTOR followed by {s}", .{
1800 self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type),1833 sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type),
1801 });1834 });
1802 return error.ParseFailed;1835 return error.MalformedObject;
1803 }1836 }
1804 break :blk true;1837 break :blk true;
1805 } else false;1838 } else false;
18061839
1807 const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| {1840 const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| {
1808 switch (err) {1841 switch (err) {
1809 error.Pcrel => macho_file.base.fatal(1842 error.Pcrel => try macho_file.reportParseError2(
1810 "{}: {s},{s}: 0x{x}: PC-relative {s} relocation",1843 self.index,
1811 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },1844 "{s},{s}: 0x{x}: PC-relative {s} relocation",
1845 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },
1812 ),1846 ),
1813 error.NonPcrel => macho_file.base.fatal(1847 error.NonPcrel => try macho_file.reportParseError2(
1814 "{}: {s},{s}: 0x{x}: non-PC-relative {s} relocation",1848 self.index,
1815 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },1849 "{s},{s}: 0x{x}: non-PC-relative {s} relocation",
1850 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },
1816 ),1851 ),
1817 error.InvalidLength => macho_file.base.fatal(1852 error.InvalidLength => try macho_file.reportParseError2(
1818 "{}: {s},{s}: 0x{x}: invalid length of {d} in {s} relocation",1853 self.index,
1819 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) },1854 "{s},{s}: 0x{x}: invalid length of {d} in {s} relocation",
1855 .{ sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) },
1820 ),1856 ),
1821 error.NonExtern => macho_file.base.fatal(1857 error.NonExtern => try macho_file.reportParseError2(
1822 "{}: {s},{s}: 0x{x}: non-extern target in {s} relocation",1858 self.index,
1823 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },1859 "{s},{s}: 0x{x}: non-extern target in {s} relocation",
1860 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },
1824 ),1861 ),
1825 }1862 }
1826 return error.ParseFailed;1863 return error.MalformedObject;
1827 };1864 };
18281865
1829 out.appendAssumeCapacity(.{1866 out.appendAssumeCapacity(.{
...@@ -1899,7 +1936,7 @@ const aarch64 = struct {...@@ -1899,7 +1936,7 @@ const aarch64 = struct {
1899 out: *std.ArrayListUnmanaged(Relocation),1936 out: *std.ArrayListUnmanaged(Relocation),
1900 macho_file: *MachO,1937 macho_file: *MachO,
1901 ) !void {1938 ) !void {
1902 const gpa = macho_file.base.allocator;1939 const gpa = macho_file.base.comp.gpa;
19031940
1904 const relocs = @as(1941 const relocs = @as(
1905 [*]align(1) const macho.relocation_info,1942 [*]align(1) const macho.relocation_info,
...@@ -1921,20 +1958,21 @@ const aarch64 = struct {...@@ -1921,20 +1958,21 @@ const aarch64 = struct {
1921 addend = rel.r_symbolnum;1958 addend = rel.r_symbolnum;
1922 i += 1;1959 i += 1;
1923 if (i >= relocs.len) {1960 if (i >= relocs.len) {
1924 macho_file.base.fatal("{}: {s},{s}: 0x{x}: unterminated ARM64_RELOC_ADDEND", .{1961 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: unterminated ARM64_RELOC_ADDEND", .{
1925 self.fmtPath(), sect.segName(), sect.sectName(), rel_offset,1962 sect.segName(), sect.sectName(), rel_offset,
1926 });1963 });
1927 return error.ParseFailed;1964 return error.MalformedObject;
1928 }1965 }
1929 rel = relocs[i];1966 rel = relocs[i];
1930 switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) {1967 switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) {
1931 .ARM64_RELOC_PAGE21, .ARM64_RELOC_PAGEOFF12 => {},1968 .ARM64_RELOC_PAGE21, .ARM64_RELOC_PAGEOFF12 => {},
1932 else => |x| {1969 else => |x| {
1933 macho_file.base.fatal(1970 try macho_file.reportParseError2(
1934 "{}: {s},{s}: 0x{x}: ARM64_RELOC_ADDEND followed by {s}",1971 self.index,
1935 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(x) },1972 "{s},{s}: 0x{x}: ARM64_RELOC_ADDEND followed by {s}",
1973 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(x) },
1936 );1974 );
1937 return error.ParseFailed;1975 return error.MalformedObject;
1938 },1976 },
1939 }1977 }
1940 },1978 },
...@@ -1958,10 +1996,10 @@ const aarch64 = struct {...@@ -1958,10 +1996,10 @@ const aarch64 = struct {
1958 else1996 else
1959 addend;1997 addend;
1960 const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse {1998 const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse {
1961 macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{1999 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{
1962 self.fmtPath(), sect.segName(), sect.sectName(), rel.r_address,2000 sect.segName(), sect.sectName(), rel.r_address,
1963 });2001 });
1964 return error.ParseFailed;2002 return error.MalformedObject;
1965 };2003 };
1966 addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file)));2004 addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file)));
1967 break :blk target;2005 break :blk target;
...@@ -1971,34 +2009,38 @@ const aarch64 = struct {...@@ -1971,34 +2009,38 @@ const aarch64 = struct {
1971 @as(macho.reloc_type_arm64, @enumFromInt(relocs[i - 1].r_type)) == .ARM64_RELOC_SUBTRACTOR)2009 @as(macho.reloc_type_arm64, @enumFromInt(relocs[i - 1].r_type)) == .ARM64_RELOC_SUBTRACTOR)
1972 blk: {2010 blk: {
1973 if (rel_type != .ARM64_RELOC_UNSIGNED) {2011 if (rel_type != .ARM64_RELOC_UNSIGNED) {
1974 macho_file.base.fatal("{}: {s},{s}: 0x{x}: ARM64_RELOC_SUBTRACTOR followed by {s}", .{2012 try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: ARM64_RELOC_SUBTRACTOR followed by {s}", .{
1975 self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type),2013 sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type),
1976 });2014 });
1977 return error.ParseFailed;2015 return error.MalformedObject;
1978 }2016 }
1979 break :blk true;2017 break :blk true;
1980 } else false;2018 } else false;
19812019
1982 const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| {2020 const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| {
1983 switch (err) {2021 switch (err) {
1984 error.Pcrel => macho_file.base.fatal(2022 error.Pcrel => try macho_file.reportParseError2(
1985 "{}: {s},{s}: 0x{x}: PC-relative {s} relocation",2023 self.index,
1986 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },2024 "{s},{s}: 0x{x}: PC-relative {s} relocation",
2025 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },
1987 ),2026 ),
1988 error.NonPcrel => macho_file.base.fatal(2027 error.NonPcrel => try macho_file.reportParseError2(
1989 "{}: {s},{s}: 0x{x}: non-PC-relative {s} relocation",2028 self.index,
1990 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },2029 "{s},{s}: 0x{x}: non-PC-relative {s} relocation",
2030 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },
1991 ),2031 ),
1992 error.InvalidLength => macho_file.base.fatal(2032 error.InvalidLength => try macho_file.reportParseError2(
1993 "{}: {s},{s}: 0x{x}: invalid length of {d} in {s} relocation",2033 self.index,
1994 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) },2034 "{s},{s}: 0x{x}: invalid length of {d} in {s} relocation",
2035 .{ sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) },
1995 ),2036 ),
1996 error.NonExtern => macho_file.base.fatal(2037 error.NonExtern => try macho_file.reportParseError2(
1997 "{}: {s},{s}: 0x{x}: non-extern target in {s} relocation",2038 self.index,
1998 .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },2039 "{s},{s}: 0x{x}: non-extern target in {s} relocation",
2040 .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) },
1999 ),2041 ),
2000 }2042 }
2001 return error.ParseFailed;2043 return error.MalformedObject;
2002 };2044 };
20032045
2004 out.appendAssumeCapacity(.{2046 out.appendAssumeCapacity(.{
src/link/MachO/Symbol.zig+1-1
...@@ -55,7 +55,7 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {...@@ -55,7 +55,7 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {
55}55}
5656
57pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 {57pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 {
58 return macho_file.string_intern.getAssumeExists(symbol.name);58 return macho_file.strings.getAssumeExists(symbol.name);
59}59}
6060
61pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom {61pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom {
src/link/MachO/UnwindInfo.zig+1-1
...@@ -372,7 +372,7 @@ pub const Encoding = extern struct {...@@ -372,7 +372,7 @@ pub const Encoding = extern struct {
372372
373 pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool {373 pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool {
374 const mode = enc.getMode();374 const mode = enc.getMode();
375 return switch (macho_file.options.cpu_arch.?) {375 return switch (macho_file.getTarget().cpu.arch) {
376 .aarch64 => @as(macho.UNWIND_ARM64_MODE, @enumFromInt(mode)) == .DWARF,376 .aarch64 => @as(macho.UNWIND_ARM64_MODE, @enumFromInt(mode)) == .DWARF,
377 .x86_64 => @as(macho.UNWIND_X86_64_MODE, @enumFromInt(mode)) == .DWARF,377 .x86_64 => @as(macho.UNWIND_X86_64_MODE, @enumFromInt(mode)) == .DWARF,
378 else => unreachable,378 else => unreachable,
src/link/MachO/eh_frame.zig+8-9
...@@ -155,10 +155,10 @@ pub const Fde = struct {...@@ -155,10 +155,10 @@ pub const Fde = struct {
155 const pc_begin = std.mem.readInt(i64, data[8..][0..8], .little);155 const pc_begin = std.mem.readInt(i64, data[8..][0..8], .little);
156 const taddr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + 8)) + pc_begin);156 const taddr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + 8)) + pc_begin);
157 fde.atom = object.findAtom(taddr) orelse {157 fde.atom = object.findAtom(taddr) orelse {
158 macho_file.base.fatal("{}: {s},{s}: 0x{x}: invalid function reference in FDE", .{158 try macho_file.reportParseError2(object.index, "{s},{s}: 0x{x}: invalid function reference in FDE", .{
159 object.fmtPath(), sect.segName(), sect.sectName(), fde.offset + 8,159 sect.segName(), sect.sectName(), fde.offset + 8,
160 });160 });
161 return error.ParseFailed;161 return error.MalformedObject;
162 };162 };
163 const atom = fde.getAtom(macho_file);163 const atom = fde.getAtom(macho_file);
164 fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file));164 fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file));
...@@ -172,11 +172,10 @@ pub const Fde = struct {...@@ -172,11 +172,10 @@ pub const Fde = struct {
172 if (cie_index) |cie| {172 if (cie_index) |cie| {
173 fde.cie = cie;173 fde.cie = cie;
174 } else {174 } else {
175 macho_file.base.fatal("{}: no matching CIE found for FDE at offset {x}", .{175 try macho_file.reportParseError2(object.index, "no matching CIE found for FDE at offset {x}", .{
176 object.fmtPath(),
177 fde.offset,176 fde.offset,
178 });177 });
179 return error.ParseFailed;178 return error.MalformedObject;
180 }179 }
181180
182 const cie = fde.getCie(macho_file);181 const cie = fde.getCie(macho_file);
...@@ -194,10 +193,10 @@ pub const Fde = struct {...@@ -194,10 +193,10 @@ pub const Fde = struct {
194 };193 };
195 const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr);194 const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr);
196 fde.lsda = object.findAtom(lsda_addr) orelse {195 fde.lsda = object.findAtom(lsda_addr) orelse {
197 macho_file.base.fatal("{}: {s},{s}: 0x{x}: invalid LSDA reference in FDE", .{196 try macho_file.reportParseError2(object.index, "{s},{s}: 0x{x}: invalid LSDA reference in FDE", .{
198 object.fmtPath(), sect.segName(), sect.sectName(), fde.offset + fde.lsda_ptr_offset,197 sect.segName(), sect.sectName(), fde.offset + fde.lsda_ptr_offset,
199 });198 });
200 return error.ParseFailed;199 return error.MalformedObject;
201 };200 };
202 const lsda_atom = fde.getLsdaAtom(macho_file).?;201 const lsda_atom = fde.getLsdaAtom(macho_file).?;
203 fde.lsda_offset = @intCast(lsda_addr - lsda_atom.getInputAddress(macho_file));202 fde.lsda_offset = @intCast(lsda_addr - lsda_atom.getInputAddress(macho_file));
src/link/MachO/synthetic.zig+17-17
...@@ -8,7 +8,7 @@ pub const GotSection = struct {...@@ -8,7 +8,7 @@ pub const GotSection = struct {
8 }8 }
99
10 pub fn addSymbol(got: *GotSection, sym_index: Symbol.Index, macho_file: *MachO) !void {10 pub fn addSymbol(got: *GotSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
11 const gpa = macho_file.base.allocator;11 const gpa = macho_file.base.comp.gpa;
12 const index = @as(Index, @intCast(got.symbols.items.len));12 const index = @as(Index, @intCast(got.symbols.items.len));
13 const entry = try got.symbols.addOne(gpa);13 const entry = try got.symbols.addOne(gpa);
14 entry.* = sym_index;14 entry.* = sym_index;
...@@ -29,7 +29,7 @@ pub const GotSection = struct {...@@ -29,7 +29,7 @@ pub const GotSection = struct {
29 pub fn addDyldRelocs(got: GotSection, macho_file: *MachO) !void {29 pub fn addDyldRelocs(got: GotSection, macho_file: *MachO) !void {
30 const tracy = trace(@src());30 const tracy = trace(@src());
31 defer tracy.end();31 defer tracy.end();
32 const gpa = macho_file.base.allocator;32 const gpa = macho_file.base.comp.gpa;
33 const seg_id = macho_file.sections.items(.segment_id)[macho_file.got_sect_index.?];33 const seg_id = macho_file.sections.items(.segment_id)[macho_file.got_sect_index.?];
34 const seg = macho_file.segments.items[seg_id];34 const seg = macho_file.segments.items[seg_id];
3535
...@@ -111,7 +111,7 @@ pub const StubsSection = struct {...@@ -111,7 +111,7 @@ pub const StubsSection = struct {
111 }111 }
112112
113 pub fn addSymbol(stubs: *StubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {113 pub fn addSymbol(stubs: *StubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
114 const gpa = macho_file.base.allocator;114 const gpa = macho_file.base.comp.gpa;
115 const index = @as(Index, @intCast(stubs.symbols.items.len));115 const index = @as(Index, @intCast(stubs.symbols.items.len));
116 const entry = try stubs.symbols.addOne(gpa);116 const entry = try stubs.symbols.addOne(gpa);
117 entry.* = sym_index;117 entry.* = sym_index;
...@@ -133,7 +133,7 @@ pub const StubsSection = struct {...@@ -133,7 +133,7 @@ pub const StubsSection = struct {
133 pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void {133 pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void {
134 const tracy = trace(@src());134 const tracy = trace(@src());
135 defer tracy.end();135 defer tracy.end();
136 const cpu_arch = macho_file.options.cpu_arch.?;136 const cpu_arch = macho_file.getTarget().cpu.arch;
137 const laptr_sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?];137 const laptr_sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?];
138138
139 for (stubs.symbols.items, 0..) |sym_index, idx| {139 for (stubs.symbols.items, 0..) |sym_index, idx| {
...@@ -213,7 +213,7 @@ pub const StubsHelperSection = struct {...@@ -213,7 +213,7 @@ pub const StubsHelperSection = struct {
213 const tracy = trace(@src());213 const tracy = trace(@src());
214 defer tracy.end();214 defer tracy.end();
215 _ = stubs_helper;215 _ = stubs_helper;
216 const cpu_arch = macho_file.options.cpu_arch.?;216 const cpu_arch = macho_file.getTarget().cpu.arch;
217 var s: usize = preambleSize(cpu_arch);217 var s: usize = preambleSize(cpu_arch);
218 for (macho_file.stubs.symbols.items) |sym_index| {218 for (macho_file.stubs.symbols.items) |sym_index| {
219 const sym = macho_file.getSymbol(sym_index);219 const sym = macho_file.getSymbol(sym_index);
...@@ -230,7 +230,7 @@ pub const StubsHelperSection = struct {...@@ -230,7 +230,7 @@ pub const StubsHelperSection = struct {
230230
231 try stubs_helper.writePreamble(macho_file, writer);231 try stubs_helper.writePreamble(macho_file, writer);
232232
233 const cpu_arch = macho_file.options.cpu_arch.?;233 const cpu_arch = macho_file.getTarget().cpu.arch;
234 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];234 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
235 const preamble_size = preambleSize(cpu_arch);235 const preamble_size = preambleSize(cpu_arch);
236 const entry_size = entrySize(cpu_arch);236 const entry_size = entrySize(cpu_arch);
...@@ -272,7 +272,7 @@ pub const StubsHelperSection = struct {...@@ -272,7 +272,7 @@ pub const StubsHelperSection = struct {
272272
273 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {273 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {
274 _ = stubs_helper;274 _ = stubs_helper;
275 const cpu_arch = macho_file.options.cpu_arch.?;275 const cpu_arch = macho_file.getTarget().cpu.arch;
276 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];276 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
277 const dyld_private_addr = target: {277 const dyld_private_addr = target: {
278 const sym = macho_file.getSymbol(macho_file.dyld_private_index.?);278 const sym = macho_file.getSymbol(macho_file.dyld_private_index.?);
...@@ -331,7 +331,7 @@ pub const LaSymbolPtrSection = struct {...@@ -331,7 +331,7 @@ pub const LaSymbolPtrSection = struct {
331 const tracy = trace(@src());331 const tracy = trace(@src());
332 defer tracy.end();332 defer tracy.end();
333 _ = laptr;333 _ = laptr;
334 const gpa = macho_file.base.allocator;334 const gpa = macho_file.base.comp.gpa;
335335
336 const sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?];336 const sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?];
337 const seg_id = macho_file.sections.items(.segment_id)[macho_file.la_symbol_ptr_sect_index.?];337 const seg_id = macho_file.sections.items(.segment_id)[macho_file.la_symbol_ptr_sect_index.?];
...@@ -371,7 +371,7 @@ pub const LaSymbolPtrSection = struct {...@@ -371,7 +371,7 @@ pub const LaSymbolPtrSection = struct {
371 const tracy = trace(@src());371 const tracy = trace(@src());
372 defer tracy.end();372 defer tracy.end();
373 _ = laptr;373 _ = laptr;
374 const cpu_arch = macho_file.options.cpu_arch.?;374 const cpu_arch = macho_file.getTarget().cpu.arch;
375 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];375 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
376 for (macho_file.stubs.symbols.items, 0..) |sym_index, idx| {376 for (macho_file.stubs.symbols.items, 0..) |sym_index, idx| {
377 const sym = macho_file.getSymbol(sym_index);377 const sym = macho_file.getSymbol(sym_index);
...@@ -397,7 +397,7 @@ pub const TlvPtrSection = struct {...@@ -397,7 +397,7 @@ pub const TlvPtrSection = struct {
397 }397 }
398398
399 pub fn addSymbol(tlv: *TlvPtrSection, sym_index: Symbol.Index, macho_file: *MachO) !void {399 pub fn addSymbol(tlv: *TlvPtrSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
400 const gpa = macho_file.base.allocator;400 const gpa = macho_file.base.comp.gpa;
401 const index = @as(Index, @intCast(tlv.symbols.items.len));401 const index = @as(Index, @intCast(tlv.symbols.items.len));
402 const entry = try tlv.symbols.addOne(gpa);402 const entry = try tlv.symbols.addOne(gpa);
403 entry.* = sym_index;403 entry.* = sym_index;
...@@ -418,7 +418,7 @@ pub const TlvPtrSection = struct {...@@ -418,7 +418,7 @@ pub const TlvPtrSection = struct {
418 pub fn addDyldRelocs(tlv: TlvPtrSection, macho_file: *MachO) !void {418 pub fn addDyldRelocs(tlv: TlvPtrSection, macho_file: *MachO) !void {
419 const tracy = trace(@src());419 const tracy = trace(@src());
420 defer tracy.end();420 defer tracy.end();
421 const gpa = macho_file.base.allocator;421 const gpa = macho_file.base.comp.gpa;
422 const seg_id = macho_file.sections.items(.segment_id)[macho_file.tlv_ptr_sect_index.?];422 const seg_id = macho_file.sections.items(.segment_id)[macho_file.tlv_ptr_sect_index.?];
423 const seg = macho_file.segments.items[seg_id];423 const seg = macho_file.segments.items[seg_id];
424424
...@@ -510,7 +510,7 @@ pub const ObjcStubsSection = struct {...@@ -510,7 +510,7 @@ pub const ObjcStubsSection = struct {
510 }510 }
511511
512 pub fn addSymbol(objc: *ObjcStubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {512 pub fn addSymbol(objc: *ObjcStubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
513 const gpa = macho_file.base.allocator;513 const gpa = macho_file.base.comp.gpa;
514 const index = @as(Index, @intCast(objc.symbols.items.len));514 const index = @as(Index, @intCast(objc.symbols.items.len));
515 const entry = try objc.symbols.addOne(gpa);515 const entry = try objc.symbols.addOne(gpa);
516 entry.* = sym_index;516 entry.* = sym_index;
...@@ -521,11 +521,11 @@ pub const ObjcStubsSection = struct {...@@ -521,11 +521,11 @@ pub const ObjcStubsSection = struct {
521 pub fn getAddress(objc: ObjcStubsSection, index: Index, macho_file: *MachO) u64 {521 pub fn getAddress(objc: ObjcStubsSection, index: Index, macho_file: *MachO) u64 {
522 assert(index < objc.symbols.items.len);522 assert(index < objc.symbols.items.len);
523 const header = macho_file.sections.items(.header)[macho_file.objc_stubs_sect_index.?];523 const header = macho_file.sections.items(.header)[macho_file.objc_stubs_sect_index.?];
524 return header.addr + index * entrySize(macho_file.options.cpu_arch.?);524 return header.addr + index * entrySize(macho_file.getTarget().cpu.arch);
525 }525 }
526526
527 pub fn size(objc: ObjcStubsSection, macho_file: *MachO) usize {527 pub fn size(objc: ObjcStubsSection, macho_file: *MachO) usize {
528 return objc.symbols.items.len * entrySize(macho_file.options.cpu_arch.?);528 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);
529 }529 }
530530
531 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void {531 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void {
...@@ -535,7 +535,7 @@ pub const ObjcStubsSection = struct {...@@ -535,7 +535,7 @@ pub const ObjcStubsSection = struct {
535 for (objc.symbols.items, 0..) |sym_index, idx| {535 for (objc.symbols.items, 0..) |sym_index, idx| {
536 const sym = macho_file.getSymbol(sym_index);536 const sym = macho_file.getSymbol(sym_index);
537 const addr = objc.getAddress(@intCast(idx), macho_file);537 const addr = objc.getAddress(@intCast(idx), macho_file);
538 switch (macho_file.options.cpu_arch.?) {538 switch (macho_file.getTarget().cpu.arch) {
539 .x86_64 => {539 .x86_64 => {
540 try writer.writeAll(&.{ 0x48, 0x8b, 0x35 });540 try writer.writeAll(&.{ 0x48, 0x8b, 0x35 });
541 {541 {
...@@ -654,12 +654,12 @@ pub const WeakBindSection = bind.WeakBind;...@@ -654,12 +654,12 @@ pub const WeakBindSection = bind.WeakBind;
654pub const LazyBindSection = bind.LazyBind;654pub const LazyBindSection = bind.LazyBind;
655pub const ExportTrieSection = Trie;655pub const ExportTrieSection = Trie;
656656
657const aarch64 = @import("../aarch64.zig");657const aarch64 = @import("../../arch/aarch64/bits.zig");
658const assert = std.debug.assert;658const assert = std.debug.assert;
659const bind = @import("dyld_info/bind.zig");659const bind = @import("dyld_info/bind.zig");
660const math = std.math;660const math = std.math;
661const std = @import("std");661const std = @import("std");
662const trace = @import("../tracy.zig").trace;662const trace = @import("../../tracy.zig").trace;
663663
664const Allocator = std.mem.Allocator;664const Allocator = std.mem.Allocator;
665const MachO = @import("../MachO.zig");665const MachO = @import("../MachO.zig");