| author | |
| committer | |
| log | 8bd01eb7a914416a772b365dc75d83890067e26c |
| tree | 712c0c17006e6fc20ee158542df0d585a245530b |
| parent | 616a8f9853e461400f6f5c49dede3bf3a0ca25b6 |
3 files changed, 97 insertions(+), 53 deletions(-)
src/link/Elf.zig+6-12| ... | @@ -1075,6 +1075,10 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1075,6 +1075,10 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1075 | // --verbose-link | 1075 | // --verbose-link |
| 1076 | if (comp.verbose_link) try self.dumpArgv(comp); | 1076 | if (comp.verbose_link) try self.dumpArgv(comp); |
| 1077 | 1077 | ||
| 1078 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); | ||
| 1079 | if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path); | ||
| 1080 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); | ||
| 1081 | |||
| 1078 | const csu = try CsuObjects.init(arena, comp); | 1082 | const csu = try CsuObjects.init(arena, comp); |
| 1079 | const compiler_rt_path: ?[]const u8 = blk: { | 1083 | const compiler_rt_path: ?[]const u8 = blk: { |
| 1080 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | 1084 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| ... | @@ -1082,10 +1086,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1082,10 +1086,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1082 | break :blk null; | 1086 | break :blk null; |
| 1083 | }; | 1087 | }; |
| 1084 | 1088 | ||
| 1085 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); | ||
| 1086 | if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path); | ||
| 1087 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); | ||
| 1088 | |||
| 1089 | // Here we will parse input positional and library files (if referenced). | 1089 | // Here we will parse input positional and library files (if referenced). |
| 1090 | // This will roughly match in any linker backend we support. | 1090 | // This will roughly match in any linker backend we support. |
| 1091 | var positionals = std.ArrayList(Compilation.LinkObject).init(arena); | 1091 | var positionals = std.ArrayList(Compilation.LinkObject).init(arena); |
| ... | @@ -1249,13 +1249,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1249,13 +1249,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1249 | 1249 | ||
| 1250 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 1250 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 1251 | 1251 | ||
| 1252 | // Init all objects | ||
| 1253 | for (self.objects.items) |index| { | ||
| 1254 | try self.file(index).?.object.init(self); | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | ||
| 1258 | |||
| 1259 | // Dedup shared objects | 1252 | // Dedup shared objects |
| 1260 | { | 1253 | { |
| 1261 | var seen_dsos = std.StringHashMap(void).init(gpa); | 1254 | var seen_dsos = std.StringHashMap(void).init(gpa); |
| ... | @@ -1651,7 +1644,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1651,7 +1644,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1651 | Compilation.dump_argv(argv.items); | 1644 | Compilation.dump_argv(argv.items); |
| 1652 | } | 1645 | } |
| 1653 | 1646 | ||
| 1654 | const ParseError = error{ | 1647 | pub const ParseError = error{ |
| 1655 | MalformedObject, | 1648 | MalformedObject, |
| 1656 | MalformedArchive, | 1649 | MalformedArchive, |
| 1657 | InvalidCpuArch, | 1650 | InvalidCpuArch, |
| ... | @@ -1662,6 +1655,7 @@ const ParseError = error{ | ... | @@ -1662,6 +1655,7 @@ const ParseError = error{ |
| 1662 | FileSystem, | 1655 | FileSystem, |
| 1663 | NotSupported, | 1656 | NotSupported, |
| 1664 | InvalidCharacter, | 1657 | InvalidCharacter, |
| 1658 | UnknownFileType, | ||
| 1665 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; | 1659 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; |
| 1666 | 1660 | ||
| 1667 | pub fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { | 1661 | pub fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
src/link/Elf/Object.zig+35-30| ... | @@ -55,12 +55,26 @@ pub fn deinit(self: *Object, allocator: Allocator) void { | ... | @@ -55,12 +55,26 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 55 | 55 | ||
| 56 | pub fn parse(self: *Object, elf_file: *Elf) !void { | 56 | pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 57 | const gpa = elf_file.base.comp.gpa; | 57 | const gpa = elf_file.base.comp.gpa; |
| 58 | const offset = if (self.archive) |ar| ar.offset else 0; | ||
| 59 | const handle = elf_file.fileHandle(self.file_handle); | 58 | const handle = elf_file.fileHandle(self.file_handle); |
| 59 | |||
| 60 | try self.parseCommon(gpa, handle, elf_file); | ||
| 61 | try self.initAtoms(gpa, handle, elf_file); | ||
| 62 | try self.initSymtab(gpa, elf_file); | ||
| 63 | |||
| 64 | for (self.shdrs.items, 0..) |shdr, i| { | ||
| 65 | const atom = elf_file.atom(self.atoms.items[i]) orelse continue; | ||
| 66 | if (!atom.flags.alive) continue; | ||
| 67 | if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame")) | ||
| 68 | try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void { | ||
| 73 | const offset = if (self.archive) |ar| ar.offset else 0; | ||
| 60 | const file_size = (try handle.stat()).size; | 74 | const file_size = (try handle.stat()).size; |
| 61 | 75 | ||
| 62 | const header_buffer = try Elf.preadAllAlloc(gpa, handle, offset, @sizeOf(elf.Elf64_Ehdr)); | 76 | const header_buffer = try Elf.preadAllAlloc(allocator, handle, offset, @sizeOf(elf.Elf64_Ehdr)); |
| 63 | defer gpa.free(header_buffer); | 77 | defer allocator.free(header_buffer); |
| 64 | self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*; | 78 | self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*; |
| 65 | 79 | ||
| 66 | const target = elf_file.base.comp.root_mod.resolved_target.result; | 80 | const target = elf_file.base.comp.root_mod.resolved_target.result; |
| ... | @@ -87,10 +101,10 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { | ... | @@ -87,10 +101,10 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 87 | return error.MalformedObject; | 101 | return error.MalformedObject; |
| 88 | } | 102 | } |
| 89 | 103 | ||
| 90 | const shdrs_buffer = try Elf.preadAllAlloc(gpa, handle, offset + shoff, shsize); | 104 | const shdrs_buffer = try Elf.preadAllAlloc(allocator, handle, offset + shoff, shsize); |
| 91 | defer gpa.free(shdrs_buffer); | 105 | defer allocator.free(shdrs_buffer); |
| 92 | const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(shdrs_buffer.ptr))[0..shnum]; | 106 | const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(shdrs_buffer.ptr))[0..shnum]; |
| 93 | try self.shdrs.appendUnalignedSlice(gpa, shdrs); | 107 | try self.shdrs.appendUnalignedSlice(allocator, shdrs); |
| 94 | 108 | ||
| 95 | for (self.shdrs.items) |shdr| { | 109 | for (self.shdrs.items) |shdr| { |
| 96 | if (shdr.sh_type != elf.SHT_NOBITS) { | 110 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| ... | @@ -101,15 +115,15 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { | ... | @@ -101,15 +115,15 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 101 | } | 115 | } |
| 102 | } | 116 | } |
| 103 | 117 | ||
| 104 | const shstrtab = try self.preadShdrContentsAlloc(gpa, handle, self.header.?.e_shstrndx); | 118 | const shstrtab = try self.preadShdrContentsAlloc(allocator, handle, self.header.?.e_shstrndx); |
| 105 | defer gpa.free(shstrtab); | 119 | defer allocator.free(shstrtab); |
| 106 | for (self.shdrs.items) |shdr| { | 120 | for (self.shdrs.items) |shdr| { |
| 107 | if (shdr.sh_name >= shstrtab.len) { | 121 | if (shdr.sh_name >= shstrtab.len) { |
| 108 | try elf_file.reportParseError2(self.index, "corrupt section name offset", .{}); | 122 | try elf_file.reportParseError2(self.index, "corrupt section name offset", .{}); |
| 109 | return error.MalformedObject; | 123 | return error.MalformedObject; |
| 110 | } | 124 | } |
| 111 | } | 125 | } |
| 112 | try self.strtab.appendSlice(gpa, shstrtab); | 126 | try self.strtab.appendSlice(allocator, shstrtab); |
| 113 | 127 | ||
| 114 | const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) { | 128 | const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) { |
| 115 | elf.SHT_SYMTAB => break @as(u16, @intCast(i)), | 129 | elf.SHT_SYMTAB => break @as(u16, @intCast(i)), |
| ... | @@ -120,8 +134,8 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { | ... | @@ -120,8 +134,8 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 120 | const shdr = self.shdrs.items[index]; | 134 | const shdr = self.shdrs.items[index]; |
| 121 | self.first_global = shdr.sh_info; | 135 | self.first_global = shdr.sh_info; |
| 122 | 136 | ||
| 123 | const raw_symtab = try self.preadShdrContentsAlloc(gpa, handle, index); | 137 | const raw_symtab = try self.preadShdrContentsAlloc(allocator, handle, index); |
| 124 | defer gpa.free(raw_symtab); | 138 | defer allocator.free(raw_symtab); |
| 125 | const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch { | 139 | const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch { |
| 126 | try elf_file.reportParseError2(self.index, "symbol table not evenly divisible", .{}); | 140 | try elf_file.reportParseError2(self.index, "symbol table not evenly divisible", .{}); |
| 127 | return error.MalformedObject; | 141 | return error.MalformedObject; |
| ... | @@ -129,11 +143,11 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { | ... | @@ -129,11 +143,11 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 129 | const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms]; | 143 | const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms]; |
| 130 | 144 | ||
| 131 | const strtab_bias = @as(u32, @intCast(self.strtab.items.len)); | 145 | const strtab_bias = @as(u32, @intCast(self.strtab.items.len)); |
| 132 | const strtab = try self.preadShdrContentsAlloc(gpa, handle, shdr.sh_link); | 146 | const strtab = try self.preadShdrContentsAlloc(allocator, handle, shdr.sh_link); |
| 133 | defer gpa.free(strtab); | 147 | defer allocator.free(strtab); |
| 134 | try self.strtab.appendSlice(gpa, strtab); | 148 | try self.strtab.appendSlice(allocator, strtab); |
| 135 | 149 | ||
| 136 | try self.symtab.ensureUnusedCapacity(gpa, symtab.len); | 150 | try self.symtab.ensureUnusedCapacity(allocator, symtab.len); |
| 137 | for (symtab) |sym| { | 151 | for (symtab) |sym| { |
| 138 | const out_sym = self.symtab.addOneAssumeCapacity(); | 152 | const out_sym = self.symtab.addOneAssumeCapacity(); |
| 139 | out_sym.* = sym; | 153 | out_sym.* = sym; |
| ... | @@ -145,21 +159,6 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { | ... | @@ -145,21 +159,6 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { |
| 145 | } | 159 | } |
| 146 | } | 160 | } |
| 147 | 161 | ||
| 148 | pub fn init(self: *Object, elf_file: *Elf) !void { | ||
| 149 | const gpa = elf_file.base.comp.gpa; | ||
| 150 | const handle = elf_file.fileHandle(self.file_handle); | ||
| 151 | |||
| 152 | try self.initAtoms(gpa, handle, elf_file); | ||
| 153 | try self.initSymtab(gpa, elf_file); | ||
| 154 | |||
| 155 | for (self.shdrs.items, 0..) |shdr, i| { | ||
| 156 | const atom = elf_file.atom(self.atoms.items[i]) orelse continue; | ||
| 157 | if (!atom.flags.alive) continue; | ||
| 158 | if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame")) | ||
| 159 | try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void { | 162 | fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void { |
| 164 | const shdrs = self.shdrs.items; | 163 | const shdrs = self.shdrs.items; |
| 165 | try self.atoms.resize(allocator, shdrs.len); | 164 | try self.atoms.resize(allocator, shdrs.len); |
| ... | @@ -782,6 +781,12 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void { | ... | @@ -782,6 +781,12 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void { |
| 782 | } | 781 | } |
| 783 | } | 782 | } |
| 784 | 783 | ||
| 784 | pub fn parseAr(self: *Object, elf_file: *Elf) !void { | ||
| 785 | const gpa = elf_file.base.comp.gpa; | ||
| 786 | const handle = elf_file.fileHandle(self.file_handle); | ||
| 787 | try self.parseCommon(gpa, handle, elf_file); | ||
| 788 | } | ||
| 789 | |||
| 785 | pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void { | 790 | pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void { |
| 786 | const comp = elf_file.base.comp; | 791 | const comp = elf_file.base.comp; |
| 787 | const gpa = comp.gpa; | 792 | const gpa = comp.gpa; |
src/link/Elf/relocatable.zig+56-11| ... | @@ -7,18 +7,20 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co | ... | @@ -7,18 +7,20 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co |
| 7 | try positionals.ensureUnusedCapacity(comp.objects.len); | 7 | try positionals.ensureUnusedCapacity(comp.objects.len); |
| 8 | positionals.appendSliceAssumeCapacity(comp.objects); | 8 | positionals.appendSliceAssumeCapacity(comp.objects); |
| 9 | 9 | ||
| 10 | // This is a set of object files emitted by clang in a single `build-exe` invocation. | ||
| 11 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up | ||
| 12 | // in this set. | ||
| 13 | for (comp.c_object_table.keys()) |key| { | 10 | for (comp.c_object_table.keys()) |key| { |
| 14 | try positionals.append(.{ .path = key.status.success.object_path }); | 11 | try positionals.append(.{ .path = key.status.success.object_path }); |
| 15 | } | 12 | } |
| 16 | 13 | ||
| 17 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 14 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 18 | 15 | ||
| 16 | if (comp.include_compiler_rt) { | ||
| 17 | try positionals.append(.{ .path = comp.compiler_rt_obj.?.full_object_path }); | ||
| 18 | } | ||
| 19 | |||
| 19 | for (positionals.items) |obj| { | 20 | for (positionals.items) |obj| { |
| 20 | elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | 21 | parsePositional(elf_file, obj.path) catch |err| switch (err) { |
| 21 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported | 22 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported |
| 23 | error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}), | ||
| 22 | else => |e| try elf_file.reportParseError( | 24 | else => |e| try elf_file.reportParseError( |
| 23 | obj.path, | 25 | obj.path, |
| 24 | "unexpected error: parsing input file failed with error {s}", | 26 | "unexpected error: parsing input file failed with error {s}", |
| ... | @@ -172,13 +174,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -172,13 +174,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 172 | 174 | ||
| 173 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 175 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 174 | 176 | ||
| 175 | // Init all objects | ||
| 176 | for (elf_file.objects.items) |index| { | ||
| 177 | try elf_file.file(index).?.object.init(elf_file); | ||
| 178 | } | ||
| 179 | |||
| 180 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | ||
| 181 | |||
| 182 | // Now, we are ready to resolve the symbols across all input files. | 177 | // Now, we are ready to resolve the symbols across all input files. |
| 183 | // We will first resolve the files in the ZigObject, next in the parsed | 178 | // We will first resolve the files in the ZigObject, next in the parsed |
| 184 | // input Object files. | 179 | // input Object files. |
| ... | @@ -214,6 +209,55 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -214,6 +209,55 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 214 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 209 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 215 | } | 210 | } |
| 216 | 211 | ||
| 212 | fn parsePositional(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | ||
| 213 | if (try Object.isObject(path)) { | ||
| 214 | try parseObject(elf_file, path); | ||
| 215 | } else if (try Archive.isArchive(path)) { | ||
| 216 | try parseArchive(elf_file, path); | ||
| 217 | } else return error.UnknownFileType; | ||
| 218 | // TODO: should we check for LD script? | ||
| 219 | // Actually, should we even unpack an archive? | ||
| 220 | } | ||
| 221 | |||
| 222 | fn parseObject(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | ||
| 223 | const gpa = elf_file.base.comp.gpa; | ||
| 224 | const handle = try std.fs.cwd().openFile(path, .{}); | ||
| 225 | const fh = try elf_file.addFileHandle(handle); | ||
| 226 | |||
| 227 | const index = @as(File.Index, @intCast(try elf_file.files.addOne(gpa))); | ||
| 228 | elf_file.files.set(index, .{ .object = .{ | ||
| 229 | .path = try gpa.dupe(u8, path), | ||
| 230 | .file_handle = fh, | ||
| 231 | .index = index, | ||
| 232 | } }); | ||
| 233 | try elf_file.objects.append(gpa, index); | ||
| 234 | |||
| 235 | const object = elf_file.file(index).?.object; | ||
| 236 | try object.parseAr(elf_file); | ||
| 237 | } | ||
| 238 | |||
| 239 | fn parseArchive(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | ||
| 240 | const gpa = elf_file.base.comp.gpa; | ||
| 241 | const handle = try std.fs.cwd().openFile(path, .{}); | ||
| 242 | const fh = try elf_file.addFileHandle(handle); | ||
| 243 | |||
| 244 | var archive = Archive{}; | ||
| 245 | defer archive.deinit(gpa); | ||
| 246 | try archive.parse(elf_file, path, fh); | ||
| 247 | |||
| 248 | const objects = try archive.objects.toOwnedSlice(gpa); | ||
| 249 | defer gpa.free(objects); | ||
| 250 | |||
| 251 | for (objects) |extracted| { | ||
| 252 | const index = @as(File.Index, @intCast(try elf_file.files.addOne(gpa))); | ||
| 253 | elf_file.files.set(index, .{ .object = extracted }); | ||
| 254 | const object = &elf_file.files.items(.data)[index].object; | ||
| 255 | object.index = index; | ||
| 256 | try object.parseAr(elf_file); | ||
| 257 | try elf_file.objects.append(gpa, index); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 217 | fn claimUnresolved(elf_file: *Elf) void { | 261 | fn claimUnresolved(elf_file: *Elf) void { |
| 218 | if (elf_file.zigObjectPtr()) |zig_object| { | 262 | if (elf_file.zigObjectPtr()) |zig_object| { |
| 219 | zig_object.claimUnresolvedObject(elf_file); | 263 | zig_object.claimUnresolvedObject(elf_file); |
| ... | @@ -518,3 +562,4 @@ const Archive = @import("Archive.zig"); | ... | @@ -518,3 +562,4 @@ const Archive = @import("Archive.zig"); |
| 518 | const Compilation = @import("../../Compilation.zig"); | 562 | const Compilation = @import("../../Compilation.zig"); |
| 519 | const Elf = @import("../Elf.zig"); | 563 | const Elf = @import("../Elf.zig"); |
| 520 | const File = @import("file.zig").File; | 564 | const File = @import("file.zig").File; |
| 565 | const Object = @import("Object.zig"); |