authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-13 17:00:36+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-13 17:00:36+02:00
log4c36da1047a83019ce7af653a32938c9d1ea616d
tree7f5c1d0bd42379172c700c0edfb9355c93082767
parent1965465ced82dc9c0fb93ea9182f196e6d6f4409

macho: fix incremental compilation


3 files changed, 251 insertions(+), 192 deletions(-)

src/link/MachO.zig+238-192
...@@ -170,6 +170,8 @@ sections_order_dirty: bool = false,...@@ -170,6 +170,8 @@ sections_order_dirty: bool = false,
170has_dices: bool = false,170has_dices: bool = false,
171has_stabs: bool = false,171has_stabs: bool = false,
172172
173args_digest: [Cache.hex_digest_len]u8 = undefined,
174
173section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{},175section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{},
174176
175/// A list of atoms that have surplus capacity. This list can have false177/// A list of atoms that have surplus capacity. This list can have false
...@@ -334,31 +336,31 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -334,31 +336,31 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
334 return self;336 return self;
335 }337 }
336338
337 if (!options.strip and options.module != null) {339 // if (!options.strip and options.module != null) {
338 // Create dSYM bundle.340 // // Create dSYM bundle.
339 const dir = options.module.?.zig_cache_artifact_directory;341 // const dir = options.module.?.zig_cache_artifact_directory;
340 log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path });342 // log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path });
341343
342 const d_sym_path = try fmt.allocPrint(344 // const d_sym_path = try fmt.allocPrint(
343 allocator,345 // allocator,
344 "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",346 // "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
345 .{sub_path},347 // .{sub_path},
346 );348 // );
347 defer allocator.free(d_sym_path);349 // defer allocator.free(d_sym_path);
348350
349 var d_sym_bundle = try dir.handle.makeOpenPath(d_sym_path, .{});351 // var d_sym_bundle = try dir.handle.makeOpenPath(d_sym_path, .{});
350 defer d_sym_bundle.close();352 // defer d_sym_bundle.close();
351353
352 const d_sym_file = try d_sym_bundle.createFile(sub_path, .{354 // const d_sym_file = try d_sym_bundle.createFile(sub_path, .{
353 .truncate = false,355 // .truncate = false,
354 .read = true,356 // .read = true,
355 });357 // });
356358
357 self.d_sym = .{359 // self.d_sym = .{
358 .base = self,360 // .base = self,
359 .file = d_sym_file,361 // .file = d_sym_file,
360 };362 // };
361 }363 // }
362364
363 // Index 0 is always a null symbol.365 // Index 0 is always a null symbol.
364 try self.locals.append(allocator, .{366 try self.locals.append(allocator, .{
...@@ -555,218 +557,256 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -555,218 +557,256 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
555 try self.strtab.append(self.base.allocator, 0);557 try self.strtab.append(self.base.allocator, 0);
556 }558 }
557559
558 // Positional arguments to the linker such as object files and static archives.560 const needs_full_relink = blk: {
559 var positionals = std.ArrayList([]const u8).init(arena);561 if (use_stage1) break :blk true;
560562
561 try positionals.appendSlice(self.base.options.objects);563 var hh: Cache.HashHelper = .{};
564 hh.addListOfBytes(self.base.options.objects);
565 for (comp.c_object_table.keys()) |key| {
566 hh.addBytes(key.status.success.object_path);
567 }
568 hh.addOptionalBytes(module_obj_path);
569 if (comp.compiler_rt_static_lib) |lib| {
570 hh.addBytes(lib.full_object_path);
571 }
572 if (self.base.options.link_libcpp) {
573 hh.addBytes(comp.libcxxabi_static_lib.?.full_object_path);
574 hh.addBytes(comp.libcxx_static_lib.?.full_object_path);
575 }
576 hh.addListOfBytes(self.base.options.lib_dirs);
577 hh.addListOfBytes(self.base.options.framework_dirs);
578 hh.addListOfBytes(self.base.options.frameworks);
579 hh.addListOfBytes(self.base.options.rpath_list);
580 hh.addStringSet(self.base.options.system_libs);
581 hh.addOptionalBytes(self.base.options.sysroot);
582 const new_digest = hh.final();
583 const needs_full_relink = !mem.eql(u8, &new_digest, &self.args_digest);
584 mem.copy(u8, &self.args_digest, &new_digest);
585 break :blk needs_full_relink;
586 };
562587
563 for (comp.c_object_table.keys()) |key| {588 if (needs_full_relink) {
564 try positionals.append(key.status.success.object_path);589 self.objects.clearRetainingCapacity();
565 }590 self.archives.clearRetainingCapacity();
591 self.dylibs.clearRetainingCapacity();
592 self.dylibs_map.clearRetainingCapacity();
593 self.referenced_dylibs.clearRetainingCapacity();
566594
567 if (module_obj_path) |p| {595 // TODO figure out how to clear atoms from objects, etc.
568 try positionals.append(p);
569 }
570596
571 if (comp.compiler_rt_static_lib) |lib| {597 // Positional arguments to the linker such as object files and static archives.
572 try positionals.append(lib.full_object_path);598 var positionals = std.ArrayList([]const u8).init(arena);
573 }
574599
575 // libc++ dep600 try positionals.appendSlice(self.base.options.objects);
576 if (self.base.options.link_libcpp) {
577 try positionals.append(comp.libcxxabi_static_lib.?.full_object_path);
578 try positionals.append(comp.libcxx_static_lib.?.full_object_path);
579 }
580601
581 // Shared and static libraries passed via `-l` flag.602 for (comp.c_object_table.keys()) |key| {
582 var search_lib_names = std.ArrayList([]const u8).init(arena);603 try positionals.append(key.status.success.object_path);
604 }
583605
584 const system_libs = self.base.options.system_libs.keys();606 if (module_obj_path) |p| {
585 for (system_libs) |link_lib| {607 try positionals.append(p);
586 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
587 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
588 // case we want to avoid prepending "-l".
589 if (Compilation.classifyFileExt(link_lib) == .shared_library) {
590 try positionals.append(link_lib);
591 continue;
592 }608 }
593609
594 try search_lib_names.append(link_lib);610 if (comp.compiler_rt_static_lib) |lib| {
595 }611 try positionals.append(lib.full_object_path);
612 }
596613
597 var lib_dirs = std.ArrayList([]const u8).init(arena);614 // libc++ dep
598 for (self.base.options.lib_dirs) |dir| {615 if (self.base.options.link_libcpp) {
599 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {616 try positionals.append(comp.libcxxabi_static_lib.?.full_object_path);
600 try lib_dirs.append(search_dir);617 try positionals.append(comp.libcxx_static_lib.?.full_object_path);
601 } else {
602 log.warn("directory not found for '-L{s}'", .{dir});
603 }618 }
604 }
605619
606 var libs = std.ArrayList([]const u8).init(arena);620 // Shared and static libraries passed via `-l` flag.
607 var lib_not_found = false;621 var search_lib_names = std.ArrayList([]const u8).init(arena);
608 for (search_lib_names.items) |lib_name| {622
609 // Assume ld64 default: -search_paths_first623 const system_libs = self.base.options.system_libs.keys();
610 // Look in each directory for a dylib (stub first), and then for archive624 for (system_libs) |link_lib| {
611 // TODO implement alternative: -search_dylibs_first625 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
612 for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {626 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
613 if (try resolveLib(arena, lib_dirs.items, lib_name, ext)) |full_path| {627 // case we want to avoid prepending "-l".
614 try libs.append(full_path);628 if (Compilation.classifyFileExt(link_lib) == .shared_library) {
615 break;629 try positionals.append(link_lib);
630 continue;
616 }631 }
617 } else {632
618 log.warn("library not found for '-l{s}'", .{lib_name});633 try search_lib_names.append(link_lib);
619 lib_not_found = true;
620 }634 }
621 }
622635
623 if (lib_not_found) {636 var lib_dirs = std.ArrayList([]const u8).init(arena);
624 log.warn("Library search paths:", .{});637 for (self.base.options.lib_dirs) |dir| {
625 for (lib_dirs.items) |dir| {638 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
626 log.warn(" {s}", .{dir});639 try lib_dirs.append(search_dir);
640 } else {
641 log.warn("directory not found for '-L{s}'", .{dir});
642 }
627 }643 }
628 }
629644
630 // If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.645 var libs = std.ArrayList([]const u8).init(arena);
631 var libsystem_available = false;646 var lib_not_found = false;
632 if (self.base.options.sysroot != null) blk: {647 for (search_lib_names.items) |lib_name| {
633 // Try stub file first. If we hit it, then we're done as the stub file648 // Assume ld64 default: -search_paths_first
634 // re-exports every single symbol definition.649 // Look in each directory for a dylib (stub first), and then for archive
635 if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {650 // TODO implement alternative: -search_dylibs_first
636 try libs.append(full_path);651 for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
637 libsystem_available = true;652 if (try resolveLib(arena, lib_dirs.items, lib_name, ext)) |full_path| {
638 break :blk;653 try libs.append(full_path);
654 break;
655 }
656 } else {
657 log.warn("library not found for '-l{s}'", .{lib_name});
658 lib_not_found = true;
659 }
639 }660 }
640 // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib661
641 // doesn't export libc.dylib which we'll need to resolve subsequently also.662 if (lib_not_found) {
642 if (try resolveLib(arena, lib_dirs.items, "System", ".dylib")) |libsystem_path| {663 log.warn("Library search paths:", .{});
643 if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {664 for (lib_dirs.items) |dir| {
644 try libs.append(libsystem_path);665 log.warn(" {s}", .{dir});
645 try libs.append(libc_path);666 }
667 }
668
669 // If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
670 var libsystem_available = false;
671 if (self.base.options.sysroot != null) blk: {
672 // Try stub file first. If we hit it, then we're done as the stub file
673 // re-exports every single symbol definition.
674 if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {
675 try libs.append(full_path);
646 libsystem_available = true;676 libsystem_available = true;
647 break :blk;677 break :blk;
648 }678 }
679 // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
680 // doesn't export libc.dylib which we'll need to resolve subsequently also.
681 if (try resolveLib(arena, lib_dirs.items, "System", ".dylib")) |libsystem_path| {
682 if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {
683 try libs.append(libsystem_path);
684 try libs.append(libc_path);
685 libsystem_available = true;
686 break :blk;
687 }
688 }
689 }
690 if (!libsystem_available) {
691 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
692 "libc", "darwin", "libSystem.B.tbd",
693 });
694 try libs.append(full_path);
649 }695 }
650 }
651 if (!libsystem_available) {
652 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
653 "libc", "darwin", "libSystem.B.tbd",
654 });
655 try libs.append(full_path);
656 }
657696
658 // frameworks697 // frameworks
659 var framework_dirs = std.ArrayList([]const u8).init(arena);698 var framework_dirs = std.ArrayList([]const u8).init(arena);
660 for (self.base.options.framework_dirs) |dir| {699 for (self.base.options.framework_dirs) |dir| {
661 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {700 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
662 try framework_dirs.append(search_dir);701 try framework_dirs.append(search_dir);
663 } else {702 } else {
664 log.warn("directory not found for '-F{s}'", .{dir});703 log.warn("directory not found for '-F{s}'", .{dir});
704 }
665 }705 }
666 }
667706
668 var framework_not_found = false;707 var framework_not_found = false;
669 for (self.base.options.frameworks) |framework| {708 for (self.base.options.frameworks) |framework| {
670 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {709 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
671 if (try resolveFramework(arena, framework_dirs.items, framework, ext)) |full_path| {710 if (try resolveFramework(arena, framework_dirs.items, framework, ext)) |full_path| {
672 try libs.append(full_path);711 try libs.append(full_path);
673 break;712 break;
713 }
714 } else {
715 log.warn("framework not found for '-framework {s}'", .{framework});
716 framework_not_found = true;
674 }717 }
675 } else {
676 log.warn("framework not found for '-framework {s}'", .{framework});
677 framework_not_found = true;
678 }718 }
679 }
680719
681 if (framework_not_found) {720 if (framework_not_found) {
682 log.warn("Framework search paths:", .{});721 log.warn("Framework search paths:", .{});
683 for (framework_dirs.items) |dir| {722 for (framework_dirs.items) |dir| {
684 log.warn(" {s}", .{dir});723 log.warn(" {s}", .{dir});
724 }
685 }725 }
686 }
687726
688 // rpaths727 // rpaths
689 var rpath_table = std.StringArrayHashMap(void).init(arena);728 var rpath_table = std.StringArrayHashMap(void).init(arena);
690 for (self.base.options.rpath_list) |rpath| {729 for (self.base.options.rpath_list) |rpath| {
691 if (rpath_table.contains(rpath)) continue;730 if (rpath_table.contains(rpath)) continue;
692 const cmdsize = @intCast(u32, mem.alignForwardGeneric(731 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
693 u64,732 u64,
694 @sizeOf(macho.rpath_command) + rpath.len + 1,733 @sizeOf(macho.rpath_command) + rpath.len + 1,
695 @sizeOf(u64),734 @sizeOf(u64),
696 ));735 ));
697 var rpath_cmd = commands.emptyGenericCommandWithData(macho.rpath_command{736 var rpath_cmd = commands.emptyGenericCommandWithData(macho.rpath_command{
698 .cmd = macho.LC_RPATH,737 .cmd = macho.LC_RPATH,
699 .cmdsize = cmdsize,738 .cmdsize = cmdsize,
700 .path = @sizeOf(macho.rpath_command),739 .path = @sizeOf(macho.rpath_command),
701 });740 });
702 rpath_cmd.data = try self.base.allocator.alloc(u8, cmdsize - rpath_cmd.inner.path);741 rpath_cmd.data = try self.base.allocator.alloc(u8, cmdsize - rpath_cmd.inner.path);
703 mem.set(u8, rpath_cmd.data, 0);742 mem.set(u8, rpath_cmd.data, 0);
704 mem.copy(u8, rpath_cmd.data, rpath);743 mem.copy(u8, rpath_cmd.data, rpath);
705 try self.load_commands.append(self.base.allocator, .{ .Rpath = rpath_cmd });744 try self.load_commands.append(self.base.allocator, .{ .Rpath = rpath_cmd });
706 try rpath_table.putNoClobber(rpath, {});745 try rpath_table.putNoClobber(rpath, {});
707 self.load_commands_dirty = true;746 self.load_commands_dirty = true;
708 }747 }
709748
710 if (self.base.options.verbose_link) {749 if (self.base.options.verbose_link) {
711 var argv = std.ArrayList([]const u8).init(arena);750 var argv = std.ArrayList([]const u8).init(arena);
712751
713 try argv.append("zig");752 try argv.append("zig");
714 try argv.append("ld");753 try argv.append("ld");
715754
716 if (is_exe_or_dyn_lib) {755 if (is_exe_or_dyn_lib) {
717 try argv.append("-dynamic");756 try argv.append("-dynamic");
718 }757 }
719758
720 if (is_dyn_lib) {759 if (is_dyn_lib) {
721 try argv.append("-dylib");760 try argv.append("-dylib");
722761
723 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{762 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{
724 self.base.options.emit.?.sub_path,763 self.base.options.emit.?.sub_path,
725 });764 });
726 try argv.append("-install_name");765 try argv.append("-install_name");
727 try argv.append(install_name);766 try argv.append(install_name);
728 }767 }
729768
730 if (self.base.options.sysroot) |syslibroot| {769 if (self.base.options.sysroot) |syslibroot| {
731 try argv.append("-syslibroot");770 try argv.append("-syslibroot");
732 try argv.append(syslibroot);771 try argv.append(syslibroot);
733 }772 }
734773
735 for (rpath_table.keys()) |rpath| {774 for (rpath_table.keys()) |rpath| {
736 try argv.append("-rpath");775 try argv.append("-rpath");
737 try argv.append(rpath);776 try argv.append(rpath);
738 }777 }
739778
740 try argv.appendSlice(positionals.items);779 try argv.appendSlice(positionals.items);
741780
742 try argv.append("-o");781 try argv.append("-o");
743 try argv.append(full_out_path);782 try argv.append(full_out_path);
744783
745 try argv.append("-lSystem");784 try argv.append("-lSystem");
746 try argv.append("-lc");785 try argv.append("-lc");
747786
748 for (search_lib_names.items) |l_name| {787 for (search_lib_names.items) |l_name| {
749 try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));788 try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));
750 }789 }
751790
752 for (self.base.options.lib_dirs) |lib_dir| {791 for (self.base.options.lib_dirs) |lib_dir| {
753 try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));792 try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));
754 }793 }
755794
756 for (self.base.options.frameworks) |framework| {795 for (self.base.options.frameworks) |framework| {
757 try argv.append(try std.fmt.allocPrint(arena, "-framework {s}", .{framework}));796 try argv.append(try std.fmt.allocPrint(arena, "-framework {s}", .{framework}));
758 }797 }
759798
760 for (self.base.options.framework_dirs) |framework_dir| {799 for (self.base.options.framework_dirs) |framework_dir| {
761 try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir}));800 try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir}));
801 }
802
803 Compilation.dump_argv(argv.items);
762 }804 }
763805
764 Compilation.dump_argv(argv.items);806 try self.parseInputFiles(positionals.items, self.base.options.sysroot);
807 try self.parseLibs(libs.items, self.base.options.sysroot);
765 }808 }
766809
767 try self.parseInputFiles(positionals.items, self.base.options.sysroot);
768 try self.parseLibs(libs.items, self.base.options.sysroot);
769
770 if (self.bss_section_index) |idx| {810 if (self.bss_section_index) |idx| {
771 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;811 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
772 const sect = &seg.sections.items[idx];812 const sect = &seg.sections.items[idx];
...@@ -778,7 +818,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -778,7 +818,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
778 sect.offset = self.tlv_bss_file_offset;818 sect.offset = self.tlv_bss_file_offset;
779 }819 }
780820
781 for (self.objects.items) |_, object_id| {821 for (self.objects.items) |*object, object_id| {
822 if (object.analyzed) continue;
782 try self.resolveSymbolsInObject(@intCast(u16, object_id));823 try self.resolveSymbolsInObject(@intCast(u16, object_id));
783 }824 }
784825
...@@ -2617,6 +2658,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {...@@ -2617,6 +2658,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
2617 defer section_metadata.deinit();2658 defer section_metadata.deinit();
26182659
2619 for (self.objects.items) |*object, object_id| {2660 for (self.objects.items) |*object, object_id| {
2661 if (object.analyzed) continue;
2662
2620 var atoms_in_objects = try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_id), self);2663 var atoms_in_objects = try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_id), self);
2621 defer atoms_in_objects.deinit();2664 defer atoms_in_objects.deinit();
26222665
...@@ -2663,6 +2706,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {...@@ -2663,6 +2706,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
2663 try first_atoms.putNoClobber(match, atom);2706 try first_atoms.putNoClobber(match, atom);
2664 }2707 }
2665 }2708 }
2709
2710 object.analyzed = true;
2666 }2711 }
26672712
2668 var it = section_metadata.iterator();2713 var it = section_metadata.iterator();
...@@ -3003,6 +3048,12 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -3003,6 +3048,12 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
3003 defer tracy.end();3048 defer tracy.end();
30043049
3005 const decl = func.owner_decl;3050 const decl = func.owner_decl;
3051 // TODO clearing the code and relocs buffer should probably be orchestrated
3052 // in a different, smarter, more automatic way somewhere else, in a more centralised
3053 // way than this.
3054 // If we don't clear the buffers here, we are up for some nasty surprises when
3055 // this atom is reused later on and was not freed by freeAtom().
3056 decl.link.macho.clearRetainingCapacity();
30063057
3007 var code_buffer = std.ArrayList(u8).init(self.base.allocator);3058 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
3008 defer code_buffer.deinit();3059 defer code_buffer.deinit();
...@@ -3038,12 +3089,6 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -3038,12 +3089,6 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
3038 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);3089 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
3039 switch (res) {3090 switch (res) {
3040 .appended => {3091 .appended => {
3041 // TODO clearing the code and relocs buffer should probably be orchestrated
3042 // in a different, smarter, more automatic way somewhere else, in a more centralised
3043 // way than this.
3044 // If we don't clear the buffers here, we are up for some nasty surprises when
3045 // this atom is reused later on and was not freed by freeAtom().
3046 decl.link.macho.code.clearAndFree(self.base.allocator);
3047 try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items);3092 try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items);
3048 },3093 },
3049 .fail => |em| {3094 .fail => |em| {
...@@ -3194,6 +3239,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64...@@ -3194,6 +3239,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
3194 });3239 });
3195 }3240 }
3196 decl.link.macho.size = code_len;3241 decl.link.macho.size = code_len;
3242 decl.link.macho.dirty = true;
31973243
3198 const new_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)});3244 const new_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)});
3199 defer self.base.allocator.free(new_name);3245 defer self.base.allocator.free(new_name);
src/link/MachO/Atom.zig+11
...@@ -600,6 +600,17 @@ pub fn deinit(self: *Atom, allocator: *Allocator) void {...@@ -600,6 +600,17 @@ pub fn deinit(self: *Atom, allocator: *Allocator) void {
600 self.code.deinit(allocator);600 self.code.deinit(allocator);
601}601}
602602
603pub fn clearRetainingCapacity(self: *Atom) void {
604 self.dices.clearRetainingCapacity();
605 self.lazy_bindings.clearRetainingCapacity();
606 self.bindings.clearRetainingCapacity();
607 self.rebases.clearRetainingCapacity();
608 self.relocs.clearRetainingCapacity();
609 self.contained.clearRetainingCapacity();
610 self.aliases.clearRetainingCapacity();
611 self.code.clearRetainingCapacity();
612}
613
603/// Returns how much room there is to grow in virtual address space.614/// Returns how much room there is to grow in virtual address space.
604/// File offset relocation happens transparently, so it is not included in615/// File offset relocation happens transparently, so it is not included in
605/// this calculation.616/// this calculation.
src/link/MachO/Object.zig+2
...@@ -64,6 +64,8 @@ sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{},...@@ -64,6 +64,8 @@ sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{},
64symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},64symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},
65reverse_symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},65reverse_symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},
6666
67analyzed: bool = false,
68
67const DebugInfo = struct {69const DebugInfo = struct {
68 inner: dwarf.DwarfInfo,70 inner: dwarf.DwarfInfo,
69 debug_info: []u8,71 debug_info: []u8,