| ... | @@ -401,35 +401,23 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -401,35 +401,23 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 401 | parent: u16, | 401 | parent: u16, |
| 402 | }, .Dynamic).init(arena); | 402 | }, .Dynamic).init(arena); |
| 403 | | 403 | |
| 404 | var parse_error_ctx: struct { | 404 | var parse_ctx = ParseErrorCtx.init(arena); |
| 405 | detected_arch: std.Target.Cpu.Arch, | | |
| 406 | detected_platform: ?Platform, | | |
| 407 | detected_stub_targets: []const []const u8, | | |
| 408 | } = .{ | | |
| 409 | .detected_arch = undefined, | | |
| 410 | .detected_platform = null, | | |
| 411 | .detected_stub_targets = &[0][]const u8{}, | | |
| 412 | }; | | |
| 413 | defer { | | |
| 414 | for (parse_error_ctx.detected_stub_targets) |target| self.base.allocator.free(target); | | |
| 415 | self.base.allocator.free(parse_error_ctx.detected_stub_targets); | | |
| 416 | } | | |
| 417 | | 405 | |
| 418 | for (libs.keys(), libs.values()) |path, lib| { | 406 | for (libs.keys(), libs.values()) |path, lib| { |
| 419 | const in_file = try std.fs.cwd().openFile(path, .{}); | 407 | const in_file = try std.fs.cwd().openFile(path, .{}); |
| 420 | defer in_file.close(); | 408 | defer in_file.close(); |
| 421 | | 409 | defer parse_ctx.detected_targets.clearRetainingCapacity(); |
| 422 | self.parseLibrary( | 410 | self.parseLibrary( |
| 423 | in_file, | 411 | in_file, |
| 424 | path, | 412 | path, |
| 425 | lib, | 413 | lib, |
| 426 | false, | 414 | false, |
| 427 | &dependent_libs, | 415 | &dependent_libs, |
| 428 | &parse_error_ctx, | 416 | &parse_ctx, |
| 429 | ) catch |err| try self.handleAndReportParseError(path, err, parse_error_ctx); | 417 | ) catch |err| try self.handleAndReportParseError(path, err, &parse_ctx); |
| 430 | } | 418 | } |
| 431 | | 419 | |
| 432 | self.parseDependentLibs(&dependent_libs, &parse_error_ctx) catch |err| { | 420 | self.parseDependentLibs(&dependent_libs, &parse_ctx) catch |err| { |
| 433 | // TODO convert to error | 421 | // TODO convert to error |
| 434 | log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)}); | 422 | log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)}); |
| 435 | }; | 423 | }; |
| ... | @@ -727,9 +715,7 @@ fn resolveLib( | ... | @@ -727,9 +715,7 @@ fn resolveLib( |
| 727 | | 715 | |
| 728 | const ParseError = error{ | 716 | const ParseError = error{ |
| 729 | UnknownFileType, | 717 | UnknownFileType, |
| 730 | MissingArchFatLib, | | |
| 731 | InvalidTarget, | 718 | InvalidTarget, |
| 732 | InvalidLibStubTargets, | | |
| 733 | DylibAlreadyExists, | 719 | DylibAlreadyExists, |
| 734 | IncompatibleDylibVersion, | 720 | IncompatibleDylibVersion, |
| 735 | OutOfMemory, | 721 | OutOfMemory, |
| ... | @@ -748,19 +734,19 @@ pub fn parsePositional( | ... | @@ -748,19 +734,19 @@ pub fn parsePositional( |
| 748 | path: []const u8, | 734 | path: []const u8, |
| 749 | must_link: bool, | 735 | must_link: bool, |
| 750 | dependent_libs: anytype, | 736 | dependent_libs: anytype, |
| 751 | error_ctx: anytype, | 737 | ctx: *ParseErrorCtx, |
| 752 | ) ParseError!void { | 738 | ) ParseError!void { |
| 753 | const tracy = trace(@src()); | 739 | const tracy = trace(@src()); |
| 754 | defer tracy.end(); | 740 | defer tracy.end(); |
| 755 | | 741 | |
| 756 | if (Object.isObject(file)) { | 742 | if (Object.isObject(file)) { |
| 757 | try self.parseObject(file, path, error_ctx); | 743 | try self.parseObject(file, path, ctx); |
| 758 | } else { | 744 | } else { |
| 759 | try self.parseLibrary(file, path, .{ | 745 | try self.parseLibrary(file, path, .{ |
| 760 | .path = null, | 746 | .path = null, |
| 761 | .needed = false, | 747 | .needed = false, |
| 762 | .weak = false, | 748 | .weak = false, |
| 763 | }, must_link, dependent_libs, error_ctx); | 749 | }, must_link, dependent_libs, ctx); |
| 764 | } | 750 | } |
| 765 | } | 751 | } |
| 766 | | 752 | |
| ... | @@ -768,7 +754,7 @@ fn parseObject( | ... | @@ -768,7 +754,7 @@ fn parseObject( |
| 768 | self: *MachO, | 754 | self: *MachO, |
| 769 | file: std.fs.File, | 755 | file: std.fs.File, |
| 770 | path: []const u8, | 756 | path: []const u8, |
| 771 | error_ctx: anytype, | 757 | ctx: *ParseErrorCtx, |
| 772 | ) ParseError!void { | 758 | ) ParseError!void { |
| 773 | const tracy = trace(@src()); | 759 | const tracy = trace(@src()); |
| 774 | defer tracy.end(); | 760 | defer tracy.end(); |
| ... | @@ -790,20 +776,21 @@ fn parseObject( | ... | @@ -790,20 +776,21 @@ fn parseObject( |
| 790 | errdefer object.deinit(gpa); | 776 | errdefer object.deinit(gpa); |
| 791 | try object.parse(gpa); | 777 | try object.parse(gpa); |
| 792 | | 778 | |
| 793 | const cpu_arch: std.Target.Cpu.Arch = switch (object.header.cputype) { | 779 | const detected_cpu_arch: std.Target.Cpu.Arch = switch (object.header.cputype) { |
| 794 | macho.CPU_TYPE_ARM64 => .aarch64, | 780 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 795 | macho.CPU_TYPE_X86_64 => .x86_64, | 781 | macho.CPU_TYPE_X86_64 => .x86_64, |
| 796 | else => unreachable, | 782 | else => unreachable, |
| 797 | }; | 783 | }; |
| 798 | error_ctx.detected_arch = cpu_arch; | 784 | const detected_platform = object.getPlatform(); |
| 799 | | 785 | const this_cpu_arch = self.base.options.target.cpu.arch; |
| 800 | if (object.getPlatform()) |platform| { | 786 | const this_platform = Platform.fromTarget(self.base.options.target); |
| 801 | error_ctx.detected_platform = platform; | | |
| 802 | } | | |
| 803 | | 787 | |
| 804 | if (self.base.options.target.cpu.arch != cpu_arch) return error.InvalidTarget; | 788 | if (this_cpu_arch != detected_cpu_arch or |
| 805 | if (error_ctx.detected_platform) |platform| { | 789 | (detected_platform != null and !detected_platform.?.eqlTarget(this_platform))) |
| 806 | if (!Platform.fromTarget(self.base.options.target).eqlTarget(platform)) return error.InvalidTarget; | 790 | { |
| | 791 | const platform = detected_platform orelse this_platform; |
| | 792 | try ctx.detected_targets.append(try platform.allocPrintTarget(ctx.arena, detected_cpu_arch)); |
| | 793 | return error.InvalidTarget; |
| 807 | } | 794 | } |
| 808 | | 795 | |
| 809 | try self.objects.append(gpa, object); | 796 | try self.objects.append(gpa, object); |
| ... | @@ -816,48 +803,61 @@ pub fn parseLibrary( | ... | @@ -816,48 +803,61 @@ pub fn parseLibrary( |
| 816 | lib: link.SystemLib, | 803 | lib: link.SystemLib, |
| 817 | must_link: bool, | 804 | must_link: bool, |
| 818 | dependent_libs: anytype, | 805 | dependent_libs: anytype, |
| 819 | error_ctx: anytype, | 806 | ctx: *ParseErrorCtx, |
| 820 | ) ParseError!void { | 807 | ) ParseError!void { |
| 821 | const tracy = trace(@src()); | 808 | const tracy = trace(@src()); |
| 822 | defer tracy.end(); | 809 | defer tracy.end(); |
| 823 | | 810 | |
| 824 | if (fat.isFatLibrary(file)) { | 811 | if (fat.isFatLibrary(file)) { |
| 825 | const offset = try self.parseFatLibrary(file, self.base.options.target.cpu.arch); | 812 | const offset = try self.parseFatLibrary(file, self.base.options.target.cpu.arch, ctx); |
| 826 | try file.seekTo(offset); | 813 | try file.seekTo(offset); |
| 827 | | 814 | |
| 828 | if (Archive.isArchive(file, offset)) { | 815 | if (Archive.isArchive(file, offset)) { |
| 829 | try self.parseArchive(path, offset, must_link, error_ctx); | 816 | try self.parseArchive(path, offset, must_link, ctx); |
| 830 | } else if (Dylib.isDylib(file, offset)) { | 817 | } else if (Dylib.isDylib(file, offset)) { |
| 831 | try self.parseDylib(file, path, offset, dependent_libs, .{ | 818 | try self.parseDylib(file, path, offset, dependent_libs, .{ |
| 832 | .needed = lib.needed, | 819 | .needed = lib.needed, |
| 833 | .weak = lib.weak, | 820 | .weak = lib.weak, |
| 834 | }, error_ctx); | 821 | }, ctx); |
| 835 | } else return error.UnknownFileType; | 822 | } else return error.UnknownFileType; |
| 836 | } else if (Archive.isArchive(file, 0)) { | 823 | } else if (Archive.isArchive(file, 0)) { |
| 837 | try self.parseArchive(path, 0, must_link, error_ctx); | 824 | try self.parseArchive(path, 0, must_link, ctx); |
| 838 | } else if (Dylib.isDylib(file, 0)) { | 825 | } else if (Dylib.isDylib(file, 0)) { |
| 839 | try self.parseDylib(file, path, 0, dependent_libs, .{ | 826 | try self.parseDylib(file, path, 0, dependent_libs, .{ |
| 840 | .needed = lib.needed, | 827 | .needed = lib.needed, |
| 841 | .weak = lib.weak, | 828 | .weak = lib.weak, |
| 842 | }, error_ctx); | 829 | }, ctx); |
| 843 | } else { | 830 | } else { |
| 844 | self.parseLibStub(file, path, dependent_libs, .{ | 831 | self.parseLibStub(file, path, dependent_libs, .{ |
| 845 | .needed = lib.needed, | 832 | .needed = lib.needed, |
| 846 | .weak = lib.weak, | 833 | .weak = lib.weak, |
| 847 | }, error_ctx) catch |err| switch (err) { | 834 | }, ctx) catch |err| switch (err) { |
| 848 | error.NotLibStub, error.UnexpectedToken => return error.UnknownFileType, | 835 | error.NotLibStub, error.UnexpectedToken => return error.UnknownFileType, |
| 849 | else => |e| return e, | 836 | else => |e| return e, |
| 850 | }; | 837 | }; |
| 851 | } | 838 | } |
| 852 | } | 839 | } |
| 853 | | 840 | |
| 854 | pub fn parseFatLibrary(self: *MachO, file: std.fs.File, cpu_arch: std.Target.Cpu.Arch) ParseError!u64 { | 841 | pub fn parseFatLibrary( |
| 855 | _ = self; | 842 | self: *MachO, |
| 856 | var buffer: [2]fat.Arch = undefined; | 843 | file: std.fs.File, |
| 857 | const fat_archs = try fat.parseArchs(file, &buffer); | 844 | cpu_arch: std.Target.Cpu.Arch, |
| | 845 | ctx: *ParseErrorCtx, |
| | 846 | ) ParseError!u64 { |
| | 847 | const gpa = self.base.allocator; |
| | 848 | |
| | 849 | const fat_archs = try fat.parseArchs(gpa, file); |
| | 850 | defer gpa.free(fat_archs); |
| | 851 | |
| 858 | const offset = for (fat_archs) |arch| { | 852 | const offset = for (fat_archs) |arch| { |
| 859 | if (arch.tag == cpu_arch) break arch.offset; | 853 | if (arch.tag == cpu_arch) break arch.offset; |
| 860 | } else return error.MissingArchFatLib; | 854 | } else { |
| | 855 | try ctx.detected_targets.ensureTotalCapacityPrecise(fat_archs.len); |
| | 856 | for (fat_archs) |arch| { |
| | 857 | ctx.detected_targets.appendAssumeCapacity(try ctx.arena.dupe(u8, @tagName(arch.tag))); |
| | 858 | } |
| | 859 | return error.InvalidTarget; |
| | 860 | }; |
| 861 | return offset; | 861 | return offset; |
| 862 | } | 862 | } |
| 863 | | 863 | |
| ... | @@ -866,7 +866,7 @@ fn parseArchive( | ... | @@ -866,7 +866,7 @@ fn parseArchive( |
| 866 | path: []const u8, | 866 | path: []const u8, |
| 867 | fat_offset: u64, | 867 | fat_offset: u64, |
| 868 | must_link: bool, | 868 | must_link: bool, |
| 869 | error_ctx: anytype, | 869 | ctx: *ParseErrorCtx, |
| 870 | ) ParseError!void { | 870 | ) ParseError!void { |
| 871 | const gpa = self.base.allocator; | 871 | const gpa = self.base.allocator; |
| 872 | | 872 | |
| ... | @@ -892,20 +892,21 @@ fn parseArchive( | ... | @@ -892,20 +892,21 @@ fn parseArchive( |
| 892 | var object = try archive.parseObject(gpa, off); // TODO we are doing all this work to pull the header only! | 892 | var object = try archive.parseObject(gpa, off); // TODO we are doing all this work to pull the header only! |
| 893 | defer object.deinit(gpa); | 893 | defer object.deinit(gpa); |
| 894 | | 894 | |
| 895 | const cpu_arch: std.Target.Cpu.Arch = switch (object.header.cputype) { | 895 | const detected_cpu_arch: std.Target.Cpu.Arch = switch (object.header.cputype) { |
| 896 | macho.CPU_TYPE_ARM64 => .aarch64, | 896 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 897 | macho.CPU_TYPE_X86_64 => .x86_64, | 897 | macho.CPU_TYPE_X86_64 => .x86_64, |
| 898 | else => unreachable, | 898 | else => unreachable, |
| 899 | }; | 899 | }; |
| 900 | error_ctx.detected_arch = cpu_arch; | 900 | const detected_platform = object.getPlatform(); |
| 901 | | 901 | const this_cpu_arch = self.base.options.target.cpu.arch; |
| 902 | if (object.getPlatform()) |platform| { | 902 | const this_platform = Platform.fromTarget(self.base.options.target); |
| 903 | error_ctx.detected_platform = platform; | | |
| 904 | } | | |
| 905 | | 903 | |
| 906 | if (self.base.options.target.cpu.arch != cpu_arch) return error.InvalidTarget; | 904 | if (this_cpu_arch != detected_cpu_arch or |
| 907 | if (error_ctx.detected_platform) |platform| { | 905 | (detected_platform != null and !detected_platform.?.eqlTarget(this_platform))) |
| 908 | if (!Platform.fromTarget(self.base.options.target).eqlTarget(platform)) return error.InvalidTarget; | 906 | { |
| | 907 | const platform = detected_platform orelse this_platform; |
| | 908 | try ctx.detected_targets.append(try platform.allocPrintTarget(gpa, detected_cpu_arch)); |
| | 909 | return error.InvalidTarget; |
| 909 | } | 910 | } |
| 910 | } | 911 | } |
| 911 | | 912 | |
| ... | @@ -941,7 +942,7 @@ fn parseDylib( | ... | @@ -941,7 +942,7 @@ fn parseDylib( |
| 941 | offset: u64, | 942 | offset: u64, |
| 942 | dependent_libs: anytype, | 943 | dependent_libs: anytype, |
| 943 | dylib_options: DylibOpts, | 944 | dylib_options: DylibOpts, |
| 944 | error_ctx: anytype, | 945 | ctx: *ParseErrorCtx, |
| 945 | ) ParseError!void { | 946 | ) ParseError!void { |
| 946 | const gpa = self.base.allocator; | 947 | const gpa = self.base.allocator; |
| 947 | const file_stat = try file.stat(); | 948 | const file_stat = try file.stat(); |
| ... | @@ -961,20 +962,21 @@ fn parseDylib( | ... | @@ -961,20 +962,21 @@ fn parseDylib( |
| 961 | contents, | 962 | contents, |
| 962 | ); | 963 | ); |
| 963 | | 964 | |
| 964 | const cpu_arch: std.Target.Cpu.Arch = switch (dylib.header.?.cputype) { | 965 | const detected_cpu_arch: std.Target.Cpu.Arch = switch (dylib.header.?.cputype) { |
| 965 | macho.CPU_TYPE_ARM64 => .aarch64, | 966 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 966 | macho.CPU_TYPE_X86_64 => .x86_64, | 967 | macho.CPU_TYPE_X86_64 => .x86_64, |
| 967 | else => unreachable, | 968 | else => unreachable, |
| 968 | }; | 969 | }; |
| 969 | error_ctx.detected_arch = cpu_arch; | 970 | const detected_platform = dylib.getPlatform(contents); |
| | 971 | const this_cpu_arch = self.base.options.target.cpu.arch; |
| | 972 | const this_platform = Platform.fromTarget(self.base.options.target); |
| 970 | | 973 | |
| 971 | if (dylib.getPlatform(contents)) |platform| { | 974 | if (this_cpu_arch != detected_cpu_arch or |
| 972 | error_ctx.detected_platform = platform; | 975 | (detected_platform != null and !detected_platform.?.eqlTarget(this_platform))) |
| 973 | } | 976 | { |
| 974 | | 977 | const platform = detected_platform orelse this_platform; |
| 975 | if (self.base.options.target.cpu.arch != cpu_arch) return error.InvalidTarget; | 978 | try ctx.detected_targets.append(try platform.allocPrintTarget(ctx.arena, detected_cpu_arch)); |
| 976 | if (error_ctx.detected_platform) |platform| { | 979 | return error.InvalidTarget; |
| 977 | if (!Platform.fromTarget(self.base.options.target).eqlTarget(platform)) return error.InvalidTarget; | | |
| 978 | } | 980 | } |
| 979 | | 981 | |
| 980 | try self.addDylib(dylib, .{ | 982 | try self.addDylib(dylib, .{ |
| ... | @@ -989,7 +991,7 @@ fn parseLibStub( | ... | @@ -989,7 +991,7 @@ fn parseLibStub( |
| 989 | path: []const u8, | 991 | path: []const u8, |
| 990 | dependent_libs: anytype, | 992 | dependent_libs: anytype, |
| 991 | dylib_options: DylibOpts, | 993 | dylib_options: DylibOpts, |
| 992 | error_ctx: anytype, | 994 | ctx: *ParseErrorCtx, |
| 993 | ) ParseError!void { | 995 | ) ParseError!void { |
| 994 | const gpa = self.base.allocator; | 996 | const gpa = self.base.allocator; |
| 995 | var lib_stub = try LibStub.loadFromFile(gpa, file); | 997 | var lib_stub = try LibStub.loadFromFile(gpa, file); |
| ... | @@ -1004,12 +1006,17 @@ fn parseLibStub( | ... | @@ -1004,12 +1006,17 @@ fn parseLibStub( |
| 1004 | | 1006 | |
| 1005 | const first_tbd = lib_stub.inner[0]; | 1007 | const first_tbd = lib_stub.inner[0]; |
| 1006 | const targets = try first_tbd.targets(gpa); | 1008 | const targets = try first_tbd.targets(gpa); |
| | 1009 | defer { |
| | 1010 | for (targets) |t| gpa.free(t); |
| | 1011 | gpa.free(targets); |
| | 1012 | } |
| 1007 | if (!matcher.matchesTarget(targets)) { | 1013 | if (!matcher.matchesTarget(targets)) { |
| 1008 | error_ctx.detected_stub_targets = targets; | 1014 | try ctx.detected_targets.ensureUnusedCapacity(targets.len); |
| 1009 | return error.InvalidLibStubTargets; | 1015 | for (targets) |t| { |
| | 1016 | ctx.detected_targets.appendAssumeCapacity(try ctx.arena.dupe(u8, t)); |
| | 1017 | } |
| | 1018 | return error.InvalidTarget; |
| 1010 | } | 1019 | } |
| 1011 | for (targets) |t| gpa.free(t); | | |
| 1012 | gpa.free(targets); | | |
| 1013 | } | 1020 | } |
| 1014 | | 1021 | |
| 1015 | var dylib = Dylib{ .weak = dylib_options.weak }; | 1022 | var dylib = Dylib{ .weak = dylib_options.weak }; |
| ... | @@ -1059,7 +1066,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts) ParseError!voi | ... | @@ -1059,7 +1066,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts) ParseError!voi |
| 1059 | } | 1066 | } |
| 1060 | } | 1067 | } |
| 1061 | | 1068 | |
| 1062 | pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anytype) ParseError!void { | 1069 | pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, ctx: *ParseErrorCtx) ParseError!void { |
| 1063 | const tracy = trace(@src()); | 1070 | const tracy = trace(@src()); |
| 1064 | defer tracy.end(); | 1071 | defer tracy.end(); |
| 1065 | | 1072 | |
| ... | @@ -1105,7 +1112,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anyt | ... | @@ -1105,7 +1112,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anyt |
| 1105 | log.debug("trying dependency at fully resolved path {s}", .{full_path}); | 1112 | log.debug("trying dependency at fully resolved path {s}", .{full_path}); |
| 1106 | | 1113 | |
| 1107 | const offset: u64 = if (fat.isFatLibrary(file)) blk: { | 1114 | const offset: u64 = if (fat.isFatLibrary(file)) blk: { |
| 1108 | const offset = try self.parseFatLibrary(file, self.base.options.target.cpu.arch); | 1115 | const offset = try self.parseFatLibrary(file, self.base.options.target.cpu.arch, ctx); |
| 1109 | try file.seekTo(offset); | 1116 | try file.seekTo(offset); |
| 1110 | break :blk offset; | 1117 | break :blk offset; |
| 1111 | } else 0; | 1118 | } else 0; |
| ... | @@ -1114,12 +1121,12 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anyt | ... | @@ -1114,12 +1121,12 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anyt |
| 1114 | try self.parseDylib(file, full_path, offset, dependent_libs, .{ | 1121 | try self.parseDylib(file, full_path, offset, dependent_libs, .{ |
| 1115 | .dependent = true, | 1122 | .dependent = true, |
| 1116 | .weak = weak, | 1123 | .weak = weak, |
| 1117 | }, error_ctx); | 1124 | }, ctx); |
| 1118 | } else { | 1125 | } else { |
| 1119 | self.parseLibStub(file, full_path, dependent_libs, .{ | 1126 | self.parseLibStub(file, full_path, dependent_libs, .{ |
| 1120 | .dependent = true, | 1127 | .dependent = true, |
| 1121 | .weak = weak, | 1128 | .weak = weak, |
| 1122 | }, error_ctx) catch |err| switch (err) { | 1129 | }, ctx) catch |err| switch (err) { |
| 1123 | error.NotLibStub, error.UnexpectedToken => continue, | 1130 | error.NotLibStub, error.UnexpectedToken => continue, |
| 1124 | else => |e| return e, | 1131 | else => |e| return e, |
| 1125 | }; | 1132 | }; |
| ... | @@ -4845,50 +4852,40 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 { | ... | @@ -4845,50 +4852,40 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 { |
| 4845 | return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence; | 4852 | return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence; |
| 4846 | } | 4853 | } |
| 4847 | | 4854 | |
| 4848 | pub fn handleAndReportParseError(self: *MachO, path: []const u8, err: ParseError, parse_error_ctx: anytype) !void { | 4855 | pub const ParseErrorCtx = struct { |
| | 4856 | arena: Allocator, |
| | 4857 | detected_targets: std.ArrayList([]const u8), |
| | 4858 | |
| | 4859 | pub fn init(arena: Allocator) ParseErrorCtx { |
| | 4860 | return .{ .arena = arena, .detected_targets = std.ArrayList([]const u8).init(arena) }; |
| | 4861 | } |
| | 4862 | }; |
| | 4863 | |
| | 4864 | pub fn handleAndReportParseError( |
| | 4865 | self: *MachO, |
| | 4866 | path: []const u8, |
| | 4867 | err: ParseError, |
| | 4868 | ctx: *const ParseErrorCtx, |
| | 4869 | ) !void { |
| 4849 | const cpu_arch = self.base.options.target.cpu.arch; | 4870 | const cpu_arch = self.base.options.target.cpu.arch; |
| 4850 | switch (err) { | 4871 | switch (err) { |
| 4851 | error.DylibAlreadyExists => {}, | 4872 | error.DylibAlreadyExists => {}, |
| 4852 | error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), | 4873 | error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), |
| 4853 | error.MissingArchFatLib => try self.reportParseError( | 4874 | error.InvalidTarget => { |
| 4854 | path, | | |
| 4855 | "missing architecture in universal file, expected '{s}'", | | |
| 4856 | .{@tagName(cpu_arch)}, | | |
| 4857 | ), | | |
| 4858 | error.InvalidTarget => if (parse_error_ctx.detected_platform) |platform| { | | |
| 4859 | try self.reportParseError(path, "invalid target '{s}-{}', expected '{s}-{}'", .{ | | |
| 4860 | @tagName(parse_error_ctx.detected_arch), | | |
| 4861 | platform.fmtTarget(), | | |
| 4862 | @tagName(cpu_arch), | | |
| 4863 | Platform.fromTarget(self.base.options.target).fmtTarget(), | | |
| 4864 | }); | | |
| 4865 | } else { | | |
| 4866 | try self.reportParseError( | | |
| 4867 | path, | | |
| 4868 | "invalid architecture '{s}', expected '{s}'", | | |
| 4869 | .{ @tagName(parse_error_ctx.detected_arch), @tagName(cpu_arch) }, | | |
| 4870 | ); | | |
| 4871 | }, | | |
| 4872 | error.InvalidLibStubTargets => { | | |
| 4873 | var targets_string = std.ArrayList(u8).init(self.base.allocator); | 4875 | var targets_string = std.ArrayList(u8).init(self.base.allocator); |
| 4874 | defer targets_string.deinit(); | 4876 | defer targets_string.deinit(); |
| 4875 | try targets_string.writer().writeAll("("); | 4877 | try targets_string.writer().writeAll("("); |
| 4876 | for (parse_error_ctx.detected_stub_targets) |t| { | 4878 | for (ctx.detected_targets.items) |t| { |
| 4877 | try targets_string.writer().print("{s}, ", .{t}); | 4879 | try targets_string.writer().print("{s}, ", .{t}); |
| 4878 | } | 4880 | } |
| 4879 | try targets_string.resize(targets_string.items.len - 2); | 4881 | try targets_string.resize(targets_string.items.len - 2); |
| 4880 | try targets_string.writer().writeAll(")"); | 4882 | try targets_string.writer().writeAll(")"); |
| 4881 | try self.reportParseError(path, "invalid targets '{s}', expected '{s}-{}'", .{ | 4883 | try self.reportParseError(path, "invalid target: expected '{}', but found '{s}'", .{ |
| | 4884 | Platform.fromTarget(self.base.options.target).fmtTarget(cpu_arch), |
| 4882 | targets_string.items, | 4885 | targets_string.items, |
| 4883 | @tagName(cpu_arch), | | |
| 4884 | Platform.fromTarget(self.base.options.target).fmtTarget(), | | |
| 4885 | }); | 4886 | }); |
| 4886 | }, | 4887 | }, |
| 4887 | else => |e| try self.reportParseError( | 4888 | else => |e| try self.reportParseError(path, "{s}: parsing object failed", .{@errorName(e)}), |
| 4888 | path, | | |
| 4889 | "parsing positional argument failed with error '{s}'", | | |
| 4890 | .{@errorName(e)}, | | |
| 4891 | ), | | |
| 4892 | } | 4889 | } |
| 4893 | } | 4890 | } |
| 4894 | | 4891 | |