| ... | @@ -170,6 +170,8 @@ sections_order_dirty: bool = false, | ... | @@ -170,6 +170,8 @@ sections_order_dirty: bool = false, |
| 170 | has_dices: bool = false, | 170 | has_dices: bool = false, |
| 171 | has_stabs: bool = false, | 171 | has_stabs: bool = false, |
| 172 | | 172 | |
| | 173 | args_digest: [Cache.hex_digest_len]u8 = undefined, |
| | 174 | |
| 173 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, | 175 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, |
| 174 | | 176 | |
| 175 | /// A list of atoms that have surplus capacity. This list can have false | 177 | /// 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 | } |
| 336 | | 338 | |
| 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 }); |
| 341 | | 343 | |
| 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); |
| 348 | | 350 | |
| 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(); |
| 351 | | 353 | |
| 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 | // }); |
| 356 | | 358 | |
| 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 | // } |
| 362 | | 364 | |
| 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 | } |
| 557 | | 559 | |
| 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; |
| 560 | | 562 | |
| 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 | }; |
| 562 | | 587 | |
| 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(); |
| 566 | | 594 | |
| 567 | if (module_obj_path) |p| { | 595 | // TODO figure out how to clear atoms from objects, etc. |
| 568 | try positionals.append(p); | | |
| 569 | } | | |
| 570 | | 596 | |
| 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 | } | | |
| 574 | | 599 | |
| 575 | // libc++ dep | 600 | 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 | } | | |
| 580 | | 601 | |
| 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 | } |
| 583 | | 605 | |
| 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 | } |
| 593 | | 609 | |
| 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 | } |
| 596 | | 613 | |
| 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 | } | | |
| 605 | | 619 | |
| 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_first | 623 | const system_libs = self.base.options.system_libs.keys(); |
| 610 | // Look in each directory for a dylib (stub first), and then for archive | 624 | for (system_libs) |link_lib| { |
| 611 | // TODO implement alternative: -search_dylibs_first | 625 | // 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 | } | | |
| 622 | | 635 | |
| 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 | } | | |
| 629 | | 644 | |
| 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 file | 648 | // 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.dylib | 661 | |
| 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 | } | | |
| 657 | | 696 | |
| 658 | // frameworks | 697 | // 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 | } | | |
| 667 | | 706 | |
| 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 | } | | |
| 680 | | 719 | |
| 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 | } | | |
| 687 | | 726 | |
| 688 | // rpaths | 727 | // 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 | } |
| 709 | | 748 | |
| 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); |
| 712 | | 751 | |
| 713 | try argv.append("zig"); | 752 | try argv.append("zig"); |
| 714 | try argv.append("ld"); | 753 | try argv.append("ld"); |
| 715 | | 754 | |
| 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 | } |
| 719 | | 758 | |
| 720 | if (is_dyn_lib) { | 759 | if (is_dyn_lib) { |
| 721 | try argv.append("-dylib"); | 760 | try argv.append("-dylib"); |
| 722 | | 761 | |
| 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 | } |
| 729 | | 768 | |
| 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 | } |
| 734 | | 773 | |
| 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 | } |
| 739 | | 778 | |
| 740 | try argv.appendSlice(positionals.items); | 779 | try argv.appendSlice(positionals.items); |
| 741 | | 780 | |
| 742 | try argv.append("-o"); | 781 | try argv.append("-o"); |
| 743 | try argv.append(full_out_path); | 782 | try argv.append(full_out_path); |
| 744 | | 783 | |
| 745 | try argv.append("-lSystem"); | 784 | try argv.append("-lSystem"); |
| 746 | try argv.append("-lc"); | 785 | try argv.append("-lc"); |
| 747 | | 786 | |
| 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 | } |
| 751 | | 790 | |
| 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 | } |
| 755 | | 794 | |
| 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 | } |
| 759 | | 798 | |
| 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 | } |
| 763 | | 805 | |
| 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 | } |
| 766 | | 809 | |
| 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 | } |
| 780 | | 820 | |
| 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 | } |
| 784 | | 825 | |
| ... | @@ -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(); |
| 2618 | | 2659 | |
| 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(); |
| 2622 | | 2665 | |
| ... | @@ -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 | } |
| 2667 | | 2712 | |
| 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(); |
| 3004 | | 3049 | |
| 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(); |
| 3006 | | 3057 | |
| 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; |
| 3197 | | 3243 | |
| 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); |