| author | |
| committer | |
| log | ce5a5c361b5b098c3b7d68f88136a9c91e7bec19 |
| tree | 713dbd96a58ada0527b2668246df813f40a09cf0 |
| parent | e1e151df0d948be7464b448c61033d4c1d80d86b |
| parent | 22661f3d67251688a1fabf9e5fe65210ce284b9f |
| signature |
link.Elf: reduce flush logic18 files changed, 201 insertions(+), 268 deletions(-)
lib/std/Build/Step/Compile.zig+12| ... | @@ -235,6 +235,7 @@ sanitize_coverage_trace_pc_guard: ?bool = null, | ... | @@ -235,6 +235,7 @@ sanitize_coverage_trace_pc_guard: ?bool = null, |
| 235 | pub const ExpectedCompileErrors = union(enum) { | 235 | pub const ExpectedCompileErrors = union(enum) { |
| 236 | contains: []const u8, | 236 | contains: []const u8, |
| 237 | exact: []const []const u8, | 237 | exact: []const []const u8, |
| 238 | starts_with: []const u8, | ||
| 238 | }; | 239 | }; |
| 239 | 240 | ||
| 240 | pub const Entry = union(enum) { | 241 | pub const Entry = union(enum) { |
| ... | @@ -1958,6 +1959,17 @@ fn checkCompileErrors(compile: *Compile) !void { | ... | @@ -1958,6 +1959,17 @@ fn checkCompileErrors(compile: *Compile) !void { |
| 1958 | 1959 | ||
| 1959 | // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile | 1960 | // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile |
| 1960 | switch (expect_errors) { | 1961 | switch (expect_errors) { |
| 1962 | .starts_with => |expect_starts_with| { | ||
| 1963 | if (std.mem.startsWith(u8, actual_stderr, expect_starts_with)) return; | ||
| 1964 | return compile.step.fail( | ||
| 1965 | \\ | ||
| 1966 | \\========= should start with: ============ | ||
| 1967 | \\{s} | ||
| 1968 | \\========= but not found: ================ | ||
| 1969 | \\{s} | ||
| 1970 | \\========================================= | ||
| 1971 | , .{ expect_starts_with, actual_stderr }); | ||
| 1972 | }, | ||
| 1961 | .contains => |expect_line| { | 1973 | .contains => |expect_line| { |
| 1962 | while (actual_line_it.next()) |actual_line| { | 1974 | while (actual_line_it.next()) |actual_line| { |
| 1963 | if (!matchCompileError(actual_line, expect_line)) continue; | 1975 | if (!matchCompileError(actual_line, expect_line)) continue; |
src/Compilation.zig+15-1| ... | @@ -280,6 +280,13 @@ pub const CRTFile = struct { | ... | @@ -280,6 +280,13 @@ pub const CRTFile = struct { |
| 280 | lock: Cache.Lock, | 280 | lock: Cache.Lock, |
| 281 | full_object_path: []const u8, | 281 | full_object_path: []const u8, |
| 282 | 282 | ||
| 283 | pub fn isObject(cf: CRTFile) bool { | ||
| 284 | return switch (classifyFileExt(cf.full_object_path)) { | ||
| 285 | .object => true, | ||
| 286 | else => false, | ||
| 287 | }; | ||
| 288 | } | ||
| 289 | |||
| 283 | pub fn deinit(self: *CRTFile, gpa: Allocator) void { | 290 | pub fn deinit(self: *CRTFile, gpa: Allocator) void { |
| 284 | self.lock.release(); | 291 | self.lock.release(); |
| 285 | gpa.free(self.full_object_path); | 292 | gpa.free(self.full_object_path); |
| ... | @@ -1018,6 +1025,13 @@ pub const LinkObject = struct { | ... | @@ -1018,6 +1025,13 @@ pub const LinkObject = struct { |
| 1018 | // | 1025 | // |
| 1019 | // Consistent with `withLOption` variable name in lld ELF driver. | 1026 | // Consistent with `withLOption` variable name in lld ELF driver. |
| 1020 | loption: bool = false, | 1027 | loption: bool = false, |
| 1028 | |||
| 1029 | pub fn isObject(lo: LinkObject) bool { | ||
| 1030 | return switch (classifyFileExt(lo.path)) { | ||
| 1031 | .object => true, | ||
| 1032 | else => false, | ||
| 1033 | }; | ||
| 1034 | } | ||
| 1021 | }; | 1035 | }; |
| 1022 | 1036 | ||
| 1023 | pub const CreateOptions = struct { | 1037 | pub const CreateOptions = struct { |
| ... | @@ -2433,7 +2447,7 @@ fn flush( | ... | @@ -2433,7 +2447,7 @@ fn flush( |
| 2433 | if (comp.bin_file) |lf| { | 2447 | if (comp.bin_file) |lf| { |
| 2434 | // This is needed before reading the error flags. | 2448 | // This is needed before reading the error flags. |
| 2435 | lf.flush(arena, tid, prog_node) catch |err| switch (err) { | 2449 | lf.flush(arena, tid, prog_node) catch |err| switch (err) { |
| 2436 | error.FlushFailure => {}, // error reported through link_error_flags | 2450 | error.FlushFailure, error.LinkFailure => {}, // error reported through link_error_flags |
| 2437 | error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr | 2451 | error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr |
| 2438 | else => |e| return e, | 2452 | else => |e| return e, |
| 2439 | }; | 2453 | }; |
src/link.zig+3-1| ... | @@ -67,7 +67,6 @@ pub const File = struct { | ... | @@ -67,7 +67,6 @@ pub const File = struct { |
| 67 | gc_sections: bool, | 67 | gc_sections: bool, |
| 68 | print_gc_sections: bool, | 68 | print_gc_sections: bool, |
| 69 | build_id: std.zig.BuildId, | 69 | build_id: std.zig.BuildId, |
| 70 | rpath_list: []const []const u8, | ||
| 71 | allow_shlib_undefined: bool, | 70 | allow_shlib_undefined: bool, |
| 72 | stack_size: u64, | 71 | stack_size: u64, |
| 73 | 72 | ||
| ... | @@ -534,7 +533,10 @@ pub const File = struct { | ... | @@ -534,7 +533,10 @@ pub const File = struct { |
| 534 | FailedToEmit, | 533 | FailedToEmit, |
| 535 | FileSystem, | 534 | FileSystem, |
| 536 | FilesOpenedWithWrongFlags, | 535 | FilesOpenedWithWrongFlags, |
| 536 | /// Indicates an error will be present in `Compilation.link_errors`. | ||
| 537 | FlushFailure, | 537 | FlushFailure, |
| 538 | /// Indicates an error will be present in `Compilation.link_errors`. | ||
| 539 | LinkFailure, | ||
| 538 | FunctionSignatureMismatch, | 540 | FunctionSignatureMismatch, |
| 539 | GlobalTypeMismatch, | 541 | GlobalTypeMismatch, |
| 540 | HotSwapUnavailableOnHostOperatingSystem, | 542 | HotSwapUnavailableOnHostOperatingSystem, |
src/link/C.zig-1| ... | @@ -148,7 +148,6 @@ pub fn createEmpty( | ... | @@ -148,7 +148,6 @@ pub fn createEmpty( |
| 148 | .file = file, | 148 | .file = file, |
| 149 | .disable_lld_caching = options.disable_lld_caching, | 149 | .disable_lld_caching = options.disable_lld_caching, |
| 150 | .build_id = options.build_id, | 150 | .build_id = options.build_id, |
| 151 | .rpath_list = options.rpath_list, | ||
| 152 | }, | 151 | }, |
| 153 | }; | 152 | }; |
| 154 | 153 |
src/link/Coff.zig-1| ... | @@ -263,7 +263,6 @@ pub fn createEmpty( | ... | @@ -263,7 +263,6 @@ pub fn createEmpty( |
| 263 | .file = null, | 263 | .file = null, |
| 264 | .disable_lld_caching = options.disable_lld_caching, | 264 | .disable_lld_caching = options.disable_lld_caching, |
| 265 | .build_id = options.build_id, | 265 | .build_id = options.build_id, |
| 266 | .rpath_list = options.rpath_list, | ||
| 267 | }, | 266 | }, |
| 268 | .ptr_width = ptr_width, | 267 | .ptr_width = ptr_width, |
| 269 | .page_size = page_size, | 268 | .page_size = page_size, |
src/link/Elf.zig+97-120| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | base: link.File, | 1 | base: link.File, |
| 2 | rpath_table: std.StringArrayHashMapUnmanaged(void), | ||
| 2 | image_base: u64, | 3 | image_base: u64, |
| 3 | emit_relocs: bool, | 4 | emit_relocs: bool, |
| 4 | z_nodelete: bool, | 5 | z_nodelete: bool, |
| ... | @@ -239,6 +240,11 @@ pub fn createEmpty( | ... | @@ -239,6 +240,11 @@ pub fn createEmpty( |
| 239 | else | 240 | else |
| 240 | try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path}); | 241 | try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path}); |
| 241 | 242 | ||
| 243 | var rpath_table: std.StringArrayHashMapUnmanaged(void) = .empty; | ||
| 244 | try rpath_table.entries.resize(arena, options.rpath_list.len); | ||
| 245 | @memcpy(rpath_table.entries.items(.key), options.rpath_list); | ||
| 246 | try rpath_table.reIndex(arena); | ||
| 247 | |||
| 242 | const self = try arena.create(Elf); | 248 | const self = try arena.create(Elf); |
| 243 | self.* = .{ | 249 | self.* = .{ |
| 244 | .base = .{ | 250 | .base = .{ |
| ... | @@ -253,8 +259,8 @@ pub fn createEmpty( | ... | @@ -253,8 +259,8 @@ pub fn createEmpty( |
| 253 | .file = null, | 259 | .file = null, |
| 254 | .disable_lld_caching = options.disable_lld_caching, | 260 | .disable_lld_caching = options.disable_lld_caching, |
| 255 | .build_id = options.build_id, | 261 | .build_id = options.build_id, |
| 256 | .rpath_list = options.rpath_list, | ||
| 257 | }, | 262 | }, |
| 263 | .rpath_table = rpath_table, | ||
| 258 | .ptr_width = ptr_width, | 264 | .ptr_width = ptr_width, |
| 259 | .page_size = page_size, | 265 | .page_size = page_size, |
| 260 | .default_sym_version = default_sym_version, | 266 | .default_sym_version = default_sym_version, |
| ... | @@ -785,8 +791,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -785,8 +791,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 785 | const target = self.getTarget(); | 791 | const target = self.getTarget(); |
| 786 | const link_mode = comp.config.link_mode; | 792 | const link_mode = comp.config.link_mode; |
| 787 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | 793 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. |
| 788 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | ||
| 789 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { | 794 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { |
| 795 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | ||
| 790 | if (fs.path.dirname(full_out_path)) |dirname| { | 796 | if (fs.path.dirname(full_out_path)) |dirname| { |
| 791 | break :blk try fs.path.join(arena, &.{ dirname, path }); | 797 | break :blk try fs.path.join(arena, &.{ dirname, path }); |
| 792 | } else { | 798 | } else { |
| ... | @@ -802,69 +808,37 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -802,69 +808,37 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 802 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); | 808 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); |
| 803 | 809 | ||
| 804 | const csu = try CsuObjects.init(arena, comp); | 810 | const csu = try CsuObjects.init(arena, comp); |
| 805 | const compiler_rt_path: ?[]const u8 = blk: { | ||
| 806 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | ||
| 807 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; | ||
| 808 | break :blk null; | ||
| 809 | }; | ||
| 810 | 811 | ||
| 811 | // Here we will parse input positional and library files (if referenced). | 812 | // Here we will parse object and library files (if referenced). |
| 812 | // This will roughly match in any linker backend we support. | ||
| 813 | var positionals = std.ArrayList(Compilation.LinkObject).init(arena); | ||
| 814 | 813 | ||
| 815 | // csu prelude | 814 | // csu prelude |
| 816 | if (csu.crt0) |v| try positionals.append(.{ .path = v }); | 815 | if (csu.crt0) |path| try parseObjectReportingFailure(self, path); |
| 817 | if (csu.crti) |v| try positionals.append(.{ .path = v }); | 816 | if (csu.crti) |path| try parseObjectReportingFailure(self, path); |
| 818 | if (csu.crtbegin) |v| try positionals.append(.{ .path = v }); | 817 | if (csu.crtbegin) |path| try parseObjectReportingFailure(self, path); |
| 819 | 818 | ||
| 820 | try positionals.ensureUnusedCapacity(comp.objects.len); | 819 | for (comp.objects) |obj| { |
| 821 | positionals.appendSliceAssumeCapacity(comp.objects); | 820 | if (obj.isObject()) { |
| 821 | try parseObjectReportingFailure(self, obj.path); | ||
| 822 | } else { | ||
| 823 | try parseLibraryReportingFailure(self, .{ .path = obj.path }, obj.must_link); | ||
| 824 | } | ||
| 825 | } | ||
| 822 | 826 | ||
| 823 | // This is a set of object files emitted by clang in a single `build-exe` invocation. | 827 | // This is a set of object files emitted by clang in a single `build-exe` invocation. |
| 824 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up | 828 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up |
| 825 | // in this set. | 829 | // in this set. |
| 826 | for (comp.c_object_table.keys()) |key| { | 830 | for (comp.c_object_table.keys()) |key| { |
| 827 | try positionals.append(.{ .path = key.status.success.object_path }); | 831 | try parseObjectReportingFailure(self, key.status.success.object_path); |
| 828 | } | ||
| 829 | |||
| 830 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | ||
| 831 | |||
| 832 | // rpaths | ||
| 833 | var rpath_table = std.StringArrayHashMap(void).init(gpa); | ||
| 834 | defer rpath_table.deinit(); | ||
| 835 | |||
| 836 | for (self.base.rpath_list) |rpath| { | ||
| 837 | _ = try rpath_table.put(rpath, {}); | ||
| 838 | } | 832 | } |
| 839 | 833 | ||
| 840 | if (comp.config.any_sanitize_thread) { | 834 | if (module_obj_path) |path| try parseObjectReportingFailure(self, path); |
| 841 | try positionals.append(.{ .path = comp.tsan_lib.?.full_object_path }); | ||
| 842 | } | ||
| 843 | 835 | ||
| 844 | if (comp.config.any_fuzz) { | 836 | if (comp.config.any_sanitize_thread) try parseCrtFileReportingFailure(self, comp.tsan_lib.?); |
| 845 | try positionals.append(.{ .path = comp.fuzzer_lib.?.full_object_path }); | 837 | if (comp.config.any_fuzz) try parseCrtFileReportingFailure(self, comp.fuzzer_lib.?); |
| 846 | } | ||
| 847 | 838 | ||
| 848 | // libc | 839 | // libc |
| 849 | if (!comp.skip_linker_dependencies and !comp.config.link_libc) { | 840 | if (!comp.skip_linker_dependencies and !comp.config.link_libc) { |
| 850 | if (comp.libc_static_lib) |lib| { | 841 | if (comp.libc_static_lib) |lib| try parseCrtFileReportingFailure(self, lib); |
| 851 | try positionals.append(.{ .path = lib.full_object_path }); | ||
| 852 | } | ||
| 853 | } | ||
| 854 | |||
| 855 | for (positionals.items) |obj| { | ||
| 856 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | ||
| 857 | error.MalformedObject, | ||
| 858 | error.MalformedArchive, | ||
| 859 | error.MismatchedEflags, | ||
| 860 | error.InvalidMachineType, | ||
| 861 | => continue, // already reported | ||
| 862 | else => |e| try self.reportParseError( | ||
| 863 | obj.path, | ||
| 864 | "unexpected error: parsing input file failed with error {s}", | ||
| 865 | .{@errorName(e)}, | ||
| 866 | ), | ||
| 867 | }; | ||
| 868 | } | 842 | } |
| 869 | 843 | ||
| 870 | var system_libs = std.ArrayList(SystemLib).init(arena); | 844 | var system_libs = std.ArrayList(SystemLib).init(arena); |
| ... | @@ -947,42 +921,23 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -947,42 +921,23 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 947 | } | 921 | } |
| 948 | 922 | ||
| 949 | for (system_libs.items) |lib| { | 923 | for (system_libs.items) |lib| { |
| 950 | self.parseLibrary(lib, false) catch |err| switch (err) { | 924 | try self.parseLibraryReportingFailure(lib, false); |
| 951 | error.MalformedObject, error.MalformedArchive, error.InvalidMachineType => continue, // already reported | ||
| 952 | else => |e| try self.reportParseError( | ||
| 953 | lib.path, | ||
| 954 | "unexpected error: parsing library failed with error {s}", | ||
| 955 | .{@errorName(e)}, | ||
| 956 | ), | ||
| 957 | }; | ||
| 958 | } | 925 | } |
| 959 | 926 | ||
| 960 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). | 927 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). |
| 961 | positionals.clearRetainingCapacity(); | ||
| 962 | 928 | ||
| 963 | // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs | 929 | // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs |
| 964 | // to be after the shared libraries, so they are picked up from the shared | 930 | // to be after the shared libraries, so they are picked up from the shared |
| 965 | // libraries, not libcompiler_rt. | 931 | // libraries, not libcompiler_rt. |
| 966 | if (compiler_rt_path) |path| try positionals.append(.{ .path = path }); | 932 | if (comp.compiler_rt_lib) |crt_file| { |
| 933 | try parseLibraryReportingFailure(self, .{ .path = crt_file.full_object_path }, false); | ||
| 934 | } else if (comp.compiler_rt_obj) |crt_file| { | ||
| 935 | try parseObjectReportingFailure(self, crt_file.full_object_path); | ||
| 936 | } | ||
| 967 | 937 | ||
| 968 | // csu postlude | 938 | // csu postlude |
| 969 | if (csu.crtend) |v| try positionals.append(.{ .path = v }); | 939 | if (csu.crtend) |path| try parseObjectReportingFailure(self, path); |
| 970 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); | 940 | if (csu.crtn) |path| try parseObjectReportingFailure(self, path); |
| 971 | |||
| 972 | for (positionals.items) |obj| { | ||
| 973 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | ||
| 974 | error.MalformedObject, | ||
| 975 | error.MalformedArchive, | ||
| 976 | error.MismatchedEflags, | ||
| 977 | error.InvalidMachineType, | ||
| 978 | => continue, // already reported | ||
| 979 | else => |e| try self.reportParseError( | ||
| 980 | obj.path, | ||
| 981 | "unexpected error: parsing input file failed with error {s}", | ||
| 982 | .{@errorName(e)}, | ||
| 983 | ), | ||
| 984 | }; | ||
| 985 | } | ||
| 986 | 941 | ||
| 987 | if (self.base.hasErrors()) return error.FlushFailure; | 942 | if (self.base.hasErrors()) return error.FlushFailure; |
| 988 | 943 | ||
| ... | @@ -1024,7 +979,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -1024,7 +979,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1024 | self.markEhFrameAtomsDead(); | 979 | self.markEhFrameAtomsDead(); |
| 1025 | try self.resolveMergeSections(); | 980 | try self.resolveMergeSections(); |
| 1026 | 981 | ||
| 1027 | try self.convertCommonSymbols(); | 982 | for (self.objects.items) |index| { |
| 983 | try self.file(index).?.object.convertCommonSymbols(self); | ||
| 984 | } | ||
| 1028 | self.markImportsExports(); | 985 | self.markImportsExports(); |
| 1029 | 986 | ||
| 1030 | if (self.base.gc_sections) { | 987 | if (self.base.gc_sections) { |
| ... | @@ -1056,7 +1013,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -1056,7 +1013,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1056 | try self.initSpecialPhdrs(); | 1013 | try self.initSpecialPhdrs(); |
| 1057 | try self.sortShdrs(); | 1014 | try self.sortShdrs(); |
| 1058 | 1015 | ||
| 1059 | try self.setDynamicSection(rpath_table.keys()); | 1016 | try self.setDynamicSection(self.rpath_table.keys()); |
| 1060 | self.sortDynamicSymtab(); | 1017 | self.sortDynamicSymtab(); |
| 1061 | try self.setHashSections(); | 1018 | try self.setHashSections(); |
| 1062 | try self.setVersionSymtab(); | 1019 | try self.setVersionSymtab(); |
| ... | @@ -1207,9 +1164,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1207,9 +1164,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1207 | try argv.appendSlice(&.{ "--entry", name }); | 1164 | try argv.appendSlice(&.{ "--entry", name }); |
| 1208 | } | 1165 | } |
| 1209 | 1166 | ||
| 1210 | for (self.base.rpath_list) |rpath| { | 1167 | for (self.rpath_table.keys()) |rpath| { |
| 1211 | try argv.append("-rpath"); | 1168 | try argv.appendSlice(&.{ "-rpath", rpath }); |
| 1212 | try argv.append(rpath); | ||
| 1213 | } | 1169 | } |
| 1214 | 1170 | ||
| 1215 | try argv.appendSlice(&.{ | 1171 | try argv.appendSlice(&.{ |
| ... | @@ -1405,10 +1361,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1405,10 +1361,9 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1405 | } | 1361 | } |
| 1406 | 1362 | ||
| 1407 | pub const ParseError = error{ | 1363 | pub const ParseError = error{ |
| 1408 | MalformedObject, | 1364 | /// Indicates the error is already reported on `Compilation.link_errors`. |
| 1409 | MalformedArchive, | 1365 | LinkFailure, |
| 1410 | InvalidMachineType, | 1366 | |
| 1411 | MismatchedEflags, | ||
| 1412 | OutOfMemory, | 1367 | OutOfMemory, |
| 1413 | Overflow, | 1368 | Overflow, |
| 1414 | InputOutput, | 1369 | InputOutput, |
| ... | @@ -1419,16 +1374,30 @@ pub const ParseError = error{ | ... | @@ -1419,16 +1374,30 @@ pub const ParseError = error{ |
| 1419 | UnknownFileType, | 1374 | UnknownFileType, |
| 1420 | } || LdScript.Error || fs.Dir.AccessError || fs.File.SeekError || fs.File.OpenError || fs.File.ReadError; | 1375 | } || LdScript.Error || fs.Dir.AccessError || fs.File.SeekError || fs.File.OpenError || fs.File.ReadError; |
| 1421 | 1376 | ||
| 1422 | pub fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { | 1377 | fn parseCrtFileReportingFailure(self: *Elf, crt_file: Compilation.CRTFile) error{OutOfMemory}!void { |
| 1423 | const tracy = trace(@src()); | 1378 | if (crt_file.isObject()) { |
| 1424 | defer tracy.end(); | 1379 | try parseObjectReportingFailure(self, crt_file.full_object_path); |
| 1425 | if (try Object.isObject(path)) { | ||
| 1426 | try self.parseObject(path); | ||
| 1427 | } else { | 1380 | } else { |
| 1428 | try self.parseLibrary(.{ .path = path }, must_link); | 1381 | try parseLibraryReportingFailure(self, .{ .path = crt_file.full_object_path }, false); |
| 1429 | } | 1382 | } |
| 1430 | } | 1383 | } |
| 1431 | 1384 | ||
| 1385 | pub fn parseObjectReportingFailure(self: *Elf, path: []const u8) error{OutOfMemory}!void { | ||
| 1386 | self.parseObject(path) catch |err| switch (err) { | ||
| 1387 | error.LinkFailure => return, // already reported | ||
| 1388 | error.OutOfMemory => return error.OutOfMemory, | ||
| 1389 | else => |e| try self.addParseError(path, "unable to parse object: {s}", .{@errorName(e)}), | ||
| 1390 | }; | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | pub fn parseLibraryReportingFailure(self: *Elf, lib: SystemLib, must_link: bool) error{OutOfMemory}!void { | ||
| 1394 | self.parseLibrary(lib, must_link) catch |err| switch (err) { | ||
| 1395 | error.LinkFailure => return, // already reported | ||
| 1396 | error.OutOfMemory => return error.OutOfMemory, | ||
| 1397 | else => |e| try self.addParseError(lib.path, "unable to parse library: {s}", .{@errorName(e)}), | ||
| 1398 | }; | ||
| 1399 | } | ||
| 1400 | |||
| 1432 | fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { | 1401 | fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { |
| 1433 | const tracy = trace(@src()); | 1402 | const tracy = trace(@src()); |
| 1434 | defer tracy.end(); | 1403 | defer tracy.end(); |
| ... | @@ -1578,8 +1547,8 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { | ... | @@ -1578,8 +1547,8 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1578 | .needed = scr_obj.needed, | 1547 | .needed = scr_obj.needed, |
| 1579 | .path = full_path, | 1548 | .path = full_path, |
| 1580 | }, false) catch |err| switch (err) { | 1549 | }, false) catch |err| switch (err) { |
| 1581 | error.MalformedObject, error.MalformedArchive, error.InvalidMachineType => continue, // already reported | 1550 | error.LinkFailure => continue, // already reported |
| 1582 | else => |e| try self.reportParseError( | 1551 | else => |e| try self.addParseError( |
| 1583 | full_path, | 1552 | full_path, |
| 1584 | "unexpected error: parsing library failed with error {s}", | 1553 | "unexpected error: parsing library failed with error {s}", |
| 1585 | .{@errorName(e)}, | 1554 | .{@errorName(e)}, |
| ... | @@ -1604,24 +1573,24 @@ pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Wor | ... | @@ -1604,24 +1573,24 @@ pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Wor |
| 1604 | self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc; | 1573 | self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc; |
| 1605 | self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso; | 1574 | self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso; |
| 1606 | 1575 | ||
| 1607 | var is_error: bool = false; | 1576 | var any_errors: bool = false; |
| 1608 | if (self_riscv_eflags.fabi != riscv_eflags.fabi) { | 1577 | if (self_riscv_eflags.fabi != riscv_eflags.fabi) { |
| 1609 | is_error = true; | 1578 | any_errors = true; |
| 1610 | _ = try self.reportParseError2( | 1579 | try self.addFileError( |
| 1611 | file_index, | 1580 | file_index, |
| 1612 | "cannot link object files with different float-point ABIs", | 1581 | "cannot link object files with different float-point ABIs", |
| 1613 | .{}, | 1582 | .{}, |
| 1614 | ); | 1583 | ); |
| 1615 | } | 1584 | } |
| 1616 | if (self_riscv_eflags.rve != riscv_eflags.rve) { | 1585 | if (self_riscv_eflags.rve != riscv_eflags.rve) { |
| 1617 | is_error = true; | 1586 | any_errors = true; |
| 1618 | _ = try self.reportParseError2( | 1587 | try self.addFileError( |
| 1619 | file_index, | 1588 | file_index, |
| 1620 | "cannot link object files with different RVEs", | 1589 | "cannot link object files with different RVEs", |
| 1621 | .{}, | 1590 | .{}, |
| 1622 | ); | 1591 | ); |
| 1623 | } | 1592 | } |
| 1624 | if (is_error) return error.MismatchedEflags; | 1593 | if (any_errors) return error.LinkFailure; |
| 1625 | } | 1594 | } |
| 1626 | }, | 1595 | }, |
| 1627 | else => {}, | 1596 | else => {}, |
| ... | @@ -1743,12 +1712,6 @@ pub fn markEhFrameAtomsDead(self: *Elf) void { | ... | @@ -1743,12 +1712,6 @@ pub fn markEhFrameAtomsDead(self: *Elf) void { |
| 1743 | } | 1712 | } |
| 1744 | } | 1713 | } |
| 1745 | 1714 | ||
| 1746 | fn convertCommonSymbols(self: *Elf) !void { | ||
| 1747 | for (self.objects.items) |index| { | ||
| 1748 | try self.file(index).?.object.convertCommonSymbols(self); | ||
| 1749 | } | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | fn markImportsExports(self: *Elf) void { | 1715 | fn markImportsExports(self: *Elf) void { |
| 1753 | if (self.zigObjectPtr()) |zo| { | 1716 | if (self.zigObjectPtr()) |zo| { |
| 1754 | zo.markImportsExports(self); | 1717 | zo.markImportsExports(self); |
| ... | @@ -1978,7 +1941,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -1978,7 +1941,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1978 | man.hash.add(self.emit_relocs); | 1941 | man.hash.add(self.emit_relocs); |
| 1979 | man.hash.add(comp.config.rdynamic); | 1942 | man.hash.add(comp.config.rdynamic); |
| 1980 | man.hash.addListOfBytes(self.lib_dirs); | 1943 | man.hash.addListOfBytes(self.lib_dirs); |
| 1981 | man.hash.addListOfBytes(self.base.rpath_list); | 1944 | man.hash.addListOfBytes(self.rpath_table.keys()); |
| 1982 | if (output_mode == .Exe) { | 1945 | if (output_mode == .Exe) { |
| 1983 | man.hash.add(self.base.stack_size); | 1946 | man.hash.add(self.base.stack_size); |
| 1984 | man.hash.add(self.base.build_id); | 1947 | man.hash.add(self.base.build_id); |
| ... | @@ -2263,14 +2226,8 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2263,14 +2226,8 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2263 | if (csu.crti) |v| try argv.append(v); | 2226 | if (csu.crti) |v| try argv.append(v); |
| 2264 | if (csu.crtbegin) |v| try argv.append(v); | 2227 | if (csu.crtbegin) |v| try argv.append(v); |
| 2265 | 2228 | ||
| 2266 | // rpaths | 2229 | for (self.rpath_table.keys()) |rpath| { |
| 2267 | var rpath_table = std.StringHashMap(void).init(gpa); | 2230 | try argv.appendSlice(&.{ "-rpath", rpath }); |
| 2268 | defer rpath_table.deinit(); | ||
| 2269 | for (self.base.rpath_list) |rpath| { | ||
| 2270 | if ((try rpath_table.fetchPut(rpath, {})) == null) { | ||
| 2271 | try argv.append("-rpath"); | ||
| 2272 | try argv.append(rpath); | ||
| 2273 | } | ||
| 2274 | } | 2231 | } |
| 2275 | 2232 | ||
| 2276 | for (self.symbol_wrap_set.keys()) |symbol_name| { | 2233 | for (self.symbol_wrap_set.keys()) |symbol_name| { |
| ... | @@ -2847,7 +2804,7 @@ pub fn resolveMergeSections(self: *Elf) !void { | ... | @@ -2847,7 +2804,7 @@ pub fn resolveMergeSections(self: *Elf) !void { |
| 2847 | const file_ptr = self.file(index).?; | 2804 | const file_ptr = self.file(index).?; |
| 2848 | if (!file_ptr.isAlive()) continue; | 2805 | if (!file_ptr.isAlive()) continue; |
| 2849 | file_ptr.object.initInputMergeSections(self) catch |err| switch (err) { | 2806 | file_ptr.object.initInputMergeSections(self) catch |err| switch (err) { |
| 2850 | error.MalformedObject => has_errors = true, | 2807 | error.LinkFailure => has_errors = true, |
| 2851 | else => |e| return e, | 2808 | else => |e| return e, |
| 2852 | }; | 2809 | }; |
| 2853 | } | 2810 | } |
| ... | @@ -2864,12 +2821,12 @@ pub fn resolveMergeSections(self: *Elf) !void { | ... | @@ -2864,12 +2821,12 @@ pub fn resolveMergeSections(self: *Elf) !void { |
| 2864 | const file_ptr = self.file(index).?; | 2821 | const file_ptr = self.file(index).?; |
| 2865 | if (!file_ptr.isAlive()) continue; | 2822 | if (!file_ptr.isAlive()) continue; |
| 2866 | file_ptr.object.resolveMergeSubsections(self) catch |err| switch (err) { | 2823 | file_ptr.object.resolveMergeSubsections(self) catch |err| switch (err) { |
| 2867 | error.MalformedObject => has_errors = true, | 2824 | error.LinkFailure => has_errors = true, |
| 2868 | else => |e| return e, | 2825 | else => |e| return e, |
| 2869 | }; | 2826 | }; |
| 2870 | } | 2827 | } |
| 2871 | 2828 | ||
| 2872 | if (has_errors) return error.FlushFailure; | 2829 | if (has_errors) return error.LinkFailure; |
| 2873 | } | 2830 | } |
| 2874 | 2831 | ||
| 2875 | pub fn finalizeMergeSections(self: *Elf) !void { | 2832 | pub fn finalizeMergeSections(self: *Elf) !void { |
| ... | @@ -5201,7 +5158,7 @@ fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { | ... | @@ -5201,7 +5158,7 @@ fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { |
| 5201 | }); | 5158 | }); |
| 5202 | } | 5159 | } |
| 5203 | 5160 | ||
| 5204 | pub fn reportParseError( | 5161 | pub fn addParseError( |
| 5205 | self: *Elf, | 5162 | self: *Elf, |
| 5206 | path: []const u8, | 5163 | path: []const u8, |
| 5207 | comptime format: []const u8, | 5164 | comptime format: []const u8, |
| ... | @@ -5212,7 +5169,7 @@ pub fn reportParseError( | ... | @@ -5212,7 +5169,7 @@ pub fn reportParseError( |
| 5212 | try err.addNote("while parsing {s}", .{path}); | 5169 | try err.addNote("while parsing {s}", .{path}); |
| 5213 | } | 5170 | } |
| 5214 | 5171 | ||
| 5215 | pub fn reportParseError2( | 5172 | pub fn addFileError( |
| 5216 | self: *Elf, | 5173 | self: *Elf, |
| 5217 | file_index: File.Index, | 5174 | file_index: File.Index, |
| 5218 | comptime format: []const u8, | 5175 | comptime format: []const u8, |
| ... | @@ -5223,6 +5180,26 @@ pub fn reportParseError2( | ... | @@ -5223,6 +5180,26 @@ pub fn reportParseError2( |
| 5223 | try err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()}); | 5180 | try err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()}); |
| 5224 | } | 5181 | } |
| 5225 | 5182 | ||
| 5183 | pub fn failFile( | ||
| 5184 | self: *Elf, | ||
| 5185 | file_index: File.Index, | ||
| 5186 | comptime format: []const u8, | ||
| 5187 | args: anytype, | ||
| 5188 | ) error{ OutOfMemory, LinkFailure } { | ||
| 5189 | try addFileError(self, file_index, format, args); | ||
| 5190 | return error.LinkFailure; | ||
| 5191 | } | ||
| 5192 | |||
| 5193 | pub fn failParse( | ||
| 5194 | self: *Elf, | ||
| 5195 | path: []const u8, | ||
| 5196 | comptime format: []const u8, | ||
| 5197 | args: anytype, | ||
| 5198 | ) error{ OutOfMemory, LinkFailure } { | ||
| 5199 | try addParseError(self, path, format, args); | ||
| 5200 | return error.LinkFailure; | ||
| 5201 | } | ||
| 5202 | |||
| 5226 | const FormatShdrCtx = struct { | 5203 | const FormatShdrCtx = struct { |
| 5227 | elf_file: *Elf, | 5204 | elf_file: *Elf, |
| 5228 | shdr: elf.Elf64_Shdr, | 5205 | shdr: elf.Elf64_Shdr, |
src/link/Elf/Archive.zig+1-2| ... | @@ -35,10 +35,9 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: []const u8, handle_index: Fil | ... | @@ -35,10 +35,9 @@ pub fn parse(self: *Archive, elf_file: *Elf, path: []const u8, handle_index: Fil |
| 35 | pos += @sizeOf(elf.ar_hdr); | 35 | pos += @sizeOf(elf.ar_hdr); |
| 36 | 36 | ||
| 37 | if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) { | 37 | if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) { |
| 38 | try elf_file.reportParseError(path, "invalid archive header delimiter: {s}", .{ | 38 | return elf_file.failParse(path, "invalid archive header delimiter: {s}", .{ |
| 39 | std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag), | 39 | std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag), |
| 40 | }); | 40 | }); |
| 41 | return error.MalformedArchive; | ||
| 42 | } | 41 | } |
| 43 | 42 | ||
| 44 | const obj_size = try hdr.size(); | 43 | const obj_size = try hdr.size(); |
src/link/Elf/LdScript.zig+4-8| ... | @@ -7,7 +7,7 @@ pub fn deinit(scr: *LdScript, allocator: Allocator) void { | ... | @@ -7,7 +7,7 @@ pub fn deinit(scr: *LdScript, allocator: Allocator) void { |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | pub const Error = error{ | 9 | pub const Error = error{ |
| 10 | InvalidLdScript, | 10 | LinkFailure, |
| 11 | UnexpectedToken, | 11 | UnexpectedToken, |
| 12 | UnknownCpuArch, | 12 | UnknownCpuArch, |
| 13 | OutOfMemory, | 13 | OutOfMemory, |
| ... | @@ -32,12 +32,9 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { | ... | @@ -32,12 +32,9 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { |
| 32 | try line_col.append(.{ .line = line, .column = column }); | 32 | try line_col.append(.{ .line = line, .column = column }); |
| 33 | switch (tok.id) { | 33 | switch (tok.id) { |
| 34 | .invalid => { | 34 | .invalid => { |
| 35 | try elf_file.reportParseError(scr.path, "invalid token in LD script: '{s}' ({d}:{d})", .{ | 35 | return elf_file.failParse(scr.path, "invalid token in LD script: '{s}' ({d}:{d})", .{ |
| 36 | std.fmt.fmtSliceEscapeLower(tok.get(data)), | 36 | std.fmt.fmtSliceEscapeLower(tok.get(data)), line, column, |
| 37 | line, | ||
| 38 | column, | ||
| 39 | }); | 37 | }); |
| 40 | return error.InvalidLdScript; | ||
| 41 | }, | 38 | }, |
| 42 | .new_line => { | 39 | .new_line => { |
| 43 | line += 1; | 40 | line += 1; |
| ... | @@ -59,13 +56,12 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { | ... | @@ -59,13 +56,12 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { |
| 59 | const last_token_id = parser.it.pos - 1; | 56 | const last_token_id = parser.it.pos - 1; |
| 60 | const last_token = parser.it.get(last_token_id); | 57 | const last_token = parser.it.get(last_token_id); |
| 61 | const lcol = line_col.items[last_token_id]; | 58 | const lcol = line_col.items[last_token_id]; |
| 62 | try elf_file.reportParseError(scr.path, "unexpected token in LD script: {s}: '{s}' ({d}:{d})", .{ | 59 | return elf_file.failParse(scr.path, "unexpected token in LD script: {s}: '{s}' ({d}:{d})", .{ |
| 63 | @tagName(last_token.id), | 60 | @tagName(last_token.id), |
| 64 | last_token.get(data), | 61 | last_token.get(data), |
| 65 | lcol.line, | 62 | lcol.line, |
| 66 | lcol.column, | 63 | lcol.column, |
| 67 | }); | 64 | }); |
| 68 | return error.InvalidLdScript; | ||
| 69 | }, | 65 | }, |
| 70 | else => |e| return e, | 66 | else => |e| return e, |
| 71 | }; | 67 | }; |
src/link/Elf/Object.zig+20-53| ... | @@ -34,18 +34,6 @@ num_dynrelocs: u32 = 0, | ... | @@ -34,18 +34,6 @@ num_dynrelocs: u32 = 0, |
| 34 | output_symtab_ctx: Elf.SymtabCtx = .{}, | 34 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 35 | output_ar_state: Archive.ArState = .{}, | 35 | output_ar_state: Archive.ArState = .{}, |
| 36 | 36 | ||
| 37 | pub fn isObject(path: []const u8) !bool { | ||
| 38 | const file = try std.fs.cwd().openFile(path, .{}); | ||
| 39 | defer file.close(); | ||
| 40 | const reader = file.reader(); | ||
| 41 | const header = reader.readStruct(elf.Elf64_Ehdr) catch return false; | ||
| 42 | if (!mem.eql(u8, header.e_ident[0..4], "\x7fELF")) return false; | ||
| 43 | if (header.e_ident[elf.EI_VERSION] != 1) return false; | ||
| 44 | if (header.e_type != elf.ET.REL) return false; | ||
| 45 | if (header.e_version != 1) return false; | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | pub fn deinit(self: *Object, allocator: Allocator) void { | 37 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 50 | if (self.archive) |*ar| allocator.free(ar.path); | 38 | if (self.archive) |*ar| allocator.free(ar.path); |
| 51 | allocator.free(self.path); | 39 | allocator.free(self.path); |
| ... | @@ -107,12 +95,9 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil | ... | @@ -107,12 +95,9 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil |
| 107 | 95 | ||
| 108 | const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine(); | 96 | const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine(); |
| 109 | if (em != self.header.?.e_machine) { | 97 | if (em != self.header.?.e_machine) { |
| 110 | try elf_file.reportParseError2( | 98 | return elf_file.failFile(self.index, "invalid ELF machine type: {s}", .{ |
| 111 | self.index, | 99 | @tagName(self.header.?.e_machine), |
| 112 | "invalid ELF machine type: {s}", | 100 | }); |
| 113 | .{@tagName(self.header.?.e_machine)}, | ||
| 114 | ); | ||
| 115 | return error.InvalidMachineType; | ||
| 116 | } | 101 | } |
| 117 | try elf_file.validateEFlags(self.index, self.header.?.e_flags); | 102 | try elf_file.validateEFlags(self.index, self.header.?.e_flags); |
| 118 | 103 | ||
| ... | @@ -122,12 +107,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil | ... | @@ -122,12 +107,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil |
| 122 | const shnum = math.cast(usize, self.header.?.e_shnum) orelse return error.Overflow; | 107 | const shnum = math.cast(usize, self.header.?.e_shnum) orelse return error.Overflow; |
| 123 | const shsize = shnum * @sizeOf(elf.Elf64_Shdr); | 108 | const shsize = shnum * @sizeOf(elf.Elf64_Shdr); |
| 124 | if (file_size < offset + shoff or file_size < offset + shoff + shsize) { | 109 | if (file_size < offset + shoff or file_size < offset + shoff + shsize) { |
| 125 | try elf_file.reportParseError2( | 110 | return elf_file.failFile(self.index, "corrupt header: section header table extends past the end of file", .{}); |
| 126 | self.index, | ||
| 127 | "corrupt header: section header table extends past the end of file", | ||
| 128 | .{}, | ||
| 129 | ); | ||
| 130 | return error.MalformedObject; | ||
| 131 | } | 111 | } |
| 132 | 112 | ||
| 133 | const shdrs_buffer = try Elf.preadAllAlloc(allocator, handle, offset + shoff, shsize); | 113 | const shdrs_buffer = try Elf.preadAllAlloc(allocator, handle, offset + shoff, shsize); |
| ... | @@ -138,8 +118,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil | ... | @@ -138,8 +118,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil |
| 138 | for (self.shdrs.items) |shdr| { | 118 | for (self.shdrs.items) |shdr| { |
| 139 | if (shdr.sh_type != elf.SHT_NOBITS) { | 119 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 140 | if (file_size < offset + shdr.sh_offset or file_size < offset + shdr.sh_offset + shdr.sh_size) { | 120 | if (file_size < offset + shdr.sh_offset or file_size < offset + shdr.sh_offset + shdr.sh_size) { |
| 141 | try elf_file.reportParseError2(self.index, "corrupt section: extends past the end of file", .{}); | 121 | return elf_file.failFile(self.index, "corrupt section: extends past the end of file", .{}); |
| 142 | return error.MalformedObject; | ||
| 143 | } | 122 | } |
| 144 | } | 123 | } |
| 145 | } | 124 | } |
| ... | @@ -148,8 +127,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil | ... | @@ -148,8 +127,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil |
| 148 | defer allocator.free(shstrtab); | 127 | defer allocator.free(shstrtab); |
| 149 | for (self.shdrs.items) |shdr| { | 128 | for (self.shdrs.items) |shdr| { |
| 150 | if (shdr.sh_name >= shstrtab.len) { | 129 | if (shdr.sh_name >= shstrtab.len) { |
| 151 | try elf_file.reportParseError2(self.index, "corrupt section name offset", .{}); | 130 | return elf_file.failFile(self.index, "corrupt section name offset", .{}); |
| 152 | return error.MalformedObject; | ||
| 153 | } | 131 | } |
| 154 | } | 132 | } |
| 155 | try self.strtab.appendSlice(allocator, shstrtab); | 133 | try self.strtab.appendSlice(allocator, shstrtab); |
| ... | @@ -166,8 +144,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil | ... | @@ -166,8 +144,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil |
| 166 | const raw_symtab = try self.preadShdrContentsAlloc(allocator, handle, index); | 144 | const raw_symtab = try self.preadShdrContentsAlloc(allocator, handle, index); |
| 167 | defer allocator.free(raw_symtab); | 145 | defer allocator.free(raw_symtab); |
| 168 | const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch { | 146 | const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch { |
| 169 | try elf_file.reportParseError2(self.index, "symbol table not evenly divisible", .{}); | 147 | return elf_file.failFile(self.index, "symbol table not evenly divisible", .{}); |
| 170 | return error.MalformedObject; | ||
| 171 | }; | 148 | }; |
| 172 | const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms]; | 149 | const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms]; |
| 173 | 150 | ||
| ... | @@ -221,30 +198,15 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: | ... | @@ -221,30 +198,15 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 221 | const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx); | 198 | const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx); |
| 222 | defer allocator.free(group_raw_data); | 199 | defer allocator.free(group_raw_data); |
| 223 | const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch { | 200 | const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch { |
| 224 | try elf_file.reportParseError2( | 201 | return elf_file.failFile(self.index, "corrupt section group: not evenly divisible ", .{}); |
| 225 | self.index, | ||
| 226 | "corrupt section group: not evenly divisible ", | ||
| 227 | .{}, | ||
| 228 | ); | ||
| 229 | return error.MalformedObject; | ||
| 230 | }; | 202 | }; |
| 231 | if (group_nmembers == 0) { | 203 | if (group_nmembers == 0) { |
| 232 | try elf_file.reportParseError2( | 204 | return elf_file.failFile(self.index, "corrupt section group: empty section", .{}); |
| 233 | self.index, | ||
| 234 | "corrupt section group: empty section", | ||
| 235 | .{}, | ||
| 236 | ); | ||
| 237 | return error.MalformedObject; | ||
| 238 | } | 205 | } |
| 239 | const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers]; | 206 | const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers]; |
| 240 | 207 | ||
| 241 | if (group_members[0] != elf.GRP_COMDAT) { | 208 | if (group_members[0] != elf.GRP_COMDAT) { |
| 242 | try elf_file.reportParseError2( | 209 | return elf_file.failFile(self.index, "corrupt section group: unknown SHT_GROUP format", .{}); |
| 243 | self.index, | ||
| 244 | "corrupt section group: unknown SHT_GROUP format", | ||
| 245 | .{}, | ||
| 246 | ); | ||
| 247 | return error.MalformedObject; | ||
| 248 | } | 210 | } |
| 249 | 211 | ||
| 250 | const group_start = @as(u32, @intCast(self.comdat_group_data.items.len)); | 212 | const group_start = @as(u32, @intCast(self.comdat_group_data.items.len)); |
| ... | @@ -722,7 +684,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -722,7 +684,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 722 | var err = try elf_file.base.addErrorWithNotes(1); | 684 | var err = try elf_file.base.addErrorWithNotes(1); |
| 723 | try err.addMsg("string not null terminated", .{}); | 685 | try err.addMsg("string not null terminated", .{}); |
| 724 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | 686 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 725 | return error.MalformedObject; | 687 | return error.LinkFailure; |
| 726 | } | 688 | } |
| 727 | end += sh_entsize; | 689 | end += sh_entsize; |
| 728 | const string = data[start..end]; | 690 | const string = data[start..end]; |
| ... | @@ -737,7 +699,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -737,7 +699,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 737 | var err = try elf_file.base.addErrorWithNotes(1); | 699 | var err = try elf_file.base.addErrorWithNotes(1); |
| 738 | try err.addMsg("size not a multiple of sh_entsize", .{}); | 700 | try err.addMsg("size not a multiple of sh_entsize", .{}); |
| 739 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | 701 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 740 | return error.MalformedObject; | 702 | return error.LinkFailure; |
| 741 | } | 703 | } |
| 742 | 704 | ||
| 743 | var pos: u32 = 0; | 705 | var pos: u32 = 0; |
| ... | @@ -765,7 +727,12 @@ pub fn initOutputMergeSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -765,7 +727,12 @@ pub fn initOutputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 765 | } | 727 | } |
| 766 | } | 728 | } |
| 767 | 729 | ||
| 768 | pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { | 730 | pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ |
| 731 | LinkFailure, | ||
| 732 | OutOfMemory, | ||
| 733 | /// TODO report the error and remove this | ||
| 734 | Overflow, | ||
| 735 | }!void { | ||
| 769 | const gpa = elf_file.base.comp.gpa; | 736 | const gpa = elf_file.base.comp.gpa; |
| 770 | 737 | ||
| 771 | for (self.input_merge_sections_indexes.items) |index| { | 738 | for (self.input_merge_sections_indexes.items) |index| { |
| ... | @@ -809,7 +776,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { | ... | @@ -809,7 +776,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 809 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); | 776 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); |
| 810 | try err.addNote("for symbol {s}", .{sym.name(elf_file)}); | 777 | try err.addNote("for symbol {s}", .{sym.name(elf_file)}); |
| 811 | try err.addNote("in {}", .{self.fmtPath()}); | 778 | try err.addNote("in {}", .{self.fmtPath()}); |
| 812 | return error.MalformedObject; | 779 | return error.LinkFailure; |
| 813 | }; | 780 | }; |
| 814 | 781 | ||
| 815 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; | 782 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; |
| ... | @@ -834,7 +801,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { | ... | @@ -834,7 +801,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 834 | var err = try elf_file.base.addErrorWithNotes(1); | 801 | var err = try elf_file.base.addErrorWithNotes(1); |
| 835 | try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); | 802 | try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); |
| 836 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | 803 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 837 | return error.MalformedObject; | 804 | return error.LinkFailure; |
| 838 | }; | 805 | }; |
| 839 | 806 | ||
| 840 | const sym_index = try self.addSymbol(gpa); | 807 | const sym_index = try self.addSymbol(gpa); |
src/link/Elf/SharedObject.zig+5-14| ... | @@ -58,24 +58,16 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { | ... | @@ -58,24 +58,16 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { |
| 58 | 58 | ||
| 59 | const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine(); | 59 | const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine(); |
| 60 | if (em != self.header.?.e_machine) { | 60 | if (em != self.header.?.e_machine) { |
| 61 | try elf_file.reportParseError2( | 61 | return elf_file.failFile(self.index, "invalid ELF machine type: {s}", .{ |
| 62 | self.index, | 62 | @tagName(self.header.?.e_machine), |
| 63 | "invalid ELF machine type: {s}", | 63 | }); |
| 64 | .{@tagName(self.header.?.e_machine)}, | ||
| 65 | ); | ||
| 66 | return error.InvalidMachineType; | ||
| 67 | } | 64 | } |
| 68 | 65 | ||
| 69 | const shoff = std.math.cast(usize, self.header.?.e_shoff) orelse return error.Overflow; | 66 | const shoff = std.math.cast(usize, self.header.?.e_shoff) orelse return error.Overflow; |
| 70 | const shnum = std.math.cast(usize, self.header.?.e_shnum) orelse return error.Overflow; | 67 | const shnum = std.math.cast(usize, self.header.?.e_shnum) orelse return error.Overflow; |
| 71 | const shsize = shnum * @sizeOf(elf.Elf64_Shdr); | 68 | const shsize = shnum * @sizeOf(elf.Elf64_Shdr); |
| 72 | if (file_size < shoff or file_size < shoff + shsize) { | 69 | if (file_size < shoff or file_size < shoff + shsize) { |
| 73 | try elf_file.reportParseError2( | 70 | return elf_file.failFile(self.index, "corrupted header: section header table extends past the end of file", .{}); |
| 74 | self.index, | ||
| 75 | "corrupted header: section header table extends past the end of file", | ||
| 76 | .{}, | ||
| 77 | ); | ||
| 78 | return error.MalformedObject; | ||
| 79 | } | 71 | } |
| 80 | 72 | ||
| 81 | const shdrs_buffer = try Elf.preadAllAlloc(gpa, handle, shoff, shsize); | 73 | const shdrs_buffer = try Elf.preadAllAlloc(gpa, handle, shoff, shsize); |
| ... | @@ -90,8 +82,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { | ... | @@ -90,8 +82,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { |
| 90 | for (self.shdrs.items, 0..) |shdr, i| { | 82 | for (self.shdrs.items, 0..) |shdr, i| { |
| 91 | if (shdr.sh_type != elf.SHT_NOBITS) { | 83 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 92 | if (file_size < shdr.sh_offset or file_size < shdr.sh_offset + shdr.sh_size) { | 84 | if (file_size < shdr.sh_offset or file_size < shdr.sh_offset + shdr.sh_size) { |
| 93 | try elf_file.reportParseError2(self.index, "corrupted section header", .{}); | 85 | return elf_file.failFile(self.index, "corrupted section header", .{}); |
| 94 | return error.MalformedObject; | ||
| 95 | } | 86 | } |
| 96 | } | 87 | } |
| 97 | switch (shdr.sh_type) { | 88 | switch (shdr.sh_type) { |
src/link/Elf/relocatable.zig+36-56| ... | @@ -1,36 +1,24 @@ | ... | @@ -1,36 +1,24 @@ |
| 1 | pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 1 | pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| 2 | const gpa = comp.gpa; | 2 | const gpa = comp.gpa; |
| 3 | 3 | ||
| 4 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | 4 | for (comp.objects) |obj| { |
| 5 | defer positionals.deinit(); | 5 | switch (Compilation.classifyFileExt(obj.path)) { |
| 6 | 6 | .object => try parseObjectStaticLibReportingFailure(elf_file, obj.path), | |
| 7 | try positionals.ensureUnusedCapacity(comp.objects.len); | 7 | .static_library => try parseArchiveStaticLibReportingFailure(elf_file, obj.path), |
| 8 | positionals.appendSliceAssumeCapacity(comp.objects); | 8 | else => try elf_file.addParseError(obj.path, "unrecognized file extension", .{}), |
| 9 | } | ||
| 10 | } | ||
| 9 | 11 | ||
| 10 | for (comp.c_object_table.keys()) |key| { | 12 | for (comp.c_object_table.keys()) |key| { |
| 11 | try positionals.append(.{ .path = key.status.success.object_path }); | 13 | try parseObjectStaticLibReportingFailure(elf_file, key.status.success.object_path); |
| 12 | } | 14 | } |
| 13 | 15 | ||
| 14 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 16 | if (module_obj_path) |path| { |
| 17 | try parseObjectStaticLibReportingFailure(elf_file, path); | ||
| 18 | } | ||
| 15 | 19 | ||
| 16 | if (comp.include_compiler_rt) { | 20 | if (comp.include_compiler_rt) { |
| 17 | try positionals.append(.{ .path = comp.compiler_rt_obj.?.full_object_path }); | 21 | try parseObjectStaticLibReportingFailure(elf_file, comp.compiler_rt_obj.?.full_object_path); |
| 18 | } | ||
| 19 | |||
| 20 | for (positionals.items) |obj| { | ||
| 21 | parsePositionalStaticLib(elf_file, obj.path) catch |err| switch (err) { | ||
| 22 | error.MalformedObject, | ||
| 23 | error.MalformedArchive, | ||
| 24 | error.InvalidMachineType, | ||
| 25 | error.MismatchedEflags, | ||
| 26 | => continue, // already reported | ||
| 27 | error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}), | ||
| 28 | else => |e| try elf_file.reportParseError( | ||
| 29 | obj.path, | ||
| 30 | "unexpected error: parsing input file failed with error {s}", | ||
| 31 | .{@errorName(e)}, | ||
| 32 | ), | ||
| 33 | }; | ||
| 34 | } | 22 | } |
| 35 | 23 | ||
| 36 | if (elf_file.base.hasErrors()) return error.FlushFailure; | 24 | if (elf_file.base.hasErrors()) return error.FlushFailure; |
| ... | @@ -153,37 +141,23 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co | ... | @@ -153,37 +141,23 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co |
| 153 | } | 141 | } |
| 154 | 142 | ||
| 155 | pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 143 | pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| 156 | const gpa = elf_file.base.comp.gpa; | 144 | for (comp.objects) |obj| { |
| 157 | 145 | if (obj.isObject()) { | |
| 158 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | 146 | try elf_file.parseObjectReportingFailure(obj.path); |
| 159 | defer positionals.deinit(); | 147 | } else { |
| 160 | try positionals.ensureUnusedCapacity(comp.objects.len); | 148 | try elf_file.parseLibraryReportingFailure(.{ .path = obj.path }, obj.must_link); |
| 161 | positionals.appendSliceAssumeCapacity(comp.objects); | 149 | } |
| 150 | } | ||
| 162 | 151 | ||
| 163 | // This is a set of object files emitted by clang in a single `build-exe` invocation. | 152 | // This is a set of object files emitted by clang in a single `build-exe` invocation. |
| 164 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up | 153 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up |
| 165 | // in this set. | 154 | // in this set. |
| 166 | for (comp.c_object_table.keys()) |key| { | 155 | for (comp.c_object_table.keys()) |key| { |
| 167 | try positionals.append(.{ .path = key.status.success.object_path }); | 156 | try elf_file.parseObjectReportingFailure(key.status.success.object_path); |
| 168 | } | ||
| 169 | |||
| 170 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | ||
| 171 | |||
| 172 | for (positionals.items) |obj| { | ||
| 173 | elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | ||
| 174 | error.MalformedObject, | ||
| 175 | error.MalformedArchive, | ||
| 176 | error.InvalidMachineType, | ||
| 177 | error.MismatchedEflags, | ||
| 178 | => continue, // already reported | ||
| 179 | else => |e| try elf_file.reportParseError( | ||
| 180 | obj.path, | ||
| 181 | "unexpected error: parsing input file failed with error {s}", | ||
| 182 | .{@errorName(e)}, | ||
| 183 | ), | ||
| 184 | }; | ||
| 185 | } | 157 | } |
| 186 | 158 | ||
| 159 | if (module_obj_path) |path| try elf_file.parseObjectReportingFailure(path); | ||
| 160 | |||
| 187 | if (elf_file.base.hasErrors()) return error.FlushFailure; | 161 | if (elf_file.base.hasErrors()) return error.FlushFailure; |
| 188 | 162 | ||
| 189 | // Now, we are ready to resolve the symbols across all input files. | 163 | // Now, we are ready to resolve the symbols across all input files. |
| ... | @@ -224,14 +198,20 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -224,14 +198,20 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 224 | if (elf_file.base.hasErrors()) return error.FlushFailure; | 198 | if (elf_file.base.hasErrors()) return error.FlushFailure; |
| 225 | } | 199 | } |
| 226 | 200 | ||
| 227 | fn parsePositionalStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 201 | fn parseObjectStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error{OutOfMemory}!void { |
| 228 | if (try Object.isObject(path)) { | 202 | parseObjectStaticLib(elf_file, path) catch |err| switch (err) { |
| 229 | try parseObjectStaticLib(elf_file, path); | 203 | error.LinkFailure => return, |
| 230 | } else if (try Archive.isArchive(path)) { | 204 | error.OutOfMemory => return error.OutOfMemory, |
| 231 | try parseArchiveStaticLib(elf_file, path); | 205 | else => |e| try elf_file.addParseError(path, "parsing object failed: {s}", .{@errorName(e)}), |
| 232 | } else return error.UnknownFileType; | 206 | }; |
| 233 | // TODO: should we check for LD script? | 207 | } |
| 234 | // Actually, should we even unpack an archive? | 208 | |
| 209 | fn parseArchiveStaticLibReportingFailure(elf_file: *Elf, path: []const u8) error{OutOfMemory}!void { | ||
| 210 | parseArchiveStaticLib(elf_file, path) catch |err| switch (err) { | ||
| 211 | error.LinkFailure => return, | ||
| 212 | error.OutOfMemory => return error.OutOfMemory, | ||
| 213 | else => |e| try elf_file.addParseError(path, "parsing static library failed: {s}", .{@errorName(e)}), | ||
| 214 | }; | ||
| 235 | } | 215 | } |
| 236 | 216 | ||
| 237 | fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 217 | fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
src/link/MachO.zig+6-5| ... | @@ -1,5 +1,7 @@ | ... | @@ -1,5 +1,7 @@ |
| 1 | base: link.File, | 1 | base: link.File, |
| 2 | 2 | ||
| 3 | rpath_list: []const []const u8, | ||
| 4 | |||
| 3 | /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. | 5 | /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. |
| 4 | llvm_object: ?LlvmObject.Ptr = null, | 6 | llvm_object: ?LlvmObject.Ptr = null, |
| 5 | 7 | ||
| ... | @@ -192,8 +194,8 @@ pub fn createEmpty( | ... | @@ -192,8 +194,8 @@ pub fn createEmpty( |
| 192 | .file = null, | 194 | .file = null, |
| 193 | .disable_lld_caching = options.disable_lld_caching, | 195 | .disable_lld_caching = options.disable_lld_caching, |
| 194 | .build_id = options.build_id, | 196 | .build_id = options.build_id, |
| 195 | .rpath_list = options.rpath_list, | ||
| 196 | }, | 197 | }, |
| 198 | .rpath_list = options.rpath_list, | ||
| 197 | .pagezero_size = options.pagezero_size, | 199 | .pagezero_size = options.pagezero_size, |
| 198 | .headerpad_size = options.headerpad_size, | 200 | .headerpad_size = options.headerpad_size, |
| 199 | .headerpad_max_install_names = options.headerpad_max_install_names, | 201 | .headerpad_max_install_names = options.headerpad_max_install_names, |
| ... | @@ -662,9 +664,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -662,9 +664,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 662 | try argv.append(syslibroot); | 664 | try argv.append(syslibroot); |
| 663 | } | 665 | } |
| 664 | 666 | ||
| 665 | for (self.base.rpath_list) |rpath| { | 667 | for (self.rpath_list) |rpath| { |
| 666 | try argv.append("-rpath"); | 668 | try argv.appendSlice(&.{ "-rpath", rpath }); |
| 667 | try argv.append(rpath); | ||
| 668 | } | 669 | } |
| 669 | 670 | ||
| 670 | if (self.pagezero_size) |size| { | 671 | if (self.pagezero_size) |size| { |
| ... | @@ -2842,7 +2843,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2842,7 +2843,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2842 | ncmds += 1; | 2843 | ncmds += 1; |
| 2843 | } | 2844 | } |
| 2844 | 2845 | ||
| 2845 | for (self.base.rpath_list) |rpath| { | 2846 | for (self.rpath_list) |rpath| { |
| 2846 | try load_commands.writeRpathLC(rpath, writer); | 2847 | try load_commands.writeRpathLC(rpath, writer); |
| 2847 | ncmds += 1; | 2848 | ncmds += 1; |
| 2848 | } | 2849 | } |
src/link/MachO/load_commands.zig+1-1| ... | @@ -63,7 +63,7 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 | ... | @@ -63,7 +63,7 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 |
| 63 | } | 63 | } |
| 64 | // LC_RPATH | 64 | // LC_RPATH |
| 65 | { | 65 | { |
| 66 | for (macho_file.base.rpath_list) |rpath| { | 66 | for (macho_file.rpath_list) |rpath| { |
| 67 | sizeofcmds += calcInstallNameLen( | 67 | sizeofcmds += calcInstallNameLen( |
| 68 | @sizeOf(macho.rpath_command), | 68 | @sizeOf(macho.rpath_command), |
| 69 | rpath, | 69 | rpath, |
src/link/NvPtx.zig-1| ... | @@ -60,7 +60,6 @@ pub fn createEmpty( | ... | @@ -60,7 +60,6 @@ pub fn createEmpty( |
| 60 | .file = null, | 60 | .file = null, |
| 61 | .disable_lld_caching = options.disable_lld_caching, | 61 | .disable_lld_caching = options.disable_lld_caching, |
| 62 | .build_id = options.build_id, | 62 | .build_id = options.build_id, |
| 63 | .rpath_list = options.rpath_list, | ||
| 64 | }, | 63 | }, |
| 65 | .llvm_object = llvm_object, | 64 | .llvm_object = llvm_object, |
| 66 | }; | 65 | }; |
src/link/Plan9.zig-1| ... | @@ -304,7 +304,6 @@ pub fn createEmpty( | ... | @@ -304,7 +304,6 @@ pub fn createEmpty( |
| 304 | .file = null, | 304 | .file = null, |
| 305 | .disable_lld_caching = options.disable_lld_caching, | 305 | .disable_lld_caching = options.disable_lld_caching, |
| 306 | .build_id = options.build_id, | 306 | .build_id = options.build_id, |
| 307 | .rpath_list = options.rpath_list, | ||
| 308 | }, | 307 | }, |
| 309 | .sixtyfour_bit = sixtyfour_bit, | 308 | .sixtyfour_bit = sixtyfour_bit, |
| 310 | .bases = undefined, | 309 | .bases = undefined, |
src/link/SpirV.zig-1| ... | @@ -74,7 +74,6 @@ pub fn createEmpty( | ... | @@ -74,7 +74,6 @@ pub fn createEmpty( |
| 74 | .file = null, | 74 | .file = null, |
| 75 | .disable_lld_caching = options.disable_lld_caching, | 75 | .disable_lld_caching = options.disable_lld_caching, |
| 76 | .build_id = options.build_id, | 76 | .build_id = options.build_id, |
| 77 | .rpath_list = options.rpath_list, | ||
| 78 | }, | 77 | }, |
| 79 | .object = codegen.Object.init(gpa), | 78 | .object = codegen.Object.init(gpa), |
| 80 | }; | 79 | }; |
src/link/Wasm.zig-1| ... | @@ -398,7 +398,6 @@ pub fn createEmpty( | ... | @@ -398,7 +398,6 @@ pub fn createEmpty( |
| 398 | .file = null, | 398 | .file = null, |
| 399 | .disable_lld_caching = options.disable_lld_caching, | 399 | .disable_lld_caching = options.disable_lld_caching, |
| 400 | .build_id = options.build_id, | 400 | .build_id = options.build_id, |
| 401 | .rpath_list = options.rpath_list, | ||
| 402 | }, | 401 | }, |
| 403 | .name = undefined, | 402 | .name = undefined, |
| 404 | .import_table = options.import_table, | 403 | .import_table = options.import_table, |
test/link/elf.zig+1-1| ... | @@ -3916,7 +3916,7 @@ fn testUnknownFileTypeError(b: *Build, opts: Options) *Step { | ... | @@ -3916,7 +3916,7 @@ fn testUnknownFileTypeError(b: *Build, opts: Options) *Step { |
| 3916 | // "note: while parsing /?/liba.dylib", | 3916 | // "note: while parsing /?/liba.dylib", |
| 3917 | // } }); | 3917 | // } }); |
| 3918 | expectLinkErrors(exe, test_step, .{ | 3918 | expectLinkErrors(exe, test_step, .{ |
| 3919 | .contains = "error: unexpected error: parsing input file failed with error InvalidLdScript", | 3919 | .starts_with = "error: invalid token in LD script: '\\x00\\x00\\x00\\x0c\\x00\\x00\\x00/usr/lib/dyld\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0d' (", |
| 3920 | }); | 3920 | }); |
| 3921 | 3921 | ||
| 3922 | return test_step; | 3922 | return test_step; |